Compare commits

..

40 Commits
5.35 ... 5.38

Author SHA1 Message Date
icex2
50ff026b85 Update changelog and docs for 5.38 release 2022-04-02 10:51:43 +02:00
Will Xyen
0ff6134b79 sdvxhook: address comments 2022-03-15 16:50:03 -07:00
Will Xyen
ae35b859d9 sdvxio-kfca: add volume overrides 2022-03-15 00:39:10 -07:00
Will Xyen
3cf3d44945 sdvxhook2: add nvapi and power hooks 2022-03-15 00:38:46 -07:00
icex2
2a80083af2 Update changelog for 5.37 2022-01-04 22:15:24 +01:00
icex2
66e0467ad3 Version bump in readme 2022-01-04 22:13:54 +01:00
icex2
c5f0116294 Add supported jubeat games to list of games 2022-01-04 22:13:39 +01:00
Will Toohey
ddfa814387 jbhook2: Move hooking further back where possible
This fixes a failure to boot (due to aciomgr hanging)
on jubeat knit append on my cab
2022-01-03 19:57:28 +10:00
Will Toohey
088d4bf338 jbhook2: fix broken windowed toggle 2022-01-03 19:56:10 +10:00
Will Toohey
f1a7621e2b jbhook1: also use ICCB 2022-01-03 18:32:31 +10:00
Will Toohey
4a3d5fa189 jbhook2: also use ICCB mode (fixes copious) 2022-01-03 17:03:44 +10:00
Will Toohey
0f2828da40 jbhook: make errors right-side-up as well 2022-01-03 16:48:12 +10:00
Will Toohey
ba2016b5bc jbhook: Fix security error when booting knit append 2022-01-03 16:46:56 +10:00
Will Toohey
b42c9aa93b jbhook: Finalise half-baked "rotate window" hooks 2022-01-03 14:57:43 +10:00
Will Toohey
8de259c639 jbhook: Add some better documentation 2022-01-03 14:30:20 +10:00
Will Toohey
0d54587787 jbhook: fix missing heap sizes in gamestart.bat 2022-01-03 14:13:33 +10:00
Will Toohey
4721ba2d3c p3ioemu: reorganise code for easy reading 2022-01-03 14:12:23 +10:00
Will Toohey
1105a2a130 jubeat: support p3io games 2021-12-31 20:23:31 +10:00
icex2
8ab92872ad Improve debugability for inline scripts in ci pipeline
Instead of a single big block of code which only shows up as a
single command executed, have each command on a separate "line"
so they show up on debug output. If one line fails, it's easier
to tell which one failed
2021-12-28 23:41:37 +01:00
icex2
a16dc82cef Bugfix gitlab-ci
Artifacts need to be yielded from build stage in order to have
these available in the following stages
2021-12-28 23:41:04 +01:00
icex2
729f5abcc0 Output to stderr instead of stdout in release message script
stdout is used for actual data output which is captured by
the ci pipeline. stderr shows up properly in debug output
2021-12-28 23:40:21 +01:00
Felix
6e0e5031ac avs: add additional avs_net_interface fields for newer AVS 2021-10-25 23:21:02 +00:00
Will Xyen
f17e8d6739 Bump version to 5.37 2021-10-11 14:01:45 -07:00
Will Xyen
ac02609948 dist: add IIDX28 support 2021-10-11 13:59:02 -07:00
icex2
c644db03ae doc/iidxhook3: Clarify usage of EAMID on iidx 14-17, network error
Add some additional symptoms and reasoning as this is different
for 14 to 17 compared to any other iidx version on how to use
the PCBID you get from server operators.
2021-09-27 21:50:16 +02:00
Will Xyen
7d5398b6af acio: minor fixes 2021-09-13 13:38:27 -07:00
Will Xyen
cac09f8f87 bio2: add definitions for 20th anniversary model 2021-09-13 02:51:19 +00:00
Will Xyen
85c9c444f1 aciotest: add RVOL test, and change to use product types instead of names 2021-09-13 02:51:19 +00:00
Will Xyen
8f2ce1f1b3 acio: add RVOL node definition 2021-09-13 02:51:19 +00:00
Will Xyen
d3bf381a4f aciodrv: add method to get product type of node
some devices share product codes (KFCA->RVOL), we really should be using type to differentiate them.
2021-09-13 02:51:19 +00:00
Will Xyen
3acbc7f251 acioemu: update name of AC_IO_ICCA_CMD_DEVICE_CONTROL 2021-09-13 02:51:19 +00:00
Will Xyen
839903ab48 acio: add MDXF node definition 2021-09-13 02:51:19 +00:00
Will Xyen
c929141e71 ddrhook: move common hooks to ddrhook-util 2021-09-13 02:51:19 +00:00
icex2
1477480836 Remove hardware docs, moved to arcade-docs project
These didn't really belong to this project to begin with but
didn't find a good home until recently. Already moved to
arcade-docs repository
2021-09-12 23:58:28 +02:00
icex2
bf4322e855 Add reference to arcade-docs project to documentation 2021-09-12 23:57:55 +02:00
icex2
3eed0a4ab3 Formatting 2021-09-12 23:56:45 +02:00
icex2
a9ade9d9d4 Refine CI/CD pipeline
Make use of GitLab features like the package registry to store dist
packages, GitLab releases and broadcast the release to different
channels.

