Compare commits

...

74 Commits
v5.26 ... v5.28

Author SHA1 Message Date
icex2
d29d9415b2 Create changelog for 5.28 release 2019-12-06 23:08:28 +01:00
icex2
3212981cc9 Readme update supported games list, add SDVX Vivid Wave 2019-12-06 23:08:09 +01:00
Will Xyen
7ea12a8517 cconfig: add some documentation to init functions 2019-12-01 15:14:04 -05:00
Will Xyen
82ac30e49f sdvxio-kfca: use cconfig instead of envvar 2019-12-01 15:01:44 -05:00
Will Xyen
d177f23476 cconfig: add ability to load configs from default path and specify alternate flag names 2019-12-01 15:00:45 -05:00
Will Xyen
13050b05e5 sdvxio-kfca: add some docs and address some comments 2019-12-01 13:32:09 -05:00
Will Xyen
673881bc47 sdvxio-kfca: node detection and allow setting port through envvar 2019-12-01 12:56:18 -05:00
Will Xyen
74ddd96d32 sdvxhook2: fix usage info naming wrong port 2019-12-01 12:38:22 -05:00
Will Xyen
48622f6a58 cconfig: allow crlf line endings 2019-12-01 11:41:09 -05:00
Will Xyen
0ca353b250 sdvxhook2: add some minor documentation to config-gfx.h 2019-11-30 21:46:25 -05:00
Will Xyen
ddd7853810 d3d9exhook: refactor d3d9ex hook from sdvxhook2 to shared library 2019-11-30 10:05:14 -05:00
Will Xyen
51a697659b sdvxhook: remove pci override for gfx hooks and general cleanup 2019-11-30 09:12:08 -05:00
Will Xyen
412ece18fc sdvxhoook2: typo in gamestart 2019-11-26 16:04:14 -05:00
Will Xyen
1d247d44d5 sdvxhook2: Add sdvxhook2 2019-11-26 15:59:57 -05:00
Will Xyen
2011bfafd6 camhook: fixup some minor formatting and enable iidxhook8-config-cam-test 2019-11-26 00:32:12 -05:00
Will Xyen
b434d7975d camhook: move camera hook facilities to their own module
makes the number of cameras configurable (up to 2), as SDVX only needs 1
2019-11-24 00:47:35 -05:00
5ee40b3373b0ab4600315554ea660a00c47813da
2d8017dbda Stop SDVX hanging on thankyou for playing
Makes the following changes to the card poll response message when
emulating new card readers:
 - change the idle status code to 0x04 instead of 0x01
 - always set keypad_started field to 0x03
2019-11-13 00:24:10 +00:00
icex2
6da3732968 makefile: Add -Werror flag for release builds, only.
Keep normal/dev builds (e.g. just run make) without this flag
to allow keeping warnings around and not being forced to clean
them up during development.
2019-11-09 20:14:24 +01:00
icex2
f3ead543ab Update README.md with pipeline status 2019-11-08 21:41:18 +00:00
icex2
ad3995eeae Update .gitlab-ci.yml, missing releasetag stage. 2019-11-08 21:30:18 +00:00
icex2
78a7fd418a Update .gitlab-ci.yml. Create release on git tag. 2019-11-08 21:27:54 +00:00
icex2
518f65b8c0 Add gitlab-ci.yml for CI. 2019-11-08 20:01:11 +00:00
Will Xyen
041d6935ff imports: add avs_fs_addfs to list of imports for 1700 2019-10-24 20:37:43 -04:00
Will Xyen
69ee95c79a dist: Speify config.exe instead of just config in config.bat (#35) 2019-10-24 20:32:47 -04:00
icex2
b6e588116d Various import fixes caused by clang-format
Added format protection block to avoid re-ordering of header files
according to formatting rules.
2019-10-22 21:04:45 +02:00
icex2
c3bc8782f4 Apply clang-format code style to all source files 2019-10-20 00:50:40 +02:00
icex2
c600e1a423 Some clang-format tweaks to optimize code style 2019-10-20 00:50:37 +02:00
icex2
6741a1f2fd Add code formatting and testing to build pipeline. #3
This adds a few new make targets for formatting, testing and
release building.
2019-10-19 23:12:31 +02:00
icex2
ce61a246a6 doc: Try to highlight the usage of d3d8to9 wrapper in iidxhook1/2 2019-10-19 21:39:48 +02:00
icex2
e96a280bde Add documentation: inject, launcher and iidxhooks using them 2019-10-19 21:33:49 +02:00
icex2
5aa9ad1e02 iidxhook8: Add missing dist files for iidx 26
I know this is slightly redundant but we should stick to this
pattern as we have multiple old games that do not use identical
conf and gamestart files.
2019-10-18 20:24:08 +02:00
Will Xyen
d60a1e0c0f iidxhook8: Fixup some missed renaming from struct cleanup 2019-10-13 11:50:56 -04:00
icex2
03a9beae41 Bump version to 5.28 2019-10-12 20:50:14 +02:00
icex2
71f0a66408 Update changelog 2019-10-12 20:44:51 +02:00
Will Xyen
0f04d5ef19 bio2emu: cleanup setupapi code a bit 2019-10-12 14:16:55 -04:00
Will Xyen
0c1bbe08c0 iidxhook8: Rename bi2a structs to be more clear 2019-10-12 14:16:22 -04:00
Will Xyen
1c415eb207 bio2emu: Remove requirement for bio2emu_init_end to be called
Instead bio2emu_setupapi_hook_init is called during init, this is safe because the game's IO thread isn't initialized at this point, and nothing could be attempting to open devices at this point in time.
2019-10-12 14:15:28 -04:00
Will Xyen
b6216c696e bio2emu: Add missing CM hooks for device index retrieval
Used by games that access the BIO2 through libacio
2019-10-12 05:37:47 -04:00
Will Xyen
a492cee93e docs: Update misc. docs for Rootage support 2019-10-12 04:40:30 -04:00
Will Xyen
e495bfb8f1 bio2emu: Refactor out the BIO2 emulation code so that it can be reused
Also make it support multiple BIO2 devices if needed (DRS)
2019-10-12 04:33:50 -04:00
icex2
073392407a architecture doc minor update 2019-10-07 20:12:33 +02:00
icex2
0a499b38a7 Add initial draft of architecture document.
Still has a bunch of TODOs where more information is required.
This commit adds the first few sections and some information
about iidxhook.
2019-10-07 20:02:32 +02:00
icex2
79495ea687 Add dev doc about IIDX's rendering loops for up-/downscaling feature 2019-10-07 19:02:28 +02:00
icex2
29526e02ec Update changelog 2019-10-07 18:20:01 +02:00
icex2
b83033587f doc/iidxhook: Update doc for iidxhook1/2 2019-10-07 16:04:27 +00:00
icex2
ff6bad2495 iidxhook1/2 config: Remove deprecated use_d3d9_hooks param 2019-10-07 16:04:26 +00:00
icex2
d64f8b2d8d iidxhook-util: Remove d3d8 module
Remove this module because it doesn't really provide any value
anymore. Using the d3d8to9 wrapper lib does not only fix some
odd d3d8 issues but also allows us to run all (IIDX) games over
d3d9. Thus and in order to reduce quite a lot of maintanance effort,
we remove this module.

Please use the d3d8to9 wrapper lib from now on in combination with
any d3d8 games and in order to use bemanitools gfx hook features.
2019-10-07 16:04:26 +00:00
icex2
8c998f6461 Add inject.exe to test package
Required by d3d9hoook test
2019-10-07 16:04:26 +00:00
icex2
a10132f62d dist/iidx: Fix default values for override window size 2019-10-07 16:04:26 +00:00
icex2
d9cc873eec iidxhook8: Refactor to use new d3d9 module 2019-10-07 16:04:26 +00:00
icex2
f4c0810ee3 iidxhook7: Refactor to use new d3d9 module 2019-10-07 16:04:26 +00:00
icex2
b1871a475d iidxhook6: Refactor to use new d3d9 module 2019-10-07 16:04:26 +00:00
icex2
a626e9e635 iidxhook5: Refactor to use new d3d9 module 2019-10-07 16:04:26 +00:00
icex2
5183547ba9 iidxhook4: Refactor to use new d3d9 module 2019-10-07 16:04:26 +00:00
icex2
53d61dcbbd iidxhook3: Refactor to use new d3d9 module 2019-10-07 16:04:26 +00:00
icex2
f201bff9ca iidxhook2: Refactor to use new d3d9 module 2019-10-07 16:04:26 +00:00
icex2
e0d7596f20 iidxhook1: Refactor to use new d3d9 module 2019-10-07 16:04:26 +00:00
icex2
3e60300273 iidxhook-util: Adapt enum name of upscaling filter names 2019-10-07 16:04:26 +00:00
icex2
77906205b5 test/check: Add check_failed func 2019-10-07 16:04:26 +00:00
icex2
c5d39d82d5 iidxhook-util: Major refactoring of d3d9 module
Uses the hook/d3d9 module with IRP handlers now. All previously
available features are implemented.

Furthermore, a new overhauled up-/downscaling method is implemented
which supports all IIDX versions now.
2019-10-07 16:04:26 +00:00
icex2
d169ee84b3 test/hook: Add tests for d3d9 hook module
Creates a simple d3d9 context and render loop allowing us to run
quick and easy integration tests of the hooking infrastructure.
2019-10-07 16:04:26 +00:00
icex2
60050d0d09 hook: Add d3d9 hook module
This module serves as a general base for any d3d9 hooks to be
implemented. It implements the IRP pattern like the iohook module.
This allows us to create irp handlers which can be chained, easier
structured and maintained compared to static IAT hooking. The latter
was the previous solution and did not work out well anymore for IIDX
which grew regarding d3d9 features.
2019-10-07 16:04:26 +00:00
Will Xyen
3436838b85 sdvxio-kfca: Add KFCA sdvxio driver 2019-09-28 17:41:27 -04:00
Will Xyen
bda056f0e4 aciotest: Add KFCA test handler 2019-09-28 17:41:27 -04:00
Will Xyen
2788b27a6f aciodrv: Add KFCA support 2019-09-28 17:41:15 -04:00
Will Xyen
89e3bbd2a3 hooklib: Allow proper passthrough of serial calls to real hardware (#26)
Only enabled / tested on IIDX CB and SDVX5

The point of this, is to allow rs232 hooks for only the descriptors that we hook.
This is because the emulation here is incomplete.
Although the IOCTL's do end up being passed to the real hardware, the game rejects some of the responses and hangs.
By short circuiting out, and calling the real Comm functions instead, it works.
And hence, card-reader passthrough works on IIDX25+/SDVX5+ finally without eamio-real
2019-09-28 17:36:22 -04:00
Will Xyen
1a567aa8ba Minor accuracy changes for KFCA emulation 2019-09-28 17:36:22 -04:00
icex2
a6386ac472 Update gitlab bug template, add config file and cmd arg sections 2019-09-28 22:47:55 +02:00
icex2
6582eff48b Add more gitlab templates
Add issue template for teatures and merge request templates for
bugfixes and features.
2019-09-28 00:50:39 +02:00
icex2
df0390e6f1 Add fork instructions to CONTRIBUTING.md 2019-09-28 00:24:31 +02:00
icex2
9874882774 README: Move contributing section from README.md to dedicated file 2019-09-27 23:36:52 +02:00
icex2
2aaaf2a864 iidxhook3: Update readme with FAQ about htpac'd assets 2019-09-27 23:25:52 +02:00
icex2
8d03db1b3d Bump version for next release to 5.27 2019-09-27 23:25:45 +02:00
icex2
b5f3eddba1 Add gitlab template for bug reporting. 2019-09-27 23:03:01 +02:00
504 changed files with 19908 additions and 13588 deletions

View File

@@ -9,23 +9,23 @@ AllowShortCaseLabelsOnASingleLine: 'false'
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: 'false'
AllowShortLoopsOnASingleLine: 'false'
AlwaysBreakAfterDefinitionReturnType: All
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: 'false'
AlwaysBreakBeforeMultilineStrings: 'true'
BinPackArguments: 'false'
BinPackParameters: 'false'
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Linux
BreakBeforeTernaryOperators: 'false'
BreakStringLiterals: 'true'
ColumnLimit: '120'
ContinuationIndentWidth: '8'
ColumnLimit: '80'
ContinuationIndentWidth: '4'
IncludeBlocks: Preserve
IndentCaseLabels: 'false'
IndentCaseLabels: 'true'
IndentPPDirectives: None
IndentWidth: '4'
IndentWrappedFunctionNames: 'false'
KeepEmptyLinesAtTheStartOfBlocks: 'false'
KeepEmptyLinesAtTheStartOfBlocks: 'true'
Language: Cpp
MaxEmptyLinesToKeep: '1'
PointerAlignment: Right

73
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,73 @@
image: debian
stages:
- build
- test
- release
- releasetag
build:
stage: build
before_script:
- apt-get update && apt-get -qq install clang mingw-w64 git make zip > /dev/null
script:
- make
artifacts:
name: "$CI_COMMIT_SHORT_SHA-$CI_JOB_NAME"
paths:
- build
only:
refs:
- master
test:
allow_failure: true
stage: test
dependencies:
- build
before_script:
- apt-get update && apt-get -qq install make wine unzip > /dev/null
- dpkg --add-architecture i386 && apt-get update && apt-get -qq install wine32 > /dev/null
script:
- ls
- make run-tests
only:
refs:
- master
release:
stage: release
variables:
GIT_STRATEGY: none
dependencies:
- build
before_script:
- apt-get update && apt-get -qq install zip > /dev/null
script:
- mv build/bemanitools.zip ./bemanitools.zip
- find . -mindepth 1 ! -regex '^./bemanitools.zip' -delete
- unzip bemanitools.zip
- rm bemanitools.zip
artifacts:
name: "$CI_COMMIT_SHORT_SHA-$CI_JOB_NAME"
paths:
- ./*
only:
refs:
- master
releasetag:
stage: releasetag
dependencies: []
before_script:
- apt-get update && apt-get -qq install 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"
only:
- tags

View File

@@ -0,0 +1,53 @@
## Summary
<!--- Provide a general summary of the issue in the Title above -->
## Expected behavior
<!--- Tell us what should happen -->
## Current behavior
<!--- 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 -->
## Steps to reproduce
<!--- Provide a detailed step by step description how to reproduce this issue -->
1.
2.
3.
4.
## Possible solution
<!--- Not obligatory, but suggest a fix/reason for the bug, -->
## Context (Environment)
### Bemanitools version(s) affected
* <!--- Add one or multiple versions as a bullet list -->
### Game(s) and version(s) affected
* <!--- Add one or multiple game versions as a bullet list -->
### Log output
See attachment.
<!--- Provide log output as attachment. Make sure to censor sensitive data like PCBIDs or device names if necessary -->
### Configuration files
See attachment.
<!--- Provide any configuration files that you used, e.g. iidxhook-XX.conf. Make sure to censor sensitive data like
PCBIDs -->
### 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. -->
### APIs used
* <!--- List all APIs you used as a bullet list, e.g. iidxio-keyboard, eamio-keyboard -->
### OS version
<!--- Provide the version of Windows you used with whatever update/build identifier -->
### Hardware specs
* CPU: <!--- Insert, e.g. Core i7 2600k 3.20ghz -->
* RAM: <!--- Insert, e.g. 16 GB -->
* GPU: <!--- Insert, e.g. Nvidia GeForce GTX 970, 4GB -->
* Controllers/IO: <!--- Insert, e.g. DJ Dao RE over USB -->

View File

@@ -0,0 +1,14 @@
## Summary
<!--- Provide a general summary of your changes in the Title above -->
## Detailed description
<!--- Describe your feature in detail -->
## Benefits
<!--- Describe the value/benefits of the feature in detail -->
## Drawbacks
<!--- Describe any drawbacks that might be introduced with this feature -->
## Current blockers
<!--- Describe any blockers that need to be resolved before implementing this feature -->

View File

@@ -0,0 +1,16 @@
## Summary
<!--- Provide a general summary of your changes in the Title above -->
## Description
<!--- Describe your changes in detail -->
## Related Issue
<!--- This project only accepts pull requests related to open issues -->
<!--- If suggesting a new feature or change, please discuss it in an issue first -->
<!--- If fixing a bug, there should be an issue describing it with steps to reproduce -->
<!--- Please link to the issue here: -->
## How Has This Been Tested?
<!--- Please describe in detail how you tested your changes. -->
<!--- Include details of your testing environment, and the tests you ran to -->
<!--- see how your change affects other areas of the code, etc. -->

View File

@@ -0,0 +1,16 @@
## Summary
<!--- Provide a general summary of your changes in the Title above -->
## Description
<!--- Describe your changes in detail -->
## Related Issue
<!--- This project only accepts pull requests related to open issues -->
<!--- If suggesting a new feature or change, please discuss it in an issue first -->
<!--- If fixing a bug, there should be an issue describing it with steps to reproduce -->
<!--- Please link to the issue here: -->
## How Has This Been Tested?
<!--- Please describe in detail how you tested your changes. -->
<!--- Include details of your testing environment, and the tests you ran to -->
<!--- see how your change affects other areas of the code, etc. -->

View File

@@ -1,4 +1,25 @@
# Release history
## 5.28
* Improve documentation in various places
* Automatic code formatting in build pipeline
* Bugfix: Recursive config.bat script
* Enable automatic building on pushes to master
* Bugfix: Stop SDVX hanging on thankyou for playing
* sdvx2: Support for Vivid Wave using sdvxhook2
* sdvxio-kfca: Driver for real sdvx cabinet IO hardware
## 5.27
* Various documentation updates regarding development and how to contribute
* KFCA emulation accuracy fixes
* Fix passthrough of serial calls when using real hardware (e.g. card reader passthrough IIDX25+/SDVX5+)
* Add sdvxio-kfca driver to talk to real SDVX hardware
* Refactor d3d9 hook module to improve maintainability. Also fixes upscaling not working on IIDX20+.
* Remove d3d8 hook module to improve maintainability. Make old d3d8 based games, e.g. iidxhook1/2, use d3d9 instead.
Requires usage of d3d8to9 wrapper library to use gfx patching features.
* Add dev doc about IIDX rendering loops
* Add an initial draft of an architecture document (will be worked on in iterations)
* Refactor BIO2 emulation to make it re-usable by other games
## 5.26
* iidxio-ezusb: Reduce sleep time to Sleep(1) to avoid framerate issues on some versions of iidx.
* Bugfix: iidx d3d9 games, mainly the newer ones iidx 20-25, freezing. Happened on boot, during song selection or during the song.

30
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,30 @@
# 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.
# 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.
When creating new issues, use our template for reporting bugs. It tells you what kind of information we need.
# 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.
Please read our [development guidelines](doc/development.md) as they contain valuable information that your contribution
meets our standards.
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.
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.
# 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

@@ -22,24 +22,58 @@ gitrev := $(shell git rev-parse HEAD)
cppflags := -I src -I src/main -I src/test -DGITREV=$(gitrev)
cflags := -O2 -pipe -ffunction-sections -fdata-sections \
-Wall -std=c99
ldflags := -Wl,--gc-sections -static-libgcc
cflags_release := -Werror
ldflags := -Wl,--gc-sections -static-libgcc
#
# The first target that GNU Make encounters becomes the default target.
# Define our ultimate target (`all') here, and also some helpers
#
all:
all: build
.PHONY: \
clean \
code-format \
print-building \
print-release \
run-tests \
version
release: \
print-release \
clean \
code-format \
all \
run-tests
build: \
print-building \
version
print-building:
@echo "Build gitrev "$(gitrev)"..."
print-release:
@echo "Starting release build..."
clean:
@echo "Cleaning up..."
$(V)rm -rf $(BUILDDIR)
code-format:
@echo "Applying clang-format..."
# -style=file enables reading .clang-format
@find src/ -iname *.h -o -iname *.c | xargs clang-format -i -style=file
run-tests:
@echo "Running tests..."
@./run-tests-wine.sh
# Generate a version file to identify the build
version:
@echo "$(gitrev)" > version
.PHONY: clean
clean:
$(V)rm -rf $(BUILDDIR)
#
# Pull in module definitions
#
@@ -54,11 +88,12 @@ libs :=
avsdlls :=
avsexes :=
testdlls :=
testexes :=
include Module.mk
modules := $(dlls) $(exes) $(libs) $(avsdlls) $(avsexes) $(testexes)
modules := $(dlls) $(exes) $(libs) $(avsdlls) $(avsexes) $(testdlls) $(testexes)
#
# $1: Bitness
@@ -70,6 +105,7 @@ define t_moddefs
cppflags_$3 += $(cppflags) -DBUILD_MODULE=$3
cflags_$3 += $(cflags)
release: cflags_$3 += $(cflags_release)
ldflags_$3 += $(ldflags)
srcdir_$3 ?= src/main/$3
@@ -94,6 +130,7 @@ $$(eval $$(foreach lib,$(libs),$$(call t_archive,$1,indep,$$(lib))))
$$(eval $$(foreach avsver,$$(avsvers_$1),$$(call t_avsver,$1,$$(avsver))))
$$(eval $$(foreach dll,$(testdlls),$$(call t_linkdll,$1,indep,$$(dll))))
$$(eval $$(foreach exe,$(testexes),$$(call t_linkexe,$1,indep,$$(exe))))
endef

View File

@@ -42,7 +42,7 @@
# 15: Patch 8: DanceDanceRevolution (2013)
# beatmania IIDX 20 tricoro
# pop'n music 21 Sunny Park
# SOUND VOLTEX (all known versions)
# SOUND VOLTEX (1-4)
# jubeat prop
#
# 16: Patch 1: beatmania IIDX 21 SPADA
@@ -53,6 +53,9 @@
# "Patch" 7: Steel Chronicle VicTroopers (not a Bemani, w/e)
#
# 17: Patch 0: beatmania IIDX 25 CANNON BALLERS
# beatmania IIDX 26 Rootage
#
# Patch 3: SOUND VOLTEX VIVID WAVE
#
cflags += \
@@ -74,10 +77,13 @@ imps += avs avs-ea3
include src/main/aciodrv/Module.mk
include src/main/acioemu/Module.mk
include src/main/aciotest/Module.mk
include src/main/bio2emu/Module.mk
include src/main/bsthook/Module.mk
include src/main/bstio/Module.mk
include src/main/camhook/Module.mk
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
@@ -129,17 +135,21 @@ include src/main/p3ioemu/Module.mk
include src/main/p4ioemu/Module.mk
include src/main/pcbidgen/Module.mk
include src/main/sdvxhook/Module.mk
include src/main/sdvxhook2/Module.mk
include src/main/sdvxio/Module.mk
include src/main/sdvxio-kfca/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/test/cconfig/Module.mk
include src/test/d3d9hook/Module.mk
include src/test/iidxhook-util/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
@@ -336,7 +346,7 @@ $(zipdir)/iidx-21-to-24.zip: \
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/iidx-25.zip: \
$(zipdir)/iidx-25-to-26.zip: \
build/bin/avs2_1700-64/iidxhook8.dll \
build/bin/avs2_1700-64/launcher.exe \
build/bin/indep-64/config.exe \
@@ -349,7 +359,9 @@ $(zipdir)/iidx-25.zip: \
build/bin/indep-64/vefxio.dll \
dist/iidx/config.bat \
dist/iidx/gamestart-25.bat \
dist/iidx/gamestart-26.bat \
dist/iidx/iidxhook-25.conf \
dist/iidx/iidxhook-26.conf \
dist/iidx/vefx.txt \
| $(zipdir)/
$(V)echo ... $@
@@ -402,12 +414,28 @@ $(zipdir)/sdvx.zip: \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
build/bin/indep-32/sdvxio.dll \
build/bin/indep-32/sdvxio-kfca.dll \
dist/sdvx/config.bat \
dist/sdvx/gamestart.bat \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/sdvx5.zip: \
build/bin/avs2_1700-64/launcher.exe \
build/bin/avs2_1700-64/sdvxhook2.dll \
build/bin/indep-64/config.exe \
build/bin/indep-64/eamio.dll \
build/bin/indep-64/geninput.dll \
build/bin/indep-64/sdvxio.dll \
build/bin/indep-64/sdvxio-kfca.dll \
dist/sdvx5/config.bat \
dist/sdvx5/gamestart.bat \
dist/sdvx5/sdvxhook2.conf \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/ddr-12-to-16.zip: \
build/bin/avs2_1508-32/launcher.exe \
build/bin/avs2_1508-32/ddrhook.dll \
@@ -444,6 +472,7 @@ $(zipdir)/bst.zip: \
$(zipdir)/doc.zip: \
doc/iidxhook \
doc/sdvxhook \
doc/jbhook \
doc/tools \
| $(zipdir)/
@@ -456,10 +485,13 @@ $(BUILDDIR)/tests.zip: \
build/bin/indep-32/cconfig-test.exe \
build/bin/indep-32/cconfig-util-test.exe \
build/bin/indep-32/cconfig-cmd-test.exe \
build/bin/indep-32/d3d9hook.dll \
build/bin/indep-32/d3d9hook-test.exe \
build/bin/indep-32/iidxhook-util-config-eamuse-test.exe \
build/bin/indep-32/iidxhook-util-config-gfx-test.exe \
build/bin/indep-32/iidxhook-util-config-misc-test.exe \
build/bin/indep-32/iidxhook-util-config-sec-test.exe \
build/bin/indep-32/inject.exe \
build/bin/indep-32/security-id-test.exe \
build/bin/indep-32/security-mcode-test.exe \
build/bin/indep-32/security-rp-test.exe \
@@ -467,6 +499,7 @@ $(BUILDDIR)/tests.zip: \
build/bin/indep-32/security-rp3-test.exe \
build/bin/indep-32/security-util-test.exe \
build/bin/indep-32/util-net-test.exe \
build/bin/indep-64/iidxhook8-config-cam-test.exe \
dist/test/run-tests.sh \
| $(zipdir)/
$(V)echo ... $@
@@ -483,12 +516,13 @@ $(BUILDDIR)/bemanitools.zip: \
$(zipdir)/iidx-19.zip \
$(zipdir)/iidx-20.zip \
$(zipdir)/iidx-21-to-24.zip \
$(zipdir)/iidx-25.zip \
$(zipdir)/iidx-25-to-26.zip \
$(zipdir)/jb-01.zip \
$(zipdir)/jb-05-to-07.zip \
$(zipdir)/jb-08.zip \
$(zipdir)/src.zip \
$(zipdir)/sdvx.zip \
$(zipdir)/sdvx5.zip \
$(zipdir)/tools.zip \
$(zipdir)/tools-x64.zip \
CHANGELOG.md \

104
README.md
View File

@@ -1,5 +1,7 @@
# Bemanitools 5
Version: 5.26</br>
[![pipeline status](https://dev.s-ul.eu/djhackers/bemanitools/badges/master/pipeline.svg)](https://dev.s-ul.eu/djhackers/bemanitools/commits/master)
Version: 5.28</br>
[Release history](CHANGELOG.md)
A collection of tools to run [various Bemani arcade games](#list-of-supported-games).
@@ -11,43 +13,45 @@ authentic gameplay experience, and easier support for a broader range of release
# List of supported games
* BeatStream
* BeatStream (bst.zip)
* BeatStream アニムトライヴ (bst.zip)
* BeatStream (bst.zip) using bsthook
* BeatStream アニムトライヴ (bst.zip) using bsthook
* Dance Dance Revolution
* Dance Dance Revolution X2 (ddr-12-to-16.zip)
* Dance Dance Revolution X3 vs. 2ndMIX (ddr-12-to-16.zip)
* Dance Dance Revolution 2013 (ddr-12-to-16.zip)
* Dance Dance Revolution 2014 (ddr-12-to-16.zip)
* Dance Dance Revolution A (ddr-12-to-16.zip)
* Dance Dance Revolution X2 (ddr-12-to-16.zip) using ddrhook
* Dance Dance Revolution X3 vs. 2ndMIX (ddr-12-to-16.zip) using ddrhook
* Dance Dance Revolution 2013 (ddr-12-to-16.zip) using ddrhook
* Dance Dance Revolution 2014 (ddr-12-to-16.zip) using ddrhook
* Dance Dance Revolution A (ddr-12-to-16.zip) using ddrhook
* Beatmania IIDX
* Beatmania IIDX 9th Style (iidx-09-to-12.zip)
* Beatmania IIDX 10th Style (iidx-09-to-12.zip)
* Beatmania IIDX 11 IIDX RED (iidx-09-to-12.zip)
* Beatmania IIDX 12 HAPPY SKY (iidx-09-to-12.zip)
* Beatmania IIDX 13 DistorteD (iidx-13.zip)
* Beatmania IIDX 14 GOLD (iidx-14-to-17.zip)
* Beatmania IIDX 15 DJ TROOPERS (iidx-14-to-17.zip)
* Beatmania IIDX 16 EMPRESS (iidx-14-to-17.zip)
* Beatmania IIDX 17 SIRIUS (iidx-14-to-17.zip)
* Beatmania IIDX 18 Resort Anthem (iidx-18.zip)
* Beatmania IIDX 19 Lincle (iidx-19.zip)
* Beatmania IIDX 20 Tricoro (iidx-20.zip)
* Beatmania IIDX 21 SPADA (iidx-21-to-24.zip)
* Beatmania IIDX 22 PENDUAL (iidx-21-to-24.zip)
* Beatmania IIDX 23 copula (iidx-21-to-24.zip)
* Beatmania IIDX 24 SINOBUZ (iidx-21-to-24.zip)
* Beatmania IIDX 25 CANNON BALLERS (iidx-25.zip)
* Beatmania IIDX 9th Style (iidx-09-to-12.zip) using [iidxhook1](doc/iidxhook/iidxhook1.md)
* Beatmania IIDX 10th Style (iidx-09-to-12.zip) using [iidxhook1](doc/iidxhook/iidxhook1.md)
* Beatmania IIDX 11 IIDX RED (iidx-09-to-12.zip) using [iidxhook1](doc/iidxhook/iidxhook1.md)
* Beatmania IIDX 12 HAPPY SKY (iidx-09-to-12.zip) using [iidxhook1](doc/iidxhook/iidxhook1.md)
* Beatmania IIDX 13 DistorteD (iidx-13.zip) using [iidxhook2](doc/iidxhook/iidxhook2.md)
* Beatmania IIDX 14 GOLD (iidx-14-to-17.zip) using [iidxhook3](doc/iidxhook/iidxhook3.md)
* Beatmania IIDX 15 DJ TROOPERS (iidx-14-to-17.zip) using [iidxhook3](doc/iidxhook/iidxhook3.md)
* Beatmania IIDX 16 EMPRESS (iidx-14-to-17.zip) using [iidxhook3](doc/iidxhook/iidxhook3.md)
* Beatmania IIDX 17 SIRIUS (iidx-14-to-17.zip) using [iidxhook3](doc/iidxhook/iidxhook3.md)
* Beatmania IIDX 18 Resort Anthem (iidx-18.zip) using [iidxhook4](doc/iidxhook/iidxhook4.md)
* Beatmania IIDX 19 Lincle (iidx-19.zip) using [iidxhook5](doc/iidxhook/iidxhook5.md)
* Beatmania IIDX 20 Tricoro (iidx-20.zip) using [iidxhook6](doc/iidxhook/iidxhook6.md)
* Beatmania IIDX 21 SPADA (iidx-21-to-24.zip) using [iidxhook7](doc/iidxhook/iidxhook7.md)
* Beatmania IIDX 22 PENDUAL (iidx-21-to-24.zip) using [iidxhook7](doc/iidxhook/iidxhook7.md)
* Beatmania IIDX 23 copula (iidx-21-to-24.zip) using [iidxhook7](doc/iidxhook/iidxhook7.md)
* Beatmania IIDX 24 SINOBUZ (iidx-21-to-24.zip) using [iidxhook7](doc/iidxhook/iidxhook7.md)
* Beatmania IIDX 25 CANNON BALLERS (iidx-25-to-26.zip) using [iidxhook8](doc/iidxhook/iidxhook8.md)
* Beatmania IIDX 26 Rootage (iidx-25-to-26.zip) using [iidxhook8](doc/iidxhook/iidxhook8.md)
* jubeat
* jubeat (experimental/buggy) (jb-01.zip)
* jubeat saucer (fulfill) (jb-05-to-07.zip)
* jubeat prop (jb-05-to-07.zip)
* jubeat Qubell (jb-05-to-07.zip)
* jubeat clan (jb-08.zip)
* jubeat (experimental/buggy) (jb-01.zip) using [jbhook1](doc/jbhook1/jbhook1.md)
* jubeat saucer (fulfill) (jb-05-to-07.zip) using jbhook
* jubeat prop (jb-05-to-07.zip) using jbhook
* jubeat Qubell (jb-05-to-07.zip) using jbhook
* jubeat clan (jb-08.zip) using jbhook
* SOUND VOLTEX
* SOUND VOLTEX BOOTH (sdvx.zip)
* SOUND VOLTEX II -infinite infection- (sdvx.zip)
* SOUND VOLTEX III GRAVITY WARS (sdvx.zip)
* SOUND VOLTEX IV HEAVENLY HAVEN (sdvx.zip)
* SOUND VOLTEX BOOTH (sdvx.zip) using sdvxhook
* SOUND VOLTEX II -infinite infection- (sdvx.zip) using sdvxhook
* SOUND VOLTEX III GRAVITY WARS (sdvx.zip) using sdvxhook
* SOUND VOLTEX IV HEAVENLY HAVEN (sdvx.zip) using sdvxhook
* SOUND VOLTEX Vivid Wave (sdvx2.zip) using sdvxhook2
# Supported platforms
Our main platforms are currently Windows XP and Windows 7 which are also the target platforms on the original hardware
@@ -63,7 +67,14 @@ 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.
# Contributions
Please refer to the [dedicated documentation](CONTRIBUTING.md).
# Development
## Architecture
A dedicate [architecture document](doc/architecture.md) outlines the architecture of Bemanitools and points out the most
important aspects you should know before you get started with development.
## API
Please refer to the [API documentation](doc/api.md).
@@ -71,31 +82,6 @@ Please refer to the [API documentation](doc/api.md).
The source code is included with this distribution package (src.zip). Please refer to the
[development document](doc/development.md) for further details.
## Bugs and TODOs
We have our own issue tracker for this. If you want to contribute or have any bugs to report, please reach out to us on
the various channels we are available on. Please help us by providing a detailed description of your concern including:
* The version of bemanitools you are using
* The games affected including version
* Log output of bemanitools and the game
* The APIs you have been using with bemanitools, e.g. iidxio-keyboard, eamio-keyboard.
* The OS version you are running this on
* Specs of your hardware including CPU, RAM, GPU
* A detailed description of your issue. Describe the symptoms and the steps to trigger and reproduce them. Videos and
screenshots might be helpful depending on the issue.
## Contributions
Patches are welcome! Let us know if you have any contributions, e.g. bugfixes, and send us a patch file. Please read
our [development guidelines](doc/development.md) as they contain valuable information that your contribution meets our
standards.
Once submitted, 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.
## 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). However, our time and workforce is limited. If you are
interested in contributing, please check the [contribution section](#contributions).
# 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.

2
dist/bst/config.bat vendored
View File

@@ -1 +1 @@
@start config bst
@start config.exe bst

2
dist/ddr/config.bat vendored
View File

@@ -1 +1 @@
@start config ddr
@start config.exe ddr

View File

@@ -1 +1 @@
@start config iidx
@start config.exe iidx

16
dist/iidx/gamestart-26.bat vendored Normal file
View File

@@ -0,0 +1,16 @@
@echo off
cd /d %~dp0
if not exist dev mkdir dev
if not exist dev\e mkdir dev\e
if not exist dev\g mkdir dev\g
if not exist dev\nvram mkdir dev\nvram
if not exist dev\raw mkdir dev\raw
if not exist dev\raw\log mkdir dev\raw\log
if not exist dev\raw\fscache mkdir dev\raw\fscache
for /R prop\defaults %%D in (*.*) do (
if not exist dev\nvram\%%~nxD copy /y prop\defaults\%%~nxD dev\nvram
)
launcher -H 134217728 -K iidxhook8.dll bm2dx.dll --config iidxhook-26.conf %*

View File

@@ -25,11 +25,11 @@ gfx.monitor_check=-1.000000
# Run the game windowed
gfx.windowed=false
# Windowed width, -1 for default size
gfx.window_width=-1
# Windowed width, 0 for default size
gfx.window_width=0
# Windowed height, -1 for default size
gfx.window_height=-1
# Windowed height, 0 for default size
gfx.window_height=0
# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter.
gfx.scale_back_buffer_width=0
@@ -43,9 +43,6 @@ gfx.scale_back_buffer_filter=none
# Disable operator clock setting system clock time
misc.disable_clock_set=false
# Use d3d9 hooks instead of d3d8 to enable d3d9 hook features not available on d3d8 (e.g. upscaling). Requires d3d8to9 wrapper library to be used with this game.
misc.use_d3d9_hooks=false
# Stub calls to rteffect.dll (10th to DistorteD)
misc.rteffect_stub=false

View File

@@ -25,11 +25,11 @@ gfx.monitor_check=-1.000000
# Run the game windowed
gfx.windowed=false
# Windowed width, -1 for default size
gfx.window_width=-1
# Windowed width, 0 for default size
gfx.window_width=0
# Windowed height, -1 for default size
gfx.window_height=-1
# Windowed height, 0 for default size
gfx.window_height=0
# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter.
gfx.scale_back_buffer_width=0
@@ -43,9 +43,6 @@ gfx.scale_back_buffer_filter=none
# Disable operator clock setting system clock time
misc.disable_clock_set=false
# Use d3d9 hooks instead of d3d8 to enable d3d9 hook features not available on d3d8 (e.g. upscaling). Requires d3d8to9 wrapper library to be used with this game.
misc.use_d3d9_hooks=false
# Stub calls to rteffect.dll (10th to DistorteD)
misc.rteffect_stub=false

View File

@@ -25,11 +25,11 @@ gfx.monitor_check=-1.000000
# Run the game windowed
gfx.windowed=false
# Windowed width, -1 for default size
gfx.window_width=-1
# Windowed width, 0 for default size
gfx.window_width=0
# Windowed height, -1 for default size
gfx.window_height=-1
# Windowed height, 0 for default size
gfx.window_height=0
# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter.
gfx.scale_back_buffer_width=0
@@ -43,9 +43,6 @@ gfx.scale_back_buffer_filter=none
# Disable operator clock setting system clock time
misc.disable_clock_set=false
# Use d3d9 hooks instead of d3d8 to enable d3d9 hook features not available on d3d8 (e.g. upscaling). Requires d3d8to9 wrapper library to be used with this game.
misc.use_d3d9_hooks=false
# Stub calls to rteffect.dll (10th to DistorteD)
misc.rteffect_stub=false

View File

@@ -25,11 +25,11 @@ gfx.monitor_check=-1.000000
# Run the game windowed
gfx.windowed=false
# Windowed width, -1 for default size
gfx.window_width=-1
# Windowed width, 0 for default size
gfx.window_width=0
# Windowed height, -1 for default size
gfx.window_height=-1
# Windowed height, 0 for default size
gfx.window_height=0
# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter.
gfx.scale_back_buffer_width=0
@@ -43,9 +43,6 @@ gfx.scale_back_buffer_filter=none
# Fix broken 3D background on Happy Sky's music select (if appearing completely white)
misc.happy_sky_ms_bg_fix=false
# Use d3d9 hooks instead of d3d8 to enable d3d9 hook features not available on d3d8 (e.g. upscaling). Requires d3d8to9 wrapper library to be used with this game.
misc.use_d3d9_hooks=false
# Disable operator clock setting system clock time
misc.disable_clock_set=false

View File

@@ -25,11 +25,11 @@ gfx.monitor_check=-1.000000
# Run the game windowed
gfx.windowed=false
# Windowed width, -1 for default size
gfx.window_width=-1
# Windowed width, 0 for default size
gfx.window_width=0
# Windowed height, -1 for default size
gfx.window_height=-1
# Windowed height, 0 for default size
gfx.window_height=0
# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter.
gfx.scale_back_buffer_width=0
@@ -43,9 +43,6 @@ gfx.scale_back_buffer_filter=none
# Fix broken 3D background on DistorteD's music select (if appearing completely black)
misc.distorted_ms_bg_fix=false
# Use d3d9 hooks instead of d3d8 to enable d3d9 hook features not available on d3d8 (e.g. upscaling). Requires d3d8to9 wrapper library to be used with this game.
misc.use_d3d9_hooks=false
# Disable operator clock setting system clock time
misc.disable_clock_set=false

View File

@@ -22,11 +22,11 @@ gfx.monitor_check=-1.000000
# Run the game windowed
gfx.windowed=false
# Windowed width, -1 for default size
gfx.window_width=-1
# Windowed width, 0 for default size
gfx.window_width=0
# Windowed height, -1 for default size
gfx.window_height=-1
# Windowed height, 0 for default size
gfx.window_height=0
# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter.
gfx.scale_back_buffer_width=0

View File

@@ -22,11 +22,11 @@ gfx.monitor_check=-1.000000
# Run the game windowed
gfx.windowed=false
# Windowed width, -1 for default size
gfx.window_width=-1
# Windowed width, 0 for default size
gfx.window_width=0
# Windowed height, -1 for default size
gfx.window_height=-1
# Windowed height, 0 for default size
gfx.window_height=0
# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter.
gfx.scale_back_buffer_width=0

View File

@@ -25,11 +25,11 @@ gfx.pci_id=1002:7146
# Run the game windowed
gfx.windowed=false
# Windowed width, -1 for default size
gfx.window_width=-1
# Windowed width, 0 for default size
gfx.window_width=0
# Windowed height, -1 for default size
gfx.window_height=-1
# Windowed height, 0 for default size
gfx.window_height=0
# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter.
gfx.scale_back_buffer_width=0

View File

@@ -25,11 +25,11 @@ gfx.pci_id=1002:7146
# Run the game windowed
gfx.windowed=false
# Windowed width, -1 for default size
gfx.window_width=-1
# Windowed width, 0 for default size
gfx.window_width=0
# Windowed height, -1 for default size
gfx.window_height=-1
# Windowed height, 0 for default size
gfx.window_height=0
# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter.
gfx.scale_back_buffer_width=0

View File

@@ -16,11 +16,11 @@ gfx.pci_id=1002:7146
# Run the game windowed
gfx.windowed=false
# Windowed width, -1 for default size
gfx.window_width=-1
# Windowed width, 0 for default size
gfx.window_width=0
# Windowed height, -1 for default size
gfx.window_height=-1
# Windowed height, 0 for default size
gfx.window_height=0
# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter.
gfx.scale_back_buffer_width=0

View File

@@ -13,11 +13,11 @@ gfx.pci_id=1002:7146
# Run the game windowed
gfx.windowed=false
# Windowed width, -1 for default size
gfx.window_width=-1
# Windowed width, 0 for default size
gfx.window_width=0
# Windowed height, -1 for default size
gfx.window_height=-1
# Windowed height, 0 for default size
gfx.window_height=0
# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter.
gfx.scale_back_buffer_width=0

View File

@@ -13,11 +13,11 @@ gfx.pci_id=1002:7146
# Run the game windowed
gfx.windowed=false
# Windowed width, -1 for default size
gfx.window_width=-1
# Windowed width, 0 for default size
gfx.window_width=0
# Windowed height, -1 for default size
gfx.window_height=-1
# Windowed height, 0 for default size
gfx.window_height=0
# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter.
gfx.scale_back_buffer_width=0

View File

@@ -13,11 +13,11 @@ gfx.pci_id=1002:7146
# Run the game windowed
gfx.windowed=false
# Windowed width, -1 for default size
gfx.window_width=-1
# Windowed width, 0 for default size
gfx.window_width=0
# Windowed height, -1 for default size
gfx.window_height=-1
# Windowed height, 0 for default size
gfx.window_height=0
# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter.
gfx.scale_back_buffer_width=0

View File

@@ -13,11 +13,11 @@ gfx.pci_id=1002:7146
# Run the game windowed
gfx.windowed=false
# Windowed width, -1 for default size
gfx.window_width=-1
# Windowed width, 0 for default size
gfx.window_width=0
# Windowed height, -1 for default size
gfx.window_height=-1
# Windowed height, 0 for default size
gfx.window_height=0
# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter.
gfx.scale_back_buffer_width=0

View File

@@ -13,11 +13,11 @@ gfx.pci_id=1002:7146
# Run the game windowed
gfx.windowed=false
# Windowed width, -1 for default size
gfx.window_width=-1
# Windowed width, 0 for default size
gfx.window_width=0
# Windowed height, -1 for default size
gfx.window_height=-1
# Windowed height, 0 for default size
gfx.window_height=0
# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter.
gfx.scale_back_buffer_width=0

View File

@@ -13,11 +13,11 @@ gfx.pci_id=1002:7146
# Run the game windowed
gfx.windowed=false
# Windowed width, -1 for default size
gfx.window_width=-1
# Windowed width, 0 for default size
gfx.window_width=0
# Windowed height, -1 for default size
gfx.window_height=-1
# Windowed height, 0 for default size
gfx.window_height=0
# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter.
gfx.scale_back_buffer_width=0

View File

@@ -13,11 +13,11 @@ gfx.pci_id=1002:7146
# Run the game windowed
gfx.windowed=false
# Windowed width, -1 for default size
gfx.window_width=-1
# Windowed width, 0 for default size
gfx.window_width=0
# Windowed height, -1 for default size
gfx.window_height=-1
# Windowed height, 0 for default size
gfx.window_height=0
# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter.
gfx.scale_back_buffer_width=0

47
dist/iidx/iidxhook-26.conf vendored Normal file
View File

@@ -0,0 +1,47 @@
# Fix stretched BG videos on newer GPUs. Might appear on Red and newer
gfx.bgvideo_uv_fix=false
# Run the game in a framed window (requires windowed option)
gfx.framed=false
# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit)
gfx.frame_rate_limit=0.0
# Patch the GPU device ID detection (leave empty to disable), format XXXX:YYYY, two 4 digit hex numbers (vid:pid). Examples: 1002:7146 (RV515, Radeon X1300), 1002:95C5 (RV620 LE, Radeon HD3450)
gfx.pci_id=1002:7146
# Run the game windowed
gfx.windowed=false
# Windowed width, 0 for default size
gfx.window_width=0
# Windowed height, 0 for default size
gfx.window_height=0
# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter.
gfx.scale_back_buffer_width=0
# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter.
gfx.scale_back_buffer_height=0
# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation).
gfx.scale_back_buffer_filter=none
# Disables the camera emulation
cam.disable_emu=false
# Override camera device ID 1 detection (copy from device manager, do not escape)
cam.device_id1=
# Override camera device ID 2 detection (copy from device manager, do not escape)
cam.device_id2=
# Disable card reader emulation and enable usage of real card reader hardware on COM0 (for games supporting slotted readers)
io.disable_card_reader_emu=false
# Disable BIO2 emulation and enable usage of real BIO2 hardware
io.disable_bio2_emu=false
# Disables the poll limiter, warning very high CPU usage may arise
io.disable_poll_limiter=false

2
dist/jb/config.bat vendored
View File

@@ -1 +1 @@
@start config jb
@start config.exe jb

View File

@@ -1 +1 @@
@start config dm
@start config.exe dm

View File

@@ -1 +1 @@
@start config gf
@start config.exe gf

View File

@@ -1 +1 @@
@start config pnm
@start config.exe pnm

View File

@@ -1 +1 @@
@start config sdvx
@start config.exe sdvx

View File

@@ -1 +1 @@
@start config sdvx
@start config.exe sdvx

1
dist/sdvx5/config.bat vendored Normal file
View File

@@ -0,0 +1 @@
@start config.exe sdvx

16
dist/sdvx5/gamestart.bat vendored Normal file
View File

@@ -0,0 +1,16 @@
@echo off
cd /d %~dp0
if not exist dev mkdir dev
if not exist dev\e mkdir dev\e
if not exist dev\g mkdir dev\g
if not exist dev\nvram mkdir dev\nvram
if not exist dev\raw mkdir dev\raw
if not exist dev\raw\log mkdir dev\raw\log
if not exist dev\raw\fscache mkdir dev\raw\fscache
for /R prop\defaults %%D in (*.*) do (
if not exist dev\nvram\%%~nxD copy /y prop\defaults\%%~nxD dev\nvram
)
launcher -H 268435456 -K sdvxhook2.dll soundvoltex.dll --options sdvxhook2.conf %*

27
dist/sdvx5/sdvxhook2.conf vendored Normal file
View File

@@ -0,0 +1,27 @@
# Disable card reader emulation and enable usage of real card reader hardware on COM2
io.disable_card_reader_emu=false
# Disable BIO2 emulation and enable usage of real BIO2 hardware
io.disable_bio2_emu=false
# Disables the poll limiter, warning very high CPU usage may arise
io.disable_poll_limiter=false
# Run the game in a framed window (requires windowed option)
gfx.framed=true
# Run the game windowed
gfx.windowed=false
# Windowed width, -1 for default size
gfx.window_width=720
# Windowed height, -1 for default size
gfx.window_height=1280
# Disables the camera emulation
cam.disable_emu=false
# Override camera device ID detection (copy from device manager, do not escape)
cam.device_id1=

View File

@@ -25,4 +25,6 @@ wine ./security-rp2-test.exe
wine ./security-rp3-test.exe
wine ./util-net-test.exe
wine ./inject.exe d3d9hook.dll d3d9hook-test.exe
echo "All tests successful."

182
doc/architecture.md Normal file
View File

@@ -0,0 +1,182 @@
# Bemanitools architecture
This document gives you an overview of the architecture of Bemanitools (5). Why do we need this? This helps document the
various design decisions and how everything comes together, in the end. At some point when things are evolving and other
developers want to pick up the project, this might give them answers to why some things were done well or not so well.
This allows them to iterate on the current design (document) to analyze if a change they want to apply might work out
or not.
Anway, enough preface...I guess you got the idea. This document will be split into several sections which address
different aspects of the architecture.
## The big picture
TODO create a graphic that presents the key modules and ideas.
## Detouring library functions, IAT hooking
One of Bemanitools's goals is to avoid patching of executables, libraries or any game data and instead rely on
intercepting calls to libraries to patch bugs or introduce new features. To support a game on a non native platform
transparently, e.g. your home desktop, this allows us to intercept I/O communication to emulate hardware or
files/filesystem features the game expects to be available.
We create a so called "hook library/hook.dll" which gets injected to the target process (the game) before the game
runs any of its application code. This is well known by the terms of dll injection and will not be further discussed
here (google it). The injected dll will replace the function addresses in the IATs to detour any calls to our own
handler functions before, eventually, calling the real function. This way, we can intercept the call and do cool things.
These features are covered by the modules in the following subfolders in src/main:
* hook: Essentially, this is capnhook: https://github.com/decafcode/capnhook. General tools for hooking Win32 API calls.
* hooklib: Some additional helper modules to take care of specific issues in Bemanitools, e.g. rs232 related stuff for
ACIO.
Check the modules for details.
## Hooking and IRP
IRP stands for "I/O request packet" and is a kernel mode structure used in Windows drivers for communication with the
OS. The data structure describes an I/O request with parameters for that request avoiding function calls with large
number of arguments to a driver.
We make use of that "IRP pattern" by creating a flexible and maintainable abstraction layer for the following hooking
modules:
* iohook: Hook I/O (e.g. file) related calls
* d3d9: Hook d3d9 graphics API calls
An IRP handler is implemented to handle selected IRP calls based on the specified operation type. IRP handlers can be
chained which allows splitting up different features/interceptors to different functions and modules allowing you to
create a clear structure. At the end of the forwarding chain, you the real API function that maps to the abstracted
operation is called. However, a handler can decide at any time to not forward calls which allows you to implement
emulation of access to selected files or I/O devices.
Modules that make use of this:
* iidxhook-util/d3d9
* ezusb-emu/device
* ezusb2-emu/device
* acioemu/emu
## Bemanitools's hook libraries, let's glue everything together
Bemanitools dlls to be injected into target game processes are refered to as "hook dlls" and come in different flavours
targetting different games and often different versions of the same game (series), for example:
* ddrhook: Hook dll for Dance Dance Revolution games
* iidxhook1-8: Hook dlls for Beatmania IIDX, we are currently at 8 different implementations due to the various
iterations the game went through, related to software and hardware.
* sdvxhook: Hook dll for SoundVoltex series
The following sub-sections will give you some brief insights on each hook implementation and what modules were used.
### bsthook
TODO
### ddrhook
TODO
### iidxhook
IIDX went through so many hard- and software iterations, it's actually amazing that the development team(s) refactored
and improved parts of the game and hardware with each iteration. However, when facing emulation and supporting
compatibility to legacy OS platforms, it can't get any worse. On the bright side, IIDX helped shaping Bemanitools a lot
and created a solid foundation other games can build on.
Because of that, we have 8 iidxhook implementations supporting sometimes different software features/fixes and
hardware. The following sub-sub-sections list the most relevant aspects and modules to point out common and different
higher level features.
Essentially, the main module file of each iidxhook implementation just glues the APIs of the modules it requires
together. An additional configuration layer allows users to tweak some of the features.
TODO go into some more detail about some differences in the hook modules, e.g. 18 to 19 look identical
-> but different AVS versions
#### iidxhook1 (9-12)
* Ezusb C02 I/O emulation
* Setupapi emulation
* Full security emulation with SRAM and round plugs
* Full serial emulation for magstripe card readers
* Full game essential I/O emulation
* d3d8 patching and extended features (superseded by d3d9 hook module + d3d8to9 wrapper)
* clock patching
* Font patching for Japanese chars
* Network related patches to enable eamuse to custom servers
* Filesystem patches to detour E and F backup drives for settings
#### iidxhook2 (13)
* Ezusb C02 I/O emulation
* Setupapi emulation
* Full security emulation with SRAM and round plugs
* Full game essential I/O emulation
* ACIO ICCA card reader emulation, slotted readers
* d3d8 patching and extended features (superseded by d3d9 hook module + d3d8to9 wrapper)
* clock patching
* Font patching for Japanese chars
* Network related patches to enable eamuse to custom servers
* Filesystem patches to detour E and F backup drives for settings
#### iidxhook3 (14-17)
* Ezusb IO2 I/O emulation
* Setupapi emulation
* Full security emulation with SRAM and round plugs
* Full game essential I/O emulation
* ACIO ICCA card reader emulation, slotted readers
* d3d9 patching and extended features
* Font patching for Japanese chars
* Network related patches to enable eamuse to custom servers
* Filesystem patches to detour E and F backup drives for settings
#### iidxhook4 (18)
* Ezusb IO2 I/O emulation
* Setupapi emulation
* Full game essential I/O emulation
* ACIO ICCA card reader emulation, slotted readers
* d3d9 patching and extended features
* Font patching for Japanese chars
* Filesystem patches to detour E and F backup drives for settings
#### iidxhook5 (19)
* Ezusb IO2 I/O emulation
* Setupapi emulation
* Full game essential I/O emulation
* ACIO ICCA card reader emulation, wave pass readers
* d3d9 patching and extended features
* Font patching for Japanese chars
* Filesystem patches to detour E and F backup drives for settings
#### iidxhook6 (20)
* Ezusb IO2 I/O emulation
* Setupapi emulation
* Full game essential I/O emulation
* ACIO ICCA card reader emulation, wave pass readers
* d3d9 patching and extended features
* Font patching for Japanese chars
#### iidxhook7 (21-24)
* Ezusb IO2 I/O emulation
* Setupapi emulation
* Full game essential I/O emulation
* ACIO ICCA card reader emulation, wave pass readers
* d3d9 patching and extended features
* Font patching for Japanese chars
#### iidxhook8 (25-26)
* ACIO BIO2 I/O emulation
* Setupapi emulation
* Full game essential I/O emulation
* ACIO ICCA card reader emulation, wave pass readers
* d3d9 patching and extended features
* Font patching for Japanese chars
### jbhook
TODO
### sdvxhook
TODO
## The ezusb (emulation) stack
TODO
## The ACIO (emulation) stack
TODO
## BT5 API
TODO
## AVS and launcher
TODO
## Inject
TODO

View File

@@ -0,0 +1,88 @@
# Notes outlining some aspects of the DirectX calls which were required to know to implement a up-/downscaling feature
As the title says, this outlines some aspects I needed to figure out in order to implement a up-/downscaling feature
within the d3d9 hook module that works on all currently available IIDX versions (9 to 26).
To analyze the rendering loops, I have used a tool called apitrace which traces the calls of many graphic APIs:
https://github.com/apitrace/apitrace
Defintely recommended to quickly figure out what is going on regarding rendering. It also allows you to let you render
parts of a scene after the application exited because it records all API calls and data passed to them.
Anyway, considering the various iterations in (GPU) hardware the game had to undergo combined with weird quirks and
"fixes" Bemanitools is undoing, I wouldn't have guessed that their rendering engine was nearly the same until IIDX 20.
That's when they introduced SD/HD mode.
In this case, that's great news because I had to craft a solution that allows up-/downscaling the final frame to
different resolutions (see the iidxhook-util/d3d9 module for more details about the feature).
But first, we need a breakdown of the render loop's most relevant parts for this:
## IIDX pre 20
Using apitrace, we can see the following outline of a frame (not counting the first one that does a lot of setup in
the beginning):
```
BeginScene
Clear
...
// Here are the main draw calls for the scene rendering to the back buffer
EndScene
Present
```
No render target switching, simply render everything to the back buffer...plain and simple.
Note: The viewport size is determined by the size returned by GetClientRect, wtf.
Welp, no official Konmai seal of approval without that. ¯\_(ツ)_/¯
## IIDX 20+
Using apitrace, we can see the following outline of a frame (not counting the first one that does a lot of setup in
the beginning):
```
BeginScene
// tex1 is a render target texture with size 1280x720 (also in SD mode)
// The game will render to this intermediate target and not directly to the fram ebuffer
SetRenderTarget(0, tex1)
...
Clear
BeginScene -> ErrInvalidCall return code
Clear
...
// Here are the main draw calls for the scene rendering to tex1
...
// Sets the render target to the original frame buffer. The size of the framebuffer is set to the output mode
// resolution, e.g. 1280x720 for HD mode and 640x480 for SD mode
SetRenderTarget(0, frame_buffer)
...
Clear
EndScene
...
// Render, texture and sampler state updates as well as a draw call that draws tex1 to a quad which fills the
// screen space.
...
EndScene -> ErrInvalidCall return code
Present
```
This is quite a different flow to implement HD and SD mode but the solution to solve that particular problem is straight
forward and easy to understand. This means that the game will always render in HD mode and only downscale the final
frame to SD resolution for 640x480 output.
Also, why the fuck do they call BeginScene and EndScene twice? Looks like they wanted to do this in two separate scenes
for some reason. Checking the return values would have revealed to them that something's not right...lucky them that
this code works nevertheless.
Another Konmai seal of approval, a job well done. ¯\_(ツ)_/¯
## iidxhook's up-/downscaling solution
The initial solution simply hooked into BeginScene and EndScene and let the game render to an intermediate render
target texture. The texture was scaled according to the actual target frame buffer size before getting presented. This
solution worked fine for pre IIDX 20 games but created a black screen on IIDX 20+.
In order to avoid two different scaling flows, the final solution that works for both does the following:
* Create a render target texture with native resolution and let the game render to it
* Set the render target to that intermediate render target texture on BeginScene
* Before Present
* Scale the intermediate render target texture to the back buffer
* Set the back buffer as the render target
* Present frame
Just an outline which follows the actual implementation that you can find in the iidxhook-util/d3d9.

View File

@@ -44,10 +44,30 @@ make
All output is located in the *build* folder including the final *bemanitools.zip* package.
### Release building
A release build is a clean build including code formatting and testing. This can be executed by running the following
command:
```
make release
```
## Code formatting
To apply our code style using clang-format, simply run the following command:
```
make code-format
```
Please also refer to the [section about](###Additional-code-style-guidelines) which cannot be covered using
clang-format.
## Testing
This still needs to be improved/implemented properly to run the unit-tests easily. Currently, you have to be on either
a Linux/MacOSX system to run *run-test-wine.sh* from the root folder. This executes all currently available unit-tests
and reports to the terminal any errors. This requires wine to be installed.
a Linux/MacOSX system and run
```
make run-tests
```
This executes all currently available unit-tests and reports to the terminal any errors. This requires wine to be
installed.
## Project structure
Now that your setup is ready to go, here is brief big picture of what you find in this project.
@@ -140,6 +160,26 @@ if (var == 2) {
printf("%d\n", var);
```
#### Empty line at the start of blocks
There are situations when you want to have an empty line at the start of the block to enhance readability, for example:
```
if (a &&
b &&
c) {
d = 5;
}
```
Here the assignment aligns with the conditions of the if-black making it hard to read. Better:
```
if (a &&
b &&
c) {
d = 5;
}
```
#### Includes
* Always keep all includes at the top of a header and source file. Exception: Documentation before include guards on
header file.
@@ -291,6 +331,20 @@ Upper-case with underscore as spacing, proper namespacing to namespace and modul
#define EZUSB_DEVICE_VID 0xFFFF
```
#### Multiple variable declarations
Only one declaration per line which also avoids various errors, for example:
```
// Nope
char a, b, b;
```
```
// Ok
char a;
char b;
char c;
```
### Testing
We advice you to write unit tests for all modules that allow proper unit testing. This applies to modules that are not
part of the actual hooking process and do not rely on external devices to be available. Add these tests to the

View File

@@ -4,6 +4,11 @@ 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.
The hook libraries must be bootstrapped either using [inject](../inject.md) or
[launcher](../launcher.md) depending on the version you want to run. Further
instructions are given in dedicated readme files for each iidxhook version
(see below).
# Versions
iidxhook comes in a few different flavors. The game and its engine changed over
@@ -17,7 +22,7 @@ games:
* [iidxhook5](iidxhook5.md): Lincle
* [iidxhook6](iidxhook6.md): Tricoro
* [iidxhook7](iidxhook7.md): SPADA, PENDUAL, copula, SINOBUZ
* [iidxhook8](../iidxhook8/iidxhook8.md): CANNON BALLERS
* [iidxhook8](iidxhook8.md): CANNON BALLERS, Rootage
When building kactools, independent packages are created for each set of games
which are ready to be dropped on top of vanilla AC data dumps. We recommend

View File

@@ -6,6 +6,8 @@ The following games are compatible with this version of iidxhook:
* RED
* HAPPY SKY
The games must be bootstrapped using [inject](../inject.md).
# Data setup and running the game
Ensure your folder with your unpacked data looks like this:
@@ -52,6 +54,14 @@ to have a pre-ceeding "-p" for every parameter added.
However, if a parameter is specifed in the configuration file and as a command
line argument, the command line argument overrides the config file's value.
# Use d3d8to9 wrapper
In order to use the gfx feature patches, e.g. window mode, monitor check,
frame rate locking, framebuffer up/-downscaling etc. you **must** use the
d3d8to9 wrapper library (get it from the bemanitools-supplement package).
Bemanitools removed the old d3d8 hooking module to provide native d3d8 hooks
due to compatibility and maintainability reasons.
# Eamuse network setup
If you want to run the games online, you have to set a valid PCBID in the
@@ -116,6 +126,10 @@ happens, run the game again.
# Troubleshooting and FAQ
## 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.
## 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
@@ -211,6 +225,3 @@ If one or multiple of these issues apply, use the built in scaling options by se
to scale to. Usually, you want to set this to the monitor's native resolution, e.g.
1920x1080 for full HD. You can play around with a few different filters using
*gfx.scale_back_buffer_filter* which impacts image quality/blurriness on upscaling.
If you want to use this with old d3d8 games (IIDX 9-13), you have to use the d3d8to9
library from bemanitools-supplement because the d3d8 hook module cannot support this
upscaling feature. Make sure to set *misc.use_d3d9_hooks=true*.

View File

@@ -3,6 +3,8 @@
The following games are compatible with this version of iidxhook:
* DistorteD
The games must be bootstrapped using [inject](../inject.md).
# Data setup and running the game
Ensure your folder with your unpacked data looks like this:
@@ -48,6 +50,14 @@ to have a pre-ceeding "-p" for every parameter added.
However, if a parameter is specifed in the configuration file and as a command
line argument, the command line argument overrides the config file's value.
# Use d3d8to9 wrapper
In order to use the gfx feature patches, e.g. window mode, monitor check,
frame rate locking, framebuffer up/-downscaling etc. you **must** use the
d3d8to9 wrapper library (get it from the bemanitools-supplement package).
Bemanitools removed the old d3d8 hooking module to provide native d3d8 hooks
due to compatibility and maintainability reasons.
# Eamuse network setup
If you want to run the games online, you have to set a valid PCBID in the
@@ -92,6 +102,10 @@ happens, run the game again.
# Troubleshooting and FAQ
## 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.
## 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
@@ -176,6 +190,3 @@ If one or multiple of these issues apply, use the built in scaling options by se
to scale to. Usually, you want to set this to the monitor's native resolution, e.g.
1920x1080 for full HD. You can play around with a few different filters using
*gfx.scale_back_buffer_filter* which impacts image quality/blurriness on upscaling.
If you want to use this with old d3d8 games (IIDX 9-13), you have to use the d3d8to9
library from bemanitools-supplement because the d3d8 hook module cannot support this
upscaling feature. Make sure to set *misc.use_d3d9_hooks=true*.

View File

@@ -6,6 +6,8 @@ The following games are compatible with this version of iidxhook:
* EMPRESS
* SIRIUS
The games must be bootstrapped using [inject](../inject.md).
# Data setup and running the game
Ensure your folder with your unpacked data looks like this:
@@ -93,6 +95,22 @@ IIDX occasionally fails to boot with a "USBIO (FM-DL TIMEOUT)" error. If this
happens, run the game again.
# Troubleshooting and FAQ
## The game does not start at all
If you try to run iidx16 or iidx17 and you see one of the following outputs when
running the gamestart-XX.bat script:
```
Failed to launch hook EXE: 00000002
```
or
```
Injecting: iidxhook3.dll
Debug active process
Resuming remote process...
```
Make sure to check if you are using non htpac'd executables on iidx16 and iidx17
and also non htpac'd libraries/dll files on iidx17. These won't work with BT
and injecting the hook libraries.
## The game does not run "well" (frame drops, drifting offsync etc)
This can be related to various issues:

View File

@@ -3,6 +3,8 @@
The following games are compatible with this version of iidxhook:
* Resort Anthem
The games must be bootstrapped using [launcher](../launcher.md).
# Data setup and running the game
We assume that you are using a clean/vanilla data dump. Ensure your ("concents")

View File

@@ -3,6 +3,8 @@
The following games are compatible with this version of iidxhook:
* Lincle
The games must be bootstrapped using [launcher](../launcher.md).
# Data setup and running the game
We assume that you are using a clean/vanilla data dump. Ensure your ("concents")

View File

@@ -3,6 +3,8 @@
The following games are compatible with this version of iidxhook:
* Tricoro
The games must be bootstrapped using [launcher](../launcher.md).
# Data setup and running the game
We assume that you are using a clean/vanilla data dump. Ensure your ("concents")

View File

@@ -6,6 +6,8 @@ The following games are compatible with this version of iidxhook:
* copula
* SINOBUZ
The games must be bootstrapped using [launcher](../launcher.md).
# Data setup and running the game
We assume that you are using a clean/vanilla data dump. Ensure your ("concents")

View File

@@ -3,6 +3,8 @@
The following games are compatible with this version of iidxhook:
* CANNON BALLERS
The games must be bootstrapped using [launcher](../launcher.md).
# Data setup and running the game
## Supported versions of Windows

18
doc/inject.md Normal file
View File

@@ -0,0 +1,18 @@
# Inject
Inject is a tool that creates a process for a specified application executable
file and injects a specified list of library/dll files into the process before
it is kicked off.
Typically, the tool is run when you use one of the bat script files to start
any of the games that require its usage, e.g. older IIDX games.
It comes with further option switches for development, e.g. Halting until
a debugger is attached, outputting debug output to a logfile etc.
Just run the application without any parameters to get a usage message:
```
inject.exe
```
How inject.exe is used can be taken from the bat script files of various
(typically older) games.

15
doc/launcher.md Normal file
View File

@@ -0,0 +1,15 @@
# Launcher
Launcher is a tool which is required to run the more recent titles. It sets up
the AVS environment for the target game to boot before it runs the it.
Typically, the tool is run when you use one of the bat script files to start
any of the games that require its usage, e.g. newer IIDX games.
It comes with option switches to configure the AVS environment and for
development, e.g. Halting until a debugger is attached, outputting debug
output to a logfile etc.
Just run the application without any parameters to get a usage message:
```
launcher.exe
```

View File

@@ -0,0 +1,16 @@
This library talks to a KFCA node through ACIO and implements the sdvxio API of BT5.
Thus, it allows you to use a KFCA device board with *any* version of SDVX that is supported by BT5.
# Setup
* Rename sdvxio-kfca.dll to sdvxio.dll.
* Ensure that your gamestart.bat actually injects the appropriate sdvxhook dll
for example:
```
launcher -K sdvxhook2.dll soundvoltex.dll ...*
```
or that the application otherwise uses sdvxio.dll
* sdvxio-kfca expects a KFCA device on COM3 by default
* You can change the port and baudrate by editing the sdvxio-kfca.conf that should be created by default
* If there is also an ICCA device on the same ACIO bus, it cannot be used with eamio-icca at this time
* Please connect any additional acio devices to their own port (ex: SDVX5 expects an ICCA by itself on COM2)

View File

@@ -25,27 +25,33 @@ enum SensorTestMode;
enum SMXUpdateCallbackReason;
struct SMXSensorTestModeData;
// All functions are nonblocking. Getters will return the most recent state. Setters will
// return immediately and do their work in the background. No functions return errors, and
// setting data on a pad which isn't connected will have no effect.
// All functions are nonblocking. Getters will return the most recent state.
// Setters will return immediately and do their work in the background. No
// functions return errors, and setting data on a pad which isn't connected will
// have no effect.
// Initialize, and start searching for devices.
//
// UpdateCallback will be called when something happens: connection or disconnection, inputs
// changed, configuration updated, test data updated, etc. It doesn't specify what's changed,
// and the user should check all state that it's interested in.
// UpdateCallback will be called when something happens: connection or
// disconnection, inputs changed, configuration updated, test data updated, etc.
// It doesn't specify what's changed, and the user should check all state that
// it's interested in.
//
// This is called asynchronously from a helper thread, so the receiver must be thread-safe.
typedef void SMXUpdateCallback(int pad, enum SMXUpdateCallbackReason reason, void *pUser);
SMX_EXTERN_C SMX_API void SMX_Start(SMXUpdateCallback UpdateCallback, void *pUser);
// This is called asynchronously from a helper thread, so the receiver must be
// thread-safe.
typedef void
SMXUpdateCallback(int pad, enum SMXUpdateCallbackReason reason, void *pUser);
SMX_EXTERN_C SMX_API void
SMX_Start(SMXUpdateCallback UpdateCallback, void *pUser);
// Shut down and disconnect from all devices. This will wait for any user callbacks to complete,
// and no user callbacks will be called after this returns. This must not be called from within
// the update callback.
// Shut down and disconnect from all devices. This will wait for any user
// callbacks to complete, and no user callbacks will be called after this
// returns. This must not be called from within the update callback.
SMX_EXTERN_C SMX_API void SMX_Stop();
// Set a function to receive diagnostic logs. By default, logs are written to stdout.
// This can be called before SMX_Start, so it affects any logs sent during initialization.
// Set a function to receive diagnostic logs. By default, logs are written to
// stdout. This can be called before SMX_Start, so it affects any logs sent
// during initialization.
typedef void SMXLogCallback(const char *log);
SMX_EXTERN_C SMX_API void SMX_SetLogCallback(SMXLogCallback callback);
@@ -55,8 +61,9 @@ SMX_EXTERN_C SMX_API void SMX_GetInfo(int pad, struct SMXInfo *info);
// Get a mask of the currently pressed panels.
SMX_EXTERN_C SMX_API uint16_t SMX_GetInputState(int pad);
// Update the lights. Both pads are always updated together. lightsData is a list of 8-bit RGB
// colors, one for each LED. Each panel has lights in the following order:
// Update the lights. Both pads are always updated together. lightsData is a
// list of 8-bit RGB colors, one for each LED. Each panel has lights in the
// following order:
//
// 0123
// 4567
@@ -69,61 +76,70 @@ SMX_EXTERN_C SMX_API uint16_t SMX_GetInputState(int pad);
// 345 CDE
// 678 F01
//
// With 18 panels, 16 LEDs per panel and 3 bytes per LED, each light update has 864 bytes of data.
// With 18 panels, 16 LEDs per panel and 3 bytes per LED, each light update has
// 864 bytes of data.
//
// Lights will update at up to 30 FPS. If lights data is sent more quickly, a best effort will be
// made to send the most recent lights data available, but the panels won't update more quickly.
// Lights will update at up to 30 FPS. If lights data is sent more quickly, a
// best effort will be made to send the most recent lights data available, but
// the panels won't update more quickly.
//
// The panels will return to automatic lighting if no lights are received for a while, so applications
// controlling lights should send light updates continually, even if the lights aren't changing.
// The panels will return to automatic lighting if no lights are received for a
// while, so applications controlling lights should send light updates
// continually, even if the lights aren't changing.
SMX_EXTERN_C SMX_API void SMX_SetLights(const char lightsData[864]);
// By default, the panels light automatically when stepped on. If a lights command is sent by
// the application, this stops happening to allow the application to fully control lighting.
// If no lights update is received for a few seconds, automatic lighting is reenabled by the
// panels.
// By default, the panels light automatically when stepped on. If a lights
// command is sent by the application, this stops happening to allow the
// application to fully control lighting. If no lights update is received for a
// few seconds, automatic lighting is reenabled by the panels.
//
// SMX_ReenableAutoLights can be called to immediately reenable auto-lighting, without waiting
// for the timeout period to elapse. Games don't need to call this, since the panels will return
// to auto-lighting mode automatically after a brief period of no updates.
// SMX_ReenableAutoLights can be called to immediately reenable auto-lighting,
// without waiting for the timeout period to elapse. Games don't need to call
// this, since the panels will return to auto-lighting mode automatically after
// a brief period of no updates.
SMX_EXTERN_C SMX_API void SMX_ReenableAutoLights();
// Get the current controller's configuration.
//
// Return true if a configuration is available. If false is returned, no panel is connected
// and no data will be set.
// Return true if a configuration is available. If false is returned, no panel
// is connected and no data will be set.
SMX_EXTERN_C SMX_API bool SMX_GetConfig(int pad, struct SMXConfig *config);
// Update the current controller's configuration. This doesn't block, and the new configuration will
// be sent in the background. SMX_GetConfig will return the new configuration as soon as this call
// returns, without waiting for it to actually be sent to the controller.
SMX_EXTERN_C SMX_API void SMX_SetConfig(int pad, const struct SMXConfig *config);
// Update the current controller's configuration. This doesn't block, and the
// new configuration will be sent in the background. SMX_GetConfig will return
// the new configuration as soon as this call returns, without waiting for it to
// actually be sent to the controller.
SMX_EXTERN_C SMX_API void
SMX_SetConfig(int pad, const struct SMXConfig *config);
// Reset a pad to its original configuration.
SMX_EXTERN_C SMX_API void SMX_FactoryReset(int pad);
// Request an immediate panel recalibration. This is normally not necessary, but can be helpful
// for diagnostics.
// Request an immediate panel recalibration. This is normally not necessary,
// but can be helpful for diagnostics.
SMX_EXTERN_C SMX_API void SMX_ForceRecalibration(int pad);
// Set a panel test mode and request test data. This is used by the configuration tool.
// Set a panel test mode and request test data. This is used by the
// configuration tool.
SMX_EXTERN_C SMX_API void SMX_SetTestMode(int pad, enum SensorTestMode mode);
SMX_EXTERN_C SMX_API bool SMX_GetTestData(int pad, struct SMXSensorTestModeData *data);
SMX_EXTERN_C SMX_API bool
SMX_GetTestData(int pad, struct SMXSensorTestModeData *data);
// Return the build version of the DLL, which is based on the git tag at build time. This
// is only intended for diagnostic logging, and it's also the version we show in SMXConfig.
// Return the build version of the DLL, which is based on the git tag at build
// time. This is only intended for diagnostic logging, and it's also the
// version we show in SMXConfig.
SMX_EXTERN_C SMX_API const char *SMX_Version();
// General info about a connected controller. This can be retrieved with SMX_GetInfo.
struct SMXInfo
{
// True if we're fully connected to this controller. If this is false, the other
// fields won't be set.
// General info about a connected controller. This can be retrieved with
// SMX_GetInfo.
struct SMXInfo {
// True if we're fully connected to this controller. If this is false, the
// other fields won't be set.
bool m_bConnected;
// This device's serial number. This can be used to distinguish devices from each
// other if more than one is connected. This is a null-terminated string instead
// of a C++ string for C# marshalling.
// This device's serial number. This can be used to distinguish devices
// from each other if more than one is connected. This is a null-terminated
// string instead of a C++ string for C# marshalling.
char m_Serial[33];
// This device's firmware version.
@@ -131,22 +147,24 @@ struct SMXInfo
};
enum SMXUpdateCallbackReason {
// This is called when a generic state change happens: connection or disconnection, inputs changed,
// test data updated, etc. It doesn't specify what's changed. We simply check the whole state.
// This is called when a generic state change happens: connection or
// disconnection, inputs changed,
// test data updated, etc. It doesn't specify what's changed. We simply
// check the whole state.
SMXUpdateCallback_Updated,
// This is called when SMX_FactoryReset completes, indicating that SMX_GetConfig will now return
// This is called when SMX_FactoryReset completes, indicating that
// SMX_GetConfig will now return
// the reset configuration.
SMXUpdateCallback_FactoryResetCommandComplete
};
// The configuration for a connected controller. This can be retrieved with SMX_GetConfig
// and modified with SMX_SetConfig.
// The configuration for a connected controller. This can be retrieved with
// SMX_GetConfig and modified with SMX_SetConfig.
//
// The order and packing of this struct corresponds to the configuration packet sent to
// the master controller, so it must not be changed.
struct SMXConfig
{
// The order and packing of this struct corresponds to the configuration packet
// sent to the master controller, so it must not be changed.
struct SMXConfig {
#if 0
// These fields are unused and must be left at their existing values.
uint8_t unused1 = 0xFF, unused2 = 0xFF;
@@ -228,9 +246,10 @@ struct SMXConfig
uint8_t panelThreshold8Low, panelThreshold8High;
#endif
};
//static_assert(sizeof(SMXConfig) == 84, "Expected 84 bytes");
// static_assert(sizeof(SMXConfig) == 84, "Expected 84 bytes");
// The values (except for Off) correspond with the protocol and must not be changed.
// The values (except for Off) correspond with the protocol and must not be
// changed.
enum SensorTestMode {
SensorTestMode_Off = 0,
// Return the raw, uncalibrated value of each sensor.
@@ -246,10 +265,11 @@ enum SensorTestMode {
SensorTestMode_Tare = '3',
};
// Data for the current SensorTestMode. The interpretation of sensorLevel depends on the mode.
struct SMXSensorTestModeData
{
// If false, sensorLevel[n][*] is zero because we didn't receive a response from that panel.
// Data for the current SensorTestMode. The interpretation of sensorLevel
// depends on the mode.
struct SMXSensorTestModeData {
// If false, sensorLevel[n][*] is zero because we didn't receive a response
// from that panel.
bool bHaveDataFromPanel[9];
int16_t sensorLevel[9][4];

View File

@@ -1,6 +1,8 @@
#ifndef IMPORTS_AVS_EA3_H
#define IMPORTS_AVS_EA3_H
#include "imports/avs.h"
void ea3_boot(struct property_node *conf);
void ea3_shutdown(void);

View File

@@ -74,45 +74,44 @@ struct property_psmap {
intptr_t xdefault;
};
#define PSMAP_BEGIN(name) \
struct property_psmap name[] = {
#define PSMAP_BEGIN(name) struct property_psmap name[] = {
#define PSMAP_REQUIRED(type, xstruct, field, path) \
{ \
type, \
0, \
offsetof(xstruct, field), \
sizeof( ((xstruct *) 0)->field ), \
path, \
0, \
}, \
{ \
type, \
0, \
offsetof(xstruct, field), \
sizeof(((xstruct *) 0)->field), \
path, \
0, \
},
#define PSMAP_OPTIONAL(type, xstruct, field, path, xdefault) \
{ \
type, \
PSMAP_FLAG_HAVE_DEFAULT, \
offsetof(xstruct, field), \
sizeof( ((xstruct *) 0)->field ), \
path, \
(intptr_t) xdefault, \
}, \
{ \
type, \
PSMAP_FLAG_HAVE_DEFAULT, \
offsetof(xstruct, field), \
sizeof(((xstruct *) 0)->field), \
path, \
(intptr_t) xdefault, \
},
#define PSMAP_END \
{ 0xFF, 0, 0, 0, NULL, 0 } \
};
#define PSMAP_END \
{ \
0xFF, 0, 0, 0, NULL, 0 \
} \
} \
;
#if AVS_VERSION >= 1500
# define AVS_LOG_WRITER(name, chars, nchars, ctx) \
void name(const char * chars , uint32_t nchars , void * ctx )
#define AVS_LOG_WRITER(name, chars, nchars, ctx) \
void name(const char *chars, uint32_t nchars, void *ctx)
typedef void (*avs_log_writer_t)(const char *chars, uint32_t nchars,
void *ctx);
typedef void (*avs_log_writer_t)(const char *chars, uint32_t nchars, void *ctx);
#else
# define AVS_LOG_WRITER(name, chars, nchars, ctx) \
void name(void * ctx , const char * chars , uint32_t nchars )
#define AVS_LOG_WRITER(name, chars, nchars, ctx) \
void name(void *ctx, const char *chars, uint32_t nchars)
typedef void (*avs_log_writer_t)(void *ctx, const char *chars,
uint32_t nchars);
typedef void (*avs_log_writer_t)(void *ctx, const char *chars, uint32_t nchars);
#endif
typedef int (*avs_reader_t)(uint32_t context, void *bytes, size_t nbytes);
@@ -120,22 +119,38 @@ typedef int (*avs_reader_t)(uint32_t context, void *bytes, size_t nbytes);
#if AVS_VERSION >= 1600
/* "avs" and "std" heaps have been unified */
typedef void (*avs_boot_t)(
struct property_node *config, void *com_heap, size_t sz_com_heap,
void *reserved, avs_log_writer_t log_writer, void *log_context);
struct property_node *config,
void *com_heap,
size_t sz_com_heap,
void *reserved,
avs_log_writer_t log_writer,
void *log_context);
void avs_boot(
struct property_node *config, void *com_heap, size_t sz_com_heap,
void *reserved, avs_log_writer_t log_writer, void *log_context);
struct property_node *config,
void *com_heap,
size_t sz_com_heap,
void *reserved,
avs_log_writer_t log_writer,
void *log_context);
#else
typedef void (*avs_boot_t)(
struct property_node *config, void *std_heap, size_t sz_std_heap,
void *avs_heap, size_t sz_avs_heap, avs_log_writer_t log_writer,
void* log_context);
struct property_node *config,
void *std_heap,
size_t sz_std_heap,
void *avs_heap,
size_t sz_avs_heap,
avs_log_writer_t log_writer,
void *log_context);
void avs_boot(
struct property_node *config, void *std_heap, size_t sz_std_heap,
void *avs_heap, size_t sz_avs_heap, avs_log_writer_t log_writer,
void *log_context);
struct property_node *config,
void *std_heap,
size_t sz_std_heap,
void *avs_heap,
size_t sz_avs_heap,
avs_log_writer_t log_writer,
void *log_context);
#endif
void avs_shutdown(void);
@@ -149,54 +164,70 @@ void log_change_level(int level);
int avs_net_ctrl(int ioctl, void *bytes, uint32_t nbytes);
int avs_thread_create(int (*proc)(void *), void *ctx, uint32_t sz_stack,
unsigned int priority);
int avs_thread_create(
int (*proc)(void *), void *ctx, uint32_t sz_stack, unsigned int priority);
void avs_thread_destroy(int thread_id);
void avs_thread_exit(int result);
void avs_thread_join(int thread_id, int *result);
uint32_t property_read_query_memsize(
avs_reader_t reader, uint32_t context, int unk0, int unk1);
struct property *property_create(
int flags, void *buffer, uint32_t buffer_size);
avs_reader_t reader, uint32_t context, int unk0, int unk1);
struct property *property_create(int flags, void *buffer, uint32_t buffer_size);
struct property_node *property_search(
struct property *prop, struct property_node *root, const char *path);
struct property *prop, struct property_node *root, const char *path);
int property_insert_read(
struct property *prop, struct property_node *root, avs_reader_t reader,
uint32_t context);
struct property *prop,
struct property_node *root,
avs_reader_t reader,
uint32_t context);
int property_mem_write(struct property *prop, void *bytes, int nbytes);
void *property_desc_to_buffer(struct property *prop);
void property_file_write(struct property *prop, const char *path);
int property_set_flag(struct property *prop, int flags, int mask);
void property_destroy(struct property *prop);
int property_psmap_import(struct property *prop, struct property_node *root,
void *dest, const struct property_psmap *psmap);
int property_psmap_export(struct property *prop, struct property_node *root,
const void *src, const struct property_psmap *psmap);
int property_psmap_import(
struct property *prop,
struct property_node *root,
void *dest,
const struct property_psmap *psmap);
int property_psmap_export(
struct property *prop,
struct property_node *root,
const void *src,
const struct property_psmap *psmap);
struct property_node *property_node_clone(
struct property *new_parent, int unk0,
struct property_node *src, bool deep);
struct property *new_parent,
int unk0,
struct property_node *src,
bool deep);
struct property_node *property_node_create(
struct property *prop, struct property_node *parent, int type,
const char *key, ...);
void property_node_name(
struct property_node *node, char *chars, int nchars);
struct property *prop,
struct property_node *parent,
int type,
const char *key,
...);
void property_node_name(struct property_node *node, char *chars, int nchars);
const char *property_node_refdata(struct property_node *node);
int property_node_refer(struct property *prop,
struct property_node *node, const char *name,
enum property_type type, void *bytes, uint32_t nbytes);
int property_node_refer(
struct property *prop,
struct property_node *node,
const char *name,
enum property_type type,
void *bytes,
uint32_t nbytes);
void property_node_remove(struct property_node *node);
enum property_type property_node_type(
struct property_node *node);
enum property_type property_node_type(struct property_node *node);
struct property_node *property_node_traversal(
struct property_node *node, enum property_node_traversal direction);
void property_node_datasize(struct property_node* node);
struct property_node *node, enum property_node_traversal direction);
void property_node_datasize(struct property_node *node);
bool std_getenv(const char *key, char *val, uint32_t nbytes);
void std_setenv(const char *key, const char *val);
void *avs_fs_mount (char* mountpoint, char* fsroot, void* fstype, int flags);
int avs_fs_addfs(void *filesys_struct);
int avs_fs_mount(
const char *mountpoint, const char *fsroot, const char *fstype, void *data);
#endif