Overall, this enables developers to be push out releases for frequently
since the amount of manual work is reduced.
2021-07-11 18:03:06 +00:00
Will Xyen
26336805d2 iidxhook: fix eamuse hook not using a sane port as the default when none are specified (#64) 2021-07-08 22:25:45 -07:00
Will Xyen
7d0e916b9f changelog: mention wavepass support in 5.35 2021-06-23 11:35:43 -07:00
Will Xyen
a03a5604ec Bump version to 5.36 2021-06-23 11:23:08 -07:00
125 changed files with 2886 additions and 1144 deletions

View File

@@ -1,55 +1,136 @@
#
# This pipeline requires packages to be switched on under the repository settings. Otherwise, you will 403s when
# uploading to the package repo is triggered.
#
# Variables to setup in GitLab CI/CD settings of the project
#
# The variables with BASE64 postfixes need to contain the base64 encoded data. Otherwise, masking
# in GitLab won't work due to not matching their pre-defined regex
#
# CI_PIGSTALL_DATA_PREFIX_BASE64
# CI_PIGSTALL_LINK_BASE64
# CI_PIGSTALL_PHP_SESSION_ID
# CI_PIGSTALL_SESSION_BASE64
#
# CI_TOOLS_UPLOAD_KEY
# CI_TOOLS_UPLOAD_URL
# CI_TOOLS_URL
image: docker:stable
variables:
DOCKER_TLS_CERTDIR: "/certs"
DIST_PACKAGE_RELATIVE_PATH: "build/docker/bemanitools.zip"
PACKAGE_REGISTRY_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/bemanitools"
services:
- docker:19.03.8-dind
before_script:
- docker info
stages:
- build
- upload-release
- upload
- release
build-master:
build:
stage: build
before_script:
- apk update && apk add make > /dev/null
script:
- make build-docker
- mv build/docker/bemanitools.zip bemanitools.zip
artifacts:
name: "$CI_COMMIT_SHORT_SHA-$CI_JOB_NAME"
paths:
- bemanitools.zip
only:
refs:
- master
build-tags:
stage: build
- tags
before_script:
- apk update && apk add make > /dev/null
script:
- make build-docker
- mv build/docker/bemanitools.zip bemanitools.zip
artifacts:
name: "$CI_COMMIT_SHORT_SHA-$CI_JOB_NAME"
paths:
- bemanitools.zip
only:
- tags
- build
expire_in: 1 week
upload-release:
stage: upload-release
dependencies:
- build-tags
before_script:
- apk update && apk add curl > /dev/null
script:
- echo "Uploading ${CI_PROJECT_NAME}-${CI_COMMIT_TAG}..."
- curl --silent --show-error -F "key=${CI_UPLOAD_KEY}" -F "filename=${CI_PROJECT_NAME}-v${CI_COMMIT_TAG}.zip" -F "file=@./bemanitools.zip" ${CI_UPLOAD_URL}
upload-package-registry:
stage: upload
image: curlimages/curl:latest
only:
- tags
refs:
- master
- tags
dependencies:
- build
script:
- |
if [ "${CI_COMMIT_TAG}" ]; then
version="${CI_COMMIT_TAG}"
else
version="${CI_COMMIT_SHORT_SHA}"
fi
- |
curl \
--silent \
--fail \
--show-error \
--header "JOB-TOKEN: ${CI_JOB_TOKEN}" \
--upload-file "${DIST_PACKAGE_RELATIVE_PATH}" \
$PACKAGE_REGISTRY_URL/${version}/bemanitools.zip
upload-tools-page:
stage: upload
image: curlimages/curl:latest
only:
refs:
- tags
dependencies:
- build
script:
- |
curl \
--silent \
--fail \
--show-error \
--connect-timeout 5 \
--max-time 10 \
--retry 5 \
-F "key=${CI_TOOLS_UPLOAD_KEY}" \
-F "filename=${CI_PROJECT_NAME}-v${CI_COMMIT_TAG}.zip" \
-F "file=@${DIST_PACKAGE_RELATIVE_PATH}" \
${CI_TOOLS_UPLOAD_URL}
release-gitlab:
stage: release
image: registry.gitlab.com/gitlab-org/release-cli:v0.8.0
only:
refs:
- tags
script:
- version="$CI_COMMIT_TAG"
- release_message="$(scripts/ci/create-release-message.sh "${version}" < CHANGELOG.md)"
- |
release-cli create \
--name "bemanitools ${version}" \
--description="${release_message}" \
--tag-name ${version} \
--assets-link "{\"name\":\"Distribution binaries\",\"url\":\"${PACKAGE_REGISTRY_URL}/${version}/bemanitools.zip\"}"
release-pigstall:
stage: release
image: curlimages/curl:latest
only:
refs:
- tags
script:
- version="${CI_COMMIT_TAG}"
- changelog_excerpt="$(scripts/ci/create-release-message.sh "${version}" < CHANGELOG.md)"
- release_message="$(printf "bemanitools ${version} released\n${CI_TOOLS_URL}/bemanitools-v${version}.zip\n${changelog_excerpt}")"
- session="$(echo "$CI_PIGSTALL_SESSION_BASE64" | base64 -d)"
- data_prefix="$(echo "$CI_PIGSTALL_DATA_PREFIX_BASE64" | base64 -d)"
- link="$(echo "$CI_PIGSTALL_LINK_BASE64" | base64 -d)"
- |
curl \
--silent \
--fail \
--connect-timeout 5 \
--max-time 10 \
--retry 5 \
--show-error \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H "Cookie: PHPSESSID=$CI_PIGSTALL_PHP_SESSION_ID; session=${session}" \
--data-raw "${data_prefix}&body=${release_message}" \
"${link}"

View File

@@ -1,7 +1,23 @@
# Release history
Note for CI/CD: Ensure the version formatting in the sections is kept identical to the versions
given in tags. The pipeline will pick this up and cuts out the relevant section for release notes.
## 5.38
* sdvxhook2: Support sound voltex exceed gear
## 5.37
* jbhook1: Support jubeat (1) and ripples
* jbhook2: Support jubeat knit and copious
* jbhook3: Support jubeat saucer, prop, qubell, clan and festo
## 5.36
* iidxhook9: Support for IIDX28
* Various bugfixes
## 5.35
* Jubeat: Add jbio-p4io
* Nostalgia: Add nostio-panb
* Misc: Add wavepass support to aciodrv-icca (and eamio-icca)
* Misc: Refactor aciodrv to support multiple devices using the same port (with aciomgr)
* Misc: Fix d3d9ex windowed hook not behaving correctly (size/framed)
* Misc: Fix docs not being included with release

View File

@@ -226,7 +226,7 @@ $$(dll_$1_$2_$3) $$(implib_$1_$2_$3): $$(obj_$1_$2_$3) $$(abslib_$1_$2_$3) \
$(V)echo ... $$(dll_$1_$2_$3)
$(V)$$(toolchain_$1)gcc -shared \
-o $$(dll_$1_$2_$3) -Wl,--out-implib,$$(implib_$1_$2_$3) \
$$^ $$(ldflags_$3)
-Wl,--start-group $$^ -Wl,--end-group $$(ldflags_$3)
$(V)$$(toolchain_$1)strip $$(dll_$1_$2_$3)
$(V)$$(toolchain_$1)ranlib $$(implib_$1_$2_$3)

View File

@@ -26,7 +26,8 @@
# 8: Patch 3: beatmania IIDX 16 Empress
# jubeat
#
# 10: Patch 4: DanceDanceRevolution X2
# 10: Patch 2: jubeat Knit
# Patch 4: DanceDanceRevolution X2
#
# 11: Patch 1: beatmania IIDX 18 Resort Anthem
# pop'n music 19 Tune Street
@@ -71,7 +72,7 @@ cflags += \
# Each AVS-dependent project should consume the earliest AVS import definition
# that is still ABI-compatible with the real build its target links against.
avsvers_32 := 1700 1603 1601 1508 1403 1304 1101 803 0
avsvers_32 := 1700 1603 1601 1508 1403 1304 1101 1002 803 0
avsvers_64 := 1700 1603 1601 1509 1508
imps += avs avs-ea3
@@ -91,6 +92,7 @@ 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-util/Module.mk
include src/main/ddrhook/Module.mk
include src/main/ddrio-mm/Module.mk
include src/main/ddrio-smx/Module.mk
@@ -135,12 +137,14 @@ include src/main/iidxio-ezusb2/Module.mk
include src/main/iidxio/Module.mk
include src/main/iidxiotest/Module.mk
include src/main/inject/Module.mk
include src/main/jbhook/Module.mk
include src/main/jbhook1/Module.mk
include src/main/jbio-magicbox/Module.mk
include src/main/jbio-p4io/Module.mk
include src/main/jbio/Module.mk
include src/main/jbiotest/Module.mk
include src/main/jbhook-util/Module.mk
include src/main/jbhook1/Module.mk
include src/main/jbhook2/Module.mk
include src/main/jbhook3/Module.mk
include src/main/launcher/Module.mk
include src/main/mempatch-hook/Module.mk
include src/main/mm/Module.mk
@@ -365,7 +369,7 @@ $(zipdir)/iidx-25-to-26.zip: \
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/iidx-27.zip: \
$(zipdir)/iidx-27-to-28.zip: \
build/bin/avs2_1700-64/iidxhook9.dll \
build/bin/avs2_1700-64/launcher.exe \
build/bin/indep-64/config.exe \
@@ -375,7 +379,9 @@ $(zipdir)/iidx-27.zip: \
build/bin/indep-64/vefxio.dll \
dist/iidx/config.bat \
dist/iidx/gamestart-27.bat \
dist/iidx/gamestart-28.bat \
dist/iidx/iidxhook-27.conf \
dist/iidx/iidxhook-28.conf \
dist/iidx/vefx.txt \
| $(zipdir)/
$(V)echo ... $@
@@ -421,28 +427,68 @@ $(zipdir)/jb-01.zip: \
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/jb-02.zip: \
build/bin/avs2_1002-32/jbhook1.dll \
build/bin/indep-32/inject.exe \
build/bin/indep-32/config.exe \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
build/bin/indep-32/jbio.dll \
dist/jb/config.bat \
dist/jb/gamestart-02.bat \
dist/jb/jbhook-02.conf \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/jb-03.zip: \
build/bin/avs2_1101-32/jbhook2.dll \
build/bin/avs2_1101-32/launcher.exe \
build/bin/indep-32/config.exe \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
build/bin/indep-32/jbio.dll \
dist/jb/config.bat \
dist/jb/gamestart-03.bat \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/jb-04.zip: \
build/bin/avs2_1304-32/jbhook2.dll \
build/bin/avs2_1304-32/launcher.exe \
build/bin/indep-32/config.exe \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
build/bin/indep-32/jbio.dll \
dist/jb/config.bat \
dist/jb/gamestart-03.bat \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/jb-05-to-07.zip: \
build/bin/avs2_1508-32/jbhook.dll \
build/bin/avs2_1508-32/jbhook3.dll \
build/bin/avs2_1508-32/launcher.exe \
build/bin/indep-32/config.exe \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
build/bin/indep-32/jbio.dll \
dist/jb/config.bat \
dist/jb/gamestart.bat \
dist/jb/gamestart-04.bat \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/jb-08.zip: \
build/bin/avs2_1700-32/jbhook.dll \
build/bin/avs2_1700-32/jbhook3.dll \
build/bin/avs2_1700-32/launcher.exe \
build/bin/indep-32/config.exe \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
build/bin/indep-32/jbio.dll \
dist/jb/config.bat \
dist/jb/gamestart.bat \
dist/jb/gamestart-04.bat \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
@@ -471,7 +517,7 @@ $(zipdir)/sdvx-01-to-04.zip: \
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/sdvx-05.zip: \
$(zipdir)/sdvx-05-to-06.zip: \
build/bin/avs2_1700-64/launcher.exe \
build/bin/avs2_1700-64/sdvxhook2.dll \
build/bin/indep-64/config.exe \
@@ -614,15 +660,18 @@ $(BUILDDIR)/bemanitools.zip: \
$(zipdir)/iidx-20.zip \
$(zipdir)/iidx-21-to-24.zip \
$(zipdir)/iidx-25-to-26.zip \
$(zipdir)/iidx-27.zip \
$(zipdir)/iidx-27-to-28.zip \
$(zipdir)/iidx-hwio-x86.zip \
$(zipdir)/iidx-hwio-x64.zip \
$(zipdir)/jb-01.zip \
$(zipdir)/jb-02.zip \
$(zipdir)/jb-03.zip \
$(zipdir)/jb-04.zip \
$(zipdir)/jb-05-to-07.zip \
$(zipdir)/jb-08.zip \
$(zipdir)/jb-hwio.zip \
$(zipdir)/sdvx-01-to-04.zip \
$(zipdir)/sdvx-05.zip \
$(zipdir)/sdvx-05-to-06.zip \
$(zipdir)/sdvx-05-cn.zip \
$(zipdir)/sdvx-hwio-x86.zip \
$(zipdir)/sdvx-hwio-x64.zip \

View File

@@ -1,7 +1,7 @@
# Bemanitools 5
[![pipeline status](https://dev.s-ul.net/djhackers/bemanitools/badges/master/pipeline.svg)](https://dev.s-ul.net/djhackers/bemanitools/commits/master)
Version: 5.35
Version: 5.38
[Release history](CHANGELOG.md)
@@ -55,19 +55,25 @@ The tl;dr version and golden rules of the sections in the document:
* 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)
* Beatmania IIDX 27 Heroic Verse (iidx-27.zip) using [iidxhook9](doc/iidxhook/iidxhook9.md)
* Beatmania IIDX 27 Heroic Verse (iidx-27-to-28.zip) using [iidxhook9](doc/iidxhook/iidxhook9.md)
* Beatmania IIDX 28 BISTROVER (iidx-27-to-28.zip) using [iidxhook9](doc/iidxhook/iidxhook9.md)
* jubeat
* 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
* jubeat (jb-01.zip) using [jbhook1](doc/jbhook/jbhook1.md)
* jubeat ripples (jb-02.zip) using [jbhook1](doc/jbhook/jbhook1.md)
* jubeat knit (jb-03.zip) using [jbhook2](doc/jbhook/jbhook2.md)
* jubeat copious (jb-04.zip) using [jbhook2](doc/jbhook/jbhook2.md)
* jubeat saucer (fulfill) (jb-05-to-07.zip) using [jbhook3](doc/jbhook/jbhook3.md)
* jubeat prop (jb-05-to-07.zip) using [jbhook3](doc/jbhook/jbhook3.md)
* jubeat qubell (jb-05-to-07.zip) using [jbhook3](doc/jbhook/jbhook3.md)
* jubeat clan (jb-08.zip) using [jbhook3](doc/jbhook/jbhook3.md)
* jubeat festo (jb-08.zip) using [jbhook3](doc/jbhook/jbhook3.md)
* SOUND VOLTEX
* SOUND VOLTEX BOOTH (sdvx-01-to-04.zip) using sdvxhook
* SOUND VOLTEX II -infinite infection- (sdvx-01-to-04.zip) using sdvxhook
* SOUND VOLTEX III GRAVITY WARS (sdvx-01-to-04.zip) using sdvxhook
* SOUND VOLTEX IV HEAVENLY HAVEN (sdvx-01-to-04.zip) using sdvxhook
* SOUND VOLTEX Vivid Wave (sdvx-05.zip) using sdvxhook2
* SOUND VOLTEX Vivid Wave (sdvx-05-to-06) using sdvxhook2
* SOUND VOLTEX EXCEED GEAR (sdvx-05-to-06) using sdvxhook2
## ViGEm clients: Expose BT5 APIs as XBOX game controllers
Play your favorite non-bemani arcade games with any hardware, e.g. real cabinet hardware, that

16
dist/iidx/gamestart-28.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 -B iidxhook9.dll bm2dx.dll --config iidxhook-28.conf %*

78
dist/iidx/iidxhook-28.conf vendored Normal file
View File

@@ -0,0 +1,78 @@
# 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
# Lightning cab mode (requires additional IO emulation)
io.lightning_mode=false
# Disable camera connection
io.disable_cams=true
# Disables the built in file hooks, requiring manual file creation
io.disable_file_hooks=false
# Turntable sensitivity multiplier (1.0 is default)
io.tt_multiplier=1.0
# Disables the camera emulation
cam.disable_emu=true
# Override camera device ID detection (copy from device manager, do not escape)
cam.device_id1=
# Override camera device ID detection (copy from device manager, do not escape)
cam.device_id2=
# Run the game in a framed window (requires windowed option)
gfx.framed=true
# Run the game windowed
gfx.windowed=false
# Confine mouse cursor to window
gfx.confined=false
# Windowed width, -1 for default size
gfx.window_width=-1
# Windowed height, -1 for default size
gfx.window_height=-1
# Windowed X, -1 for default X position
gfx.window_x=-1
# Windowed Y, -1 for default Y position
gfx.window_y=-1
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
gfx.forced_refresh_rate=-1
# D3D9ex device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
gfx.device_adapter=-1
# Orientation to force monitor into, -1 to use default, 0, 1, 2, 3 to do 0, 90, 180, 270 degrees
gfx.force_orientation=-1
# Force a screen resolution (width), -1 to disable. Use this if the game does not auto detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720.
gfx.force_screen_res.width=-1
# Force a screen resolution (height), -1 to disable. Use this if the game does not auto detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720.
gfx.force_screen_res.height=-1
# IP of adapter to force override with
adapter.override_ip=
# Force ASIO audio mode/device (if applicable / TDJ default)
asio.force_asio=false
# Force WASAPI audio mode (if applicable / LDJ default)
asio.force_wasapi=true
# The ASIO device name to use
asio.device_name=XONAR SOUND CARD(64)

5
dist/jb/gamestart-02.bat vendored Normal file
View File

@@ -0,0 +1,5 @@
@echo off
cd /d %~dp0
inject jbhook1.dll jubeat.exe --config jbhook-02.conf %*

View File

@@ -7,4 +7,4 @@ if not exist dev\nvram\coin.xml copy prop\defaults\coin.xml dev\nvram\coin.xml
if not exist dev\nvram\eacoin.xml copy prop\defaults\eacoin.xml dev\nvram\eacoin.xml
if not exist dev\raw mkdir dev\raw
launcher -H 33554432 -K jbhook.dll jubeat.dll
launcher -H 33554432 -K jbhook2.dll jubeat.dll

10
dist/jb/gamestart-04.bat vendored Normal file
View File

@@ -0,0 +1,10 @@
@echo off
cd /d %~dp0
if not exist dev\nvram mkdir dev\nvram
if not exist dev\nvram\coin.xml copy prop\defaults\coin.xml dev\nvram\coin.xml
if not exist dev\nvram\eacoin.xml copy prop\defaults\eacoin.xml dev\nvram\eacoin.xml
if not exist dev\raw mkdir dev\raw
launcher -H 33554432 -K jbhook3.dll jubeat.dll

View File

@@ -1,6 +1,9 @@
# Run the game windowed
gfx.windowed=false
# rotate the normally-horizontal game window to be vertical
gfx.vertical=false
# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80.
eamuse.server=localhost:80

18
dist/jb/jbhook-02.conf vendored Normal file
View File

@@ -0,0 +1,18 @@
# Run the game windowed
gfx.windowed=false
# rotate the normally-horizontal game window to be vertical
gfx.vertical=false
# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80.
eamuse.server=localhost:80
# PCBID
eamuse.pcbid=0101020304050607086F
# EAMID
eamuse.eamid=0101020304050607086F
# Mcode of the game to run.
security.mcode=GCI44JAA

View File

@@ -13,6 +13,15 @@ io.force_headphones=false
# Disables the built in file hooks, requiring manual file creation (/dev/raw/j.dest)
io.disable_file_hooks=false
# Disables the built in power control hooks, allowing game to modify system power settings
io.disable_power_hooks=false
# Disables the built in NVAPI control hooks, allowing game to modify system monitor settings
io.disable_nvapi_hooks=false
# Emulates the card reader on COM1 instead of COM2
io.com1_card_reader=false
# Run the game in a framed window (requires windowed option)
gfx.framed=true
@@ -43,6 +52,12 @@ gfx.device_adapter=-1
# Orientation to force monitor into, -1 to use default, 0, 1, 2, 3 to do 0, 90, 180, 270 degrees
gfx.force_orientation=-1
# Force a screen resolution (width), -1 to disable. Use this if the game does not auto detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720.
gfx.force_screen_res.width=-1
# Force a screen resolution (height), -1 to disable. Use this if the game does not auto detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720.
gfx.force_screen_res.height=-1
# Disables the camera emulation
cam.disable_emu=false

View File

@@ -1,21 +1,29 @@
# Bemanitools 5 documentation
This folder contains various types of documentation.
Table of contents:
* Key tools
* [Inject](inject.md): Readme for one of BT5's key applications, `inject.exe`
* [Launcher](launcher.md): Readme for another one of BT5's key applications, `launcher.exe`
* [Tools](tools/README.md): Documentation for additional user and development tooling
* [Inject](inject.md): Readme for one of BT5's key applications, `inject.exe`
* [Launcher](launcher.md): Readme for another one of BT5's key applications, `launcher.exe`
* [Tools](tools/README.md): Documentation for additional user and development tooling
* Game hooks
* [ddrhook](ddrhook/README.md): Documentation relevant to `ddrhook` implementations
* [iidxhook](iidxhook/README.md): Documentation relevant to `iidxhook` implementations
* [jbhook](jbhook/README.md): Documentation relevant to `jbhook` implementations
* [sdvxhook](sdvxhook/README.md): Documentation relevant to `sdvxhook` implementations
* [ddrhook](ddrhook/README.md): Documentation relevant to `ddrhook` implementations
* [iidxhook](iidxhook/README.md): Documentation relevant to `iidxhook` implementations
* [jbhook](jbhook/README.md): Documentation relevant to `jbhook` implementations
* [sdvxhook](sdvxhook/README.md): Documentation relevant to `sdvxhook` implementations
* Development
* [API](api.md): Available APIs for BT5 and instructions how to use them
* [Architecture](architecture.md): Outline of BT5's architecture, how things are designed and why
* [Development](development.md): Development environment, building, releasing, etc.
* [Developer documentation](dev/README.md): Various lose documentation/notes by developers
* [Tools](tools/README.md): Documentation for additional user and development tooling
* Hardware
* [Hardware](hardware/README.md): Anything related to hardware, e.g. IO boards
* [API](api.md): Available APIs for BT5 and instructions how to use them
* [Architecture](architecture.md): Outline of BT5's architecture, how things are designed and why
* [Development](development.md): Development environment, building, releasing, etc.
* [Developer documentation](dev/README.md): Various lose documentation/notes by developers
* [Tools](tools/README.md): Documentation for additional user and development tooling
## Further external documentation
A list of external documentation that can be useful when dealing with bemanitools,
supported data and hardware.
* [arcade-docs](https://github.com/Shizmob/arcade-docs): An open (to read and contribute) repository
of arcade hardware and software documentation

View File

@@ -1,55 +0,0 @@
# BIO2 sub IO turntable bypass cable
If you upgraded a C02 wired cabinet, the turntables are connected to the
sub IO via a serial line that goes to another sub IO behind the front panel
next to the 16seg display. This introduces additional latency as the input
data needs to pass through multiple systems/PCBs until it reaches the game.
This can be reduced by using a so-called "bypass" cable, that connects the
turntables directly to the BIO2 sub IO board by emulating the wiring of a
D01 cabinet, reducing latency significantly.
This cable could be ordered with the IIDX Rootage upgrade kit but can also
be easily created from scratch.
## Parts
* Some wires
* [JST HL](https://jst.de/file/download/219/pitch-3-96-mm-wtw-hl2-pdf) 2x4 pin female connector
* [JST HVQ](https://jst.de/file/download/637/hvq) 8 pin female connector
* Matching terminals for the connectors
## Pinout
```text
JST HL 2x4 pin front view connector
notch at top
___
|---------|
| 1 2 3 4 |
| 5 6 7 8 |
|---------|
```
```
JST HVQ 8 pin front view connector
Numbering on connector matches
notch at top
___________________
-------------------
|-----------------|
| 1 2 3 4 5 6 7 8 |
|-----------------|
```
Pins of the two connectors need to be connected like this:
| JST HL 2x4 pin | JST 8 pin |
|----------------|-----------|
| 1 | 1 |
| 2 | 1 |
| 3 | 3 |
| 4 | 2 |
| 5 | 5 |
| 6 | 4 |
| 7 | 8 |
| 8 | 8 |

View File

@@ -1,51 +0,0 @@
# Ezusb 1/2 RJ45 to DIN8 connector pinout
This was created from using the BIO2 sub IO board to connect pre IIDX 25 cabinet hardware to the
BIO2 IO board. The two connector types from different generation IO boards, RJ45 on the ezusb FX
(C02) board and a round DIN8 connector on the ezusb FX2 (IO2) board are just different connectors to
the same hardware on the PCB.
Therefore, any C02 wired cabinet can be easily upgraded to IO2 wiring and vice versa by building
a simple RJ45 -> DIN8 or DIN8 -> RJ45 adapter.
The following connection information was traced on a original Konami BIO2 sub IO board.
RJ45 (female) connector, top view:
```text
plug insert
|
|
v
|-----------|
| Top view |
| |
| Pins |
| 7 5 3 1 |
| 8 6 4 2 |
|-----------|
```
DIN8 (female) connector, top view:
```text
plug insert
|
|
v
|-----------|
| Top view |
| Pins |
| 3 1 2 6 |
| 7 4 5 8 9 |
|-----------|
```
The two connectors are interconnected on the PCB like this:
| RJ45 pins | DIN8 pins |
|-----------|-----------|
| 1 | 1 |
| 2 | 7 |
| 3 | 4 |
| 4 | 6 |
| 5 | 5 |
| 6 | 3 |
| 7 | 2 |
| 8 | 1 |

View File

@@ -23,14 +23,14 @@ games:
* [iidxhook8](iidxhook8.md): CANNON BALLERS, Rootage
* [iidxhook8](iidxhook9.md): Heroic Verse
When building kactools, independent packages are created for each set of games
When building bemanitools, independent packages are created for each set of games
which are ready to be dropped on top of vanilla AC data dumps. We recommend
using prestine dumps to avoid any conflicts with other hardcoded hacks or
using pristine dumps to avoid any conflicts with other hardcoded hacks or
binary patches.
## How to run
To run your game with iidxhook, you have to use the inject tool to inject the
DLL to the game process. *dist/iidx* contains bat scripts with all the
DLL to the game process. `dist/iidx` contains bat scripts with all the
important parameters configured. Further parameters can be added but might not
be required to run the game with default settings.
Further information on how to setup the data for each specific version are
@@ -47,4 +47,4 @@ IO hardware you want to use:
game controllers
* [iidxio-bio2](iidxhook/iidxio-bio2.md): Support BIO2 hardware
* [iidxio-ezusb](iidxhook/iidxio-ezusb.md): Support C02 ezusb FX hardware
* [iidxio-ezusb2](iidxhook/iidxio-ezusb2.md): Support IO2 ezusb FX2 hardware
* [iidxio-ezusb2](iidxhook/iidxio-ezusb2.md): Support IO2 ezusb FX2 hardware

View File

@@ -57,6 +57,12 @@ If you want to run the games online, you have to set a valid PCBID and EAMID
argument. You also have to set the url of the eamuse server you want to
connect to.
Additional note regarding EAMID: This is new compared to the prior games and
is provided as the identifier of the "eamuse license" to the server. Depending
on the implementation of the server, this can lead to authentication failure
resulting in
[a network error on boot or warning during gameplay](#network-warning-instead-of-network-ok).
Run the game with the gamestart-XX.bat file and enable network on the operator
menu. When enabled, the game seems to hang and expects you to power
cycle the machine (i.e. quit the game and restart it).
@@ -134,7 +140,7 @@ value to cut down start-up times.
## "NETWORK WARNING" instead of "NETWORK OK"
This can be caused by:
* Invalid PCBID
* Invalid PCBID/EAMID: Ensure both are [set to the same ID](#eamuse-network-setup)
* Firewall blocking connections
* Invalid eamuse url or port specified
* Game is not run using the Administrator account

View File

@@ -2,6 +2,7 @@
The following games are compatible with this version of iidxhook:
* Heroic Verse
* BISTROVER
The games must be bootstrapped using [launcher](../launcher.md).

77
doc/jbhook/README.md Normal file
View File

@@ -0,0 +1,77 @@
# jbhook
jbhook is a collection of hook libraries for jubeat 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 jbhook version
(see below).
# Versions
jbhook comes in a few different flavors. The game and its engine changed over
the years. Some game versions might require patches/parameters enabled which
others don't need or have different AVS versions. Here is the list of supported
games:
* [jbhook1](jbhook1.md): jubeat, ripples
* [jbhook2](jbhook2.md): knit, copious
* [jbhook3](jbhook3.md): saucer, prop, qubell, clan, festo
I sure have trouble remembering which jubeat version is which, here's a handy
guide:
* 01 - jubeat
* 02 - ripples
* 03 - knit
* 04 - copious
* 05 - saucer
* 06 - prop
* 07 - qubell
* 08 - clan
* 09 - festo
When building bemanitools, independent packages are created for each set of games
which are ready to be dropped on top of vanilla AC data dumps. We recommend
using pristine dumps to avoid any conflicts with other hardcoded hacks or
binary patches.
# How to run
To run your game with jbhook, you have to use the inject tool to inject the
DLL to the game process. `dist/jb` contains bat scripts with all the
important parameters configured. Further parameters can be added but might not
be required to run the game with default settings.
Further information on how to setup the data for each specific version are
elaborated in their dedicated readme files.
# Data setup and running the game
Ensure your folder with your unpacked data looks like this:
- `data`
- `prop`
- Various dll files including `jubeat.dll` **OR** `jubeat.exe`
Unpack the package containing jbhook into the folder containing the jubeat
binary file.
Run the `gamestart-XX.bat` file where `XX` denotes the version of the game you want to run.
# Eamuse network setup
Running jubeat or ripples? Modify jbhook-01.conf or jbhook-02.conf.
Running anything newer?
* Open the `prop/ea3-config.xml`
* Replace the `ea3/network/services` URL with network service URL of your
choice (for example http://my.eamuse.com)
* Edit the `ea3/id/pcbid`
# Real hardware support
Run the launcher without the hook dll: `launcher jubeat.dll`
# Command line options
Add the argument *-h* when running inject with jbhook to print help/usage
information with a list of parameters you can apply to tweak various things.

View File

@@ -1,31 +0,0 @@
# Game list
The following games are compatible with this version of jbhook:
* saucer
* prop
* qubell
# Data setup and running the game
Ensure your folder with your unpacked data looks like this:
- data
- prop
- Various dll files including jubeat.dll
Unpack the package containing jbhook into the folder containing the jubeat.dll
file.
Run the gamestart.bat file.
# Eamuse network setup
* Open the prop/ea3-config.xml
* Replace the *ea3/network/services* URL with network service URL of your
choice (for example http://my.eamuse.com)
* Edit the *ea3/id/pcbid*
# Real hardware support
Run the launcher without the hook dll: *launcher jubeat.dll*
# Troubleshooting and FAQ

42
doc/jbhook/jbhook1.md Normal file
View File

@@ -0,0 +1,42 @@
# Game list
The following games are compatible with this version of jbhook:
* jubeat
* jubeat ripples
The games must be bootstrapped using [inject](../inject.md).
# Data setup and running the game
Unpack the package containing jbhook1 into the revision folder of your choice.
Most likely, you want to target the latest revision you have to run the latest
binary of the game with any bugfixes by developers.
The DLLs in this package should be in the same location as the game DLLs and
executable - i.e. all these files should be in the same folder:
- `inject.exe`
- `jubeat.exe`
- `jbhook-01.conf`
- `eamio.dll`
- `libavs-win32.dll`
- etc
Run the `gamestart-01.bat` file as admin.
# Eamuse network setup
If you want to run the games online, you have to set a valid PCBID in the
configuration file. You also have to set the url of the eamuse server you want
to connect to.
# Eamuse network setup
If you want to run the games online, you have to set a valid PCBID and EAMID
(use the PCBID as the EAMID) in the configuration file or as a command line
argument. You also have to set the url of the eamuse server you want to
connect to.
Additional note regarding EAMID: This is provided as the identifier of the
"eamuse license" to the server. Depending on the implementation of the server,
this can lead to authentication failure resulting in a network error on boot or
warning during gameplay.

42
doc/jbhook/jbhook2.md Normal file
View File

@@ -0,0 +1,42 @@
# Game list
The following games are compatible with this version of jbhook:
* jubeat knit
* jubeat copious
The games must be bootstrapped using [launcher](../launcher.md).
# Data setup and running the game
Unpack the package containing jbhook2 into the revision folder of your choice.
Most likely, you want to target the latest revision you have to run the latest
binary of the game with any bugfixes by developers.
The DLLs in this package should be in the same location as the game DLLs and
executable - i.e. all these files should be in the same folder:
- `launcher.exe`
- `jubeat.dll`
- `eamio.dll`
- `jbhook2.dll`
- `libavs-win32.dll`
- etc
Run the `gamestart-02.bat` file as admin.
# Eamuse network setup
If you want to run the games online, you have to set a valid PCBID in the
configuration file. You also have to set the url of the eamuse server you want
to connect to.
# Eamuse network setup
If you want to run the games online, you have to set a valid PCBID and EAMID
(use the PCBID as the EAMID) in the configuration file or as a command line
argument. You also have to set the url of the eamuse server you want to
connect to.
Additional note regarding EAMID: This is provided as the identifier of the
"eamuse license" to the server. Depending on the implementation of the server,
this can lead to authentication failure resulting in a network error on boot or
warning during gameplay.

18
doc/jbhook/jbhook3.md Normal file
View File

@@ -0,0 +1,18 @@
# Game list
The following games are compatible with this version of jbhook:
* jubeat saucer
* jubeat prop
* jubeat qubell
* jubeat clan
* jubeat festo
The games must be bootstrapped using [launcher](../launcher.md).
# Data setup and running the game
Unpack the package containing jbhook3 into the revision folder of your choice.
Most likely, you want to target the latest revision you have to run the latest
binary of the game with any bugfixes by developers.
Run the `gamestart-03.bat` file as admin.

View File

@@ -0,0 +1,28 @@
#!/bin/sh
VERSION="$1"
section_active=""
changelog_excerpt=""
while IFS= read -r line; do
if [ "$section_active" ]; then
if [[ "$(echo "$line" | grep '^#')" ]]; then
section_active=""
else
changelog_excerpt="$(printf "%s\n%s" "$changelog_excerpt" "$line")"
fi
else
if [ "$line" = "## $VERSION" ]; then
section_active="1"
fi
fi
done
if [ "$changelog_excerpt" ]; then
printf "%s" "$changelog_excerpt"
exit 0
else
>&2 echo "Could not find version in changelog: $VERSION"
exit 1
fi

View File

@@ -46,6 +46,12 @@ struct property_node;
struct avs_net_interface {
uint8_t mac_addr[6];
uint8_t unknown[30];
#if AVS_VERSION >= 1603
uint8_t unknown2[6];
#endif
#if AVS_VERSION >= 1700
uint8_t unknown3[6];
#endif
};
enum psmap_type {

10
src/imports/glhelper.h Normal file
View File

@@ -0,0 +1,10 @@
#include <GL/gl.h>
void glFramebufferTexture2DEXT(GLenum target,
GLenum attachment,
GLenum textarget,
GLuint texture,
GLint level);
void glGenFramebuffersEXT(GLsizei n,
GLuint *ids);

View File

@@ -0,0 +1,5 @@
LIBRARY libavs-win32-ea3
EXPORTS
ea3_boot
ea3_shutdown

View File

@@ -0,0 +1,37 @@
LIBRARY libavs-win32
EXPORTS
avs_boot
avs_net_ctrl
avs_shutdown
avs_thread_create
avs_thread_destroy
avs_thread_exit
avs_thread_join
log_body_fatal
log_body_info
log_body_misc
log_body_warning
log_boot
log_change_level
property_create
property_desc_to_buffer
property_destroy
property_file_write
property_insert_read
property_mem_write
property_read_query_memsize
property_search
property_set_flag
property_node_clone
property_node_create
property_node_datasize
property_node_name
property_node_refer
property_node_remove
property_node_type
property_node_traversal
property_node_refdata
std_getenv
std_setenv

View File

@@ -0,0 +1,6 @@
LIBRARY glhelper
EXPORTS
glBindFramebufferEXT
glFramebufferTexture2DEXT
glGenFramebuffersEXT

View File

@@ -0,0 +1,6 @@
LIBRARY glhelper
EXPORTS
glBindFramebufferEXT
glFramebufferTexture2DEXT
glGenFramebuffersEXT

View File

@@ -0,0 +1,6 @@
LIBRARY glhelper
EXPORTS
glBindFramebufferEXT
glFramebufferTexture2DEXT
glGenFramebuffersEXT

View File

@@ -0,0 +1,6 @@
LIBRARY glhelper
EXPORTS
glBindFramebufferEXT
glFramebufferTexture2DEXT
glGenFramebuffersEXT

View File

@@ -9,7 +9,9 @@
#include "acio/hdxs.h"
#include "acio/icca.h"
#include "acio/kfca.h"
#include "acio/mdxf.h"
#include "acio/panb.h"
#include "acio/rvol.h"
#define AC_IO_SOF 0xAA
#define AC_IO_ESCAPE 0xFF
@@ -37,9 +39,11 @@ enum ac_io_node_type {
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_RVOL = 0x09060001,
AC_IO_NODE_TYPE_MDXF = 0x09070000,
AC_IO_NODE_TYPE_PANB = 0x090E0000,
AC_IO_NODE_TYPE_BMPU = 0x0B000000,
AC_IO_NODE_TYPE_BI2A = 0x0D060000,
};
#pragma pack(push, 1)
@@ -84,6 +88,12 @@ struct ac_io_message {
struct ac_io_panb_poll_out panb_poll_out;
struct ac_io_hdxs_output hdxs_output;
struct ac_io_rvol_poll_in rvol_poll_in;
struct ac_io_rvol_poll_out rvol_poll_out;
struct ac_io_mdxf_poll_in mdxf_poll_in;
struct ac_io_mdxf_light_out mdxf_light_out;
};
} cmd;

View File

@@ -4,13 +4,15 @@
#include <stdint.h>
enum ac_io_icca_cmd {
/* found on jubeat, sent right after queue loop start */
AC_IO_ICCA_CMD_UNKN_0116 = 0x0116,
/* Yet unknown command encountered first on jubeat (1) */
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_DEVICE_CONTROL = 0x013A,
AC_IO_ICCA_CMD_POLL_FELICA = 0x0161,
AC_IO_ICCA_CMD_KEY_EXCHANGE = 0x0160,
AC_IO_ICCA_CMD_POLL_ENCRYPTED = 0x0164,

View File

@@ -1,48 +0,0 @@
#ifndef AC_IO_ICCB_H
#define AC_IO_ICCB_H
#include <stdint.h>
enum ac_io_iccb_cmd {
/* found on jubeat prop, sent after acio init req, maybe fw update? */
AC_IO_ICCB_CMD_UNK_0100 = 0x0100,
/* found on jubeat prop, sent right after queue loop start */
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_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
};
enum ac_io_iccb_sensor_state {
AC_IO_ICCB_SENSOR_CARD = 0x02,
AC_IO_ICCB_SENSOR_NO_CARD = 0x04
};
enum ac_io_iccb_card_type {
AC_IO_ICCB_CARD_TYPE_ISO15696 = 0x0,
AC_IO_ICCB_CARD_TYPE_FELICA = 0x1,
};
#pragma pack(push, 1)
struct ac_io_iccb_misc {
uint8_t unknown;
uint8_t subcmd;
};
struct ac_io_iccb_state {
uint8_t sensor_state;
uint8_t card_type;
uint8_t uid[8];
uint8_t unk2;
uint8_t unk3;
uint8_t unk4[4];
};
#pragma pack(pop)
#endif

49
src/main/acio/mdxf.h Normal file
View File

@@ -0,0 +1,49 @@
#ifndef AC_IO_MDXF_H
#define AC_IO_MDXF_H
#include <stdint.h>
#define AC_IO_CMD_MDXF_POLL 0x0110
#define AC_IO_CMD_MDXF_AUTO_GET_START 0x0116
#define AC_IO_CMD_MDXF_LIGHT 0x0113
#pragma pack(push, 1)
union mdxf_panel_sensors_individual {
struct {
uint8_t right : 1;
uint8_t left : 1;
uint8_t down : 1;
uint8_t up : 1;
uint8_t unused : 4;
};
uint8_t raw;
};
struct mdxf_panel_sensors {
uint8_t down : 4;
uint8_t up : 4;
uint8_t right : 4;
uint8_t left : 4;
};
struct ac_io_mdxf_poll_in {
struct mdxf_panel_sensors panel;
uint8_t unk;
};
struct mdxf_lights {
uint8_t up_right;
uint8_t down_left;
uint8_t up_left;
uint8_t down_right;
uint8_t unk;
};
struct ac_io_mdxf_light_out {
struct mdxf_lights side[2];
};
#pragma pack(pop)
#endif

74
src/main/acio/rvol.h Normal file
View File

@@ -0,0 +1,74 @@
#ifndef AC_IO_RVOL_H
#define AC_IO_RVOL_H
#include <stdint.h>
// technically RVOL also can poll with CMD 0x0113
// but museca never uses this (it's controlled by if the watchdog is on/off)
#define AC_IO_CMD_RVOL_POLL 0x0112
#define AC_IO_CMD_RVOL_SET_EXPAND_MODE 0x0114
#define AC_IO_CMD_RVOL_AMP_CONTROL 0x0128
#pragma pack(push, 1)
struct ac_io_rvol_buttons_1 {
uint8_t unk0 : 1;
uint8_t unk1 : 1;
uint8_t spinner_4 : 1;
uint8_t pedal : 1;
uint8_t spinner_5 : 1;
uint8_t unk5 : 1;
uint8_t unk6 : 1;
uint8_t unk7 : 1;
};
struct ac_io_rvol_buttons_2 {
uint8_t spinner_2 : 1;
uint8_t unk1 : 1;
uint8_t unk2 : 1;
uint8_t spinner_1 : 1;
uint8_t unk4 : 1;
uint8_t unk5 : 1;
uint8_t unk6 : 1;
uint8_t unk7 : 1;
};
struct ac_io_rvol_buttons_3 {
uint8_t unk0 : 1;
uint8_t unk1 : 1;
uint8_t unk2 : 1;
uint8_t spinner_3 : 1;
uint8_t unk4 : 1;
uint8_t unk5 : 1;
uint8_t unk6 : 1;
uint8_t unk7 : 1;
};
struct ac_io_rvol_poll_in {
uint8_t unk_0;
struct ac_io_rvol_buttons_1 buttons_1;
uint8_t unk_2_8[7];
struct ac_io_rvol_buttons_2 buttons_2;
uint8_t unk_10;
struct ac_io_rvol_buttons_3 buttons_3;
uint8_t unk_12_15[4];
uint8_t spinners[5];
uint8_t unk_21_22[2];
};
struct light_rgb {
uint8_t r;
uint8_t g;
uint8_t b;
};
struct ac_io_rvol_poll_out {
uint8_t unk0_3[4];
struct light_rgb spinner[5];
struct light_rgb title;
uint8_t unk22_31[10];
};
#pragma pack(pop)
#endif

View File

@@ -8,5 +8,6 @@ src_aciodrv := \
icca.c \
kfca.c \
panb.c \
rvol.c \
port.c \

View File

@@ -300,6 +300,7 @@ static bool aciodrv_device_get_version(struct aciodrv_device_ctx *device, uint8_
msg.cmd.version.time);
memcpy(version->product, msg.cmd.version.product_code, ACIO_NODE_PRODUCT_CODE_LEN);
version->type = ac_io_u32(msg.cmd.version.type);
version->major = msg.cmd.version.major;
version->minor = msg.cmd.version.minor;
version->revision = msg.cmd.version.revision;
@@ -392,6 +393,14 @@ bool aciodrv_device_get_node_product_ident(struct aciodrv_device_ctx *device, ui
memcpy(product, device->node_versions[node_id].product, ACIO_NODE_PRODUCT_CODE_LEN);
return true;
}
uint32_t aciodrv_device_get_node_product_type(struct aciodrv_device_ctx *device, uint8_t node_id)
{
if (device->node_count == 0 || node_id > device->node_count) {
return 0;
}
return device->node_versions[node_id].type;
}
const struct aciodrv_device_node_version *aciodrv_device_get_node_product_version(struct aciodrv_device_ctx *device, uint8_t node_id)
{

View File

@@ -13,6 +13,7 @@ struct aciodrv_device_ctx;
struct aciodrv_device_node_version {
char product[ACIO_NODE_PRODUCT_CODE_LEN];
uint32_t type;
uint8_t major;
uint8_t minor;
uint8_t revision;
@@ -52,6 +53,15 @@ uint8_t aciodrv_device_get_node_count(struct aciodrv_device_ctx *device);
*/
bool aciodrv_device_get_node_product_ident(struct aciodrv_device_ctx *device, uint8_t node_id, char product[ACIO_NODE_PRODUCT_CODE_LEN]);
/**
* Get the product identifier of an enumerated node.
*
* @param device Context of opened device
* @param node_id Id of the node. Needs to be in range of the total node count.
* @return product type ID on success, or 0 on failure
*/
uint32_t aciodrv_device_get_node_product_type(struct aciodrv_device_ctx *device, uint8_t node_id);
/**
* Get the product version of an enumerated node.
*

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

@@ -0,0 +1,80 @@
#define LOG_MODULE "aciodrv-rvol"
#include <stdio.h>
#include <string.h>
#include "aciodrv/device.h"
#include "util/log.h"
static bool aciodrv_rvol_change_expand_mode(
struct aciodrv_device_ctx *device,
uint8_t node_id,
uint8_t mode)
{
struct ac_io_message msg;
log_assert(device);
msg.addr = node_id + 1;
msg.cmd.code = ac_io_u16(AC_IO_CMD_RVOL_SET_EXPAND_MODE);
msg.cmd.nbytes = 1;
msg.cmd.raw[0] = (mode | (2 * mode)) << 6;
if (!aciodrv_send_and_recv(
device, &msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
log_warning("RVOL change expand mode failed %d", node_id);
return false;
}
log_info("I/O expand mode set %d, mode: %d",
node_id, mode);
return true;
}
bool aciodrv_rvol_init(
struct aciodrv_device_ctx *device,
uint8_t node_id)
{
log_assert(device);
if (!aciodrv_rvol_change_expand_mode(device, node_id, 1)) {
return false;
}
return true;
}
bool aciodrv_rvol_poll(
struct aciodrv_device_ctx *device,
uint8_t node_id,
const struct ac_io_rvol_poll_out *pout,
struct ac_io_rvol_poll_in *pin)
{
struct ac_io_message msg;
log_assert(device);
log_assert(pout);
msg.addr = node_id + 1;
msg.cmd.code = ac_io_u16(AC_IO_CMD_RVOL_POLL);
msg.cmd.nbytes = sizeof(*pout);
/* buffer size of data we expect */
msg.cmd.rvol_poll_out = *pout;
if (!aciodrv_send_and_recv(
device,
&msg,
offsetof(struct ac_io_message, cmd.raw) + sizeof(*pin))) {
log_warning("Polling of node %d failed", node_id + 1);
return false;
}
if (pin != NULL) {
memcpy(pin, &msg.cmd.rvol_poll_in, sizeof(*pin));
}
return true;
}

36
src/main/aciodrv/rvol.h Normal file
View File

@@ -0,0 +1,36 @@
#ifndef ACIODRV_RVOL_H
#define ACIODRV_RVOL_H
#include "acio/rvol.h"
/**
* Initialize a Revolte (KFCA 1.5) IO board
*
* @param device Context of opened device
* @param node_id Id of the node to initialize (0 based).
* @return True if successful, false on error.
* @note This module is supposed to be used in combination with the common
* device driver foundation.
* @see driver.h
*/
bool aciodrv_rvol_init(struct aciodrv_device_ctx *device, uint8_t node_id);
/**
* Poll a Revolte (KFCA 1.5) IO board
*
* @param device Context of opened device
* @param node_id Id of the node to query (0 based).
* @param pout Pointer to a state struct to write to device
* @param pin Pointer to a state struct to return the current state to
* @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_rvol_poll(
struct aciodrv_device_ctx *device,
uint8_t node_id,
const struct ac_io_rvol_poll_out *pout,
struct ac_io_rvol_poll_in *pin);
#endif

View File

@@ -6,6 +6,5 @@ src_acioemu := \
h44b.c \
hdxs.c \
icca.c \
iccb.c \
pipe.c \

View File

@@ -63,6 +63,8 @@ void ac_io_emu_icca_init(
// default to 1.6.0
icca->version = v160;
// default, most common code
ac_io_emu_icca_set_product_code(icca, AC_IO_EMU_PROD_CODE_ICCA);
}
void ac_io_emu_icca_set_version(
@@ -71,6 +73,12 @@ void ac_io_emu_icca_set_version(
icca->version = version;
}
void ac_io_emu_icca_set_product_code(
struct ac_io_emu_icca *icca, const char product_code[4])
{
memcpy(icca->product_code, product_code, sizeof(icca->product_code));
}
void ac_io_emu_icca_dispatch_request(
struct ac_io_emu_icca *icca, const struct ac_io_message *req)
{
@@ -119,14 +127,15 @@ void ac_io_emu_icca_dispatch_request(
break;
case AC_IO_ICCA_CMD_UNKN_0116:
case AC_IO_ICCA_CMD_UNKN_0120:
log_misc("AC_IO_ICCA_CMD_UNKN_0120(%d)", req->addr);
log_misc("AC_IO_ICCA_CMD_UNK_%04X(%d)", cmd_code, req->addr);
ac_io_emu_icca_send_status(icca, req, 0x00);
break;
case AC_IO_ICCA_CMD_BEGIN_KEYPAD:
log_misc("AC_IO_ICCA_CMD_BEGIN_KEYPAD(%d)", req->addr);
case AC_IO_ICCA_CMD_DEVICE_CONTROL:
log_misc("AC_IO_ICCA_CMD_DEVICE_CONTROL(%d)", req->addr);
ac_io_emu_icca_send_status(icca, req, 0x00);
icca->keypad_started = true;
@@ -138,48 +147,52 @@ 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;
uint8_t cmd;
if(icca->version == v150) {
ac_io_emu_icca_send_state(icca, req, 0, false);
} else {
struct ac_io_icca_misc *misc =
(struct ac_io_icca_misc *) &req->cmd.raw;
uint8_t cmd;
switch (misc->subcmd) {
case AC_IO_ICCA_SUBCMD_CARD_SLOT_CLOSE:
cmd = EAM_IO_CARD_SLOT_CMD_CLOSE;
break;
switch (misc->subcmd) {
case AC_IO_ICCA_SUBCMD_CARD_SLOT_CLOSE:
cmd = EAM_IO_CARD_SLOT_CMD_CLOSE;
break;
case AC_IO_ICCA_SUBCMD_CARD_SLOT_OPEN:
cmd = EAM_IO_CARD_SLOT_CMD_OPEN;
break;
case AC_IO_ICCA_SUBCMD_CARD_SLOT_OPEN:
cmd = EAM_IO_CARD_SLOT_CMD_OPEN;
break;
case AC_IO_ICCA_SUBCMD_CARD_SLOT_EJECT:
cmd = EAM_IO_CARD_SLOT_CMD_EJECT;
icca->engaged = false;
break;
case AC_IO_ICCA_SUBCMD_CARD_SLOT_EJECT:
cmd = EAM_IO_CARD_SLOT_CMD_EJECT;
icca->engaged = false;
break;
case 3:
cmd = EAM_IO_CARD_SLOT_CMD_READ;
break;
case 3:
cmd = EAM_IO_CARD_SLOT_CMD_READ;
break;
default:
cmd = 0xFF;
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);
default:
cmd = 0xFF;
log_warning(
"Unhandled slot command %X, node %d",
misc->subcmd,
icca->unit_no);
break;
}
}
/* response with current slot state */
ac_io_emu_icca_send_status(icca, req, misc->subcmd);
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);
}
}
/* response with current slot state */
ac_io_emu_icca_send_status(icca, req, misc->subcmd);
}
break;
}
@@ -202,12 +215,14 @@ void ac_io_emu_icca_dispatch_request(
break;
case AC_IO_ICCA_CMD_POLL_FELICA:
icca->detected_new_reader = true;
if (icca->version == v170) {
if (icca->version == v150) {
ac_io_emu_icca_send_state(icca, req, 0, false);
} else if (icca->version == v170) {
ac_io_emu_icca_send_empty(icca, req);
icca->detected_new_reader = true;
} else {
ac_io_emu_icca_send_status(icca, req, 0x01);
icca->detected_new_reader = true;
}
break;
@@ -244,8 +259,6 @@ static void ac_io_emu_icca_cmd_send_version(
resp.cmd.version.major = 0x01;
if (icca->version == v150) {
log_warning(
"ICCA v1.5.0 emulation requested, please remove this log once implemented");
resp.cmd.version.minor = 0x05;
} else if (icca->version == v160) {
resp.cmd.version.minor = 0x06;
@@ -262,7 +275,7 @@ static void ac_io_emu_icca_cmd_send_version(
memcpy(
resp.cmd.version.product_code,
"ICCA",
icca->product_code,
sizeof(resp.cmd.version.product_code));
strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date));
strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time));

View File

@@ -12,6 +12,11 @@ enum ac_io_emu_icca_version {
v170 = 0x7,
};
// ICC product types for ac_io_emu_icca_set_product_code
#define AC_IO_EMU_PROD_CODE_ICCA "ICCA"
#define AC_IO_EMU_PROD_CODE_ICCB "ICCB"
#define AC_IO_EMU_PROD_CODE_ICCC "ICCC"
struct ac_io_emu_icca {
struct ac_io_emu *emu;
uint8_t unit_no;
@@ -28,6 +33,7 @@ struct ac_io_emu_icca {
uint64_t time_counter_last_poll;
enum ac_io_emu_icca_version version;
char product_code[4];
bool cipher_started;
uint32_t cipher_keys[4];
};
@@ -39,6 +45,12 @@ void ac_io_emu_icca_init(
void ac_io_emu_icca_set_version(
struct ac_io_emu_icca *icca, enum ac_io_emu_icca_version version);
// optional, call after init to override default "ICCA" product code.
// Some games may refuse to boot or expect a different packet format when using
// one of the alternative codes such as ICCB or ICCC
void ac_io_emu_icca_set_product_code(
struct ac_io_emu_icca *icca, const char product_code[4]);
void ac_io_emu_icca_dispatch_request(
struct ac_io_emu_icca *icca, const struct ac_io_message *req);

View File

@@ -1,223 +0,0 @@
#define LOG_MODULE "acioemu-iccb"
#include "acioemu/iccb.h"
#include <windows.h> /* for _BitScanForward */
#include <stdint.h>
#include <string.h>
#include "acio/iccb.h"
#include "acioemu/emu.h"
#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);
static void ac_io_emu_iccb_send_state(
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);
static void ac_io_emu_iccb_send_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)
{
memset(iccb, 0, sizeof(*iccb));
iccb->emu = emu;
iccb->unit_no = unit_no;
}
void ac_io_emu_iccb_dispatch_request(
struct ac_io_emu_iccb *iccb, const struct ac_io_message *req)
{
uint16_t cmd_code;
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_iccb_cmd_send_version(iccb, req);
break;
case AC_IO_CMD_START_UP:
log_misc("AC_IO_CMD_START_UP(%d)", req->addr);
ac_io_emu_iccb_send_status(iccb, req, 0x00);
break;
case AC_IO_CMD_KEEPALIVE:
ac_io_emu_iccb_send_empty(iccb, req);
break;
case AC_IO_ICCB_CMD_QUEUE_LOOP_START:
log_misc("AC_IO_CMD_QUEUE_LOOP_START(%d)", req->addr);
ac_io_emu_iccb_send_status(iccb, req, 0x00);
break;
case AC_IO_ICCB_CMD_UNK_0100:
case AC_IO_ICCB_CMD_UNK_0116:
case AC_IO_ICCB_CMD_UNK_0120:
log_misc("AC_IO_ICCB_CMD_UNK_%04X(%d)", cmd_code, req->addr);
ac_io_emu_iccb_send_status(iccb, req, 0x00);
break;
case AC_IO_ICCB_CMD_SLEEP:
ac_io_emu_iccb_send_status(iccb, req, 0x00);
break;
case AC_IO_ICCB_CMD_UNK_135:
/* log_misc("AC_IO_ICCB_CMD_UNK_135"); */
ac_io_emu_iccb_send_state(iccb, req);
break;
case AC_IO_ICCB_CMD_POLL:
/* log_misc("AC_IO_ICCB_CMD_POLL"); */
ac_io_emu_iccb_send_state(iccb, req);
break;
case AC_IO_ICCB_CMD_READ_CARD:
/* log_misc("AC_IO_ICCB_CMD_READ_CARD"); */
ac_io_emu_iccb_send_state(iccb, req);
break;
default:
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_message resp;
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
resp.cmd.code = req->cmd.code;
resp.cmd.seq_no = req->cmd.seq_no;
resp.cmd.nbytes = sizeof(resp.cmd.version);
resp.cmd.version.type = ac_io_u32(AC_IO_NODE_TYPE_ICCB);
resp.cmd.version.flag = 0x00;
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));
strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date));
strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time));
ac_io_emu_response_push(iccb->emu, &resp, 0);
}
static void ac_io_emu_iccb_send_empty(
struct ac_io_emu_iccb *iccb, const struct ac_io_message *req)
{
struct ac_io_message resp;
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
resp.cmd.code = req->cmd.code;
resp.cmd.seq_no = req->cmd.seq_no;
resp.cmd.nbytes = 0;
ac_io_emu_response_push(iccb->emu, &resp, 0);
}
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_message resp;
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
resp.cmd.code = req->cmd.code;
resp.cmd.seq_no = req->cmd.seq_no;
resp.cmd.nbytes = sizeof(resp.cmd.status);
resp.cmd.status = status;
ac_io_emu_response_push(iccb->emu, &resp, 0);
}
static void ac_io_emu_iccb_send_state(
struct ac_io_emu_iccb *iccb, const struct ac_io_message *req)
{
struct ac_io_message resp;
struct ac_io_iccb_state *body;
bool sensor;
/* state update */
if (!eam_io_poll(iccb->unit_no)) {
log_warning("Polling eamio failed");
}
sensor = eam_io_get_sensor_state(iccb->unit_no);
if (sensor != iccb->last_sensor) {
if (sensor) {
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);
} else {
iccb->fault = false;
}
}
iccb->last_sensor = sensor;
if (iccb->fault) {
memset(iccb->uid, 0, sizeof(iccb->uid));
}
/* create response */
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
resp.cmd.code = req->cmd.code;
resp.cmd.seq_no = req->cmd.seq_no;
resp.cmd.nbytes = sizeof(struct ac_io_iccb_state);
body = (struct ac_io_iccb_state *) &resp.cmd.raw;
if (sensor) {
body->sensor_state = AC_IO_ICCB_SENSOR_CARD;
} else {
body->sensor_state = AC_IO_ICCB_SENSOR_NO_CARD;
}
if (!iccb->fault) {
memcpy(body->uid, iccb->uid, sizeof(body->uid));
}
body->card_type = 0x30 | (iccb->card_result - 1);
body->unk2 = 0;
// 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
body->unk3 = 0x03;
memset(body->unk4, 0, sizeof(body->unk4));
ac_io_emu_response_push(iccb->emu, &resp, 0);
}