View File

@@ -5,6 +5,7 @@ EXPORTS
avs_thread_destroy @7 NONAME
avs_thread_exit @11 NONAME
avs_thread_join @12 NONAME
avs_fs_addfs @73 NONAME
avs_fs_mount @76 NONAME
avs_net_ctrl @119 NONAME
property_create @145 NONAME

View File

@@ -5,6 +5,7 @@ EXPORTS
avs_thread_destroy @7 NONAME
avs_thread_exit @11 NONAME
avs_thread_join @12 NONAME
avs_fs_addfs @73 NONAME
avs_fs_mount @76 NONAME
avs_net_ctrl @119 NONAME
property_create @145 NONAME

View File

@@ -8,33 +8,33 @@
#include "acio/icca.h"
#include "acio/kfca.h"
#define AC_IO_SOF 0xAA
#define AC_IO_ESCAPE 0xFF
#define AC_IO_RESPONSE_FLAG 0x80
#define AC_IO_BROADCAST 0x70
#define AC_IO_SOF 0xAA
#define AC_IO_ESCAPE 0xFF
#define AC_IO_RESPONSE_FLAG 0x80
#define AC_IO_BROADCAST 0x70
#define ac_io_u16(x) _byteswap_ushort(x)
#define ac_io_u32(x) _byteswap_ulong(x)
#define ac_io_u16(x) _byteswap_ushort(x)
#define ac_io_u32(x) _byteswap_ulong(x)
enum ac_io_cmd {
AC_IO_CMD_ASSIGN_ADDRS = 0x0001,
AC_IO_CMD_GET_VERSION = 0x0002,
AC_IO_CMD_START_UP = 0x0003,
AC_IO_CMD_KEEPALIVE = 0x0080,
AC_IO_CMD_ASSIGN_ADDRS = 0x0001,
AC_IO_CMD_GET_VERSION = 0x0002,
AC_IO_CMD_START_UP = 0x0003,
AC_IO_CMD_KEEPALIVE = 0x0080,
/* Yet unknown command encountered first on jubeat (1) */
AC_IO_CMD_UNKN_00FF = 0x00FF,
AC_IO_CMD_CLEAR = 0x0100,
AC_IO_CMD_UNKN_00FF = 0x00FF,
AC_IO_CMD_CLEAR = 0x0100,
};
enum ac_io_node_type {
AC_IO_NODE_TYPE_H44B = 0x04010000,
AC_IO_NODE_TYPE_ICCA = 0x03000000,
AC_IO_NODE_TYPE_H44B = 0x04010000,
AC_IO_NODE_TYPE_ICCA = 0x03000000,
/* same as ICCA */
AC_IO_NODE_TYPE_ICCB = 0x03000000,
AC_IO_NODE_TYPE_LED_STRIP = 0x04020000,
AC_IO_NODE_TYPE_LED_SPIKE = 0x05010000,
AC_IO_NODE_TYPE_KFCA = 0x09060000,
AC_IO_NODE_TYPE_BI2A = 0x0d060000,
AC_IO_NODE_TYPE_ICCB = 0x03000000,
AC_IO_NODE_TYPE_LED_STRIP = 0x04020000,
AC_IO_NODE_TYPE_LED_SPIKE = 0x05010000,
AC_IO_NODE_TYPE_KFCA = 0x09060000,
AC_IO_NODE_TYPE_BI2A = 0x0d060000,
};
#pragma pack(push, 1)
@@ -52,7 +52,7 @@ struct ac_io_version {
};
struct ac_io_message {
uint8_t addr; /* High bit: clear = req, set = resp */
uint8_t addr; /* High bit: clear = req, set = resp */
union {
struct {
@@ -76,7 +76,7 @@ struct ac_io_message {
struct {
uint8_t nbytes;
uint8_t raw[0xFF]; /* 0xFFucked if I know */
uint8_t raw[0xFF]; /* 0xFFucked if I know */
} bcast;
};
};

View File

@@ -5,13 +5,13 @@
enum ac_io_icca_cmd {
/* Yet unknown command encountered first on jubeat (1) */
AC_IO_ICCA_CMD_UNKN_0120 = 0x0120,
AC_IO_ICCA_CMD_UNKN_0120 = 0x0120,
AC_IO_ICCA_CMD_QUEUE_LOOP_START = 0x0130,
AC_IO_ICCA_CMD_ENGAGE = 0x0131,
AC_IO_ICCA_CMD_POLL = 0x0134,
AC_IO_ICCA_CMD_SET_SLOT_STATE = 0x0135,
AC_IO_ICCA_CMD_BEGIN_KEYPAD = 0x013A,
AC_IO_ICCA_CMD_POLL_FELICA = 0x0161,
AC_IO_ICCA_CMD_ENGAGE = 0x0131,
AC_IO_ICCA_CMD_POLL = 0x0134,
AC_IO_ICCA_CMD_SET_SLOT_STATE = 0x0135,
AC_IO_ICCA_CMD_BEGIN_KEYPAD = 0x013A,
AC_IO_ICCA_CMD_POLL_FELICA = 0x0161,
};
enum ac_io_icca_slot_state {

View File

@@ -5,16 +5,16 @@
enum ac_io_iccb_cmd {
/* found on jubeat prop, sent after acio init req, maybe fw update? */
AC_IO_ICCB_CMD_UNK_0100 = 0x0100,
AC_IO_ICCB_CMD_UNK_0100 = 0x0100,
/* found on jubeat prop, sent right after queue loop start */
AC_IO_ICCB_CMD_UNK_0116 = 0x0116,
AC_IO_ICCB_CMD_UNK_0116 = 0x0116,
/* found on jubeat prop, sent after 0100 req */
AC_IO_ICCB_CMD_UNK_0120 = 0x0120,
AC_IO_ICCB_CMD_UNK_0120 = 0x0120,
AC_IO_ICCB_CMD_QUEUE_LOOP_START = 0x0130,
AC_IO_ICCB_CMD_POLL = 0x0134,
AC_IO_ICCB_CMD_UNK_135 = 0x0135,
AC_IO_ICCB_CMD_SLEEP = 0x013A,
AC_IO_ICCB_CMD_READ_CARD = 0x0161
AC_IO_ICCB_CMD_POLL = 0x0134,
AC_IO_ICCB_CMD_UNK_135 = 0x0135,
AC_IO_ICCB_CMD_SLEEP = 0x013A,
AC_IO_ICCB_CMD_READ_CARD = 0x0161
};
enum ac_io_iccb_sensor_state {

View File

@@ -1,24 +1,25 @@
#ifndef AC_IO_KFCA_H
#define AC_IO_KFCA_H
#define AC_IO_CMD_KFCA_POLL 0x0113
#define AC_IO_CMD_KFCA_UNK_0120 0x0120
#define AC_IO_CMD_KFCA_UNK_0128 0x0128
#define AC_IO_CMD_KFCA_POLL 0x0113
#define AC_IO_CMD_KFCA_WATCHDOG 0x0120
#define AC_IO_CMD_KFCA_AMP_CONTROL 0x0128
#define AC_IO_KFCA_IN_GPIO_SYS_COIN 0x04
#define AC_IO_KFCA_IN_GPIO_SYS_COIN 0x04
/* ... AC_IO_KFCA_IN_GPIO_SYS_COIN2 0x08 (maybe?) */
#define AC_IO_KFCA_IN_GPIO_SYS_TEST 0x10
#define AC_IO_KFCA_IN_GPIO_SYS_SERVICE 0x20
#define AC_IO_KFCA_IN_GPIO_SYS_TEST 0x10
#define AC_IO_KFCA_IN_GPIO_SYS_SERVICE 0x20
#define AC_IO_KFCA_IN_GPIO_0_C 0x0001
#define AC_IO_KFCA_IN_GPIO_0_B 0x0002
#define AC_IO_KFCA_IN_GPIO_0_A 0x0004
#define AC_IO_KFCA_IN_GPIO_0_START 0x0008
#define AC_IO_KFCA_IN_GPIO_0_HEADPHONE 0x0020
#define AC_IO_KFCA_IN_GPIO_0_C 0x0001
#define AC_IO_KFCA_IN_GPIO_0_B 0x0002
#define AC_IO_KFCA_IN_GPIO_0_A 0x0004
#define AC_IO_KFCA_IN_GPIO_0_START 0x0008
#define AC_IO_KFCA_IN_GPIO_0_RECORDER 0x0010
#define AC_IO_KFCA_IN_GPIO_0_HEADPHONE 0x0020
#define AC_IO_KFCA_IN_GPIO_1_FX_R 0x0008
#define AC_IO_KFCA_IN_GPIO_1_FX_L 0x0010
#define AC_IO_KFCA_IN_GPIO_1_D 0x0020
#define AC_IO_KFCA_IN_GPIO_1_FX_R 0x0008
#define AC_IO_KFCA_IN_GPIO_1_FX_L 0x0010
#define AC_IO_KFCA_IN_GPIO_1_D 0x0020
#pragma pack(push, 1)
@@ -39,6 +40,7 @@ struct ac_io_kfca_poll_in {
struct ac_io_kfca_poll_out {
uint32_t gpio;
uint8_t pwm[18];
uint8_t unk[2];
};
#pragma pack(pop)

View File

@@ -5,5 +5,6 @@ libs_aciodrv := \
src_aciodrv := \
device.c \
icca.c \
kfca.c \
port.c \

View File

@@ -43,17 +43,17 @@ static bool aciodrv_device_init(void)
}
#ifdef AC_IO_MSG_LOG
static void aciodrv_device_log_buffer(const char* msg, const uint8_t* buffer,
int length)
static void
aciodrv_device_log_buffer(const char *msg, const uint8_t *buffer, int length)
{
char str[4096];
hex_encode_uc((const void*) buffer, length, str, sizeof(str));
hex_encode_uc((const void *) buffer, length, str, sizeof(str));
log_misc("%s, length %d: %s", msg, length, str);
}
#endif
static bool aciodrv_device_send(const uint8_t* buffer, int length)
static bool aciodrv_device_send(const uint8_t *buffer, int length)
{
uint8_t send_buf[512];
int send_buf_pos = 0;
@@ -102,7 +102,7 @@ static bool aciodrv_device_send(const uint8_t* buffer, int length)
return true;
}
static int aciodrv_device_receive(uint8_t* buffer, int size)
static int aciodrv_device_receive(uint8_t *buffer, int size)
{
uint8_t recv_buf[512];
int recv_size = 0;
@@ -142,8 +142,7 @@ static int aciodrv_device_receive(uint8_t* buffer, int size)
/* check for escape byte. these don't count towards the
size we expect! */
if (recv_buf[recv_size] == AC_IO_ESCAPE)
{
if (recv_buf[recv_size] == AC_IO_ESCAPE) {
/* next byte is our real data
overwrite escape byte */
do {
@@ -162,7 +161,7 @@ static int aciodrv_device_receive(uint8_t* buffer, int size)
}
#ifdef AC_IO_MSG_LOG
aciodrv_device_log_buffer("Recv (1)", recv_buf, recv_size);
aciodrv_device_log_buffer("Recv (1)", recv_buf, recv_size);
#endif
/* recv_size - 1: omit checksum for checksum calc */
@@ -174,12 +173,14 @@ 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("Recv (2)", buffer, result_size);
#endif
if (checksum != recv_buf[recv_size - 1]) {
log_warning("Invalid message checksum: %02X != %02X",
checksum, recv_buf[recv_size - 1]);
log_warning(
"Invalid message checksum: %02X != %02X",
checksum,
recv_buf[recv_size - 1]);
return -1;
}
@@ -198,7 +199,8 @@ static uint8_t aciodrv_device_enum_nodes(void)
msg.cmd.nbytes = 1;
msg.cmd.count = 0;
if (!aciodrv_send_and_recv(&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
if (!aciodrv_send_and_recv(
&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
log_warning("Enumerating nodes failed");
return 0;
}
@@ -216,13 +218,16 @@ static bool aciodrv_device_get_version(uint8_t node_id, char product[4])
msg.cmd.code = ac_io_u16(AC_IO_CMD_GET_VERSION);
msg.cmd.nbytes = 0;
if ( !aciodrv_send_and_recv(&msg, offsetof(struct ac_io_message, cmd.raw) +
sizeof(struct ac_io_version))) {
if (!aciodrv_send_and_recv(
&msg,
offsetof(struct ac_io_message, cmd.raw) +
sizeof(struct ac_io_version))) {
log_warning("Get version of node %d failed", node_id);
return false;
}
log_info("Node %d: type %d, flag %d, version %d.%d.%d, product %c%c%c%c, "
log_info(
"Node %d: type %d, flag %d, version %d.%d.%d, product %c%c%c%c, "
"build date: %s %s",
node_id,
msg.cmd.version.type,
@@ -250,7 +255,8 @@ static bool aciodrv_device_start_node(uint8_t node_id)
msg.cmd.code = ac_io_u16(AC_IO_CMD_START_UP);
msg.cmd.nbytes = 0;
if (!aciodrv_send_and_recv(&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
if (!aciodrv_send_and_recv(
&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
log_warning("Starting node %d failed", node_id);
return false;
}
@@ -259,7 +265,7 @@ static bool aciodrv_device_start_node(uint8_t node_id)
return true;
}
bool aciodrv_device_open(const char* port, int baud)
bool aciodrv_device_open(const char *port, int baud)
{
if (!aciodrv_port_open(port, baud)) {
return false;
@@ -275,7 +281,8 @@ bool aciodrv_device_open(const char* port, int baud)
}
for (uint8_t i = 0; i < aciodrv_device_node_count; i++) {
if (!aciodrv_device_get_version(i + 1, aviodrv_device_node_products[i])) {
if (!aciodrv_device_get_version(
i + 1, aviodrv_device_node_products[i])) {
return false;
}
}
@@ -304,25 +311,27 @@ bool aciodrv_device_get_node_product_ident(uint8_t node_id, char product[4])
return true;
}
bool aciodrv_send_and_recv(struct ac_io_message* msg, int resp_size)
bool aciodrv_send_and_recv(struct ac_io_message *msg, int resp_size)
{
msg->cmd.seq_no = aciodrv_device_msg_counter++;
if (aciodrv_device_send((uint8_t*) msg,
if (aciodrv_device_send(
(uint8_t *) msg,
offsetof(struct ac_io_message, cmd.raw) + msg->cmd.nbytes) <= 0) {
return false;
}
uint16_t req_code = msg->cmd.code;
if (aciodrv_device_receive((uint8_t*) msg,
resp_size) <= 0) {
if (aciodrv_device_receive((uint8_t *) msg, resp_size) <= 0) {
return false;
}
if (req_code != msg->cmd.code) {
log_warning("Received invalid response %04X for request %04X",
msg->cmd.code, req_code);
log_warning(
"Received invalid response %04X for request %04X",
msg->cmd.code,
req_code);
return false;
}

View File

@@ -13,7 +13,7 @@
* @return True if opening the port and resetting the device was successful,
* false on error.
*/
bool aciodrv_device_open(const char* port, int baud);
bool aciodrv_device_open(const char *port, int baud);
/**
* Get the node count on the opened device.
@@ -27,8 +27,8 @@ uint8_t aciodrv_device_get_node_count(void);
*
* @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.
* @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]);
@@ -42,7 +42,7 @@ bool aciodrv_device_get_node_product_ident(uint8_t node_id, char product[4]);
* @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 ac_io_message *msg, int resp_size);
/**
* Close the previously opened ACIO device.

View File

@@ -15,13 +15,14 @@ static bool aciodrv_icca_queue_loop_start(uint8_t node_id)
msg.cmd.nbytes = 1;
msg.cmd.status = 0;
if (!aciodrv_send_and_recv(&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
if (!aciodrv_send_and_recv(
&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
log_warning("Starting queue loop failed");
return false;
}
log_info("Started queue loop of node %d, status: %d",
node_id, msg.cmd.status);
log_info(
"Started queue loop of node %d, status: %d", node_id, msg.cmd.status);
return true;
}
@@ -35,8 +36,8 @@ bool aciodrv_icca_init(uint8_t node_id)
return true;
}
bool aciodrv_icca_set_state(uint8_t node_id, int slot_state,
struct ac_io_icca_state* state)
bool aciodrv_icca_set_state(
uint8_t node_id, int slot_state, struct ac_io_icca_state *state)
{
struct ac_io_message msg;
@@ -47,8 +48,8 @@ bool aciodrv_icca_set_state(uint8_t node_id, int slot_state,
msg.cmd.raw[0] = sizeof(struct ac_io_icca_state);
msg.cmd.raw[1] = slot_state;
if ( !aciodrv_send_and_recv(&msg, offsetof(struct ac_io_message, cmd.raw) +
msg.cmd.raw[0])) {
if (!aciodrv_send_and_recv(
&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;
}
@@ -60,7 +61,7 @@ bool aciodrv_icca_set_state(uint8_t node_id, int slot_state,
return true;
}
bool aciodrv_icca_get_state(uint8_t node_id, struct ac_io_icca_state* state)
bool aciodrv_icca_get_state(uint8_t node_id, struct ac_io_icca_state *state)
{
struct ac_io_message msg;
@@ -70,8 +71,8 @@ bool aciodrv_icca_get_state(uint8_t node_id, struct ac_io_icca_state* state)
/* buffer size of data we expect */
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)) {
if (!aciodrv_send_and_recv(
&msg, offsetof(struct ac_io_message, cmd.raw) + msg.cmd.count)) {
log_warning("Getting state of node %d failed", node_id + 1);
return false;
}
@@ -83,7 +84,7 @@ 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(uint8_t node_id, struct ac_io_icca_state *state)
{
struct ac_io_message msg;
@@ -93,8 +94,8 @@ bool aciodrv_icca_read_card(uint8_t node_id, struct ac_io_icca_state* state)
/* buffer size of data we expect */
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)) {
if (!aciodrv_send_and_recv(
&msg, offsetof(struct ac_io_message, cmd.raw) + msg.cmd.count)) {
log_warning("Reading card of node %d failed", node_id + 1);
return false;
}

View File

@@ -26,7 +26,8 @@ bool aciodrv_icca_init(uint8_t node_id);
* device driver foundation.
* @see driver.h
*/
bool aciodrv_icca_set_state(uint8_t node_id, int slot_state, struct ac_io_icca_state* state);
bool aciodrv_icca_set_state(
uint8_t node_id, int slot_state, struct ac_io_icca_state *state);
/**
* Get the current state of an ICCA node.
@@ -39,7 +40,7 @@ bool aciodrv_icca_set_state(uint8_t node_id, int slot_state, struct ac_io_icca_s
* 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(uint8_t node_id, struct ac_io_icca_state *state);
/**
* Trigger a card read action on the ICCA reader. Make sure to call this
@@ -55,6 +56,6 @@ 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(uint8_t node_id, struct ac_io_icca_state *state);
#endif

103
src/main/aciodrv/kfca.c Normal file
View File

@@ -0,0 +1,103 @@
#define LOG_MODULE "aciodrv-kfca"
#include <stdio.h>
#include <string.h>
#include "aciodrv/device.h"
#include "util/log.h"
static bool aciodrv_kfca_watchdog_start(uint8_t node_id)
{
// exit early and don't actually call watchdog
// the watchdog call actually returns different sized packets depending on
// the state this results in an issue during packet processing (see: #68)
return true;
/*
struct ac_io_message msg;
msg.addr = node_id + 1;
msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_WATCHDOG);
msg.cmd.nbytes = 2;
msg.cmd.nbytes = 2;
// uint16_t: 6000
msg.cmd.raw[0] = 23;
msg.cmd.raw[1] = 112;
if (!aciodrv_send_and_recv(&msg, offsetof(struct ac_io_message, cmd.raw) +
2)) { log_warning("Starting watchdog failed"); return false;
}
log_warning("Started watchdog of node %d, status: %d",
node_id, msg.cmd.status);
return true;
*/
}
static bool aciodrv_kfca_amp(uint8_t node_id)
{
struct ac_io_message msg;
msg.addr = node_id + 1;
msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_AMP_CONTROL);
msg.cmd.nbytes = 4;
// yes this sets the amp to 100% volume
// TODO: expose this to sdvxio instead at some point
msg.cmd.raw[0] = 0;
msg.cmd.raw[1] = 0;
msg.cmd.raw[2] = 0;
msg.cmd.raw[3] = 0;
if (!aciodrv_send_and_recv(
&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
log_warning("Setting AMP failed");
return false;
}
log_warning("Started AMP node %d", node_id);
return true;
}
bool aciodrv_kfca_init(uint8_t node_id)
{
if (!aciodrv_kfca_watchdog_start(node_id)) {
return false;
}
if (!aciodrv_kfca_amp(node_id)) {
return false;
}
return true;
}
bool aciodrv_kfca_poll(
uint8_t node_id,
const struct ac_io_kfca_poll_out *pout,
struct ac_io_kfca_poll_in *pin)
{
struct ac_io_message msg;
msg.addr = node_id + 1;
msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_POLL);
msg.cmd.nbytes = sizeof(*pout);
/* buffer size of data we expect */
msg.cmd.kfca_poll_out = *pout;
if (!aciodrv_send_and_recv(
&msg, offsetof(struct ac_io_message, cmd.raw) + sizeof(*pin))) {
log_warning("Polling of node %d failed", node_id + 1);
return false;
}
if (pin != NULL) {
memcpy(pin, &msg.cmd.kfca_poll_in, sizeof(*pin));
}
return true;
}

33
src/main/aciodrv/kfca.h Normal file
View File

@@ -0,0 +1,33 @@
#ifndef ACIODRV_KFCA_H
#define ACIODRV_KFCA_H
#include "acio/kfca.h"
/**
* Initialize an KFCA node.
*
* @param node_id Id of the node to initialize (0 based).
* @return True if successful, false on error.
* @note This module is supposed to be used in combination with the common
* device driver foundation.
* @see driver.h
*/
bool aciodrv_kfca_init(uint8_t node_id);
/**
* Poll the KFCA io board
*
* @param node_id Id of the node to query (0 based).
* @param state Pointer to a state struct to return the current state to
* (optional, NULL for none).
* @return True on success, false on error.
* @note This module is supposed to be used in combination with the common
* device driver foundation.
* @see driver.h
*/
bool aciodrv_kfca_poll(
uint8_t node_id,
const struct ac_io_kfca_poll_out *pout,
struct ac_io_kfca_poll_in *pin);
#endif

View File

@@ -9,15 +9,21 @@
static HANDLE aciodrv_port_fd;
bool aciodrv_port_open(const char* port, int baud)
bool aciodrv_port_open(const char *port, int baud)
{
COMMTIMEOUTS ct;
DCB dcb;
log_info("Opening ACIO on %s at %d baud", port, baud);
aciodrv_port_fd = CreateFile(port, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH | FILE_ATTRIBUTE_NORMAL, NULL);
aciodrv_port_fd = CreateFile(
port,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_WRITE_THROUGH | FILE_ATTRIBUTE_NORMAL,
NULL);
if (aciodrv_port_fd == INVALID_HANDLE_VALUE) {
log_warning("Failed to open %s", port);
@@ -37,9 +43,9 @@ bool aciodrv_port_open(const char* port, int baud)
goto fail;
}
if (!PurgeComm(aciodrv_port_fd,
PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR)) {
if (!PurgeComm(
aciodrv_port_fd,
PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR)) {
log_warning("PurgeComm failed");
goto fail;
@@ -143,7 +149,7 @@ int aciodrv_port_write(const void *bytes, int nbytes)
log_warning("WriteFile failed: err = %lu", GetLastError());
return -1;
}
}
return nwrit;
}
@@ -154,4 +160,3 @@ void aciodrv_port_close(void)
CloseHandle(aciodrv_port_fd);
}
}

View File

@@ -1,8 +1,8 @@
#ifndef ACIODRV_PORT_H
#define ACIODRV_PORT_H
#include <stdint.h>
#include <stdbool.h>
#include <stdint.h>
/**
* Open a serial port for communication with a ACIO device.
@@ -12,7 +12,7 @@
* @return True if opening the com port was successful, false on error.
* @note This will open and setup the com port, only.
*/
bool aciodrv_port_open(const char* port, int baud);
bool aciodrv_port_open(const char *port, int baud);
/**
* Read data from the opened com port.

View File

@@ -8,9 +8,7 @@
#include "util/log.h"
void ac_io_emu_cmd_assign_addrs(
struct ac_io_emu *emu,
const struct ac_io_message *req,
uint8_t node_count)
struct ac_io_emu *emu, const struct ac_io_message *req, uint8_t node_count)
{
struct ac_io_message resp;
uint16_t cmd;
@@ -21,9 +19,7 @@ void ac_io_emu_cmd_assign_addrs(
cmd = ac_io_u16(req->cmd.code);
if (cmd != AC_IO_CMD_ASSIGN_ADDRS) {
log_warning(
"Address 0 expects address assignment cmd, got %04x",
cmd);
log_warning("Address 0 expects address assignment cmd, got %04x", cmd);
return;
}

View File

@@ -8,8 +8,6 @@
#include <stdint.h>
void ac_io_emu_cmd_assign_addrs(
struct ac_io_emu *emu,
const struct ac_io_message *req,
uint8_t node_count);
struct ac_io_emu *emu, const struct ac_io_message *req, uint8_t node_count);
#endif

View File

@@ -1,8 +1,11 @@
#include <windows.h> /* Usermode API */
#include <windows.h> /* Usermode API */
#include <ntdef.h> /* Kernel-mode API for ioctls */
// clang-format off
// Don't format because the order is important here
#include <ntdef.h>
#include <devioctl.h>
#include <ntddser.h>
// clang-format on
#include <stdbool.h>
#include <stdint.h>
@@ -61,18 +64,26 @@ bool ac_io_emu_match_irp(const struct ac_io_emu *emu, const struct irp *irp)
}
}
HRESULT ac_io_emu_dispatch_irp(struct ac_io_emu *emu, struct irp *irp)
HRESULT
ac_io_emu_dispatch_irp(struct ac_io_emu *emu, struct irp *irp)
{
log_assert(irp != NULL);
switch (irp->op) {
case IRP_OP_OPEN: return ac_io_emu_open(emu, irp);
case IRP_OP_CLOSE: return ac_io_emu_close(emu, irp);
case IRP_OP_READ: return ac_io_emu_read(emu, irp);
case IRP_OP_WRITE: return ac_io_emu_write(emu, irp);
case IRP_OP_IOCTL: return ac_io_emu_ioctl(emu, irp);
case IRP_OP_FSYNC: return S_FALSE;
default: return E_NOTIMPL;
case IRP_OP_OPEN:
return ac_io_emu_open(emu, irp);
case IRP_OP_CLOSE:
return ac_io_emu_close(emu, irp);
case IRP_OP_READ:
return ac_io_emu_read(emu, irp);
case IRP_OP_WRITE:
return ac_io_emu_write(emu, irp);
case IRP_OP_IOCTL:
return ac_io_emu_ioctl(emu, irp);
case IRP_OP_FSYNC:
return S_FALSE;
default:
return E_NOTIMPL;
}
}
@@ -129,29 +140,30 @@ static HRESULT ac_io_emu_ioctl(struct ac_io_emu *emu, struct irp *irp)
log_assert(irp != NULL);
switch (irp->ioctl) {
case IOCTL_SERIAL_GET_COMMSTATUS:
if (irp->read.bytes == NULL) {
log_warning("IOCTL_SERIAL_GET_COMMSTATUS: Output buffer is NULL");
case IOCTL_SERIAL_GET_COMMSTATUS:
if (irp->read.bytes == NULL) {
log_warning(
"IOCTL_SERIAL_GET_COMMSTATUS: Output buffer is NULL");
return E_INVALIDARG;
}
return E_INVALIDARG;
}
if (irp->read.nbytes < sizeof(*status)) {
log_warning("IOCTL_SERIAL_GET_COMMSTATUS: Buffer is too small");
if (irp->read.nbytes < sizeof(*status)) {
log_warning("IOCTL_SERIAL_GET_COMMSTATUS: Buffer is too small");
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
status = (SERIAL_STATUS *) irp->read.bytes;
status->Errors = 0;
status->AmountInInQueue = ac_io_in_is_msg_pending(&emu->in);
status = (SERIAL_STATUS *) irp->read.bytes;
status->Errors = 0;
status->AmountInInQueue = ac_io_in_is_msg_pending(&emu->in);
irp->read.pos = sizeof(*status);
irp->read.pos = sizeof(*status);
return S_FALSE;
return S_FALSE;
default:
return S_FALSE;
default:
return S_FALSE;
}
}
@@ -170,9 +182,7 @@ void ac_io_emu_request_pop(struct ac_io_emu *emu)
}
void ac_io_emu_response_push(
struct ac_io_emu *emu,
const struct ac_io_message *resp,
uint64_t delay_us)
struct ac_io_emu *emu, const struct ac_io_message *resp, uint64_t delay_us)
{
log_assert(emu != NULL);
log_assert(resp != NULL);
@@ -181,14 +191,10 @@ void ac_io_emu_response_push(
}
void ac_io_emu_response_push_thunk(
struct ac_io_emu *emu,
ac_io_in_thunk_t thunk,
void *ctx,
uint64_t delay_us)
struct ac_io_emu *emu, ac_io_in_thunk_t thunk, void *ctx, uint64_t delay_us)
{
log_assert(emu != NULL);
log_assert(thunk != NULL);
ac_io_in_supply_thunk(&emu->in, thunk, ctx, delay_us);
}

View File

@@ -27,13 +27,11 @@ HRESULT ac_io_emu_dispatch_irp(struct ac_io_emu *emu, struct irp *irp);
const struct ac_io_message *ac_io_emu_request_peek(const struct ac_io_emu *emu);
void ac_io_emu_request_pop(struct ac_io_emu *emu);
void ac_io_emu_response_push(
struct ac_io_emu *emu,
const struct ac_io_message *resp,
uint64_t delay_ms);
struct ac_io_emu *emu, const struct ac_io_message *resp, uint64_t delay_ms);
void ac_io_emu_response_push_thunk(
struct ac_io_emu *emu,
ac_io_in_thunk_t thunk,
void *ctx,
uint64_t delay_ms);
struct ac_io_emu *emu,
ac_io_in_thunk_t thunk,
void *ctx,
uint64_t delay_ms);
#endif

View File

@@ -16,18 +16,15 @@
#include "util/hex.h"
static void ac_io_emu_h44b_cmd_send_version(
struct ac_io_emu_h44b *h44b,
const struct ac_io_message *req);
struct ac_io_emu_h44b *h44b, const struct ac_io_message *req);
static void ac_io_emu_h44b_send_status(
struct ac_io_emu_h44b *h44b,
const struct ac_io_message *req,
uint8_t status);
struct ac_io_emu_h44b *h44b,
const struct ac_io_message *req,
uint8_t status);
void ac_io_emu_h44b_init(
struct ac_io_emu_h44b *h44b,
struct ac_io_emu *emu,
uint8_t unit_no)
struct ac_io_emu_h44b *h44b, struct ac_io_emu *emu, uint8_t unit_no)
{
memset(h44b, 0, sizeof(*h44b));
h44b->emu = emu;
@@ -35,8 +32,7 @@ void ac_io_emu_h44b_init(
}
void ac_io_emu_h44b_dispatch_request(
struct ac_io_emu_h44b *h44b,
const struct ac_io_message *req)
struct ac_io_emu_h44b *h44b, const struct ac_io_message *req)
{
uint16_t cmd_code;
@@ -58,7 +54,8 @@ void ac_io_emu_h44b_dispatch_request(
case AC_IO_H44B_CMD_SET_OUTPUTS:
/* Not using the struct ac_io_h44b_output here */
for (int i = 0; i < 6; i++) {
jb_io_set_rgb_led((enum jb_io_rgb_led) i,
jb_io_set_rgb_led(
(enum jb_io_rgb_led) i,
req->cmd.raw[i * 3],
req->cmd.raw[i * 3 + 1],
req->cmd.raw[i * 3 + 2]);
@@ -71,16 +68,17 @@ void ac_io_emu_h44b_dispatch_request(
break;
default:
log_warning("Unknown ACIO message %04x on h44b node, addr=%d",
cmd_code, req->addr);
log_warning(
"Unknown ACIO message %04x on h44b node, addr=%d",
cmd_code,
req->addr);
break;
}
}
static void ac_io_emu_h44b_cmd_send_version(
struct ac_io_emu_h44b *h44b,
const struct ac_io_message *req)
struct ac_io_emu_h44b *h44b, const struct ac_io_message *req)
{
struct ac_io_message resp;
@@ -93,8 +91,10 @@ static void ac_io_emu_h44b_cmd_send_version(
resp.cmd.version.major = 0x01;
resp.cmd.version.minor = 0x00;
resp.cmd.version.revision = 0x02;
memcpy(resp.cmd.version.product_code, "H44B",
sizeof(resp.cmd.version.product_code));
memcpy(
resp.cmd.version.product_code,
"H44B",
sizeof(resp.cmd.version.product_code));
strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date));
strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time));
@@ -102,9 +102,9 @@ static void ac_io_emu_h44b_cmd_send_version(
}
static void ac_io_emu_h44b_send_status(
struct ac_io_emu_h44b *h44b,
const struct ac_io_message *req,
uint8_t status)
struct ac_io_emu_h44b *h44b,
const struct ac_io_message *req,
uint8_t status)
{
struct ac_io_message resp;

View File

@@ -15,12 +15,9 @@ struct ac_io_emu_h44b {
void acioemu_h44b_init(void);
void ac_io_emu_h44b_init(
struct ac_io_emu_h44b *h44b,
struct ac_io_emu *emu,
uint8_t unit_no);
struct ac_io_emu_h44b *h44b, struct ac_io_emu *emu, uint8_t unit_no);
void ac_io_emu_h44b_dispatch_request(
struct ac_io_emu_h44b *h44b,
const struct ac_io_message *req);
struct ac_io_emu_h44b *h44b, const struct ac_io_message *req);
#endif

View File

@@ -8,21 +8,17 @@
#include "util/log.h"
static void ac_io_emu_hdxs_cmd_send_version(
struct ac_io_emu_hdxs *hdxs,
const struct ac_io_message *req);
struct ac_io_emu_hdxs *hdxs, const struct ac_io_message *req);
static void ac_io_emu_hdxs_send_empty(
struct ac_io_emu_hdxs *hdxs,
const struct ac_io_message *req);
struct ac_io_emu_hdxs *hdxs, const struct ac_io_message *req);
static void ac_io_emu_hdxs_send_status(
struct ac_io_emu_hdxs *hdxs,
const struct ac_io_message *req,
uint8_t status);
struct ac_io_emu_hdxs *hdxs,
const struct ac_io_message *req,
uint8_t status);
void ac_io_emu_hdxs_init(
struct ac_io_emu_hdxs *hdxs,
struct ac_io_emu *emu)
void ac_io_emu_hdxs_init(struct ac_io_emu_hdxs *hdxs, struct ac_io_emu *emu)
{
log_assert(hdxs != NULL);
log_assert(emu != NULL);
@@ -31,8 +27,7 @@ void ac_io_emu_hdxs_init(
}
void ac_io_emu_hdxs_dispatch_request(
struct ac_io_emu_hdxs *hdxs,
const struct ac_io_message *req)
struct ac_io_emu_hdxs *hdxs, const struct ac_io_message *req)
{
uint16_t cmd_code;
@@ -42,46 +37,45 @@ void ac_io_emu_hdxs_dispatch_request(
cmd_code = ac_io_u16(req->cmd.code);
switch (cmd_code) {
case AC_IO_CMD_GET_VERSION:
log_misc("AC_IO_CMD_GET_VERSION(%d)", req->addr);
ac_io_emu_hdxs_cmd_send_version(hdxs, req);
case AC_IO_CMD_GET_VERSION:
log_misc("AC_IO_CMD_GET_VERSION(%d)", req->addr);
ac_io_emu_hdxs_cmd_send_version(hdxs, req);
break;
break;
case AC_IO_CMD_START_UP:
log_misc("AC_IO_CMD_START_UP(%d)", req->addr);
ac_io_emu_hdxs_send_status(hdxs, req, 0x00);
case AC_IO_CMD_START_UP:
log_misc("AC_IO_CMD_START_UP(%d)", req->addr);
ac_io_emu_hdxs_send_status(hdxs, req, 0x00);
break;
break;
case AC_IO_CMD_CLEAR:
log_misc("AC_IO_CMD_CLEAR(%d)", req->addr);
case AC_IO_CMD_CLEAR:
log_misc("AC_IO_CMD_CLEAR(%d)", req->addr);
case 0x110:
case 0x112:
case 0x128:
ac_io_emu_hdxs_send_status(hdxs, req, 0x00);
case 0x110:
case 0x112:
case 0x128:
ac_io_emu_hdxs_send_status(hdxs, req, 0x00);
break;
break;
case AC_IO_CMD_KEEPALIVE:
ac_io_emu_hdxs_send_empty(hdxs, req);
case AC_IO_CMD_KEEPALIVE:
ac_io_emu_hdxs_send_empty(hdxs, req);
break;
break;
default:
log_warning(
default:
log_warning(
"Unknown ACIO message %04x on HDXS node, addr=%d",
cmd_code,
req->addr);
break;
break;
}
}
static void ac_io_emu_hdxs_cmd_send_version(
struct ac_io_emu_hdxs *hdxs,
const struct ac_io_message *req)
struct ac_io_emu_hdxs *hdxs, const struct ac_io_message *req)
{
struct ac_io_message resp;
@@ -94,8 +88,10 @@ static void ac_io_emu_hdxs_cmd_send_version(
resp.cmd.version.major = 0x01;
resp.cmd.version.minor = 0x06;
resp.cmd.version.revision = 0x00;
memcpy(resp.cmd.version.product_code, "HDXS",
sizeof(resp.cmd.version.product_code));
memcpy(
resp.cmd.version.product_code,
"HDXS",
sizeof(resp.cmd.version.product_code));
strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date));
strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time));
@@ -103,8 +99,7 @@ static void ac_io_emu_hdxs_cmd_send_version(
}
static void ac_io_emu_hdxs_send_empty(
struct ac_io_emu_hdxs *hdxs,
const struct ac_io_message *req)
struct ac_io_emu_hdxs *hdxs, const struct ac_io_message *req)
{
struct ac_io_message resp;
@@ -117,9 +112,9 @@ static void ac_io_emu_hdxs_send_empty(
}
static void ac_io_emu_hdxs_send_status(
struct ac_io_emu_hdxs *hdxs,
const struct ac_io_message *req,
uint8_t status)
struct ac_io_emu_hdxs *hdxs,
const struct ac_io_message *req,
uint8_t status)
{
struct ac_io_message resp;

View File

@@ -10,12 +10,9 @@ struct ac_io_emu_hdxs {
// TODO ops vtbl
};
void ac_io_emu_hdxs_init(
struct ac_io_emu_hdxs *hdxs,
struct ac_io_emu *emu);
void ac_io_emu_hdxs_init(struct ac_io_emu_hdxs *hdxs, struct ac_io_emu *emu);
void ac_io_emu_hdxs_dispatch_request(
struct ac_io_emu_hdxs *hdxs,
const struct ac_io_message *req);
struct ac_io_emu_hdxs *hdxs, const struct ac_io_message *req);
#endif

View File

@@ -23,39 +23,36 @@ enum ac_io_icca_subcmd {
};
enum ac_io_icca_flag {
AC_IO_ICCA_FLAG_FRONT_SENSOR = 0x10,
AC_IO_ICCA_FLAG_REAR_SENSOR = 0x20,
AC_IO_ICCA_FLAG_SOLENOID = 0x40
AC_IO_ICCA_FLAG_FRONT_SENSOR = 0x10,
AC_IO_ICCA_FLAG_REAR_SENSOR = 0x20,
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_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);
struct ac_io_emu_icca *icca, const struct ac_io_message *req);
static void ac_io_emu_icca_send_state(
struct ac_io_emu_icca *icca,
const struct ac_io_message *req,
uint64_t delay_us);
struct ac_io_emu_icca *icca,
const struct ac_io_message *req,
uint64_t delay_us);
static void ac_io_emu_icca_send_empty(
struct ac_io_emu_icca *icca,
const struct ac_io_message *req);
struct ac_io_emu_icca *icca, const struct ac_io_message *req);
static void ac_io_emu_icca_send_status(
struct ac_io_emu_icca *icca,
const struct ac_io_message *req,
uint8_t status);
struct ac_io_emu_icca *icca,
const struct ac_io_message *req,
uint8_t status);
void ac_io_emu_icca_init(
struct ac_io_emu_icca *icca,
struct ac_io_emu *emu,
uint8_t unit_no)
struct ac_io_emu_icca *icca, struct ac_io_emu *emu, uint8_t unit_no)
{
memset(icca, 0, sizeof(*icca));
icca->emu = emu;
@@ -65,8 +62,7 @@ void ac_io_emu_icca_init(
}
void ac_io_emu_icca_dispatch_request(
struct ac_io_emu_icca *icca,
const struct ac_io_message *req)
struct ac_io_emu_icca *icca, const struct ac_io_message *req)
{
uint16_t cmd_code;
uint64_t delay_us;
@@ -131,10 +127,9 @@ void ac_io_emu_icca_dispatch_request(
break;
case AC_IO_ICCA_CMD_SET_SLOT_STATE:
{
struct ac_io_icca_misc* misc =
(struct ac_io_icca_misc*) &req->cmd.raw;
case AC_IO_ICCA_CMD_SET_SLOT_STATE: {
struct ac_io_icca_misc *misc =
(struct ac_io_icca_misc *) &req->cmd.raw;
uint8_t cmd;
switch (misc->subcmd) {
@@ -157,15 +152,19 @@ void ac_io_emu_icca_dispatch_request(
default:
cmd = 0xFF;
log_warning("Unhandled slot command %X, node %d",
misc->subcmd, icca->unit_no);
log_warning(
"Unhandled slot command %X, node %d",
misc->subcmd,
icca->unit_no);
break;
}
if (cmd != 0xFF) {
if (!eam_io_card_slot_cmd(icca->unit_no, cmd)) {
log_warning("Eamio failed to handle slot cmd %d for node %d",
cmd, icca->unit_no);
log_warning(
"Eamio failed to handle slot cmd %d for node %d",
cmd,
icca->unit_no);
}
}
@@ -176,9 +175,11 @@ void ac_io_emu_icca_dispatch_request(
}
case AC_IO_ICCA_CMD_POLL:
delay_us = time_get_elapsed_us(time_get_counter() - icca->time_counter_last_poll);
delay_us = time_get_elapsed_us(
time_get_counter() - icca->time_counter_last_poll);
/* emulating delay implemented by hardware. do not delay messages that exceed a certain threshold. */
/* emulating delay implemented by hardware. do not delay messages
* that exceed a certain threshold. */
if (delay_us > 16000) {
delay_us = 0;
}
@@ -195,16 +196,17 @@ void ac_io_emu_icca_dispatch_request(
break;
default:
log_warning("Unknown ACIO message %04x on ICCA node, addr=%d",
cmd_code, req->addr);
log_warning(
"Unknown ACIO message %04x on ICCA node, addr=%d",
cmd_code,
req->addr);
break;
}
}
static void ac_io_emu_icca_cmd_send_version(
struct ac_io_emu_icca *icca,
const struct ac_io_message *req)
struct ac_io_emu_icca *icca, const struct ac_io_message *req)
{
struct ac_io_message resp;
@@ -217,8 +219,10 @@ static void ac_io_emu_icca_cmd_send_version(
resp.cmd.version.major = 0x01;
resp.cmd.version.minor = 0x06;
resp.cmd.version.revision = 0x00;
memcpy(resp.cmd.version.product_code, "ICCA",
sizeof(resp.cmd.version.product_code));
memcpy(
resp.cmd.version.product_code,
"ICCA",
sizeof(resp.cmd.version.product_code));
strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date));
strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time));
@@ -226,8 +230,7 @@ static void ac_io_emu_icca_cmd_send_version(
}
static void ac_io_emu_icca_send_empty(
struct ac_io_emu_icca *icca,
const struct ac_io_message *req)
struct ac_io_emu_icca *icca, const struct ac_io_message *req)
{
struct ac_io_message resp;
@@ -240,9 +243,9 @@ static void ac_io_emu_icca_send_empty(
}
static void ac_io_emu_icca_send_status(
struct ac_io_emu_icca *icca,
const struct ac_io_message *req,
uint8_t status)
struct ac_io_emu_icca *icca,
const struct ac_io_message *req,
uint8_t status)
{
struct ac_io_message resp;
@@ -256,9 +259,9 @@ static void ac_io_emu_icca_send_status(
}
static void ac_io_emu_icca_send_state(
struct ac_io_emu_icca *icca,
const struct ac_io_message *req,
uint64_t delay_us)
struct ac_io_emu_icca *icca,
const struct ac_io_message *req,
uint64_t delay_us)
{
struct ac_io_message resp;
struct ac_io_icca_state *body;
@@ -277,25 +280,22 @@ static void ac_io_emu_icca_send_state(
keypad = eam_io_get_keypad_state(icca->unit_no);
sensor_state = eam_io_get_sensor_state(icca->unit_no);
keypad_rise = keypad & (icca->last_keypad ^ keypad);
card_full_insert = sensor_state & (1 << EAM_IO_SENSOR_FRONT) &&
sensor_state & (1 << EAM_IO_SENSOR_BACK);
if (sensor_state != icca->last_sensor) {
if (card_full_insert) {
if (!eam_io_card_slot_cmd(icca->unit_no,
EAM_IO_CARD_SLOT_CMD_READ)) {
log_warning("EAM_IO_CARD_SLOT_CMD_READ to unit %d failed",
if (!eam_io_card_slot_cmd(
icca->unit_no, EAM_IO_CARD_SLOT_CMD_READ)) {
log_warning(
"EAM_IO_CARD_SLOT_CMD_READ to unit %d failed",
icca->unit_no);
}
icca->card_result = eam_io_read_card(
icca->unit_no,
icca->uid,
sizeof(icca->uid));
icca->card_result =
eam_io_read_card(icca->unit_no, icca->uid, sizeof(icca->uid));
// fault if sensor says to read but we got no card
icca->fault = (icca->card_result == EAM_IO_CARD_NONE);
@@ -319,7 +319,11 @@ static void ac_io_emu_icca_send_state(
} else if (card_full_insert) {
body->status_code = AC_IO_ICCA_STATUS_GOT_UID;
} else {
body->status_code = AC_IO_ICCA_STATUS_IDLE;
if (icca->detected_new_reader) {
body->status_code = AC_IO_ICCA_STATUS_IDLE_NEW;
} else {
body->status_code = AC_IO_ICCA_STATUS_IDLE;
}
}
body->sensor_state = 0;
@@ -338,8 +342,8 @@ static void ac_io_emu_icca_send_state(
memcpy(body->uid, icca->uid, sizeof(body->uid));
body->card_type = 0;
if (body->status_code == AC_IO_ICCA_STATUS_GOT_UID){
if (icca->detected_new_reader){
if (body->status_code == AC_IO_ICCA_STATUS_GOT_UID) {
if (icca->detected_new_reader) {
// sensor_state actually refers to cardtype for wavepass readers
// EAM_IO_CARD_ISO15696 = 1 -> 0
// EAM_IO_CARD_FELICA = 2 -> 1
@@ -349,7 +353,6 @@ static void ac_io_emu_icca_send_state(
}
if (keypad_rise) {
if (icca->key_events[0]) {
event = (icca->key_events[0] + 0x10) & 0xF0;
} else {
@@ -365,7 +368,8 @@ static void ac_io_emu_icca_send_state(
// this doesn't seem to be an error code. If this is not set to 0x03
// on slotted readers (only?), the game throws an unknown status error
if (icca->keypad_started) {
// and on SDVX4 it hangs on the thank you screen
if (icca->keypad_started || icca->detected_new_reader) {
body->keypad_started = 0x03;
} else {
body->keypad_started = 0x00;
@@ -382,4 +386,3 @@ static void ac_io_emu_icca_send_state(
ac_io_emu_response_push(icca->emu, &resp, delay_us);
}

View File

@@ -23,12 +23,9 @@ struct ac_io_emu_icca {
};
void ac_io_emu_icca_init(
struct ac_io_emu_icca *icca,
struct ac_io_emu *emu,
uint8_t unit_no);
struct ac_io_emu_icca *icca, struct ac_io_emu *emu, uint8_t unit_no);
void ac_io_emu_icca_dispatch_request(
struct ac_io_emu_icca *icca,
const struct ac_io_message *req);
struct ac_io_emu_icca *icca, const struct ac_io_message *req);
#endif

View File

@@ -14,26 +14,21 @@
#include "bemanitools/eamio.h"
static void ac_io_emu_iccb_cmd_send_version(
struct ac_io_emu_iccb *iccb,
const struct ac_io_message *req);
struct ac_io_emu_iccb *iccb, const struct ac_io_message *req);
static void ac_io_emu_iccb_send_state(
struct ac_io_emu_iccb *iccb,
const struct ac_io_message *req);
struct ac_io_emu_iccb *iccb, const struct ac_io_message *req);
static void ac_io_emu_iccb_send_empty(
struct ac_io_emu_iccb *iccb,
const struct ac_io_message *req);
struct ac_io_emu_iccb *iccb, const struct ac_io_message *req);
static void ac_io_emu_iccb_send_status(
struct ac_io_emu_iccb *iccb,
const struct ac_io_message *req,
uint8_t status);
struct ac_io_emu_iccb *iccb,
const struct ac_io_message *req,
uint8_t status);
void ac_io_emu_iccb_init(
struct ac_io_emu_iccb *iccb,
struct ac_io_emu *emu,
uint8_t unit_no)
struct ac_io_emu_iccb *iccb, struct ac_io_emu *emu, uint8_t unit_no)
{
memset(iccb, 0, sizeof(*iccb));
iccb->emu = emu;
@@ -41,8 +36,7 @@ void ac_io_emu_iccb_init(
}
void ac_io_emu_iccb_dispatch_request(
struct ac_io_emu_iccb *iccb,
const struct ac_io_message *req)
struct ac_io_emu_iccb *iccb, const struct ac_io_message *req)
{
uint16_t cmd_code;
@@ -104,16 +98,17 @@ void ac_io_emu_iccb_dispatch_request(
break;
default:
log_warning("Unknown ACIO message %04x on ICCB node, addr=%d",
cmd_code, req->addr);
log_warning(
"Unknown ACIO message %04x on ICCB node, addr=%d",
cmd_code,
req->addr);
break;
}
}
static void ac_io_emu_iccb_cmd_send_version(
struct ac_io_emu_iccb *iccb,
const struct ac_io_message *req)
struct ac_io_emu_iccb *iccb, const struct ac_io_message *req)
{
struct ac_io_message resp;
@@ -126,8 +121,10 @@ static void ac_io_emu_iccb_cmd_send_version(
resp.cmd.version.major = 0x01;
resp.cmd.version.minor = 0x05;
resp.cmd.version.revision = 0x01;
memcpy(resp.cmd.version.product_code, "ICCB",
sizeof(resp.cmd.version.product_code));
memcpy(
resp.cmd.version.product_code,
"ICCB",
sizeof(resp.cmd.version.product_code));
strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date));
strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time));
@@ -135,8 +132,7 @@ static void ac_io_emu_iccb_cmd_send_version(
}
static void ac_io_emu_iccb_send_empty(
struct ac_io_emu_iccb *iccb,
const struct ac_io_message *req)
struct ac_io_emu_iccb *iccb, const struct ac_io_message *req)
{
struct ac_io_message resp;
@@ -149,9 +145,9 @@ static void ac_io_emu_iccb_send_empty(
}
static void ac_io_emu_iccb_send_status(
struct ac_io_emu_iccb *iccb,
const struct ac_io_message *req,
uint8_t status)
struct ac_io_emu_iccb *iccb,
const struct ac_io_message *req,
uint8_t status)
{
struct ac_io_message resp;
@@ -165,8 +161,7 @@ static void ac_io_emu_iccb_send_status(
}
static void ac_io_emu_iccb_send_state(
struct ac_io_emu_iccb *iccb,
const struct ac_io_message *req)
struct ac_io_emu_iccb *iccb, const struct ac_io_message *req)
{
struct ac_io_message resp;
struct ac_io_iccb_state *body;
@@ -178,10 +173,8 @@ static void ac_io_emu_iccb_send_state(
if (sensor != iccb->last_sensor) {
if (sensor) {
iccb->card_result = eam_io_read_card(
iccb->unit_no,
iccb->uid,
sizeof(iccb->uid));
iccb->card_result =
eam_io_read_card(iccb->unit_no, iccb->uid, sizeof(iccb->uid));
// fault if sensor says to read but we got no card
iccb->fault = (iccb->card_result == EAM_IO_CARD_NONE);
@@ -224,4 +217,3 @@ static void ac_io_emu_iccb_send_state(
ac_io_emu_response_push(iccb->emu, &resp, 0);
}

View File

@@ -16,12 +16,9 @@ struct ac_io_emu_iccb {
};
void ac_io_emu_iccb_init(
struct ac_io_emu_iccb *iccb,
struct ac_io_emu *emu,
uint8_t unit_no);
struct ac_io_emu_iccb *iccb, struct ac_io_emu *emu, uint8_t unit_no);
void ac_io_emu_iccb_dispatch_request(
struct ac_io_emu_iccb *iccb,
const struct ac_io_message *req);
struct ac_io_emu_iccb *iccb, const struct ac_io_message *req);
#endif

View File

@@ -13,11 +13,10 @@
#include "util/mem.h"
#include "util/time.h"
static struct ac_io_in_queued *ac_io_in_queued_alloc(struct ac_io_in *in,
uint64_t delay_us);
static struct ac_io_in_queued *
ac_io_in_queued_alloc(struct ac_io_in *in, uint64_t delay_us);
static void ac_io_in_queued_populate(
struct ac_io_in_queued *iq,
const struct ac_io_message *msg);
struct ac_io_in_queued *iq, const struct ac_io_message *msg);
static void ac_io_in_queued_putc(struct ac_io_in_queued *iq, uint8_t b);
static bool ac_io_out_supply_byte(struct ac_io_out *out, uint8_t b);
@@ -30,8 +29,8 @@ static bool ac_io_out_reject_message(struct ac_io_out *out);
static bool ac_io_enable_legacy_mode = false;
static struct ac_io_in_queued *ac_io_in_queued_alloc(struct ac_io_in *in,
uint64_t delay_us)
static struct ac_io_in_queued *
ac_io_in_queued_alloc(struct ac_io_in *in, uint64_t delay_us)
{
struct ac_io_in_queued *iq;
@@ -51,8 +50,7 @@ static struct ac_io_in_queued *ac_io_in_queued_alloc(struct ac_io_in *in,
}
static void ac_io_in_queued_populate(
struct ac_io_in_queued *iq,
const struct ac_io_message *msg)
struct ac_io_in_queued *iq, const struct ac_io_message *msg)
{
uint8_t checksum;
const uint8_t *src;
@@ -68,7 +66,7 @@ static void ac_io_in_queued_populate(
src = (const uint8_t *) msg;
checksum = 0;
for (i = 0 ; i < nbytes ; i++) {
for (i = 0; i < nbytes; i++) {
ac_io_in_queued_putc(iq, src[i]);
checksum += src[i];
}
@@ -97,8 +95,8 @@ void ac_io_in_init(struct ac_io_in *in)
list_init(&in->queue);
}
void ac_io_in_supply(struct ac_io_in *in, const struct ac_io_message *msg,
uint64_t delay_us)
void ac_io_in_supply(
struct ac_io_in *in, const struct ac_io_message *msg, uint64_t delay_us)
{
struct ac_io_in_queued *dest;
@@ -113,10 +111,7 @@ void ac_io_in_supply(struct ac_io_in *in, const struct ac_io_message *msg,
}
void ac_io_in_supply_thunk(
struct ac_io_in *in,
ac_io_in_thunk_t thunk,
void *ctx,
uint64_t delay_us)
struct ac_io_in *in, ac_io_in_thunk_t thunk, void *ctx, uint64_t delay_us)
{
struct ac_io_in_queued *dest;
@@ -177,7 +172,7 @@ void ac_io_in_drain(struct ac_io_in *in, struct iobuf *dest)
if (ac_io_enable_legacy_mode) {
break;
}
} while (nmoved > 0);
} while (nmoved > 0);
}
bool ac_io_in_is_msg_pending(const struct ac_io_in *in)
@@ -209,7 +204,6 @@ static bool ac_io_out_supply_byte(struct ac_io_out *out, uint8_t b)
if (out->in_frame) {
return ac_io_out_supply_frame_byte(out, b);
} else {
if (b == AC_IO_SOF) {
out->in_frame = true;
} else if (b == AC_IO_ESCAPE) {
@@ -235,7 +229,6 @@ static bool ac_io_out_supply_frame_byte(struct ac_io_out *out, uint8_t b)
return true;
} else if (b == AC_IO_SOF) {
if (out->pos == 0) {
/* Got autobaud/empty message */
out->have_message = true;
@@ -247,7 +240,6 @@ static bool ac_io_out_supply_frame_byte(struct ac_io_out *out, uint8_t b)
return true;
}
}
/* Payload byte */
@@ -257,13 +249,11 @@ static bool ac_io_out_supply_frame_byte(struct ac_io_out *out, uint8_t b)
/* Handle contextually-implied end-of-packet events */
if (out->pos > offsetof(struct ac_io_message, addr)) {
if (out->msg.addr == AC_IO_BROADCAST) {
return ac_io_out_detect_broadcast_eof(out);
} else {
return ac_io_out_detect_command_eof(out);
}
}
return true;
@@ -274,9 +264,8 @@ static bool ac_io_out_detect_broadcast_eof(struct ac_io_out *out)
size_t end;
if (out->pos > offsetof(struct ac_io_message, bcast.nbytes)) {
end = offsetof(struct ac_io_message,bcast.raw)
+ out->msg.bcast.nbytes
+ 1;
end = offsetof(struct ac_io_message, bcast.raw) +
out->msg.bcast.nbytes + 1;
if (out->pos == end) {
return ac_io_out_check_sum(out);
@@ -291,9 +280,7 @@ static bool ac_io_out_detect_command_eof(struct ac_io_out *out)
size_t end;
if (out->pos > offsetof(struct ac_io_message, cmd.nbytes)) {
end = offsetof(struct ac_io_message, cmd.raw)
+ out->msg.cmd.nbytes
+ 1;
end = offsetof(struct ac_io_message, cmd.raw) + out->msg.cmd.nbytes + 1;
if (out->pos == end) {
return ac_io_out_check_sum(out);
@@ -310,15 +297,17 @@ static bool ac_io_out_check_sum(struct ac_io_out *out)
checksum = 0;
for (i = 0 ; i < out->pos - 1 ; i++) {
for (i = 0; i < out->pos - 1; i++) {
checksum += out->bytes[i];
}
if (checksum == out->bytes[out->pos - 1]) {
return ac_io_out_accept_message(out);
} else {
log_warning("Checksum bad: expected %02x got %02x",
checksum, out->bytes[out->pos - 1]);
log_warning(
"Checksum bad: expected %02x got %02x",
checksum,
out->bytes[out->pos - 1]);
return ac_io_out_reject_message(out);
}
@@ -363,4 +352,3 @@ void ac_io_out_consume_message(struct ac_io_out *out)
out->have_message = false;
out->escape = false;
}

View File

@@ -47,13 +47,10 @@ struct ac_io_out {
void ac_io_legacy_mode(void);
void ac_io_in_init(struct ac_io_in *in);
void ac_io_in_supply(struct ac_io_in *in, const struct ac_io_message *msg,
uint64_t delay);
void ac_io_in_supply(
struct ac_io_in *in, const struct ac_io_message *msg, uint64_t delay);
void ac_io_in_supply_thunk(
struct ac_io_in *in,
ac_io_in_thunk_t thunk,
void *ctx,
uint64_t delay);
struct ac_io_in *in, ac_io_in_thunk_t thunk, void *ctx, uint64_t delay);
void ac_io_in_drain(struct ac_io_in *in, struct iobuf *dest);
bool ac_io_in_is_msg_pending(const struct ac_io_in *in);

View File

@@ -6,4 +6,5 @@ libs_aciotest := \
src_aciotest := \
icca.c \
kfca.c \
main.c \

View File

@@ -6,11 +6,10 @@ static const uint8_t aciotest_handler_max = 16;
/**
* Handler interface for an ACIO device.
*/
struct aciotest_handler_node_handler
{
void* ctx;
bool (*init)(uint8_t node_id, void** ctx);
bool (*update)(uint8_t node_id, void* ctx);
struct aciotest_handler_node_handler {
void *ctx;
bool (*init)(uint8_t node_id, void **ctx);
bool (*update)(uint8_t node_id, void *ctx);
};
#endif

View File

@@ -1,28 +1,28 @@
#include "aciotest/icca.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include "aciodrv/icca.h"
bool aciotest_icca_handler_init(uint8_t node_id, void** ctx)
bool aciotest_icca_handler_init(uint8_t node_id, void **ctx)
{
*ctx = malloc(sizeof(uint32_t));
*((uint32_t*) *ctx) = 0;
*((uint32_t *) *ctx) = 0;
return aciodrv_icca_init(node_id);
}
bool aciotest_icca_handler_update(uint8_t node_id, void* ctx)
bool aciotest_icca_handler_update(uint8_t node_id, void *ctx)
{
if (*((uint32_t*) ctx) == 0) {
*((uint32_t*) ctx) = 1;
if (*((uint32_t *) ctx) == 0) {
*((uint32_t *) ctx) = 1;
/* eject cards that were left in the reader */
if (!aciodrv_icca_set_state(node_id, AC_IO_ICCA_SLOT_STATE_EJECT, NULL)) {
if (!aciodrv_icca_set_state(
node_id, AC_IO_ICCA_SLOT_STATE_EJECT, NULL)) {
return false;
}
}
struct ac_io_icca_state state;
@@ -31,7 +31,8 @@ bool aciotest_icca_handler_update(uint8_t node_id, void* ctx)
return false;
}
printf(">>> ICCA %d:\n"
printf(
">>> ICCA %d:\n"
"status_code: %d\n"
"sensor_state: %d\n"
"keypad_started: %d\n"
@@ -40,43 +41,51 @@ bool aciotest_icca_handler_update(uint8_t node_id, void* ctx)
"key_state: %04X\n"
"key_events[0]: %02X\n"
"key_events[1]: %02X\n",
node_id, state.status_code, state.sensor_state, state.keypad_started,
state.card_type,
state.uid[0], state.uid[1], state.uid[2], state.uid[3],
state.uid[4], state.uid[5], state.uid[6], state.uid[7],
state.key_state, state.key_events[0], state.key_events[1]);
node_id,
state.status_code,
state.sensor_state,
state.keypad_started,
state.card_type,
state.uid[0],
state.uid[1],
state.uid[2],
state.uid[3],
state.uid[4],
state.uid[5],
state.uid[6],
state.uid[7],
state.key_state,
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)) {
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)) {
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)) {
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 (!aciodrv_icca_read_card(node_id, NULL)) {
return false;
}
}
return true;

View File

@@ -1,10 +1,10 @@
#ifndef ACIOTEST_ICCA_H
#define ACIOTEST_ICCA_H
#include <stdint.h>
#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);
bool aciotest_icca_handler_init(uint8_t node_id, void **ctx);
bool aciotest_icca_handler_update(uint8_t node_id, void *ctx);
#endif

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

@@ -0,0 +1,76 @@
#include "aciotest/kfca.h"
#include "acio/acio.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "aciodrv/kfca.h"
bool aciotest_kfca_handler_init(uint8_t node_id, void **ctx)
{
*ctx = malloc(sizeof(uint32_t));
*((uint32_t *) *ctx) = 0;
return aciodrv_kfca_init(node_id);
}
bool aciotest_kfca_handler_update(uint8_t node_id, void *ctx)
{
struct ac_io_kfca_poll_in pin;
struct ac_io_kfca_poll_out pout;
static int gpio_test_pin = 0;
static int gpio_test_counter = 0;
memset(&pout, 0, sizeof(pout));
pout.gpio |= 1 << gpio_test_pin;
pout.gpio = ac_io_u32(pout.gpio);
if (!aciodrv_kfca_poll(node_id, &pout, &pin)) {
return false;
}
pin.adc[0] = ac_io_u16(pin.adc[0]);
pin.adc[1] = ac_io_u16(pin.adc[1]);
pin.gpio[0] = ac_io_u16(pin.gpio[0]);
pin.gpio[1] = ac_io_u16(pin.gpio[1]);
printf(
">>> KFCA %d: GPIO ON %d\n"
"BTN A B C D: %d %d %d %d\n"
"FX-L R: %d %d\n"
"VOL L: %d\n"
"VOL R: %d\n"
"START COIN TEST SERV REC HP: %d %d %d %d %d %d\n",
node_id,
gpio_test_pin,
pin.gpio[0] & AC_IO_KFCA_IN_GPIO_0_A,
pin.gpio[0] & AC_IO_KFCA_IN_GPIO_0_B,
pin.gpio[0] & AC_IO_KFCA_IN_GPIO_0_C,
pin.gpio[1] & AC_IO_KFCA_IN_GPIO_1_D,
pin.gpio[1] & AC_IO_KFCA_IN_GPIO_1_FX_L,
pin.gpio[1] & AC_IO_KFCA_IN_GPIO_1_FX_R,
(pin.adc[0] >> 6) & 0x3FF,
(pin.adc[1] >> 6) & 0x3FF,
pin.gpio[0] & AC_IO_KFCA_IN_GPIO_0_START,
(pin.gpio_sys) & AC_IO_KFCA_IN_GPIO_SYS_COIN,
(pin.gpio_sys) & AC_IO_KFCA_IN_GPIO_SYS_TEST,
(pin.gpio_sys) & AC_IO_KFCA_IN_GPIO_SYS_SERVICE,
pin.gpio[0] & AC_IO_KFCA_IN_GPIO_0_RECORDER,
pin.gpio[0] & AC_IO_KFCA_IN_GPIO_0_HEADPHONE);
++gpio_test_counter;
if (gpio_test_counter >= 4) {
gpio_test_counter = 0;
++gpio_test_pin;
if (gpio_test_pin >= 16) {
gpio_test_pin = 0;
}
}
return true;
}

10
src/main/aciotest/kfca.h Normal file
View File

@@ -0,0 +1,10 @@
#ifndef ACIOTEST_KFCA_H
#define ACIOTEST_KFCA_H
#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);
#endif

View File

@@ -1,6 +1,6 @@
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <windows.h>
@@ -8,6 +8,7 @@
#include "aciotest/handler.h"
#include "aciotest/icca.h"
#include "aciotest/kfca.h"
#include "util/log.h"
@@ -16,33 +17,41 @@ static uint8_t aciotest_cnt = 0;
/**
* Enumerate supported ACIO nodes based on their product id.
*/
static bool aciotest_assign_handler(char product[4],
struct aciotest_handler_node_handler* handler)
static bool aciotest_assign_handler(
char product[4], struct aciotest_handler_node_handler *handler)
{
if (!memcmp(product, "ICCA", 4)
|| !memcmp(product, "ICCB", 4)
|| !memcmp(product, "ICCC", 4)
){
if (!memcmp(product, "ICCA", 4) || !memcmp(product, "ICCB", 4) ||
!memcmp(product, "ICCC", 4)) {
handler->init = aciotest_icca_handler_init;
handler->update = aciotest_icca_handler_update;
return true;
}
if (!memcmp(product, "KFCA", 4)) {
handler->init = aciotest_kfca_handler_init;
handler->update = aciotest_kfca_handler_update;
return true;
}
return false;
}
/**
* Tool to test real ACIO hardware.
*/
int main(int argc, char** argv)
int main(int argc, char **argv)
{
if (argc < 3) {
printf(
"aciotest, build "__DATE__ " " __TIME__ "\n"
"aciotest, build "__DATE__
" " __TIME__
"\n"
"Usage: %s <com port str> <baud rate>\n"
"Example for two slotted readers: %s COM1 57600\n",
argv[0], argv[0]);
argv[0],
argv[0]);
return -1;
}
@@ -59,33 +68,40 @@ int main(int argc, char** argv)
printf("Enumerated %d nodes\n", node_count);
struct aciotest_handler_node_handler handler[aciotest_handler_max];
memset(&handler, 0,
memset(
&handler,
0,
sizeof(struct aciotest_handler_node_handler) * aciotest_handler_max);
for (uint8_t i = 0; i < node_count; i++) {
char product[4];
aciodrv_device_get_node_product_ident(i, product);
printf("> %d: %c%c%c%c\n", i + 1,
product[0], product[1], product[2], product[3]);
printf(
"> %d: %c%c%c%c\n",
i + 1,
product[0],
product[1],
product[2],
product[3]);
if (!aciotest_assign_handler(product, &handler[i])) {
printf("ERROR: Unsupported acio node product %c%c%c%c on node %d\n",
product[0], product[1], product[2], product[3], i);
printf(
"ERROR: Unsupported acio node product %c%c%c%c on node %d\n",
product[0],
product[1],
product[2],
product[3],
i);
}
}
for (uint8_t i = 0; i < aciotest_handler_max; i++) {
if (handler[i].init != NULL) {
if (!handler[i].init(i, &handler[i].ctx)) {
printf("ERROR: Initializing node %d failed\n", i);
handler[i].update = NULL;
}
}
}
printf(">>> Initializing done, press enter to start update loop <<<\n");
@@ -99,17 +115,13 @@ int main(int argc, char** argv)
printf("%d\n", aciotest_cnt++);
for (uint8_t i = 0; i < aciotest_handler_max; i++) {
if (handler[i].update != NULL) {
if (!handler[i].update(i, handler[i].ctx)) {
printf("ERROR: Updating node %d, removed from loop\n", i);
handler[i].update = NULL;
Sleep(5000);
}
}
}
/* avoid cpu banging */

View File

@@ -18,8 +18,11 @@ enum bst_io_in_gpio_sys_bit {
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 bst_io_set_loggers(log_formatter_t misc, log_formatter_t info,
log_formatter_t warning, log_formatter_t fatal);
void bst_io_set_loggers(
log_formatter_t misc,
log_formatter_t info,
log_formatter_t warning,
log_formatter_t fatal);
/* Initialize your BST IO emulation DLL. Thread management functions are
provided to you; you must use these functions to create your own threads if
@@ -29,8 +32,10 @@ void bst_io_set_loggers(log_formatter_t misc, log_formatter_t info,
See glue.h and geninput.h for further details. */
bool bst_io_init(thread_create_t thread_create, thread_join_t thread_join,
thread_destroy_t thread_destroy);
bool bst_io_init(
thread_create_t thread_create,
thread_join_t thread_join,
thread_destroy_t thread_destroy);
/* Shut down your SDVX IO emulation DLL */

View File

@@ -62,8 +62,11 @@ enum extio_light_bit {
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 ddr_io_set_loggers(log_formatter_t misc, log_formatter_t info,
log_formatter_t warning, log_formatter_t fatal);
void ddr_io_set_loggers(
log_formatter_t misc,
log_formatter_t info,
log_formatter_t warning,
log_formatter_t fatal);
/* Initialize your DDR IO emulation DLL. Thread management functions are
provided to you; you must use these functions to create your own threads if
@@ -73,8 +76,10 @@ void ddr_io_set_loggers(log_formatter_t misc, log_formatter_t info,
See glue.h and geninput.h for further details. */
bool ddr_io_init(thread_create_t thread_create, thread_join_t thread_join,
thread_destroy_t thread_destroy);
bool ddr_io_init(
thread_create_t thread_create,
thread_join_t thread_join,
thread_destroy_t thread_destroy);
uint32_t ddr_io_read_pad(void);
void ddr_io_set_lights_extio(uint32_t extio_lights);

View File

@@ -15,20 +15,20 @@
return from eam_io_get_keypad_state(). */
enum eam_io_keypad_scan_code {
EAM_IO_KEYPAD_0 = 0,
EAM_IO_KEYPAD_1 = 1,
EAM_IO_KEYPAD_4 = 2,
EAM_IO_KEYPAD_7 = 3,
EAM_IO_KEYPAD_00 = 4,
EAM_IO_KEYPAD_2 = 5,
EAM_IO_KEYPAD_5 = 6,
EAM_IO_KEYPAD_8 = 7,
EAM_IO_KEYPAD_DECIMAL = 8,
EAM_IO_KEYPAD_3 = 9,
EAM_IO_KEYPAD_6 = 10,
EAM_IO_KEYPAD_9 = 11,
EAM_IO_KEYPAD_0 = 0,
EAM_IO_KEYPAD_1 = 1,
EAM_IO_KEYPAD_4 = 2,
EAM_IO_KEYPAD_7 = 3,
EAM_IO_KEYPAD_00 = 4,
EAM_IO_KEYPAD_2 = 5,
EAM_IO_KEYPAD_5 = 6,
EAM_IO_KEYPAD_8 = 7,
EAM_IO_KEYPAD_DECIMAL = 8,
EAM_IO_KEYPAD_3 = 9,
EAM_IO_KEYPAD_6 = 10,
EAM_IO_KEYPAD_9 = 11,
EAM_IO_KEYPAD_COUNT = 12, /* Not an actual scan code */
EAM_IO_KEYPAD_COUNT = 12, /* Not an actual scan code */
};
/* Emulating the sensors of a slotted card reader. The reader has one
@@ -70,8 +70,11 @@ struct eam_io_config_api;
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 eam_io_set_loggers(log_formatter_t misc, log_formatter_t info,
log_formatter_t warning, log_formatter_t fatal);
void eam_io_set_loggers(
log_formatter_t misc,
log_formatter_t info,
log_formatter_t warning,
log_formatter_t fatal);
/* Initialize your card reader emulation DLL. Thread management functions are
provided to you; you must use these functions to create your own threads if
@@ -81,8 +84,10 @@ void eam_io_set_loggers(log_formatter_t misc, log_formatter_t info,
See glue.h and geninput.h for further details. */
bool eam_io_init(thread_create_t thread_create, thread_join_t thread_join,
thread_destroy_t thread_destroy);
bool eam_io_init(
thread_create_t thread_create,
thread_join_t thread_join,
thread_destroy_t thread_destroy);
/* Shut down your card reader emulation DLL. */

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