View File

@@ -1,24 +0,0 @@
#ifndef AC_IO_EMU_ICCB_H
#define AC_IO_EMU_ICCB_H
#include <stdbool.h>
#include <stdint.h>
#include "acioemu/emu.h"
struct ac_io_emu_iccb {
struct ac_io_emu *emu;
uint8_t unit_no;
bool fault;
bool last_sensor;
uint8_t uid[8];
uint8_t card_result;
};
void ac_io_emu_iccb_init(
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);
#endif

View File

@@ -9,6 +9,7 @@ libs_aciotest := \
src_aciotest := \
icca.c \
kfca.c \
bi2a-sdvx.c \
panb.c \
rvol.c \
bi2a-sdvx.c \
main.c \

View File

@@ -11,6 +11,7 @@
#include "aciotest/icca.h"
#include "aciotest/kfca.h"
#include "aciotest/panb.h"
#include "aciotest/rvol.h"
#include "util/log.h"
@@ -21,31 +22,37 @@ static uint8_t bi2a_mode = 0;
* Enumerate supported ACIO nodes based on their product id.
*/
static bool aciotest_assign_handler(
char product[4], struct aciotest_handler_node_handler *handler)
uint32_t product_type, struct aciotest_handler_node_handler *handler)
{
if (!memcmp(product, "ICCA", 4) || !memcmp(product, "ICCB", 4) ||
!memcmp(product, "ICCC", 4)) {
if (product_type == AC_IO_NODE_TYPE_ICCA) {
handler->init = aciotest_icca_handler_init;
handler->update = aciotest_icca_handler_update;
return true;
}
if (!memcmp(product, "KFCA", 4)) {
if (product_type == AC_IO_NODE_TYPE_KFCA) {
handler->init = aciotest_kfca_handler_init;
handler->update = aciotest_kfca_handler_update;
return true;
}
if (!memcmp(product, "PANB", 4)) {
if (product_type == AC_IO_NODE_TYPE_PANB) {
handler->init = aciotest_panb_handler_init;
handler->update = aciotest_panb_handler_update;
return true;
}
if (!memcmp(product, "BI2A", 4)) {
if (product_type == AC_IO_NODE_TYPE_RVOL) {
handler->init = aciotest_rvol_handler_init;
handler->update = aciotest_rvol_handler_update;
return true;
}
if (product_type == AC_IO_NODE_TYPE_BI2A) {
if (bi2a_mode == 0) {
handler->init = aciotest_bi2a_sdvx_handler_init;
handler->update = aciotest_bi2a_sdvx_handler_update;
@@ -99,22 +106,22 @@ int main(int argc, char **argv)
for (uint8_t i = 0; i < node_count; i++) {
char product[4];
uint32_t product_type = aciodrv_device_get_node_product_type(device, i);
aciodrv_device_get_node_product_ident(device, i, product);
printf(
"> %d: %c%c%c%c\n",
"> %d: %c%c%c%c (%08x)\n",
i + 1,
product[0],
product[1],
product[2],
product[3]);
product[3],
product_type);
if (!aciotest_assign_handler(product, &handler[i])) {
if (!aciotest_assign_handler(product_type, &handler[i])) {
printf(
"ERROR: Unsupported acio node product %c%c%c%c on node %d\n",
product[0],
product[1],
product[2],
product[3],
"ERROR: Unsupported acio node product %08x on node %d\n",
product_type,
i);
}
}

73
src/main/aciotest/rvol.c Normal file
View File

@@ -0,0 +1,73 @@
#include "aciotest/rvol.h"
#include "acio/acio.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "aciodrv/rvol.h"
static struct ac_io_rvol_poll_out pout;
bool aciotest_rvol_handler_init(
struct aciodrv_device_ctx *device, uint8_t node_id, void **ctx)
{
memset(&pout, 0, sizeof(pout));
return aciodrv_rvol_init(device, node_id);
}
bool aciotest_rvol_handler_update(
struct aciodrv_device_ctx *device, uint8_t node_id, void *ctx)
{
struct ac_io_rvol_poll_in pin;
if (!aciodrv_rvol_poll(device, node_id, &pout, &pin)) {
return false;
}
uint8_t selected_light = pin.spinners[0] / 43;
printf(
">>> RVOL %d\n"
"Press: %3d %3d %3d\n"
" %3d %3d\n"
"\n"
"Spin: %3d %3d %3d\n"
" %3d %3d\n"
"\n"
"Pedal: %3d\n"
"\n"
"Editing light #%d R: %d G: %d B: %d\n"
"(Change light with Spinner 1, values with 3-5)\n",
node_id,
pin.buttons_2.spinner_1,
pin.buttons_3.spinner_3,
pin.buttons_1.spinner_5,
pin.buttons_2.spinner_2,
pin.buttons_1.spinner_4,
pin.spinners[0],
pin.spinners[2],
pin.spinners[4],
pin.spinners[1],
pin.spinners[3],
!pin.buttons_1.pedal,
selected_light,
pin.spinners[2] / 2,
pin.spinners[3] / 2,
pin.spinners[4] / 2
);
memset(&pout, 0, sizeof(pout));
if (selected_light == 5) {
pout.title.r = pin.spinners[2] / 2;
pout.title.g = pin.spinners[3] / 2;
pout.title.b = pin.spinners[4] / 2;
} else {
pout.spinner[selected_light].r = pin.spinners[2] / 2;
pout.spinner[selected_light].g = pin.spinners[3] / 2;
pout.spinner[selected_light].b = pin.spinners[4] / 2;
}
return true;
}

14
src/main/aciotest/rvol.h Normal file
View File

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

56
src/main/bio2/bi2a-ddr.h Normal file
View File

@@ -0,0 +1,56 @@
#ifndef BIO2_BI2A_DDR
#define BIO2_BI2A_DDR
#include "bio2/bio2.h"
#pragma pack(push, 1)
struct bi2a_ddr_system_panel {
uint8_t b_unk1 : 1;
uint8_t b_coin : 1;
uint8_t b_service : 1;
uint8_t b_test : 1;
uint8_t b_un2 : 4;
};
struct bi2a_ddr_player_1_panel {
uint8_t b_unk : 3;
uint8_t b_right : 1;
uint8_t b_left : 1;
uint8_t b_down : 1;
uint8_t b_up : 1;
uint8_t b_start : 1;
};
struct bi2a_ddr_player_2_panel {
uint8_t b_unk1 : 1;
uint8_t b_right : 1;
uint8_t b_left : 1;
uint8_t b_down : 1;
uint8_t b_up : 1;
uint8_t b_start : 1;
uint8_t b_unk2 : 2;
};
struct bi2a_ddr_state_in {
uint8_t unk1;
struct bi2a_ddr_system_panel system;
uint8_t unk2[7];
struct bi2a_ddr_player_1_panel player_1;
struct bi2a_ddr_player_2_panel player_2;
uint8_t unk3[5];
};
struct bi2a_ddr_state_out {
uint8_t unk1[40];
};
_Static_assert(
sizeof(struct bi2a_ddr_state_in) == 16,
"bi2a_ddr_state_in is the wrong size");
_Static_assert(
sizeof(struct bi2a_ddr_state_out) == 40,
"bi2a_ddr_state_out is the wrong size");
#pragma pack(pop)
#endif

View File

@@ -11,6 +11,11 @@ enum bio2_bi2a_cmd {
BIO2_BI2A_CMD_INIT = 0x0100,
BIO2_BI2A_CMD_WATCHDOG = 0x0120,
BIO2_BI2A_CMD_POLL = 0x0152, // For IIDX
// For games using libacio for BIO2 communication
BIO2_BI2A_CMD_ACIO_POLL_NOWD = 0x0112,
BIO2_BI2A_CMD_ACIO_POLL_WD = 0x0113,
BIO2_BI2A_CMD_TAPELED_INIT = 0x0140,
BIO2_BI2A_CMD_TAPELED_SEND = 0x0141,
};
#endif

View File

@@ -52,7 +52,7 @@ void d3d9exhook_config_gfx_init(struct cconfig *config)
config,
D3D9EXHOOK_CONFIG_GFX_CONFINED_KEY,
D3D9EXHOOK_CONFIG_GFX_DEFAULT_CONFINED_VALUE,
"Confine mouse coursor to window");
"Confine mouse cursor to window");
cconfig_util_set_int(
config,

View File

@@ -0,0 +1,13 @@
libs += ddrhook-util
libs_ddrhook-util := \
hook \
hooklib \
util \
src_ddrhook-util := \
dinput.c \
gfx.c \
guid.c \
misc.c \
monitor.c \

View File

@@ -1,4 +1,4 @@
#include <initguid.h>
#include <windows.h>
#include "ddrhook/monitor.h"
#include "ddrhook-util/monitor.h"

View File

@@ -2,7 +2,7 @@
#include <stdint.h>
#include "ddrhook/gfx.h"
#include "ddrhook-util/gfx.h"
#include "hook/pe.h"
#include "hook/table.h"

View File

@@ -7,7 +7,7 @@
#include <stdbool.h>
#include <wchar.h>
#include "ddrhook/monitor.h"
#include "ddrhook-util/monitor.h"
#include "hook/table.h"

View File

@@ -5,6 +5,7 @@ deplibs_ddrhook := \
libs_ddrhook := \
acioemu \
ddrhook-util \
p3ioemu \
p3io \
hook \
@@ -17,12 +18,7 @@ src_ddrhook := \
extio.c \
dllmain.c \
_com4.c \
dinput.c \
gfx.c \
guid.c \
master.c \
misc.c \
monitor.c \
p3io.c \
usbmem.c \
spike.c

View File

@@ -5,9 +5,10 @@
#include "bemanitools/ddrio.h"
#include "bemanitools/eamio.h"
#include "ddrhook-util/gfx.h"
#include "ddrhook/_com4.h"
#include "ddrhook/extio.h"
#include "ddrhook/gfx.h"
#include "ddrhook/master.h"
#include "ddrhook/p3io.h"
#include "ddrhook/spike.h"

View File

@@ -1,8 +1,9 @@
#include "ddrhook/master.h"
#include "ddrhook/dinput.h"
#include "ddrhook/gfx.h"
#include "ddrhook/misc.h"
#include "ddrhook/monitor.h"
#include "ddrhook-util/dinput.h"
#include "ddrhook-util/gfx.h"
#include "ddrhook-util/misc.h"
#include "ddrhook-util/monitor.h"
#include "hook/table.h"

View File

@@ -168,6 +168,14 @@ void eamuse_set_addr(const struct net_addr *addr)
tmp_str2 = net_addr_to_str(&eamuse_server_addr_resolved);
// when resolving URLs with net_str_parse
// it will default to NET_INVALID_PORT if no port is specified
// assume default 80 here as a good sanity check
if (eamuse_server_addr_resolved.ipv4.port == NET_INVALID_PORT) {
log_info("No port was specified, using port 80 as fallback");
eamuse_server_addr_resolved.ipv4.port = 80;
}
log_info("Target eamuse server %s resolved to %s", tmp_str, tmp_str2);
free(tmp_str);

View File

@@ -0,0 +1,13 @@
libs += jbhook-util
libs_jbhook-util := \
acioemu \
src_jbhook-util := \
acio.c \
eamuse.c \
gfx.c \
mixer.c \
locale.c \
p3io.c \
p4io.c \

View File

@@ -18,7 +18,7 @@
#include "hook/iohook.h"
#include "jbhook/acio.h"
#include "jbhook-util/acio.h"
#include "imports/avs.h"
@@ -32,20 +32,25 @@ static struct ac_io_emu ac_io_emu;
static struct ac_io_emu_icca ac_io_emu_icca;
static struct ac_io_emu_h44b ac_io_emu_h44b;
void ac_io_port_init(void)
void jbhook_util_ac_io_port_init(const wchar_t *filename)
{
ac_io_emu_init(&ac_io_emu, L"COM1");
ac_io_emu_init(&ac_io_emu, filename);
ac_io_emu_icca_init(&ac_io_emu_icca, &ac_io_emu, 0);
ac_io_emu_h44b_init(&ac_io_emu_h44b, &ac_io_emu, 1);
}
void ac_io_port_fini(void)
void jbhook_util_ac_io_port_fini(void)
{
ac_io_emu_fini(&ac_io_emu);
}
void jbhook_util_ac_io_set_iccb(void) {
ac_io_emu_icca_set_version(&ac_io_emu_icca, v150);
ac_io_emu_icca_set_product_code(&ac_io_emu_icca, AC_IO_EMU_PROD_CODE_ICCB);
}
HRESULT
ac_io_port_dispatch_irp(struct irp *irp)
jbhook_util_ac_io_port_dispatch_irp(struct irp *irp)
{
const struct ac_io_message *msg;
HRESULT hr;

View File

@@ -0,0 +1,28 @@
#ifndef JBHOOK1_ACIO_H
#define JBHOOK1_ACIO_H
#include "hook/iohook.h"
/**
* Initialize the ACIO backend for jubeat on the specified COM port.
*/
void jbhook_util_ac_io_port_init(const wchar_t *filename);
/**
* Shutdown the ACIO backend.
*/
void jbhook_util_ac_io_port_fini(void);
/**
* ACIO backend dispatch irp function. This needs to be hooked up to the iohook
* module in order to receive system calls to dispatch for emulation.
*/
HRESULT jbhook_util_ac_io_port_dispatch_irp(struct irp *irp);
/**
* Enable ICCB emulation instead of the default ICCA emulation - some jubeats
* will have IO errors unless explicitly set to ICCB mode.
*/
void jbhook_util_ac_io_set_iccb(void);
#endif

View File

@@ -0,0 +1,144 @@
#define LOG_MODULE "eamuse-hook"
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "hook/table.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/net.h"
#include "util/str.h"
static const char *jbhook_eamuse_konami_url = "eamuse.konami.";
static int(STDCALL *real_getaddrinfo)(
PCSTR pNodeName,
PCSTR pServiceName,
const ADDRINFOA *pHints,
PADDRINFOA *ppResult);
static int STDCALL my_getaddrinfo(
PCSTR pNodeName,
PCSTR pServiceName,
const ADDRINFOA *pHints,
PADDRINFOA *ppResult);
static DWORD WINAPI my_GetIpAddrTable(
PMIB_IPADDRTABLE pIpAddrTable,
PULONG pdwSize,
BOOL bOrder
);
static const struct hook_symbol eamuse_hook_syms[] = {
{
.name = "getaddrinfo",
.ordinal = 176,
.patch = my_getaddrinfo,
.link = (void **) &real_getaddrinfo,
},
};
static const struct hook_symbol network_hook_syms[] = {
{
.name = "GetIpAddrTable",
.patch = my_GetIpAddrTable,
},
};
static int STDCALL my_getaddrinfo(
PCSTR pNodeName,
PCSTR pServiceName,
const ADDRINFOA *pHints,
PADDRINFOA *ppResult)
{
log_misc("my_getaddrinfo: %s, %s", pNodeName, pServiceName);
/* resolve eamuse.konami.fun/com to 127.0.0.1 to avoid lag spikes every
150 seconds which might happen in-game as well */
if (!strncmp(
pNodeName,
jbhook_eamuse_konami_url,
strlen(jbhook_eamuse_konami_url))) {
log_info("Resolve konami.eamuse.XXX -> localhost");
pNodeName = "localhost";
}
return real_getaddrinfo(pNodeName, pServiceName, pHints, ppResult);
}
static DWORD get_best_ip(void) {
PIP_ADAPTER_INFO info = NULL;
struct net_addr addr;
// fallback to a very obviously wrong value
DWORD ret = (5 << 24) | (7 << 16) | (3 << 8) | (0 << 0);
ULONG sz = 0;
// this uses our hooked GetAdaptersInfo from hooklib/adapter.c, thus using
// the preferred interface instead of the default order
log_assert(GetAdaptersInfo(info, &sz) == ERROR_BUFFER_OVERFLOW);
info = malloc(sz);
if(GetAdaptersInfo(info, &sz) != NO_ERROR) {
goto CLEANUP;
}
if(!net_str_parse(info->IpAddressList.IpAddress.String, &addr)) {
goto CLEANUP;
}
// MS docs say this should be in network byte order, but we need to return
// host byte order for the game to not throw the IP error
ret = addr.ipv4.addr;
CLEANUP:
free(info);
return ret;
}
/**
* In new games via network.dll:network_addr_is_changed and in old games
* directly, this function is called to compare the current IP address vs the IP
* address when the game was first loaded. If the two are different, an error is
* printed. It can be dismissed but will show up every ~10 seconds, impeding
* gameplay. Because GetAdaptersInfo is hooked to return a (sometimes) different
* adapter, computers with multiple interfaces will often fail this comparison
* check. By also hooking this function, the IP addresses of the two calls will
* agree.
*/
static DWORD WINAPI my_GetIpAddrTable(
PMIB_IPADDRTABLE pIpAddrTable,
PULONG pdwSize,
BOOL bOrder
) {
ULONG in = *pdwSize;
// 1 element return table
*pdwSize = sizeof(MIB_IPADDRTABLE) + sizeof(MIB_IPADDRROW);
if(in < *pdwSize) {
return ERROR_INSUFFICIENT_BUFFER;
}
pIpAddrTable->dwNumEntries = 1;
pIpAddrTable->table[0].dwAddr = get_best_ip();
return NO_ERROR;
}
void jbhook_util_eamuse_hook_init(void)
{
hook_table_apply(
NULL, "ws2_32.dll", eamuse_hook_syms, lengthof(eamuse_hook_syms));
hook_table_apply(
NULL, "iphlpapi.dll", network_hook_syms, lengthof(network_hook_syms));
log_info("Inserted eamuse hooks");
}

View File

@@ -0,0 +1,6 @@
#ifndef JBHOOK_UTIL_EAMUSE_H
#define JBHOOK_UTIL_EAMUSE_H
void jbhook_util_eamuse_hook_init(void);
#endif

219
src/main/jbhook-util/gfx.c Normal file
View File

@@ -0,0 +1,219 @@
#define LOG_MODULE "jbhook-gfx"
#include <windows.h>
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <GL/gl.h>
#include <GL/glext.h>
#include "hook/com-proxy.h"
#include "hook/table.h"
#include "imports/glhelper.h"
#include "jbhook-util/gfx.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/str.h"
#include "util/time.h"
static void __stdcall hook_glFlush(void);
static void (__stdcall *real_glFlush)(void);
static void hook_glBindFramebufferEXT(GLenum target, GLuint framebuffer);
static void (*real_glBindFramebufferEXT)(GLenum target, GLuint framebuffer);
static void hook_infodispcore_set_angle(void* this, int angle);
static const struct hook_symbol jbhook1_opengl_hook_syms[] = {
{.name = "glFlush",
.patch = hook_glFlush,
.link = (void **) &real_glFlush},
};
static const struct hook_symbol jbhook1_glhelper_hook_syms[] = {
{.name = "glBindFramebufferEXT",
.patch = hook_glBindFramebufferEXT,
.link = (void **) &real_glBindFramebufferEXT},
};
// on knit/copious, this gives us right-side-up errors, too!
static const struct hook_symbol jbhook_infodisp_hook_syms[] = {
{.name = "?set_angle@infodispcore@@QAEXH@Z",
.patch = hook_infodispcore_set_angle},
};
static DWORD STDCALL my_GetGlyphOutline(
HDC hdc,
UINT uChar,
UINT uFormat,
LPGLYPHMETRICS lpgm,
DWORD cbBuffer,
LPVOID lpvBuffer,
const MAT2 *lpmat2);
static DWORD(STDCALL *real_GetGlyphOutline)(
HDC hdc,
UINT uChar,
UINT uFormat,
LPGLYPHMETRICS lpgm,
DWORD cbBuffer,
LPVOID lpvBuffer,
const MAT2 *lpmat2);
static const struct hook_symbol gfx_hook_syms[] = {
{.name = "GetGlyphOutlineA",
.patch = my_GetGlyphOutline,
.link = (void **) &real_GetGlyphOutline},
{
.name = "IsDBCSLeadByteEx",
.patch = my_GetGlyphOutline, // !??
.link = (void **) &real_GetGlyphOutline // !??
},
};
static DWORD STDCALL my_GetGlyphOutline(
HDC hdc,
UINT uChar,
UINT uFormat,
LPGLYPHMETRICS lpgm,
DWORD cbBuffer,
LPVOID lpvBuffer,
const MAT2 *lpmat2)
{
if (IsDBCSLeadByteEx(CP_ACP, uChar & 0xFF)) {
log_warning("!!!!!!!!");
char tmp[2];
tmp[0] = uChar & 0xFF;
tmp[1] = (uChar >> 8) & 0xFF;
MultiByteToWideChar(
CP_ACP, MB_USEGLYPHCHARS, tmp, 2, lpvBuffer, cbBuffer);
}
return real_GetGlyphOutline(
hdc, uChar, uFormat, lpgm, cbBuffer, lpvBuffer, lpmat2);
}
void jbhook_util_gfx_hook_init(void)
{
hook_table_apply(NULL, "gdi32.dll", gfx_hook_syms, lengthof(gfx_hook_syms));
log_info("Inserted gfx hooks");
}
void jbhook_util_gfx_set_windowed(bool framed)
{
}
void jbhook_util_gfx_install_vertical_hooks(void) {
hook_table_apply(
NULL,
"opengl32.dll",
jbhook1_opengl_hook_syms,
lengthof(jbhook1_opengl_hook_syms));
hook_table_apply(
NULL,
"glhelper.dll",
jbhook1_glhelper_hook_syms,
lengthof(jbhook1_glhelper_hook_syms));
hook_table_apply(
NULL,
"infodisp.dll",
jbhook_infodisp_hook_syms,
lengthof(jbhook_infodisp_hook_syms));
log_info("Inserted vertical display hooks");
}
static void hook_infodispcore_set_angle(void* this, int angle) {
// ignore
}
// Welcome to OpenGL land! There is a ton of boilerplate needed here "just" to
// rotate the render output
// only jubeat uses openGL, let alone needs rotation at all, so hardcode for now
#define W 768
#define H 1360
// the framebuffer we redirect renders to instead of rendering to the screen
static GLuint fb;
static GLuint color;
static void fb_init(void) {
static bool init_done = false;
if(init_done) {
return;
}
init_done = true;
glGenFramebuffersEXT(1, &fb);
glGenTextures(1, &color);
}
static void __stdcall hook_glFlush(void) {
// 3 bytes per RGB pixel
// these could really be stack variables but they are too big for gcc's
// default stack size, and it's no problem for 6MiB of data to hang around
static uint8_t pixels_raw[W*H*3];
static uint8_t pixels_rot[W*H*3];
glReadPixels(0, 0, H, W, GL_RGB, GL_UNSIGNED_BYTE, pixels_raw);
// CPU copies may seem slow here, but this runs fine on my jubeat cab, so
// speed is not a huge concern.
for(size_t x = 0; x < W; x++) {
for(size_t y = 0; y < H; y++) {
memcpy(&pixels_rot[3*(y*W + x)], &pixels_raw[3*((W-x)*H + y)], 3);
}
}
// now *we* get to draw to the main display
real_glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
// the scissor test clips pixels to the game window - must be disabled or
// the draw area is cut off vertically
glDisable(GL_SCISSOR_TEST);
glDrawPixels(W, H, GL_RGB, GL_UNSIGNED_BYTE, pixels_rot);
real_glFlush();
// reset the framebuffer for the next draw - must be after flush (i.e. when
// all state is reset) and before the game tries to draw anything
fb_init();
real_glBindFramebufferEXT(GL_FRAMEBUFFER, fb);
glBindTexture(GL_TEXTURE_2D, color);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, H, W, 0, GL_RGBA,GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
}
// hooking something in glhelper.dll (a jubeat supplied DLL) might seem
// insufficiently generic compared to something in opengl32.dll, but the render
// loop of the game makes it very difficult to "catch" the rendering at the
// right place otherwise. This works with all horizontal jubeats, and they
// stopped needing rotation fixes starting with saucer.
static void hook_glBindFramebufferEXT(GLenum target, GLuint framebuffer) {
fb_init();
// check this is actually the screen - the game also uses internal
// framebuffers for some parts of the display
if(target == GL_FRAMEBUFFER && framebuffer == 0) {
framebuffer = fb;
}
return real_glBindFramebufferEXT(target, framebuffer);
}

View File

@@ -7,7 +7,7 @@
* Hook some gfx related functions to patch gfx related stuff
* like enabling window mode.
*/
void gfx_hook_init(void);
void jbhook_util_gfx_hook_init(void);
/**
* Set the game to window mode.
@@ -15,6 +15,11 @@ void gfx_hook_init(void);
* @param framed True to add a window frame and make the window
* movable, resizable, minizable. False for no frame.
*/
void gfx_set_windowed(bool framed);
void jbhook_util_gfx_set_windowed(bool framed);
/**
* Rotate a horizontal-by-default jubeat window to vertical
*/
void jbhook_util_gfx_install_vertical_hooks(void);
#endif

View File

@@ -0,0 +1,37 @@
#define LOG_MODULE "jbhook-locale"
#include <windows.h>
#include "hook/table.h"
#include "util/defs.h"
#include "util/log.h"
// ANSI/OEM Japanese; Japanese (Shift-JIS)
#define CODEPAGE_SHIFT_JIS 932
static UINT WINAPI hook_GetACP();
static UINT WINAPI hook_GetOEMCP();
static const struct hook_symbol locale_hook_syms[] = {
{.name = "GetOEMCP",
.patch = hook_GetACP},
{.name = "GetOEMCP",
.patch = hook_GetOEMCP},
};
static UINT WINAPI hook_GetACP() {
return CODEPAGE_SHIFT_JIS;
}
static UINT WINAPI hook_GetOEMCP() {
return CODEPAGE_SHIFT_JIS;
}
void jbhook_util_locale_hook_init(void)
{
hook_table_apply(NULL, "kernel32.dll", locale_hook_syms, lengthof(locale_hook_syms));
log_info("Inserted locale hooks");
}

View File

@@ -0,0 +1,6 @@
#ifndef JBHOOK_LOCALE_H
#define JBHOOK_LOCALE_H
void jbhook_util_locale_hook_init(void);
#endif

View File

@@ -0,0 +1,79 @@
#define LOG_MODULE "jbhook-mixer"
#include <windows.h>
#include <mmsystem.h>
#include "hook/table.h"
#include "util/defs.h"
#include "util/log.h"
MMRESULT STDCALL hook_mixerGetLineControlsA(HMIXEROBJ hmxobj, LPMIXERLINECONTROLSA pmxlc, DWORD fdwControls);
MMRESULT STDCALL hook_mixerGetDevCapsA(UINT_PTR uMxId, LPMIXERCAPSA pmxcaps, UINT cbmxcaps);
MMRESULT STDCALL hook_mixerOpen(LPHMIXER phmx, UINT uMxId, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen);
MMRESULT STDCALL hook_mixerSetControlDetails(HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails);
MMRESULT STDCALL hook_mixerGetControlDetailsA(HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails);
MMRESULT STDCALL hook_mixerClose(HMIXER hmx);
MMRESULT STDCALL hook_mixerGetLineInfoA(HMIXEROBJ hmxobj, LPMIXERLINEA pmxl, DWORD fdwInfo);
static const struct hook_symbol mixer_hook_syms[] = {
{.name = "mixerGetLineControlsA",
.patch = hook_mixerGetLineControlsA},
{.name = "mixerGetDevCapsA",
.patch = hook_mixerGetDevCapsA},
{.name = "mixerOpen",
.patch = hook_mixerOpen},
{.name = "mixerSetControlDetails",
.patch = hook_mixerSetControlDetails},
{.name = "mixerGetControlDetailsA",
.patch = hook_mixerGetControlDetailsA},
{.name = "mixerClose",
.patch = hook_mixerClose},
{.name = "mixerGetLineInfoA",
.patch = hook_mixerGetLineInfoA},
};
/*
Some of these functions return values which are used as pointer offsets into
memory, but that doesn't matter because the game never *modifies* the
pointed-to value, only passes it to the other mixer functions. So it's safe
to not set any of the returning data.
*/
MMRESULT STDCALL hook_mixerOpen(LPHMIXER phmx, UINT uMxId, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen) {
*(DWORD*)phmx = 1234; // any non-zero value is fine
return MMSYSERR_NOERROR;
}
MMRESULT STDCALL hook_mixerClose(HMIXER hmx) {
return MMSYSERR_NOERROR;
}
MMRESULT STDCALL hook_mixerGetLineControlsA(HMIXEROBJ hmxobj, LPMIXERLINECONTROLSA pmxlc, DWORD fdwControls) {
return MMSYSERR_NOERROR;
}
MMRESULT STDCALL hook_mixerGetDevCapsA(UINT_PTR uMxId, LPMIXERCAPSA pmxcaps, UINT cbmxcaps) {
return MMSYSERR_NOERROR;
}
MMRESULT STDCALL hook_mixerGetControlDetailsA(HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails) {
return MMSYSERR_NOERROR;
}
MMRESULT STDCALL hook_mixerGetLineInfoA(HMIXEROBJ hmxobj, LPMIXERLINEA pmxl, DWORD fdwInfo) {
return MMSYSERR_NOERROR;
}
MMRESULT STDCALL hook_mixerSetControlDetails(HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails) {
return MMSYSERR_NOERROR;
}
void jbhook_util_mixer_hook_init(void)
{
hook_table_apply(NULL, "winmm.dll", mixer_hook_syms, lengthof(mixer_hook_syms));
log_info("Inserted mixer hooks");
}

View File

@@ -0,0 +1,11 @@
#ifndef JBHOOK_MIXER_H
#define JBHOOK_MIXER_H
/**
* Hook some mixer related functions and stub out attempts to change the volume.
* In addition to being annoying, this can fail on Vista+ on some outputs,
* despite not actually preventing sound from playing.
*/
void jbhook_util_mixer_hook_init(void);
#endif

206
src/main/jbhook-util/p3io.c Normal file
View File

@@ -0,0 +1,206 @@
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include "bemanitools/jbio.h"
#include "jbhook-util/p3io.h"
#include "p3ioemu/emu.h"
#include "p3ioemu/uart.h"
#include "security/rp-sign-key.h"
#include "security/rp3.h"
#include "util/log.h"
static HRESULT jbhook_p3io_read_jamma(void *ctx, uint32_t *state);
static HRESULT jbhook_p3io_get_roundplug(
void *ctx, uint8_t plug_id, uint8_t *rom, uint8_t *eeprom);
static HRESULT jbhook_p3io_set_outputs(void *ctx, uint32_t state);
/*
0:0 b13
0:1 -
0:2 b15
0:3 -
0:4 test
0:5 coin
0:6 service
0:7 -
1:0 -
1:1 b4
1:2 b8
1:3 b12
1:4 b16
1:5 b3
1:6 b7
1:7 b11
2:0 -
2:1 b2
2:2 b6
2:3 b10
2:4 b14
2:5 b1
2:6 b5
2:7 b9
3:0 -
3:1 -
3:2 -
3:3 -
3:4 -
3:5 -
3:6 -
3:7 -
*/
static const uint32_t jbhook_p3io_panel_mappings[] = {
(1 << 21),
(1 << 17),
(1 << 13),
(1 << 9),
(1 << 22),
(1 << 18),
(1 << 14),
(1 << 10),
(1 << 23),
(1 << 19),
(1 << 15),
(1 << 11),
(1 << 0),
(1 << 20),
(1 << 2),
(1 << 12),
};
static const uint32_t jbhook_p3io_sys_button_mappings[] = {
(1 << 4),
(1 << 6),
(1 << 5),
};
static struct security_mcode jbhook_p3io_mcode;
static struct security_id jbhook_p3io_pcbid;
static struct security_id jbhook_p3io_eamid;
static const struct p3io_ops p3io_ddr_ops = {
.read_jamma = jbhook_p3io_read_jamma,
.get_roundplug = jbhook_p3io_get_roundplug,
.set_outputs = jbhook_p3io_set_outputs,
};
void jbhook_util_p3io_init(
const struct security_mcode *mcode,
const struct security_id *pcbid,
const struct security_id *eamid)
{
memcpy(&jbhook_p3io_mcode, mcode, sizeof(struct security_mcode));
memcpy(&jbhook_p3io_pcbid, pcbid, sizeof(struct security_id));
memcpy(&jbhook_p3io_eamid, eamid, sizeof(struct security_id));
p3io_emu_init(&p3io_ddr_ops, NULL);
}
void jbhook_util_p3io_fini(void)
{
p3io_emu_fini();
}
static HRESULT jbhook_p3io_read_jamma(void *ctx, uint32_t *state)
{
uint16_t panels;
uint8_t buttons;
log_assert(state != NULL);
*state = 0;
if (!jb_io_read_inputs()) {
log_warning("Reading inputs from jbio failed");
return E_FAIL;
}
panels = jb_io_get_panel_inputs();
buttons = jb_io_get_sys_inputs();
for (uint8_t i = 0; i < 16; i++) {
// panels are active-low
if ((panels & (1 << i)) == 0) {
*state |= jbhook_p3io_panel_mappings[i];
}
}
for (uint8_t i = 0; i < 2; i++) {
// sys buttons are active-high
if (buttons & (1 << i)) {
*state |= jbhook_p3io_sys_button_mappings[i];
}
}
return S_OK;
}
static HRESULT jbhook_p3io_get_roundplug(
void *ctx, uint8_t plug_id, uint8_t *rom, uint8_t *eeprom)
{
struct security_rp3_eeprom eeprom_out;
if (plug_id == 0) {
/* black */
memcpy(rom, jbhook_p3io_pcbid.id, sizeof(jbhook_p3io_pcbid.id));
security_rp3_generate_signed_eeprom_data(
SECURITY_RP_UTIL_RP_TYPE_BLACK,
&security_rp_sign_key_black_gfdmv4,
&jbhook_p3io_mcode,
&jbhook_p3io_pcbid,
&eeprom_out);
} else {
/* white */
memcpy(rom, jbhook_p3io_eamid.id, sizeof(jbhook_p3io_eamid.id));
security_rp3_generate_signed_eeprom_data(
SECURITY_RP_UTIL_RP_TYPE_WHITE,
&security_rp_sign_key_white_eamuse,
&security_mcode_eamuse,
&jbhook_p3io_eamid,
&eeprom_out);
}
memcpy(eeprom, &eeprom_out, sizeof(struct security_rp3_eeprom));
return S_OK;
}
static HRESULT jbhook_p3io_set_outputs(void *ctx, uint32_t state) {
uint8_t p3io_panel = (state & 0x00FF00) >> 8;
uint8_t p3io_coinblocker = (state & 0xFF0000) >> 16;
enum jb_io_panel_mode panel_mode;
switch(p3io_panel) {
case 5:
panel_mode = JB_IO_PANEL_MODE_TOP_LEFT;
break;
case 4:
panel_mode = JB_IO_PANEL_MODE_TOP_RIGHT;
break;
case 6:
panel_mode = JB_IO_PANEL_MODE_BOTTOM_RIGHT;
break;
case 7:
panel_mode = JB_IO_PANEL_MODE_BOTTOM_LEFT;
break;
default:
panel_mode = JB_IO_PANEL_MODE_ALL;
break;
}
jb_io_set_panel_mode(panel_mode);
// 0x40 has been seen to unblock, no other values observed
jb_io_set_coin_blocker(p3io_coinblocker == 0x00);
return S_OK;
}

View File

@@ -9,13 +9,13 @@
#include "security/mcode.h"
/**
* Initialize the jbhook1 specific p3io emulation backend.
* Initialize the jb01-04 specific p3io emulation backend.
*
* @param mcode Mcode of the target game to run. Required for dongle emulation.
* @param pcbid PCBDID
* @param eamid EAMID
*/
void jbhook1_p3io_init(
void jbhook_util_p3io_init(
const struct security_mcode *mcode,
const struct security_id *pcbid,
const struct security_id *eamid);
@@ -23,6 +23,6 @@ void jbhook1_p3io_init(
/**
* Shutdown the p3io emulation backend.
*/
void jbhook1_p3io_fini(void);
void jbhook_util_p3io_fini(void);
#endif

View File

@@ -6,7 +6,7 @@
#include "imports/avs.h"
#include "jbhook/io.h"
#include "jbhook-util/p4io.h"
#include "p4io/cmd.h"
@@ -20,7 +20,7 @@ static uint32_t jbhook_command_handle(
void *resp,
uint32_t resp_max_len);
static const struct p4ioemu_device_msg_hook jbhook_io_msg = {
static const struct p4ioemu_device_msg_hook jbhook_p4io_msg = {
.jamma2_read = jbhook_io_jamma2_read,
.command_handle = jbhook_command_handle,
.roundplug_read_id = NULL,
@@ -181,7 +181,7 @@ static uint32_t jbhook_command_handle(
}
}
const struct p4ioemu_device_msg_hook *jbhook_io_init(void)
const struct p4ioemu_device_msg_hook *jbhook_p4io_init(void)
{
return &jbhook_io_msg;
return &jbhook_p4io_msg;
}

View File

@@ -3,6 +3,6 @@
#include "p4ioemu/device.h"
const struct p4ioemu_device_msg_hook *jbhook_io_init(void);
const struct p4ioemu_device_msg_hook *jbhook_p4io_init(void);
#endif
#endif

View File

@@ -1,25 +0,0 @@
avsdlls += jbhook
deplibs_jbhook := \
avs \
ldflags_jbhook := \
-lws2_32 \
-liphlpapi \
libs_jbhook := \
acioemu \
eamio \
jbio \
p4ioemu \
hook \
hooklib \
util \
src_jbhook := \
acio.c \
dllmain.c \
eamuse.c \
gfx.c \
options.c \
io.c

View File

@@ -1,98 +0,0 @@
// clang-format off
// Don't format because the order is important here
#include <windows.h>
#include <ntdef.h>
#include <devioctl.h>
#include <ntddser.h>
// clang-format on
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "acioemu/addr.h"
#include "acioemu/emu.h"
#include "acioemu/h44b.h"
#include "acioemu/iccb.h"
#include "hook/iohook.h"
#include "jbhook/acio.h"
#include "imports/avs.h"
#include "util/defs.h"
#include "util/hex.h"
#include "util/iobuf.h"
#include "util/log.h"
#include "util/str.h"
static struct ac_io_emu ac_io_emu;
static struct ac_io_emu_iccb ac_io_emu_iccb;
static struct ac_io_emu_h44b ac_io_emu_h44b;
void ac_io_port_init(void)
{
ac_io_emu_init(&ac_io_emu, L"COM2");
ac_io_emu_iccb_init(&ac_io_emu_iccb, &ac_io_emu, 0);
ac_io_emu_h44b_init(&ac_io_emu_h44b, &ac_io_emu, 1);
}
void ac_io_port_fini(void)
{
ac_io_emu_fini(&ac_io_emu);
}
HRESULT
ac_io_port_dispatch_irp(struct irp *irp)
{
const struct ac_io_message *msg;
HRESULT hr;
log_assert(irp != NULL);
if (!ac_io_emu_match_irp(&ac_io_emu, irp)) {
return iohook_invoke_next(irp);
}
for (;;) {
hr = ac_io_emu_dispatch_irp(&ac_io_emu, irp);
if (hr != S_OK) {
return hr;
}
msg = ac_io_emu_request_peek(&ac_io_emu);
switch (msg->addr) {
case 0:
ac_io_emu_cmd_assign_addrs(&ac_io_emu, msg, 2);
break;
case 1:
ac_io_emu_iccb_dispatch_request(&ac_io_emu_iccb, msg);
break;
case 2:
ac_io_emu_h44b_dispatch_request(&ac_io_emu_h44b, msg);
break;
case AC_IO_BROADCAST:
log_warning("Broadcast(?) message on jubeat ACIO bus?");
break;
default:
log_warning(
"ACIO message on unhandled bus address: %d", msg->addr);
break;
}
ac_io_emu_request_pop(&ac_io_emu);
}
}

View File

@@ -1,8 +0,0 @@
#ifndef JBHOOK_ACIO_H
#define JBHOOK_ACIO_H
void ac_io_port_init(void);
void ac_io_port_fini(void);
HRESULT ac_io_port_dispatch_irp(struct irp *irp);
#endif

View File

@@ -1,67 +0,0 @@
#define LOG_MODULE "eamuse-hook"
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "hook/table.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/str.h"
static const char *jbhook_eamuse_konami_url = "eamuse.konami.";
static int(STDCALL *real_getaddrinfo)(
PCSTR pNodeName,
PCSTR pServiceName,
const ADDRINFOA *pHints,
PADDRINFOA *ppResult);
static int STDCALL my_getaddrinfo(
PCSTR pNodeName,
PCSTR pServiceName,
const ADDRINFOA *pHints,
PADDRINFOA *ppResult);
static const struct hook_symbol eamuse_hook_syms[] = {
{
.name = "getaddrinfo",
.ordinal = 176,
.patch = my_getaddrinfo,
.link = (void **) &real_getaddrinfo,
},
};
static int STDCALL my_getaddrinfo(
PCSTR pNodeName,
PCSTR pServiceName,
const ADDRINFOA *pHints,
PADDRINFOA *ppResult)
{
log_misc("my_getaddrinfo: %s, %s", pNodeName, pServiceName);
/* resolve eamuse.konami.fun/com to 127.0.0.1 to avoid lag spikes every
150 seconds which might happen in-game as well */
if (!strncmp(
pNodeName,
jbhook_eamuse_konami_url,
strlen(jbhook_eamuse_konami_url))) {
log_info("Resolve konami.eamuse.XXX -> localhost");
pNodeName = "localhost";
}
return real_getaddrinfo(pNodeName, pServiceName, pHints, ppResult);
}
void jbhook_eamuse_hook_init(void)
{
hook_table_apply(
NULL, "ws2_32.dll", eamuse_hook_syms, lengthof(eamuse_hook_syms));
log_info("Inserted eamuse hooks");
}

View File

@@ -1,6 +0,0 @@
#ifndef JBHOOK_EAMUSE_H
#define JBHOOK_EAMUSE_H
void jbhook_eamuse_hook_init(void);
#endif

View File

@@ -1,83 +0,0 @@
#define LOG_MODULE "jbhook-gfx"
#include <windows.h>
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "hook/com-proxy.h"
#include "hook/table.h"
#include "jbhook/gfx.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/str.h"
#include "util/time.h"
static DWORD STDCALL my_GetGlyphOutline(
HDC hdc,
UINT uChar,
UINT uFormat,
LPGLYPHMETRICS lpgm,
DWORD cbBuffer,
LPVOID lpvBuffer,
const MAT2 *lpmat2);
static DWORD(STDCALL *real_GetGlyphOutline)(
HDC hdc,
UINT uChar,
UINT uFormat,
LPGLYPHMETRICS lpgm,
DWORD cbBuffer,
LPVOID lpvBuffer,
const MAT2 *lpmat2);
static const struct hook_symbol gfx_hook_syms[] = {
{.name = "GetGlyphOutlineA",
.patch = my_GetGlyphOutline,
.link = (void **) &real_GetGlyphOutline},
{
.name = "IsDBCSLeadByteEx",
.patch = my_GetGlyphOutline, // !??
.link = (void **) &real_GetGlyphOutline // !??
},
};
static DWORD STDCALL my_GetGlyphOutline(
HDC hdc,
UINT uChar,
UINT uFormat,
LPGLYPHMETRICS lpgm,
DWORD cbBuffer,
LPVOID lpvBuffer,
const MAT2 *lpmat2)
{
if (IsDBCSLeadByteEx(CP_ACP, uChar & 0xFF)) {
log_warning("!!!!!!!!");
char tmp[2];
tmp[0] = uChar & 0xFF;
tmp[1] = (uChar >> 8) & 0xFF;
MultiByteToWideChar(
CP_ACP, MB_USEGLYPHCHARS, tmp, 2, lpvBuffer, cbBuffer);
}
return real_GetGlyphOutline(
hdc, uChar, uFormat, lpgm, cbBuffer, lpvBuffer, lpmat2);
}
void gfx_hook_init(void)
{
hook_table_apply(NULL, "gdi32.dll", gfx_hook_syms, lengthof(gfx_hook_syms));
log_info("Inserted gfx hooks");
}
void gfx_set_windowed(bool framed)
{
}

View File

@@ -1,17 +1,21 @@
avsdlls += jbhook1
imps += glhelper
deplibs_jbhook1 := \
avs \
glhelper \
ldflags_jbhook1 := \
-lws2_32 \
-liphlpapi \
-lopengl32 \
libs_jbhook1 := \
acioemu \
cconfig \
eamio \
jbio \
jbhook-util \
p3ioemu \
p3io \
hook \
@@ -20,11 +24,9 @@ libs_jbhook1 := \
util \
src_jbhook1 := \
acio.c \
avs-boot.c \
config-gfx.c \
config-eamuse.c \
config-security.c \
dllmain.c \
log-gftools.c \
p3io.c \

View File

@@ -1,22 +0,0 @@
#ifndef JBHOOK1_ACIO_H
#define JBHOOK1_ACIO_H
#include "hook/iohook.h"
/**
* Initialize the ACIO backend for jubeat.
*/
void ac_io_port_init(void);
/**
* Shutdown the ACIO backend.
*/
void ac_io_port_fini(void);
/**
* ACIO backend dispatch irp function. This needs to be hooked up to the iohook
* module in order to receive system calls to dispatch for emulation.
*/
HRESULT ac_io_port_dispatch_irp(struct irp *irp);
#endif

View File

@@ -7,8 +7,10 @@
#include "util/log.h"
#define JBHOOK1_CONFIG_GFX_WINDOWED_KEY "gfx.windowed"
#define JBHOOK1_CONFIG_GFX_VERTICAL_KEY "gfx.vertical"
#define JBHOOK1_CONFIG_GFX_DEFAULT_WINDOWED_VALUE false
#define JBHOOK1_CONFIG_GFX_DEFAULT_VERTICAL_VALUE true
void jbhook1_config_gfx_init(struct cconfig *config)
{
@@ -17,6 +19,11 @@ void jbhook1_config_gfx_init(struct cconfig *config)
JBHOOK1_CONFIG_GFX_WINDOWED_KEY,
JBHOOK1_CONFIG_GFX_DEFAULT_WINDOWED_VALUE,
"Run the game windowed");
cconfig_util_set_bool(
config,
JBHOOK1_CONFIG_GFX_VERTICAL_KEY,
JBHOOK1_CONFIG_GFX_DEFAULT_VERTICAL_VALUE,
"Adjust the rotation of the game window so it runs vertically");
}
void jbhook1_config_gfx_get(
@@ -33,4 +40,15 @@ void jbhook1_config_gfx_get(
JBHOOK1_CONFIG_GFX_WINDOWED_KEY,
JBHOOK1_CONFIG_GFX_DEFAULT_WINDOWED_VALUE);
}
if (!cconfig_util_get_bool(
config,
JBHOOK1_CONFIG_GFX_VERTICAL_KEY,
&config_gfx->vertical,
JBHOOK1_CONFIG_GFX_DEFAULT_VERTICAL_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
JBHOOK1_CONFIG_GFX_VERTICAL_KEY,
JBHOOK1_CONFIG_GFX_DEFAULT_VERTICAL_VALUE);
}
}

View File

@@ -8,6 +8,7 @@
*/
struct jbhook1_config_gfx {
bool windowed;
bool vertical;
};
/**
@@ -27,4 +28,4 @@ void jbhook1_config_gfx_init(struct cconfig *config);
void jbhook1_config_gfx_get(
struct jbhook1_config_gfx *config_gfx, struct cconfig *config);
#endif
#endif

View File

@@ -11,10 +11,7 @@
#define JBHOOK1_CONFIG_SECURITY_MCODE_KEY "security.mcode"
#define JBHOOK1_CONFIG_SECURITY_DEFAULT_MCODE_VALUE \
jbhook1_config_security_default_mcode
static const struct security_mcode jbhook1_config_security_default_mcode = {
static const struct security_mcode security_mcode_h44 = {
.header = SECURITY_MCODE_HEADER,
.unkn = SECURITY_MCODE_UNKN_C,
.game = SECURITY_MCODE_GAME_JB_1,
@@ -27,7 +24,7 @@ void jbhook1_config_security_init(struct cconfig *config)
{
char *tmp;
tmp = security_mcode_to_str(&JBHOOK1_CONFIG_SECURITY_DEFAULT_MCODE_VALUE);
tmp = security_mcode_to_str(&security_mcode_h44);
cconfig_util_set_str(
config,
@@ -45,7 +42,7 @@ void jbhook1_config_security_get(
char mcode[9];
tmp_default =
security_mcode_to_str(&JBHOOK1_CONFIG_SECURITY_DEFAULT_MCODE_VALUE);
security_mcode_to_str(&security_mcode_h44);
if (!cconfig_util_get_str(
config,
@@ -70,7 +67,7 @@ void jbhook1_config_security_get(
memcpy(
&config_security->mcode,
&JBHOOK1_CONFIG_SECURITY_DEFAULT_MCODE_VALUE,
&security_mcode_h44,
sizeof(struct security_mcode));
}

View File

@@ -16,13 +16,17 @@
#include "hooklib/adapter.h"
#include "hooklib/rs232.h"
#include "jbhook1/acio.h"
#include "jbhook1/avs-boot.h"
#include "jbhook1/config-eamuse.h"
#include "jbhook1/config-gfx.h"
#include "jbhook1/config-security.h"
#include "jbhook1/log-gftools.h"
#include "jbhook1/p3io.h"
#include "jbhook-util/acio.h"
#include "jbhook-util/eamuse.h"
#include "jbhook-util/gfx.h"
#include "jbhook-util/mixer.h"
#include "jbhook-util/p3io.h"
#include "p3ioemu/devmgr.h"
#include "p3ioemu/emu.h"
@@ -72,6 +76,8 @@ static HWND CDECL my_mwindow_create(
log_info("---------------- Begin jbhook mwindow_create ----------------");
log_info("-------------------------------------------------------------");
jbhook_util_mixer_hook_init();
config = cconfig_init();
jbhook1_config_gfx_init(config);
@@ -101,6 +107,14 @@ static HWND CDECL my_mwindow_create(
fullscreen = !config_gfx.windowed;
if(config_gfx.vertical) {
DWORD tmp = window_width;
window_width = window_height;
window_height = tmp;
jbhook_util_gfx_install_vertical_hooks();
}
log_info("Starting up jubeat IO backend");
jb_io_set_loggers(
@@ -119,14 +133,17 @@ static HWND CDECL my_mwindow_create(
log_fatal("Initializing card reader backend failed");
}
jbhook_util_eamuse_hook_init();
iohook_push_handler(p3io_emu_dispatch_irp);
iohook_push_handler(ac_io_port_dispatch_irp);
iohook_push_handler(jbhook_util_ac_io_port_dispatch_irp);
rs232_hook_init();
ac_io_port_init();
jbhook_util_ac_io_port_init(L"COM1");
jbhook_util_ac_io_set_iccb();
p3io_setupapi_insert_hooks(NULL);
jbhook1_p3io_init(
jbhook_util_p3io_init(
&config_security.mcode, &config_eamuse.pcbid, &config_eamuse.eamid);
log_info("-------------------------------------------------------------");

View File

@@ -1,171 +0,0 @@
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include "bemanitools/jbio.h"
#include "jbhook1/p3io.h"
#include "p3ioemu/emu.h"
#include "p3ioemu/uart.h"
#include "security/rp-sign-key.h"
#include "security/rp3.h"
#include "util/log.h"
static HRESULT jbhook1_p3io_read_jamma(void *ctx, uint32_t *state);
static HRESULT jbhook1_p3io_get_roundplug(
void *ctx, uint8_t plug_id, uint8_t *rom, uint8_t *eeprom);
/*
0:0 b13
0:1 -
0:2 b15
0:3 -
0:4 test
0:5 coin
0:6 service
0:7 -
1:0 -
1:1 b4
1:2 b8
1:3 b12
1:4 b16
1:5 b3
1:6 b7
1:7 b11
2:0 -
2:1 b2
2:2 b6
2:3 b10
2:4 b14
2:5 b1
2:6 b5
2:7 b9
3:0 -
3:1 -
3:2 -
3:3 -
3:4 -
3:5 -
3:6 -
3:7 -
*/
static const uint32_t jbhook1_p3io_panel_mappings[] = {
(1 << 21),
(1 << 17),
(1 << 13),
(1 << 9),
(1 << 22),
(1 << 18),
(1 << 14),
(1 << 10),
(1 << 23),
(1 << 19),
(1 << 15),
(1 << 11),
(1 << 0),
(1 << 20),
(1 << 2),
(1 << 12),
};
static const uint32_t jbhook1_p3io_sys_button_mappings[] = {
(1 << 4),
(1 << 6),
(1 << 5),
};
static struct security_mcode jbhook1_p3io_mcode;
static struct security_id jbhook1_p3io_pcbid;
static struct security_id jbhook1_p3io_eamid;
static const struct p3io_ops p3io_ddr_ops = {
.read_jamma = jbhook1_p3io_read_jamma,
.get_roundplug = jbhook1_p3io_get_roundplug,
};
void jbhook1_p3io_init(
const struct security_mcode *mcode,
const struct security_id *pcbid,
const struct security_id *eamid)
{
memcpy(&jbhook1_p3io_mcode, mcode, sizeof(struct security_mcode));
memcpy(&jbhook1_p3io_pcbid, pcbid, sizeof(struct security_id));
memcpy(&jbhook1_p3io_eamid, eamid, sizeof(struct security_id));
p3io_emu_init(&p3io_ddr_ops, NULL);
}
void jbhook1_p3io_finit(void)
{
p3io_emu_fini();
}
static HRESULT jbhook1_p3io_read_jamma(void *ctx, uint32_t *state)
{
uint16_t panels;
uint8_t buttons;
log_assert(state != NULL);
/* lower three bytes low active, highest byte high active */
*state = 0;
if (!jb_io_read_inputs()) {
log_warning("Reading inputs from jbio failed");
return E_FAIL;
}
panels = jb_io_get_panel_inputs();
buttons = jb_io_get_sys_inputs();
for (uint8_t i = 0; i < 16; i++) {
if (panels & (1 << i)) {
*state |= jbhook1_p3io_panel_mappings[i];
}
}
for (uint8_t i = 0; i < 2; i++) {
if (buttons & (1 << i)) {
*state |= jbhook1_p3io_sys_button_mappings[i];
}
}
return S_OK;
}
static HRESULT jbhook1_p3io_get_roundplug(
void *ctx, uint8_t plug_id, uint8_t *rom, uint8_t *eeprom)
{
struct security_rp3_eeprom eeprom_out;
if (plug_id == 0) {
/* black */
memcpy(rom, jbhook1_p3io_pcbid.id, sizeof(jbhook1_p3io_pcbid.id));
security_rp3_generate_signed_eeprom_data(
SECURITY_RP_UTIL_RP_TYPE_BLACK,
&security_rp_sign_key_black_gfdmv4,
&jbhook1_p3io_mcode,
&jbhook1_p3io_pcbid,
&eeprom_out);
} else {
/* white */
memcpy(rom, jbhook1_p3io_eamid.id, sizeof(jbhook1_p3io_eamid.id));
security_rp3_generate_signed_eeprom_data(
SECURITY_RP_UTIL_RP_TYPE_WHITE,
&security_rp_sign_key_white_eamuse,
&security_mcode_eamuse,
&jbhook1_p3io_eamid,
&eeprom_out);
}
memcpy(eeprom, &eeprom_out, sizeof(struct security_rp3_eeprom));
return S_OK;
}

View File

@@ -0,0 +1,27 @@
avsdlls += jbhook2
deplibs_jbhook2 := \
avs \
glhelper \
ldflags_jbhook2 := \
-lws2_32 \
-liphlpapi \
-lopengl32 \
libs_jbhook2 := \
acioemu \
eamio \
jbio \
jbhook-util \
p3ioemu \
p3io \
p4ioemu \
hook \
hooklib \
security \
util \
src_jbhook2 := \
dllmain.c \
options.c

221
src/main/jbhook2/dllmain.c Normal file
View File

@@ -0,0 +1,221 @@
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "bemanitools/eamio.h"
#include "bemanitools/jbio.h"
#include "hook/iohook.h"
#include "hook/table.h"
#include "hooklib/adapter.h"
#include "hooklib/app.h"
#include "hooklib/rs232.h"
#include "hooklib/setupapi.h"
#include "imports/avs.h"
#include "jbhook2/options.h"
#include "jbhook-util/acio.h"
#include "jbhook-util/eamuse.h"
#include "jbhook-util/gfx.h"
#include "jbhook-util/p3io.h"
#include "p3ioemu/devmgr.h"
#include "p3ioemu/emu.h"
#include "p4ioemu/device.h"
#include "p4ioemu/setupapi.h"
#include "security/id.h"
#include "security/mcode.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/thread.h"
static struct options options;
static const struct security_mcode security_mcode_j44 = {
.header = SECURITY_MCODE_HEADER,
.unkn = SECURITY_MCODE_UNKN_C,
.game = SECURITY_MCODE_GAME_JB_3,
.region = SECURITY_MCODE_REGION_JAPAN,
.cabinet = SECURITY_MCODE_CABINET_C,
.revision = SECURITY_MCODE_REVISION_A,
};
static bool my_dll_entry_init(char *sidcode, struct property_node *param)
{
bool eam_io_ok;
bool jb_io_ok;
eam_io_ok = false;
jb_io_ok = false;
log_info("--- Begin jbhook dll_entry_init ---");
if(options.vertical) {
jbhook_util_gfx_install_vertical_hooks();
}
if (!options.disable_p3ioemu) {
iohook_push_handler(p3io_emu_dispatch_irp);
p3io_setupapi_insert_hooks(NULL);
log_assert(sidcode != NULL);
// pcbid and eamid are only used here for sec check, the ones used for
// network access are taken from ea3-config.xml.
// When booting knit append (and on no other version), the code must
// actually match, so the ID used is for append (JCA)
jbhook_util_p3io_init(
&security_mcode_j44,
&security_id_default, &security_id_default);
log_info("Starting up jubeat IO backend");
jb_io_set_loggers(
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
jb_io_ok =
jb_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy);
if (!jb_io_ok) {
goto fail;
}
}
if (!options.disable_cardemu) {
iohook_push_handler(jbhook_util_ac_io_port_dispatch_irp);
rs232_hook_init();
jbhook_util_ac_io_port_init(L"COM1");
jbhook_util_ac_io_set_iccb();
log_info("Starting up card reader backend");
eam_io_set_loggers(
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
eam_io_ok =
eam_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy);
if (!eam_io_ok) {
goto fail;
}
}
log_info("--- End jbhook dll_entry_init ---");
bool ret = app_hook_invoke_init(sidcode, param);
return ret;
fail:
if (eam_io_ok) {
eam_io_fini();
}
if (jb_io_ok) {
jb_io_fini();
}
return false;
}
static bool my_dll_entry_main(void)
{
bool result;
result = app_hook_invoke_main();
log_info("Shutting down card reader backend");
eam_io_fini();
log_info("Shutting down Jubeat IO backend");
jb_io_fini();
if (!options.disable_cardemu) {
jbhook_util_ac_io_port_fini();
}
if (!options.disable_p3ioemu) {
jbhook_util_p3io_fini();
}
options_fini(&options);
return result;
}
static HWND CDECL
my_mwindow_create(HINSTANCE, void *, const char *, DWORD, DWORD, BOOL);
static HWND(CDECL *real_mwindow_create)(
HINSTANCE, void *, const char *, DWORD, DWORD, BOOL);
static const struct hook_symbol init_hook_syms[] = {
{
.name = "mwindow_create",
.patch = my_mwindow_create,
.link = (void **) &real_mwindow_create,
},
};
static HWND CDECL my_mwindow_create(
HINSTANCE hinstance,
void *callback,
const char *window_title,
DWORD window_width,
DWORD window_height,
BOOL fullscreen)
{
log_info("-------------------------------------------------------------");
log_info("---------------- Begin jbhook mwindow_create ----------------");
log_info("-------------------------------------------------------------");
if(options.vertical) {
DWORD tmp = window_width;
window_width = window_height;
window_height = tmp;
}
fullscreen = !options.windowed;
return real_mwindow_create(
hinstance,
callback,
window_title,
window_width,
window_height,
fullscreen);
}
BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx)
{
if (reason != DLL_PROCESS_ATTACH) {
return TRUE;
}
log_to_external(
log_body_misc, log_body_info, log_body_warning, log_body_fatal);
options_init_from_cmdline(&options);
hook_table_apply(
NULL, "mwindow.dll", init_hook_syms, lengthof(init_hook_syms));
app_hook_init(my_dll_entry_init, my_dll_entry_main);
if (!options.disable_adapteremu) {
adapter_hook_init();
}
jbhook_util_gfx_hook_init();
jbhook_util_eamuse_hook_init();
return TRUE;
}

View File

@@ -1,4 +1,4 @@
LIBRARY jbhook
LIBRARY jbhook2
EXPORTS
DllMain@12 @1 NONAME

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