Compare commits

..

71 Commits
5.44 ... 5.46

Author SHA1 Message Date
icex2
882a3557c9 chore(doc): Fix release process notes
Update outdated references and improve some phrasing
2023-11-03 15:46:11 +01:00
icex2
2454141cab chore: Housekeeping, remove dead link, fix description 2023-11-03 15:46:11 +01:00
icex2
4b740c13e8 chore: Remove obsolete gitlab-ci yaml
Repository is not on gitlab anymore, left over
from migration
2023-11-03 15:46:11 +01:00
icex2
ec4e81d9d3 chore: Update changelog 2023-11-03 15:46:11 +01:00
icex2
9a964e6bdb doc: Add info/instructions regarding ddrio-async 2023-11-03 15:46:11 +01:00
icex2
9b2ed6910e feat: ddrio-async wrapper/shim driver for async IO
Wrapper/shim library to drive another ddrio in a dedicated
IO thread. Depending on the other ddrio backend used, this
can significantly improve performance while staying
compatible to the existing ddrio API interface

This turned out to be a good solution to solve performance
problems when running MAME with ddrio-p3io that is
(currently) implemented with synchronous IO calls that are
very costly: ~12 ms for a write over the ACIO protocol, ~4 ms
for a read using an IOCTL. As this already adds up to nearly
a full frame (60 fps) regarding latency, there isn't a lot
of time left to do other stuff in a synchronous update loop.
MAME's performance was unstable and dropped all the time below
100%. The result was a choppy gameplay experience.

Combining ddrio-async with ddrio-p3io, the combined backend
is able to drive inputs/outputs at a rate of ~250hz = ~4
updates per frame. This results in an average input latency
of ~4 ms which is as good as it can get with the p3io
hardware's performance limitations that I measured (see
the 4 ms for the IOCTL mentioned above).

This is more than good enough as as update frequency of
the 573 hardware is slightly less than that (I got told
something ~180 hz?).

tl;dr: Gameplay on MAME is great, smooth frame rate, IO feels
amazing and responsive.
2023-11-03 15:46:11 +01:00
Will Toohey
82343d8cf1 Fix missing xml for jb04. Fixes booting Ave. 2023-10-18 23:29:19 +02:00
Will Toohey
c0101cb614 Fix missing xml for jb03. Closes #258. 2023-10-18 23:29:19 +02:00
Will Toohey
820036087d Revert "Make roundplug PCBID/EAMID verification fail a hard error"
This reverts commit 67de6639ef.
2023-10-18 23:29:19 +02:00
Will Toohey
ebd80d3749 Make roundplug PCBID/EAMID verification fail a hard error
This was previously a soft error, and also said "reverting to default"
without actually doing so. We should be forcing correct format.
2023-10-18 23:29:19 +02:00
Will Toohey
3bff7f8a5e jbhook1: If gfx.vertical is set, rotate error messages too
By hooking CreateProcessA, we can adjust the commandline to
disable any rotation, which displays the error box at the correct
place on screen (no additional x/y adjustment is needed)
2023-10-18 23:29:19 +02:00
Will Toohey
9ce47e7050 jbhook1: More effectively setup avs boot config
The NVRAM redirection was silently failing because the prop
delete/recreate pair didn't work. This just recreates the entire
config from scratch instead, which guarantees success every time.
By making the NVRAM type "fs", we also make it easier to debug
any issues that people may have.
2023-10-18 23:29:19 +02:00
MatryoshkaLJY
13c87eaf8d feat: Add bi2a-iidx support for aciotest (#263) 2023-10-18 23:06:10 +02:00
icex2
f8d394e124 chore: Bump version to 5.46 to start next development cycle 2023-10-18 01:24:15 +02:00
icex2
09080f7ae2 chore: Update changelog for 5.45 release 2023-10-18 01:09:46 +02:00
icex2
e673cf694f feat(iidx): Support iidx 30 2023-10-18 01:09:45 +02:00
Will Toohey
9afb28a759 acio: Add BIOB and BI2B identifiers 2023-10-09 19:11:37 +02:00
Will Toohey
2920e2b2cf Update BIO2 IIDX emulation to support watchdog poll 2023-10-09 19:11:37 +02:00
icex2
5c08e966d9 doc: Update documentation for various tools and ddrio added 2023-06-25 13:24:07 +02:00
icex2
6be7bdc403 chore(module.mk): Add various ddr related IO tools 2023-06-25 13:24:07 +02:00
icex2
20c6e46a71 feat(ddriotest): Add driotest tool to test ddrio API implementations 2023-06-25 13:24:07 +02:00
icex2
d7c4128a28 doc(dev/journal): Add notes when working on the P3IO driver 2023-06-25 13:24:07 +02:00
icex2
0961bae99f feat(ddrio-p3io): Add ddrio API implementation for DDR P3IO
Also includes EXTIO. Run a SD style cabinet with bemanitools
ddrio API.
2023-06-25 13:24:07 +02:00
icex2
3a89502498 feat(p3io-ddr-tool): CLI tool to test and debug a real DDR P3IO
Extensive tool with subcommands to trigger the various
P3IO commands and run the P3IO + EXTIO DDR hardware
combo with a hardware test menu.
2023-06-25 13:24:07 +02:00
icex2
23ca366f78 chore(module.mk): Add extio related sub-projects 2023-06-25 13:24:07 +02:00
icex2
ec374ec291 feat(extiotest): Add testing tool for real EXTIO devices
A small but helpful tool to run a quick functional test
of a real EXTIO device connected to the target machine.
2023-06-25 13:24:07 +02:00
icex2
db2d71e13c feat(extiodrv): Add (DDR) EXTIO driver
Initial version that supports the most important
features to operate a DDR SD cabinet with all
inputs and outputs working.

Note that the individual sensor cycling modes are
currently broken. The driver will always set the
sensor read mode to all for now.
2023-06-25 13:24:07 +02:00
icex2
2bbbfccd13 feat(extio): Add EXTIO command data structures
Reverse engineered from a real EXTIO device, open-io
project as further reference
2023-06-25 13:24:07 +02:00
icex2
c22ec4fcff feat(p3iodrv): Add DDR compatible P3IO driver
Initial version that supports the most important
features to operate all inputs and outputs of a
DDR SD cabinet.
2023-06-25 13:24:07 +02:00
icex2
1a86cc7ee5 feat(p3io/ddr): Add data structures for DDR P3IO data
Reverse engineered using a real P3IO DDR IO board and
the DDR 16 game binary for additional reference
2023-06-25 13:24:07 +02:00
icex2
069981ef63 refactor(unicorntail): Adjust to p3io command structure changes 2023-06-25 13:24:07 +02:00
icex2
4c3febfcad refactor(p3ioemu/emu): Adjust to command structure changes
Various structures were improved, some slightly changed
even. Behavior/functionality expected to be identical.
2023-06-25 13:24:07 +02:00
icex2
7d9b837463 refactor(p3ioemu/uart): Adjust to command structure changes 2023-06-25 13:24:07 +02:00
icex2
c5bba84940 refactor(p3io/cmd): Add and improve p3io command helper functions
With the overhaul of commands, some helpers needed tweaks while
new ones were added to abstract p3io command details with a
common interface, e.g. dealing with the command length field.
2023-06-25 13:24:07 +02:00
icex2
5ef190f0af feat(p3io/cmd): Overhaul based on real P3IO DDR hardware tests
Using a real DDR P3IO (Dragon PCB), the overall P3IO command
structures improved significantly. Added further notes about
unknown/unclear commands that were not derivable from the
DDR 18 game binary either.

Note that this module is also used by jubeat to some extend.
The initial design apparently assumed a greater overlap in
commands. This now seems less likely as many commands appear
to be DDR specific.

Refactoring/splitting this is a major effort that is not being
addressed here.
2023-06-25 13:24:07 +02:00
icex2
ed0ce2de35 refactor(p3io/frame): Lift magic numbers to macro
Aligns the code with other ACIO code where the
init and escape chars have proper macros to
improve readability
2023-06-25 13:24:07 +02:00
icex2
f2628a954c feat(util/iobuf): Improve log output
Output the full buffer and the buffer up to the
currently set position. Makes debugging a lot
easier if you know the position set is ok to
only look at the output up to there.

Otherwise, having the full view is also important
to check if data got truncated or checking for
odd looking "garbage" data.
2023-06-25 13:24:07 +02:00
icex2
96d7c4ed91 feat(util/log): Expose proper log level definition with enum
Internally, this was already used but it lacked a clean
public interface to set different log levels from the outside.

Useful for various command line tooling to implement verbosity
levels, e.g. -v, -vv, -vvv
2023-06-25 13:24:07 +02:00
Jeffrey Paine
3c185d5fde fix(iidx): Fix stretched BGAs in 9th and 10th style
This adds edge cases to the existing logic that checks the
vertex UV values to fix stretched BG videos on 11 to 17
already.

However, 9 and 10 also show this issue on modern GPU
hardware though it does not appear on all BG videos but
only on videos from 1st to 3rd style songs.

This commit addresses that issue by adding the missing
checks to the existing logic. Additional refactoring of
configuration naming etc. to match the extended
functionality is included.
2023-06-25 13:02:02 +02:00
Shiz
d3f192976c launcher: print build info at startup 2023-06-25 12:51:33 +02:00
Shiz
7d0c502c45 inject: mark version.c as volatile 2023-06-25 12:51:33 +02:00
Shiz
387dc046f4 build: add volatile_$module variable for targets that need to be always rebuilt 2023-06-25 12:51:33 +02:00
icex2
e40709ddf7 chore: Apply code formatting 2023-04-15 22:37:07 +02:00
icex2
bf83bd89e5 feat(doc/journal): Add dev notes about iidx HD era upscaling feature 2023-04-15 22:37:07 +02:00
icex2
9c9e554234 feat(iidx 20-26): Hook new "HD era scaling" module
Replace the old module, re-use the configuration for now to
avoid introducing breaking changes in the configuration API.

This can be further cleaned up, once the monolithic
iidxhook-util/d3d9 module is further broken up.
2023-04-15 22:37:07 +02:00
icex2
782a23db74 feat(iidx 20-26): New up-/downscaling gfx module, old one doesn't work
This replaces the scaling feature of iidxhook-util/d3d9 as the
game engine changed significantly that the old one is incompatible.

Create a new module because the logic to implement a scaling
feature is very different now. This also avoids further cluttering
the already badly overloaded old module.

The new module is light weight and "plugable" on a hooking
level. Further modules will follow to de-clutter the
iidxhook-util/d3d9 module
2023-04-15 22:37:07 +02:00
icex2
6ea099fd9e feat(d3d9-util): Add separate module for d3d9 utils/helpers
Currently includes:

* dx9 error formatting helpers. Turn error codes into readable
  text
* Vertex struct and helper function
2023-04-15 22:37:07 +02:00
icex2
6dea29ec6a feat(hook/d3d9): Support hooking of SetScissorRect 2023-04-15 22:37:07 +02:00
din
b864c0dcfd Feature: vigem driver for ddrio (#247)
Reads state of ddrio and updates vigem pads. Similar in vein to
viggem-sdvxio and vigem-iidxio

Useful for playing xinput related games with official hardware.
2023-04-11 18:04:36 +02:00
icex2
c4e77a9152 fix(workflow): Permission issues when creating releases on tagging 2023-04-11 00:29:06 +02:00
icex2
736c82975f chore(workflow): Improve workflow names
These show up on github under "Actions" and it should be possible
to tell them apart.
2023-04-11 00:29:06 +02:00
din
ecd598185b unicorn tail doc update 2023-04-11 00:16:07 +02:00
icex2
89efe0cc86 feat(dev): Add github build and release workflows 2023-04-10 23:55:20 +02:00
Jeffrey Paine
3249e70cc2 iidx25-29 - Fix settings description in config files
Co-authored-by: icex2 <icex2@users.noreply.github.com>
2023-04-10 21:44:52 +02:00
Jeffrey Paine
d54627c3fc iidx25-29 - Fix settings description in config files
Co-authored-by: icex2 <icex2@users.noreply.github.com>
2023-04-10 21:44:52 +02:00
Jeffrey Paine
be4b303ed7 iidx25-29 - Fix settings description in config files
Co-authored-by: icex2 <icex2@users.noreply.github.com>
2023-04-10 21:44:52 +02:00
Jeffrey Paine
d438cd320e iidx25-29 - Fix settings description in config files
Co-authored-by: icex2 <icex2@users.noreply.github.com>
2023-04-10 21:44:52 +02:00
Jeffrey Paine
4b23860f8c iidx28/29 - Add cam.disable_camera options to config files 2023-04-10 21:44:52 +02:00
Jeffrey Paine
3d36da6751 iidx28/29 - Add cam.disable_camera options to config files 2023-04-10 21:44:52 +02:00
Jeffrey Paine
9dd7a81033 iidx26 - Fix cam.disable_camera1 default 2023-04-10 21:44:52 +02:00
Jeffrey Paine
6eb415a9d7 iidx27 - Add cam.disable_cam options and align cam.disable_emu with 28/29 2023-04-10 21:44:52 +02:00
Jeffrey Paine
df9a617062 iidx25/26 - Add cam.disable_camera options to config files 2023-04-10 21:44:52 +02:00
Jeffrey Paine
11f670b5a1 iidx25/26 - Add cam.disable_camera options to config files 2023-04-10 21:44:52 +02:00
Jeffrey Paine
139c658d03 camhook: Add disable_camera options
Allow users to manually disable specific cameras
2023-04-10 21:44:52 +02:00
Jeffrey Paine
043906e353 camhook: Add disable_camera options
Allow users to manually disable specific cameras
2023-04-10 21:44:52 +02:00
Jeffrey Paine
c38ea64ea9 Update iidxhook-26.conf
Add info on new SKIP feature for cameras
2023-04-10 21:44:52 +02:00
Jeffrey Paine
cd7425a3b9 Update iidxhook-25.conf
Added instructions on the new SKIP feature for cameras
2023-04-10 21:44:52 +02:00
Jeffrey Paine
8fb42aff73 Update cam.c
The user can now set a custom camera device override of "SKIP" to leave that camera unassigned
2023-04-10 21:44:52 +02:00
Jeffrey Paine
fc052b2d7f Fix link to bemanitools-supplement to point to github instead of s-ul 2023-04-10 21:41:33 +02:00
Will Xyen
e9d24f7f90 camhook: fix convert_path_to_fakesym failing on some versions of mingw 2023-04-07 23:03:42 -07:00
icex2
64901bdb61 chore: Bump version to 5.45 to start next development cycle 2023-04-06 15:56:31 +02:00
138 changed files with 9060 additions and 522 deletions

39
.github/workflows/build-master.yaml vendored Normal file
View File

@@ -0,0 +1,39 @@
name: "Build bemanitools"
on:
push:
branches:
- master
jobs:
build:
runs-on: "ubuntu-22.04"
steps:
- name: "Checkout repository"
uses: "actions/checkout@v2"
- name: "Install prerequisites"
run: |
sudo apt-get update
sudo apt-get install -y runc containerd docker.io
- name: "Build"
run: |
make build-docker
# Do some unpacking of the dist zip. Artifact upload repackages stuff
- name: "Prepare artifact package"
run: |
mkdir artifact
cd artifact
unzip ../build/bemanitools.zip
cd ..
- name: "Upload artifact"
uses: "actions/upload-artifact@v2"
with:
name: bemanitools-${{ github.sha }}
retention-days: 90
if-no-files-found: "error"
path: |
artifact/**

75
.github/workflows/build-tag.yaml vendored Normal file
View File

@@ -0,0 +1,75 @@
name: "Build bemanitools and publish release"
permissions:
contents: write
packages: write
on:
push:
tags:
- "*.*"
jobs:
build:
runs-on: "ubuntu-22.04"
steps:
- name: "Checkout repository"
uses: "actions/checkout@v2"
# Building bootstrapped using docker containers
- name: "Install prerequisites"
run: |
sudo apt-get update
sudo apt-get install -y runc containerd docker.io
- name: "Build"
run: |
make build-docker
# Do some unpacking of the dist zip. Artifact upload repackages stuff
- name: "Prepare artifact package"
run: |
mkdir artifact
cd artifact
unzip ../build/bemanitools.zip
cd ..
- name: "Upload artifact"
uses: "actions/upload-artifact@v2"
with:
name: bemanitools-${{ github.sha }}
retention-days: 90
if-no-files-found: "error"
path: |
artifact/**
publish-release:
needs: "build"
runs-on: "ubuntu-22.04"
steps:
# This already extracts the contents of the artifact
- name: "Download artifact"
uses: "actions/download-artifact@v2"
with:
name: bemanitools-${{ github.sha }}
- name: "Get the version"
id: get_version
run: |
echo ::set-output name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3)
# The publish release action does not package the artifact *sigh*
- name: "Create release package"
run: |
zip bemanitools-${{ steps.get_version.outputs.VERSION }}.zip *
- name: "Publish release"
uses: "marvinpinto/action-automatic-releases@v1.2.1"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
automatic_release_tag: "latest"
draft: false
prerelease: true
title: ${{ steps.get_version.outputs.VERSION }}
files: |
bemanitools-${{ steps.get_version.outputs.VERSION }}.zip

View File

@@ -1,136 +0,0 @@
#
# 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
stages:
- build
- upload
- release
build:
stage: build
only:
refs:
- master
- tags
before_script:
- apk update && apk add make > /dev/null
script:
- make build-docker
artifacts:
paths:
- build
expire_in: 1 week
upload-package-registry:
stage: upload
image: curlimages/curl:latest
only:
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

@@ -2,6 +2,32 @@
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.46
### Features
* feat(ddrio): Wrapper/shim library to drive another ddrio in a dedicated IO thread. Improves performance for highly IO
bound ddrio implementations, e.g. ddrio-p3io
* feat(iidxiotest): bi2a-iidx support
### Fixes
* fix(jb03/04): Missing XML in gamestart script
* fix(jbhook1): Rotate error message box when screen is rotated
* fix(jbhook1): Improve/fix automatic config/nvram fs initialization
## 5.45
### Features
* feat(iidx 30): Added support
* feat(ddr): Add ddrio implementation with P3IO driver backend
* feat(ddr): Add p3io-ddr-tool for testing/debugging real P3IO devices with EXTIO
* feat(ddr): Add testing tool for real EXTIO devices
* feat(ddr): Add extio driver
* feat(ddr): Add p3io driver
* feat(iidx 20-26): New/fixed gfx up-/downscaling feature, old one was broken
* feat(ddr): Vigem driver for ddrio
* feat(iidx 25-30): The user can now set a custom camera device override of "SKIP" to leave that camera unassigned
### Fixes
* fix(iidx 09/10): Fix stretched BGAs on 1st and 3rd style videos
## 5.44
### Features
* feat(doc): ezusb dev journal entry, 10th style ezusb boot up and security setup

View File

@@ -37,6 +37,8 @@ ldflags := -Wl,--gc-sections -static-libgcc
all: build
FORCE:
.PHONY: \
build-docker \
clean \
@@ -44,7 +46,8 @@ code-format \
print-building \
print-release \
run-tests \
version
version \
FORCE
release: \
print-release \
@@ -193,6 +196,8 @@ $$(depdir_$1_$2_$3):
$$(objdir_$1_$2_$3):
$(V)mkdir -p $$@
$$(volatile_$3:%.c=$$(objdir_$1_$2_$3)/%.o): FORCE
$$(objdir_$1_$2_$3)/%.o: $$(srcdir_$3)/%.c \
| $$(depdir_$1_$2_$3) $$(objdir_$1_$2_$3)
$(V)echo ... $$@

View File

@@ -99,17 +99,24 @@ include src/main/bstio/Module.mk
include src/main/camhook/Module.mk
include src/main/cconfig/Module.mk
include src/main/config/Module.mk
include src/main/d3d9-util/Module.mk
include src/main/d3d9exhook/Module.mk
include src/main/ddrhook-util/Module.mk
include src/main/ddrhook1/Module.mk
include src/main/ddrhook2/Module.mk
include src/main/ddrio-async/Module.mk
include src/main/ddrio-p3io/Module.mk
include src/main/ddrio-mm/Module.mk
include src/main/ddrio-smx/Module.mk
include src/main/ddriotest/Module.mk
include src/main/ddrio/Module.mk
include src/main/dinput/Module.mk
include src/main/eamio-icca/Module.mk
include src/main/eamio/Module.mk
include src/main/eamiotest/Module.mk
include src/main/extio/Module.mk
include src/main/extiodrv/Module.mk
include src/main/extiotest/Module.mk
include src/main/ezusb-emu/Module.mk
include src/main/ezusb-iidx-16seg-emu/Module.mk
include src/main/ezusb-iidx-emu/Module.mk
@@ -133,6 +140,7 @@ include src/main/iidx-bio2-exit-hook/Module.mk
include src/main/iidx-ezusb-exit-hook/Module.mk
include src/main/iidx-ezusb2-exit-hook/Module.mk
include src/main/iidx-irbeat-patch/Module.mk
include src/main/iidxhook-d3d9/Module.mk
include src/main/iidxhook-util/Module.mk
include src/main/iidxhook1/Module.mk
include src/main/iidxhook2/Module.mk
@@ -164,7 +172,9 @@ include src/main/launcher/Module.mk
include src/main/mempatch-hook/Module.mk
include src/main/mm/Module.mk
include src/main/p3io/Module.mk
include src/main/p3iodrv/Module.mk
include src/main/p3ioemu/Module.mk
include src/main/p3io-ddr-tool/Module.mk
include src/main/p4iodrv/Module.mk
include src/main/p4ioemu/Module.mk
include src/main/popnhook-util/Module.mk
@@ -183,6 +193,7 @@ include src/main/util/Module.mk
include src/main/vefxio/Module.mk
include src/main/vigem-iidxio/Module.mk
include src/main/vigem-sdvxio/Module.mk
include src/main/vigem-ddrio/Module.mk
include src/main/vigemstub/Module.mk
include src/test/cconfig/Module.mk
@@ -204,6 +215,7 @@ $(zipdir)/:
$(zipdir)/tools.zip: \
build/bin/indep-32/aciotest.exe \
build/bin/indep-32/ddriotest.exe \
build/bin/indep-32/eamiotest.exe \
build/bin/indep-32/ezusb-iidx-fpga-flash.exe \
build/bin/indep-32/ezusb-iidx-sram-flash.exe \
@@ -225,6 +237,7 @@ $(zipdir)/tools.zip: \
$(zipdir)/tools-x64.zip: \
build/bin/indep-64/aciotest.exe \
build/bin/indep-64/ddriotest.exe \
build/bin/indep-64/eamiotest.exe \
build/bin/indep-64/iidxiotest.exe \
build/bin/indep-64/iidx-bio2-exit-hook.dll \
@@ -417,7 +430,7 @@ $(zipdir)/iidx-25-to-26.zip: \
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/iidx-27-to-29.zip: \
$(zipdir)/iidx-27-to-30.zip: \
build/bin/avs2_1700-64/iidxhook9.dll \
build/bin/avs2_1700-64/launcher.exe \
build/bin/indep-64/config.exe \
@@ -429,9 +442,11 @@ $(zipdir)/iidx-27-to-29.zip: \
dist/iidx/gamestart-27.bat \
dist/iidx/gamestart-28.bat \
dist/iidx/gamestart-29.bat \
dist/iidx/gamestart-30.bat \
dist/iidx/iidxhook-27.conf \
dist/iidx/iidxhook-28.conf \
dist/iidx/iidxhook-29.conf \
dist/iidx/iidxhook-30.conf \
dist/iidx/vefx.txt \
| $(zipdir)/
$(V)echo ... $@
@@ -691,8 +706,6 @@ $(zipdir)/ddr-14-to-16.zip: \
build/bin/avs2_1508-32/unicorntail.dll \
build/bin/indep-32/config.exe \
build/bin/indep-32/ddrio.dll \
build/bin/indep-32/ddrio-mm.dll \
build/bin/indep-32/ddrio-smx.dll \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
dist/ddr/config.bat \
@@ -709,8 +722,6 @@ $(zipdir)/ddr-16-x64.zip: \
build/bin/avs2_1603-64/unicorntail.dll \
build/bin/indep-64/config.exe \
build/bin/indep-64/ddrio.dll \
build/bin/indep-64/ddrio-mm.dll \
build/bin/indep-64/ddrio-smx.dll \
build/bin/indep-64/eamio.dll \
build/bin/indep-64/geninput.dll \
dist/ddr/config.bat \
@@ -719,6 +730,30 @@ $(zipdir)/ddr-16-x64.zip: \
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/ddr-hwio-x86.zip: \
build/bin/indep-32/ddrio-async.dll \
build/bin/indep-32/ddrio-p3io.dll \
build/bin/indep-32/ddrio-mm.dll \
build/bin/indep-32/ddrio-smx.dll \
build/bin/indep-32/extiotest.exe \
build/bin/indep-32/p3io-ddr-tool.exe \
build/bin/indep-32/vigem-ddrio.exe \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/ddr-hwio-x64.zip: \
build/bin/indep-64/ddrio-async.dll \
build/bin/indep-64/ddrio-p3io.dll \
build/bin/indep-64/ddrio-mm.dll \
build/bin/indep-64/ddrio-smx.dll \
build/bin/indep-64/extiotest.exe \
build/bin/indep-64/p3io-ddr-tool.exe \
build/bin/indep-64/vigem-ddrio.exe \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/bst.zip: \
build/bin/avs2_1603-64/bsthook.dll \
build/bin/avs2_1603-64/launcher.exe \
@@ -794,6 +829,8 @@ $(BUILDDIR)/bemanitools.zip: \
$(zipdir)/ddr-13.zip \
$(zipdir)/ddr-14-to-16.zip \
$(zipdir)/ddr-16-x64.zip \
$(zipdir)/ddr-hwio-x86.zip \
$(zipdir)/ddr-hwio-x64.zip \
$(zipdir)/doc.zip \
$(zipdir)/iidx-09-to-12.zip \
$(zipdir)/iidx-13.zip \
@@ -805,7 +842,7 @@ $(BUILDDIR)/bemanitools.zip: \
$(zipdir)/iidx-20-cn.zip \
$(zipdir)/iidx-21-to-24.zip \
$(zipdir)/iidx-25-to-26.zip \
$(zipdir)/iidx-27-to-29.zip \
$(zipdir)/iidx-27-to-30.zip \
$(zipdir)/iidx-hwio-x86.zip \
$(zipdir)/iidx-hwio-x64.zip \
$(zipdir)/jb-01.zip \

View File

@@ -1,9 +1,8 @@
# 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.44
Version: `5.46`
[Release history](CHANGELOG.md)
[Changelog](CHANGELOG.md)
A collection of tools to run [various Bemani arcade games](#supported-games).
@@ -59,9 +58,10 @@ The following games are supported with their corresponding hook-libraries.
* Beatmania IIDX 24 SINOBUZ (`iidx-21-to-24.zip`): [iidxhook7](doc/iidxhook/iidxhook7.md)
* Beatmania IIDX 25 CANNON BALLERS (`iidx-25-to-26.zip`): [iidxhook8](doc/iidxhook/iidxhook8.md)
* Beatmania IIDX 26 Rootage (`iidx-25-to-26.zip`): [iidxhook8](doc/iidxhook/iidxhook8.md)
* Beatmania IIDX 27 Heroic Verse (`iidx-27-to-29.zip`): [iidxhook9](doc/iidxhook/iidxhook9.md)
* Beatmania IIDX 28 BISTROVER (`iidx-27-to-29.zip`): [iidxhook9](doc/iidxhook/iidxhook9.md)
* Beatmania IIDX 29 CASTHOUR (`iidx-27-to-29.zip`): [iidxhook9](doc/iidxhook/iidxhook9.md)
* Beatmania IIDX 27 Heroic Verse (`iidx-27-to-30.zip`): [iidxhook9](doc/iidxhook/iidxhook9.md)
* Beatmania IIDX 28 BISTROVER (`iidx-27-to-30.zip`): [iidxhook9](doc/iidxhook/iidxhook9.md)
* Beatmania IIDX 29 CASTHOUR (`iidx-27-to-30.zip`): [iidxhook9](doc/iidxhook/iidxhook9.md)
* Beatmania IIDX 30 RESIDENT (`iidx-27-to-30.zip`): [iidxhook9](doc/iidxhook/iidxhook9.md)
* [jubeat](doc/jbhook/README.md)
* jubeat (`jb-01.zip`): [jbhook1](doc/jbhook/jbhook1.md)
* jubeat ripples (`jb-02.zip`): [jbhook1](doc/jbhook/jbhook1.md)
@@ -100,9 +100,13 @@ The following games are supported with their corresponding hook-libraries.
* [iidx-bio2-exit-hook](doc/tools/iidx-bio2-exit-hook.md): For IIDX with BIO2 IO
* [iidx-ezusb2-exit-hook](doc/tools/iidx-ezusb-exit-hook.md): For IIDX with ezusb FX2 IO
* Bemanitools API testing: Tools for testing bemanitools API implementations
* [ddriotest](doc/tools/ddriotest.md): For [ddrio API](doc/api.md#io-boards)
* [eamiotest](doc/tools/eamiotest.md): For [eamio API](doc/api.md#eamuse-readers)
* [iidxiotest](doc/tools/iidxiotest.md): For [iidxio API](doc/api.md#io-boards)
* [jbiotest](doc/tools/jbiotest.md): For [jbio API](doc/api.md#io-boards)
* DDR IO testing: Tools for testing hardware of a real DDR cabinet
* [p3io-ddr-tool](doc/tools/p3io-ddr-tool.md)
* [extiotest](doc/tools/extiotest.md)
* [aciotest](doc/tools/aciotest.md): Command line tool to quickly test ACIO devices
* config: UI input/output configuration tool when using the default bemanitools API (geninput)
* ir-beat-patch-9/10: Patch the IR beat phase on IIDX 9 and 10
@@ -142,7 +146,7 @@ Depending on the game, you also need the following dependencies installed:
* The [DirectX 9 End-User Runtimes (June 2010)](https://www.microsoft.com/en-us/download/details.aspx?id=8109)
See also
[bemanitools-supplements](https://dev.s-ul.net/djhackers/bemanitools-supplement/-/blob/master/misc/win-runtime/README.md)
[bemanitools-supplement](https://www.github.com/djhackersdev/bemanitools-supplement/)
for files.
## Development

16
dist/iidx/gamestart-30.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
)
modules\launcher -H 134217728 -B iidxhook9.dll bm2dx.dll --config iidxhook-30.conf %*

View File

@@ -10,7 +10,7 @@ eamuse.pcbid=0101020304050607086F
# EAMID
eamuse.eamid=0101020304050607086F
# Fix stretched BG videos on newer GPUs. Might appear on Red and newer
# Fix stretched BG videos on newer GPUs. Might appear on SIRIUS and older. On 9th and 10th style this issue may only affect older BGAs (from 1st-3rd style)
gfx.bgvideo_uv_fix=false
# Run the game in a framed window (requires windowed option)

View File

@@ -10,7 +10,7 @@ eamuse.pcbid=0101020304050607086F
# EAMID
eamuse.eamid=0101020304050607086F
# Fix stretched BG videos on newer GPUs. Might appear on Red and newer
# Fix stretched BG videos on newer GPUs. Might appear on SIRIUS and older. On 9th and 10th style this issue may only affect older BGAs (from 1st-3rd style)
gfx.bgvideo_uv_fix=false
# Run the game in a framed window (requires windowed option)

View File

@@ -10,7 +10,7 @@ eamuse.pcbid=0101020304050607086F
# EAMID
eamuse.eamid=0101020304050607086F
# Fix stretched BG videos on newer GPUs. Might appear on Red and newer
# Fix stretched BG videos on newer GPUs. Might appear on SIRIUS and older. On 9th and 10th style this issue may only affect older BGAs (from 1st-3rd style)
gfx.bgvideo_uv_fix=false
# Run the game in a framed window (requires windowed option)

View File

@@ -10,7 +10,7 @@ eamuse.pcbid=0101020304050607086F
# EAMID
eamuse.eamid=0101020304050607086F
# Fix stretched BG videos on newer GPUs. Might appear on Red and newer
# Fix stretched BG videos on newer GPUs. Might appear on SIRIUS and older. On 9th and 10th style this issue may only affect older BGAs (from 1st-3rd style)
gfx.bgvideo_uv_fix=false
# Run the game in a framed window (requires windowed option)

View File

@@ -10,7 +10,7 @@ eamuse.pcbid=0101020304050607086F
# EAMID
eamuse.eamid=0101020304050607086F
# Fix stretched BG videos on newer GPUs. Might appear on Red and newer
# Fix stretched BG videos on newer GPUs. Might appear on SIRIUS and older. On 9th and 10th style this issue may only affect older BGAs (from 1st-3rd style)
gfx.bgvideo_uv_fix=false
# Run the game in a framed window (requires windowed option)

View File

@@ -7,7 +7,7 @@ eamuse.pcbid=0101020304050607086F
# EAMID
eamuse.eamid=0101020304050607086F
# Fix stretched BG videos on newer GPUs. Might appear on Red and newer
# Fix stretched BG videos on newer GPUs. Might appear on SIRIUS and older. On 9th and 10th style this issue may only affect older BGAs (from 1st-3rd style)
gfx.bgvideo_uv_fix=false
# Run the game in a framed window (requires windowed option)

View File

@@ -7,7 +7,7 @@ eamuse.pcbid=0101020304050607086F
# EAMID
eamuse.eamid=0101020304050607086F
# Fix stretched BG videos on newer GPUs. Might appear on Red and newer
# Fix stretched BG videos on newer GPUs. Might appear on SIRIUS and older. On 9th and 10th style this issue may only affect older BGAs (from 1st-3rd style)
gfx.bgvideo_uv_fix=false
# Run the game in a framed window (requires windowed option)

View File

@@ -7,7 +7,7 @@ eamuse.pcbid=0101020304050607086F
# EAMID
eamuse.eamid=0101020304050607086F
# Fix stretched BG videos on newer GPUs. Might appear on Red and newer
# Fix stretched BG videos on newer GPUs. Might appear on SIRIUS and older. On 9th and 10th style this issue may only affect older BGAs (from 1st-3rd style)
gfx.bgvideo_uv_fix=false
# Run the game in a framed window (requires windowed option)

View File

@@ -7,7 +7,7 @@ eamuse.pcbid=0101020304050607086F
# EAMID
eamuse.eamid=0101020304050607086F
# Fix stretched BG videos on newer GPUs. Might appear on Red and newer
# Fix stretched BG videos on newer GPUs. Might appear on SIRIUS and older. On 9th and 10th style this issue may only affect older BGAs (from 1st-3rd style)
gfx.bgvideo_uv_fix=false
# Run the game in a framed window (requires windowed option)

View File

@@ -1,9 +1,6 @@
# PCBID
eamuse.pcbid=0101020304050607086F
# Fix stretched BG videos on newer GPUs. Might appear on Red and newer
gfx.bgvideo_uv_fix=false
# Run the game in a framed window (requires windowed option)
gfx.framed=false

View File

@@ -1,6 +1,3 @@
# Fix stretched BG videos on newer GPUs. Might appear on Red and newer
gfx.bgvideo_uv_fix=false
# Run the game in a framed window (requires windowed option)
gfx.framed=false

View File

@@ -1,6 +1,3 @@
# Fix stretched BG videos on newer GPUs. Might appear on Red and newer
gfx.bgvideo_uv_fix=false
# Run the game in a framed window (requires windowed option)
gfx.framed=false

View File

@@ -1,9 +1,6 @@
# PCBID
eamuse.pcbid=0101020304050607086F
# Fix stretched BG videos on newer GPUs. Might appear on Red and newer
gfx.bgvideo_uv_fix=false
# Run the game in a framed window (requires windowed option)
gfx.framed=false

View File

@@ -1,6 +1,3 @@
# Fix stretched BG videos on newer GPUs. Might appear on Red and newer
gfx.bgvideo_uv_fix=false
# Run the game in a framed window (requires windowed option)
gfx.framed=false

View File

@@ -1,6 +1,3 @@
# Fix stretched BG videos on newer GPUs. Might appear on Red and newer
gfx.bgvideo_uv_fix=false
# Run the game in a framed window (requires windowed option)
gfx.framed=false

View File

@@ -1,6 +1,3 @@
# Fix stretched BG videos on newer GPUs. Might appear on Red and newer
gfx.bgvideo_uv_fix=false
# Run the game in a framed window (requires windowed option)
gfx.framed=false

View File

@@ -1,6 +1,3 @@
# Fix stretched BG videos on newer GPUs. Might appear on Red and newer
gfx.bgvideo_uv_fix=false
# Run the game in a framed window (requires windowed option)
gfx.framed=false

View File

@@ -1,6 +1,3 @@
# Fix stretched BG videos on newer GPUs. Might appear on Red and newer
gfx.bgvideo_uv_fix=false
# Run the game in a framed window (requires windowed option)
gfx.framed=false

View File

@@ -1,6 +1,3 @@
# Fix stretched BG videos on newer GPUs. Might appear on Red and newer
gfx.bgvideo_uv_fix=false
# Run the game in a framed window (requires windowed option)
gfx.framed=false
@@ -37,10 +34,16 @@ gfx.device_adapter=-1
# Disables the camera emulation
cam.disable_emu=false
# Override camera device ID 1 detection (copy from device manager, do not escape)
# Disable camera 1. Use, i.e., if you only have one camera and want it to be mapped to camera 2 ingame.
cam.disable_camera1=false
# Disable camera 2. Use, i.e., if you have more than one camera but only want to map camera 1 ingame.
cam.disable_camera2=false
# Override camera device ID 1 detection (copy from device manager, do not escape) Leave blank to automatically detect
cam.device_id1=
# Override camera device ID 2 detection (copy from device manager, do not escape)
# Override camera device ID 2 detection (copy from device manager, do not escape) Leave blank to automatically detect
cam.device_id2=
# Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted readers)
@@ -50,4 +53,4 @@ io.disable_card_reader_emu=false
io.disable_bio2_emu=false
# Disables the poll limiter, warning very high CPU usage may arise
io.disable_poll_limiter=false
io.disable_poll_limiter=false

View File

@@ -1,6 +1,3 @@
# Fix stretched BG videos on newer GPUs. Might appear on Red and newer
gfx.bgvideo_uv_fix=false
# Run the game in a framed window (requires windowed option)
gfx.framed=false
@@ -37,10 +34,16 @@ gfx.device_adapter=-1
# Disables the camera emulation
cam.disable_emu=false
# Override camera device ID 1 detection (copy from device manager, do not escape)
# Disable camera 1. Use, i.e., if you only have one camera and want it to be mapped to camera 2 ingame.
cam.disable_camera1=false
# Disable camera 2. Use, i.e., if you have more than one camera but only want to map camera 1 ingame.
cam.disable_camera2=false
# Override camera device ID 1 detection (copy from device manager, do not escape) Leave blank to automatically detect
cam.device_id1=
# Override camera device ID 2 detection (copy from device manager, do not escape)
# Override camera device ID 2 detection (copy from device manager, do not escape) Leave blank to automatically detect
cam.device_id2=
# Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted readers)
@@ -50,4 +53,4 @@ io.disable_card_reader_emu=false
io.disable_bio2_emu=false
# Disables the poll limiter, warning very high CPU usage may arise
io.disable_poll_limiter=false
io.disable_poll_limiter=false

View File

@@ -20,7 +20,13 @@ io.disable_file_hooks=false
io.tt_multiplier=1.0
# Disables the camera emulation
cam.disable_emu=false
cam.disable_emu=true
# Disable camera 1. Use, i.e., if you only have one camera and want it to be mapped to camera 2 ingame.
cam.disable_camera1=false
# Disable camera 2. Use, i.e., if you have more than one camera but only want to map camera 1 ingame.
cam.disable_camera2=false
# Override camera device ID detection (copy from device manager, do not escape)
cam.device_id1=

View File

@@ -22,6 +22,12 @@ io.tt_multiplier=1.0
# Disables the camera emulation
cam.disable_emu=true
# Disable camera 1. Use, i.e., if you only have one camera and want it to be mapped to camera 2 ingame.
cam.disable_camera1=false
# Disable camera 2. Use, i.e., if you have more than one camera but only want to map camera 1 ingame.
cam.disable_camera2=false
# Override camera device ID detection (copy from device manager, do not escape)
cam.device_id1=

View File

@@ -22,6 +22,12 @@ io.tt_multiplier=1.0
# Disables the camera emulation
cam.disable_emu=true
# Disable camera 1. Use, i.e., if you only have one camera and want it to be mapped to camera 2 ingame.
cam.disable_camera1=true
# Disable camera 2. Use, i.e., if you have more than one camera but only want to map camera 1 ingame.
cam.disable_camera2=false
# Override camera device ID detection (copy from device manager, do not escape)
cam.device_id1=

84
dist/iidx/iidxhook-30.conf vendored Normal file
View File

@@ -0,0 +1,84 @@
# Disable card reader emulation and enable usage of real card reader hardware on COM1 (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
# Disable camera 1. Use, i.e., if you only have one camera and want it to be mapped to camera 2 ingame.
cam.disable_camera1=true
# Disable camera 2. Use, i.e., if you have more than one camera but only want to map camera 1 ingame.
cam.disable_camera2=false
# 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)

View File

@@ -3,6 +3,7 @@
cd /d %~dp0
if not exist dev\nvram mkdir dev\nvram
if not exist dev\nvram\ea3-config.xml copy prop\ea3-config.xml dev\nvram\ea3-config.xml
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

View File

@@ -3,6 +3,7 @@
cd /d %~dp0
if not exist dev\nvram mkdir dev\nvram
if not exist dev\nvram\ea3-config.xml copy prop\ea3-config.xml dev\nvram\ea3-config.xml
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

View File

@@ -18,7 +18,8 @@ Table of contents:
* [popnhook](popnhook/README.md): Documentation relevant to `popnhook` implementations
* [sdvxhook](sdvxhook/README.md): Documentation relevant to `sdvxhook` implementations
* Development
* [API](api.md): Available APIs for BT5 and instructions how to use them
* [API](api.md): Available APIs and IO (hardware) implementations 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

View File

@@ -22,8 +22,11 @@ The following implementations are already shipped with BT5.
* bstio.dll (default): Keyboard, joystick and mouse input
* Dance Dance Revolution
* ddrio.dll (default): Keyboard, joystick and mouse input
* [ddrio-p3io.dll](ddrhook/ddrio-p3io.md): DDR P3IO (Dragon PCB) + EXTIO hardware
* ddrio-mm.dll: Minimaid hardware
* ddrio-smx.dll: StepManiaX platforms
* [ddrio-smx.dll](ddrhook/ddrio-smx.md): StepManiaX platforms
* [ddrio-async](ddrhook/ddrio-async.md): Wrapper/shim library to drive another ddrio in
a dedicated IO thread
* Beatmania IIDX
* iidxio.dll (default): Keyboard, joystick and mouse input
* [iidxio-bio2.dll](iidxhook/iidxio-bio2.md): BIO2 driver

View File

@@ -46,7 +46,10 @@ IO hardware you want to use:
* `ddrio`: Default implementation supporting keyboard, mouse and USB
game controllers
* ddrio-mm: Support Minimaid custom interface
* [ddrio-smx](ddrhook/ddrio-smx.md): Support for StepManiaX dance platforms
* [ddrio-smx](ddrio-smx.md): Support for StepManiaX dance platforms
* [ddrio-p3io](ddrio-p3io.md): P3IO + EXTIO driver implementation
* [ddrio-async](ddrio-async.md): Wrapper/shim library to drive another ddrio in
a dedicated IO thread
## Unicorntail

View File

@@ -0,0 +1,36 @@
# Asynchronous proxy wrapper for other ddrio implementations
This implementation of the Bemanitools API is not implementing support for any
specific IO hardware. It is a proxy/shim library that loads another ddrio
library, e.g. ddrio-p3io, and drives the entire backend in a dedicated IO
thread. By implementing this behind the ddrio API, it is fully transparent to
any existing application using it.
The main benefit is the improved IO polling performance depending on how
expensive the synchronous calls of the actual hardware are. For example,
*ddrio-p3io* has very expensive write calls with ~12 ms duration while read
calls take ~4 ms. Therefore, a full update cycle is already about as costly
as rendering an entire frame (at 60 fps).
## Setup
For hook libraries, i.e. ddrhookX, but likely applicable to 3rd party
applications (consolidate their manuals).
* Have `ddrio-async.dll` in the same folder as your `ddrhookX.dll`
* Rename `ddrio-async.dll` to `ddrio.dll`
* Pick another ddrio library as the backend of your choice, e.g. `ddrio-p3io.dl`
and put it next to the async `ddrio.dll`
* Rename it to `ddrio-async-child.dll`, ddrio-async is looking for that filename
in the same folder
* Ensure that your `gamestart.bat` actually injects the appropriate `ddrhook.dll`, for example:
```bat
inject ddrhook1.dll ddr.exe ...*
```
or
```bat
launcher -K ddrhook2.dll arkmdxp3.dll ...*
```

27
doc/ddrhook/ddrio-p3io.md Normal file
View File

@@ -0,0 +1,27 @@
# ddrio API implementation with DDR P3IO (Dragon) and EXTIO
This implementation of BT5's ddrio API allows you to use the native DDR P3IO
of a "Dragon PCB" plus the EXTIO with anything the ddrio API supports.
This is not required to run the actual games supporting the hardware natively.
However, there are various 3rd party applications using the ddrio API where you
might benefit from using actual SD cabinet hardware, e.g.
[vigem-ddrio](../vigem/README.md).
## Setup
For hooks, but likely applicable to 3rd party applications (consolidate their
manuals).
* Driver: You must have the P3IO driver intalled on your system
* Driver from [bemanitools-supplements](https://github.com/djhackersdev/bemanitools-supplement/blob/master/ddr/p3io/README.md)
* Have `ddrio-p3io.dll` in the same folder as your `ddrhookX.dll`
* Rename `ddrio-p3io.dll` to `ddrio.dll`
* Ensure that your `gamestart.bat` actually injects the appropriate ddrhook dll, for example:
```bat
inject ddrhook1.dll ddr.exe ...*
```
or
```bat
launcher -K ddrhook2.dll arkmdxp3.dll ...*
```

View File

@@ -17,10 +17,11 @@ A Chimera PCB however is different in many aspects to the Dragon PCB and require
The Dragon's P3IO has two serial ports that the regular P3IOs do not, and one of these serial ports
is used to communicate with the card readers. Note that these are actual serial ports driven
directly by the P3IO microcontroller, these are NOT just passed through to the motherboard like the
proprietary COM1 and COM2 connectors. Unicorn Tail intercepts serial port IO commands being sent to
the P3IO and redirects them to COM2 instead, since COM2 is unused on SD cabinets (on HD cabinets it
connects to a second ACIO bus which drives the extra lighting glitz like the light spikes and maybe
the LED strip).
proprietary COM1 and COM2 connectors.
Unicorn Tail intercepts serial port IO commands being sent to the P3IO and redirects them to a
COM4 in Windows instead, where two readers can be connected via the motherboard's RS232 port or
a usb RS232 adapter.
## Drivers
@@ -28,6 +29,16 @@ You need the P3IO driver installed on your target system. These can be acquired
HDD or grabbed from
[bemanitools-supplements](https://dev.s-ul.net/djhackers/bemanitools-supplement/-/blob/master/gfdm/p3io/README.md).
## COM Port Setup
Using Device Manager in Windows, ensure the following COM ports are connected and setup.
COM1: EXTIO
COM4: Two readers
Windows is often poor about saving the COM port number, so ewf commit (if applicable) and
reboot after saving this setting to ensure it sticks.
## Setup and run
Edit the `gamestart.bat` file that you are using and append `unicorntail.dll` to the list of hooks,

View File

@@ -0,0 +1,57 @@
# IIDX 24 GFX upscaling notes
Date: 2023-04-15
Author: icex2
Notes about my work on fixing the upscaling/downscaling feature of bemanitools for IIDX 20 to 26.
I realized that the render backend changed significantly that the old method that worked fine
doesn't work anymore.
The tool used in the screenshots is [apitrace](https://github.com/apitrace/apitrace).
## IIDX 24
The GFX engine in IIDX from 20 to 26 has a changed render loop that includes built-in scaling to
implement the SD and HD/HD* screen settings that are selectable in the operator menu
### Frame 0 - GFX init part
Setting up the context and device, as well as the frame buffer. This also creates the intermediate
texture that is configured as the render target once it begins drawing the scene.
![](2023-04-13-iidx-24-gfx-upscaling/init.png)
### Frame 1 - A clean main render path
Start the scene and set the render target to the intermediate texture.
![](2023-04-13-iidx-24-gfx-upscaling/beginscene.png)
After done drawing the scene, the intermediate texture is blended to the framebuffer. With a target
2D plane having the size of the target resolution, the blending applies linear scaling to either
up- or downscale the final image.
![](2023-04-13-iidx-24-gfx-upscaling/scaling.png)
## IIDX 10
A recap of the old stuff, see also [my previous notes](2019-10-07-iidx-gfx-rendering-loops.md),
as I had to look at everything again to properly understand the differences.
### Frame 0 - GFX init part
Setting up the context and device, as well as the frame buffer. Renders directly to the frame
buffer.
![](2023-04-13-iidx-24-gfx-upscaling/init10.png)
### Frame 1 - A clean main render path
Beginning the scene excerpt. The viewport needs to match the target resolution to display the
final image correctly.
![](2023-04-13-iidx-24-gfx-upscaling/beginscene10.png)
Ending the scene excerpt, nothing fancy here, just swapping the back buffer.
![](2023-04-13-iidx-24-gfx-upscaling/endscene10.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 641 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 KiB

View File

@@ -0,0 +1,194 @@
# DDR p3io driver work, various notes
Date: 2023-05-28
Author: icex2
Notes about my work on writing a DDR P3io driver.
## Python IO board hardware breakout interface
PCB breakout interfaces/connectors on the side of the boards.
### P2IO DDR
Descriptions assume cabinet hardware of an upgraded DDR "black SD cabinet"
* `LINE OUT 1`: Primary audio out to amplifier
* `LINE OUT 2`: N.C.
* `RGB`: Video out to monitor, supports 15khz/31khz based on hardware switch for video freq/mode selection
* `COM1`: Virtual com port that connects to the EXTIO
* `COM2`: Virtual com port that connects to a pair of ICCA card readers
* `LAN`: Network connection
* `PWR`: 100V power in
* `ANALOG`: N.C.
* `PORT 1`: Lights output for cabinet lights, e.g. menu button lights, top header lights
* `PORT 2`: N.C.
* `DIPSW`
* `1`: ???
* `2`: On = force all sensor polling mode and allow running the game without an EXTIO
* `3`: ???
* `4`: On = force 15 khz monitor output
* `PLUG 1`: Black dongle
* `PLUG 2`: White dongle
### P3IO GF/DM
Descriptions assume usage of a P3IO from a GF/DM in a "chimera style PCB build" on an upgraded
DDR "black SD cabinet"
* `PWR`: 100V power in
* `12V-OUT`: +12V out for external devices
* `PORT 1`: Lights output for cabinet lights, e.g. menu button lights, top header lights
* `PORT 2`: N.C.
* `COM1`: To EXTIO
* `COM2`: To card readers
* `RGB`: Video out to monitor, supports 15khz/31khz based on hardware switch for video freq/mode selection
* `LINE OUT 1`: Primary audio out to amplifier
* `LINE OUT 2`: N.C.
* `DIPSW`
* `1`:
* `2`:
* `3`:
* `4`: On = force 15 khz monitor output
* `PLUG 1`: Roundplug black dongle
* `PLUG 2`: Roundplug white dongle
### P3IO DDR(X)
Descriptions assume cabinet hardware of an upgraded DDR "black SD cabinet"
* `PWR`: 100V power in
* `USB`: USB memory card readers on cabinet
* `PORT 1`: Lights output for cabinet lights, e.g. menu button lights, top header lights
* `COM3-4`: Virtual COM ports
* COM3 (VCOM1): Pins 1,3,5 on connector -> To card readers
* COM4 (VCOM0): Pins 2,4,6 on connector -> N.C.
* `PLUG`: Breakout to security round plugs (black and white dongles)
* `COM1`: To EXTIO
* Pinout (pins left to right)
* 1: TXD1
* 2: RXD1
* 3: N.C.
* 4: N.C.
* 5: GND
* `COM2`: N/A (light spires on black HD cabinet)
* Pinout (pins left to right)
* 1: TXD2
* 2: RXD2
* 3: GND
* `RGB`: Video out to monitor, supports 15khz/31khz based on hardware switch for video freq/mode selection
* `LINE OUT1`: Primary audio out to amplifier
* `LINE OUT2`: N.C.
* `LAN`: Network
* `DIP SW`
* `1`:
* `2`:
* `3`:
* `4`: On = force 15 khz monitor output
## Python IO boards and differences
### P3IO DDR(X)
* Connects to USB and actually enumerates as a USB device and not a virtual COM port
* COM ports 1-4 on breakout of the PCB are being passed through as actual COM ports to the operating system
### P3IO GF/DM
* Connects to USB and actually enumerates as a USB device and not a virtual COM port
* COM ports 1-2 on breakout of the PCB are just virtual COM ports
* These do not show up as COM ports on the operating system
* The game drives the COM ports through the main P3IO protocol with additional P3IO commands
to open, read, write and close these virtual COM ports
### P2IO DDR
* Connects to USB and actually enumerates as a USB device and not a virtual COM port
* COM ports 1-2 on breakout of the PCB are just virtual COM ports
* These do not show up as COM ports on the operating system
* The game drives the COM ports through the main P3IO protocol with additional P3IO commands
to open, read, write and close these virtual COM ports
## Pinout card reader P1 -> P2 mini din8 male to mini din8 male
Port 1 2 and 3:
* Pin 3: TX
* Pin 4: GND
* Pin 5 : RX
Pin 3 and 5 need to be reversed inbetween readers
They are all the same, so your cable needs to bridge them over.
A standard male to male mini din 8 cable does not do that.
### Pinout card reader stock cable s-sub9 to round pin9
```text
dsub-9 female -> mini-din8 male
2 (TXD) -> 3
3 (RXD) -> 5
5 (GND) -> 4
```
## ADE board and com port assignments
Default or incorrectly configured?
* `COM1` -> on mainboard
* `COM2` -> COM2 on P3IO breakout
* `COM3` -> ???
* `COM4` -> COM1 on P3IO breakout
## P3IO command init sequence on DDR 18
From the ddrio-python23 library
```text
.data:1002D5D0 g_init_pakets db 0AAh, 2, 0, 1, 29h dup(0); field_0.field_0
.data:1002D5D0 ; DATA XREF: initialize_and_send_pakets+5↑o
.data:1002D5D0 db 0AAh, 2, 0, 2Fh, 29h dup(0); field_0.field_0
.data:1002D5D0 db 0AAh, 3, 1, 27h, 1, 28h dup(0); field_0.field_0
.data:1002D5D0 db 0AAh, 2 dup(2), 31h, 29h dup(0); field_0.field_0
.data:1002D5D0 db 0AAh, 2, 3, 1, 29h dup(0); field_0.field_0
.data:1002D5D0 db 0AAh, 3, 4, 27h, 29h dup(0); field_0.field_0
.data:1002D5D0 db 0AAh, 2Bh, 5, 25h, 10h, 28h dup(0); field_0.field_0
.data:1002D5D0 db 0AAh, 2Bh, 6, 25h, 10h, 28h dup(0); field_0.field_0
.data:1002D5D0 db 0AAh, 2Bh, 7, 25h, 10h, 28h dup(0); field_0.field_0
.data:1002D5D0 db 0AAh, 2Bh, 8, 25h, 10h, 28h dup(0); field_0.field_0
.data:1002D5D0 db 0AAh, 2Bh, 9, 25h, 10h, 28h dup(0); field_0.field_0
.data:1002D5D0 db 0AAh, 2Bh, 0Ah, 25h, 29h dup(0); field_0.field_0
.data:1002D5D0 db 0AAh, 2Bh, 0Bh, 25h, 29h dup(0); field_0.field_0
.data:1002D5D0 db 0AAh, 2Bh, 0Ch, 25h, 29h dup(0); field_0.field_0
.data:1002D5D0 db 0AAh, 2Bh, 0Dh, 25h, 29h dup(0); field_0.field_0
.data:1002D5D0 db 0AAh, 2Bh, 0Eh, 25h, 29h dup(0); field_0.field_0
.data:1002D5D0 db 0AAh, 3, 0Fh, 5, 29h dup(0); field_0.field_0
.data:1002D5D0 db 0AAh, 3, 0, 2Bh, 1, 28h dup(0); field_0.field_0
.data:1002D5D0 db 0AAh, 3, 1, 29h, 5, 28h dup(0); field_0.field_0
.data:1002D5D0 db 0AAh, 3, 2, 5, 30h, 28h dup(0); field_0.field_0
.data:1002D5D0 db 0AAh, 2 dup(3), 27h, 29h dup(0); field_0.field_0
``
```text
// 01: get version <- this is part of a "flush" of old data?
// 2F: set mode
// 27: get cab type or dispsw
// 31: get coinstock
// 1: get version
// 27: get cab type or dipsw
// 25: read plug
// 25: read plug
// 25: read plug
// 25: read plug
// 25: read plug
// 25: read plug
// 25: read plug
// 25: read plug
// 25: read plug
// 25: read plug
// 5: set watchdog
// 2b: unknown
// 29: get video freq
// 5: set watchdog
// 27: get cab type or dipsw
```

View File

@@ -4,6 +4,7 @@ The following games are compatible with this version of iidxhook:
* Heroic Verse
* BISTROVER
* CASTHOUR
* RESIDENT
The games must be bootstrapped using [launcher](../launcher.md).
@@ -22,17 +23,19 @@ Make sure to have the following dependencies installed:
## Data setup
We assume that you are using a clean/vanilla data dump. Ensure your ("concents")
We assume that you are using a clean/vanilla data dump. Ensure your ("contents")
folder with your unpacked data looks like this:
- data
- modules
- prop
* Copy/Move all files from the *modules* directory to the root folder, so they
are located next to the *data* and *prop* folders.
* For versions 27-29, only
* Copy/Move all files from the *modules* directory to the root folder, so they
are located next to the *data* and *prop* folders.
* Copy all files from *prop/defaults* to the *prop* folder.
* Setup proper paths for *dev/nvram* and *dev/raw* in *prop/avs-config.xml* by
replacing the *<fs>*-block in that file with the following block:
```
<fs>
<root>
@@ -46,9 +49,17 @@ replacing the *<fs>*-block in that file with the following block:
<nr_filedesc __type="u16">256</nr_filedesc>
</fs>
```
* Unpack the package containing iidxhook9 into the root folder so iidxhook9.dll
and all other files are located in the same folder as *data*, *prop*,
*bm2dx.dll*, etc.
* For versions 27-29, only
* Unpack the package containing iidxhook9 into the root folder so iidxhook9.dll
and all other files are located in the same folder as *data*, *prop*,
*bm2dx.dll*, etc.
* For version 30
* Unpack the package containing iidxhook9 into the `modules` folder so iidxhook9.dll
and all other files are located in the same folder as the game's DLLs, e.g.
*bm2dx.dll*, etc.
* Move the `gamestart-30.bat` to the root folder so it is located next to the
`modules`, `data` and `prop` folders
* Run the gamestart-XX.bat file as admin. Where XX matches the version you
want to run.

View File

@@ -1,18 +1,24 @@
# Release process
For bemanitools maintainers, steps for the release process:
For maintainers, steps for the release process:
1. Update the corresponding section in the [changelog](CHANGELOG.md) with bullet points reflecting
major features merged into master since the previous release
major features merged into master since the previous release
1. Make sure you have the latest `master` state pulled to your local copy
1. Tag the release with the next release number which also be found at the
[top of the readme](#bemanitools-5) as it always reflects the current version beinged worked on
on the `master` branch , e.g. 5.35: `git tag 5.35`
[top of the readme](../README.md) as it always reflects the current version being worked on
on the `master` branch , e.g. 0.04: `git tag 5.35`
1. Push the tag to upstream: `git push origin 5.35`
1. The [build pipeline](https://dev.s-ul.net/djhackers/bemanitools/-/pipelines) should start
automatically once the tag is pushed including the steps `build` and `upload-release`
1. Once completed successfully, the release is uploaded
1. Take the changelog of the published version and notify the pigs in the stall about it:
1. The [build pipeline](https://github.com/djhackersdev/bemanitools/actions) should start
automatically once the tag is pushed including the steps `build` and `publish-release`
1. Once completed successfully, the release is published on the
[releases page](https://github.com/djhackersdev/bemanitools/releases/)
1. Edit the latest release
1. Copy-pate the change log section of the respective version into the description
1. Un-check *Set as pre-release*
1. Check *Set as the latest release*
1. Click *Update release*
1. Notify any other channels, e.g. the pigs in the stall, about the latest release:
1. New post in thread
```
<insert version here> released: <direct link to published version>
@@ -23,7 +29,7 @@ automatically once the tag is pushed including the steps `build` and `upload-rel
1. Update the OP title by bumping the version number in it
1. Update the OP post by extending it accordingly (see previous entries)
1. Bump the version number at the [top of this readme](#bemanitools-5) and add a new empty section
in the [changelog](CHANGELOG.md) with the new version number as title. Commit changes and push to
1. Bump the version number at the [top of the readme](../README.md) and add a new empty section
in the [changelog](../CHANGELOG.md) with the new version number as title. Commit changes and push to
`master` branch
1. Continue developing and merging MRs until you decide its time for another release
1. Continue developing and merging PRs until you decide its time for another release

View File

@@ -6,6 +6,7 @@ BT5's supported games, but provides additional features for users and developers
Various command line tools for quick and easy testing of BT5 API implementations witohut having
to run any target games.
* [ddriotest](ddriotest.md): `ddrio` API
* [eamiotest](eamiotest.md): `eamio` API
* [iidxiotest](iidxiotest.md): `iidxio` API
* [jbiotest](jbiotest.md): `jbio` API
@@ -15,6 +16,10 @@ to run any target games.
* [aciotest](aciotest.md): Command line tool for quick and easy testing of ACIO devices without
having to run a game.
### P3IO DDR testing tool
* [p3io-ddr-tool](p3io-ddr-tool.md): Extensive command line tool to test and debug a real P3IO DDR
(Dragon PCB) IO board + EXTIO
### Ezusb
* [ezusb-iidx-fpga-flash](ezusb-iidx-fpga-flash.md): Tool for flashing the FPGA on ezusb 1 boards.
Required if you want to run games without native ezusb support using BT5's iidxio API.

3
doc/tools/ddriotest.md Normal file
View File

@@ -0,0 +1,3 @@
Testing tool for development of ddrio libraries used for emulating the main io
hardware on bemanitools for DanceDanceRevoluion. Just place ddriotest.exe and your
custom ddrio.dll in the same folder and run ddriotest.exe.

View File

@@ -0,0 +1,2 @@
Test your real DDR P3IO (Dragon) + EXTIO hardware connected to your machine
using this tool. Just execute it and follow the usage instructions.

View File

@@ -44,6 +44,8 @@ enum ac_io_node_type {
AC_IO_NODE_TYPE_PANB = 0x090E0000,
AC_IO_NODE_TYPE_BMPU = 0x0B000000,
AC_IO_NODE_TYPE_BI2A = 0x0D060000,
AC_IO_NODE_TYPE_BIOB = 0x0D050100,
AC_IO_NODE_TYPE_BI2B = 0x0D060100,
};
#pragma pack(push, 1)

View File

@@ -11,5 +11,6 @@ src_aciotest := \
kfca.c \
panb.c \
rvol.c \
bi2a-iidx.c \
bi2a-sdvx.c \
main.c \

View File

@@ -0,0 +1,109 @@
#include "aciotest/bi2a-iidx.h"
#include "acio/acio.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bio2drv/bi2a-iidx.h"
bool aciotest_bi2a_iidx_handler_init(
struct aciodrv_device_ctx *device, uint8_t node_id, void **ctx)
{
*ctx = malloc(sizeof(uint32_t));
*((uint32_t *) *ctx) = 0;
return bio2drv_bi2a_iidx_init(device, node_id);
}
bool aciotest_bi2a_iidx_handler_update(
struct aciodrv_device_ctx *device, uint8_t node_id, void *ctx)
{
struct bi2a_iidx_state_in pin;
struct bi2a_iidx_state_out pout;
memset(&pout, 0, sizeof(pout));
if (!bio2drv_bi2a_iidx_poll(device, node_id, &pout, &pin)) {
return false;
}
printf(
"|---------------------------------------|\n"
"| R Y G B Neons B G Y R |\n"
"| %d %d %d %d %d %d %d %d %d |\n"
"|---------------------------------------|\n"
"| NOW PLAYING: %c%c%c%c%c%c%c%c%c |\n"
"|---------------------------------------|\n"
"| Effect %d S1 S2 S3 S4 S5 Test %d|\n"
"|StartP1 %d %02d %02d %02d %02d %02d StartP2 %d|\n"
"| VEFX %d Service %d|\n"
"_________________________________________\n"
"| __ __ |\n"
"| / \\ _ / \\ |\n"
"| | %03d| %d %d %d |%d| %d %d %d | %03d| |\n"
"| \\___/ %d %d %d %d |_| %d %d %d %d \\___/ |\n"
"| |\n"
"|---------------------------------------|\n"
"|---------------------------------------|\n",
pout.SPOTLIGHT2[0].l_state,
pout.SPOTLIGHT2[1].l_state,
pout.SPOTLIGHT2[2].l_state,
pout.SPOTLIGHT2[3].l_state,
pout.NEONLAMP.l_state,
pout.SPOTLIGHT1[0].l_state,
pout.SPOTLIGHT1[1].l_state,
pout.SPOTLIGHT1[2].l_state,
pout.SPOTLIGHT1[3].l_state,
pout.SEG16[0],
pout.SEG16[1],
pout.SEG16[2],
pout.SEG16[3],
pout.SEG16[4],
pout.SEG16[5],
pout.SEG16[6],
pout.SEG16[7],
pout.SEG16[8],
pin.PANEL.y_effect,
pin.SYSTEM.v_test,
pin.PANEL.y_start1,
pin.SLIDER1.s_val,
pin.SLIDER2.s_val,
pin.SLIDER3.s_val,
pin.SLIDER4.s_val,
pin.SLIDER5.s_val,
pin.PANEL.y_start2,
pin.PANEL.y_vefx,
pin.SYSTEM.v_service,
pin.TURNTABLE1,
pin.P1SW2.b_val,
pin.P1SW4.b_val,
pin.P1SW6.b_val,
pin.SYSTEM.v_coin,
pin.P2SW2.b_val,
pin.P2SW4.b_val,
pin.P2SW6.b_val,
pin.TURNTABLE2,
pin.P1SW1.b_val,
pin.P1SW3.b_val,
pin.P1SW5.b_val,
pin.P1SW7.b_val,
pin.P2SW1.b_val,
pin.P2SW3.b_val,
pin.P2SW5.b_val,
pin.P2SW7.b_val
);
return true;
}

View File

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

View File

@@ -1,5 +1,6 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
@@ -7,6 +8,7 @@
#include "aciodrv/device.h"
#include "aciotest/bi2a-sdvx.h"
#include "aciotest/bi2a-iidx.h"
#include "aciotest/handler.h"
#include "aciotest/icca.h"
#include "aciotest/kfca.h"
@@ -16,7 +18,7 @@
#include "util/log.h"
static uint8_t aciotest_cnt = 0;
static uint8_t bi2a_mode = 0;
static uint8_t bi2a_mode = 255;
/**
* Enumerate supported ACIO nodes based on their product id.
@@ -53,14 +55,30 @@ static bool aciotest_assign_handler(
}
if (product_type == AC_IO_NODE_TYPE_BI2A) {
if (bi2a_mode == 0) {
if (bi2a_mode == 255) {
printf(
"Unknown BI2A mode specified, please check your command.\n"
"Using bi2a-sdvx mode as default, press ENTER to continue\n"
);
bi2a_mode = 0;
getchar();
}
switch (bi2a_mode)
{
case 0:
handler->init = aciotest_bi2a_sdvx_handler_init;
handler->update = aciotest_bi2a_sdvx_handler_update;
break;
case 1:
handler->init = aciotest_bi2a_iidx_handler_init;
handler->update = aciotest_bi2a_iidx_handler_update;
break;
return true;
} else {
printf("Unknown BI2A device specified");
default:
break;
}
return true;
}
return false;
@@ -76,13 +94,26 @@ int main(int argc, char **argv)
"aciotest, build "__DATE__
" " __TIME__
"\n"
"Usage: %s <com port str> <baud rate>\n"
"Example for two slotted readers: %s COM1 57600\n",
"Usage: %s <com port str> <baud rate> <bi2a mode(optional)>\n"
"Example:\n"
"\"%s COM1 57600\" for generic acio device\n"
"\"%s COM1 57600 bi2a-iidx\" for the iidx BI2A mode\n"
"\"%s COM1 57600 bi2a-sdvx\" for the sdvx BI2A mode\n",
argv[0],
argv[0],
argv[0],
argv[0]);
return -1;
}
if (argc == 4) {
if(!strcmp(argv[3],"bi2a-iidx")) {
bi2a_mode = 1;
} else if(!strcmp(argv[3],"bi2a-sdvx")) {
bi2a_mode = 0;
}
}
log_to_writer(log_writer_stdout, NULL);
struct aciodrv_device_ctx *device =
@@ -93,7 +124,8 @@ int main(int argc, char **argv)
return -1;
}
printf("Opening acio device successful\n");
printf("Opening acio device successful, press ENTER to continue\n");
getchar();
uint8_t node_count = aciodrv_device_get_node_count(device);
printf("Enumerated %d nodes\n", node_count);

View File

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

View File

@@ -91,11 +91,12 @@ void bio2_emu_bi2a_dispatch_request(
break;
case BIO2_BI2A_CMD_WATCHDOG:
log_misc("BIO2_BI2A_CMD_WATCHDOGX(%d)", req->addr);
log_misc("BIO2_BI2A_CMD_WATCHDOG(%d)", req->addr);
bio2_emu_bi2a_send_status(&bio2port->acio, req, 0x00);
break;
case BIO2_BI2A_CMD_POLL:
case BIO2_BI2A_CMD_POLL_WD:
// log_misc("BIO2_BI2A_CMD_POLL");
bio2_emu_bi2a_send_state(&bio2port->acio, req);
break;

View File

@@ -550,8 +550,8 @@ char *grab_next_camera_id(char *buffer, size_t bsz)
goto done;
}
log_info("Detected webcam: %s\n", buffer);
wcstombs(buffer, wSymLink, bsz);
log_info("Detected webcam: %s\n", buffer);
++gotten;
done:
@@ -659,16 +659,19 @@ bool convert_path_to_fakesym(const char *path, wchar_t *sym, char *extra_o)
strtolower(mistr);
strtolower(extra);
swprintf(
sym,
char buffer[CAMERA_DATA_STRING_SIZE];
snprintf(
buffer,
CAMERA_DATA_STRING_SIZE,
L"\\\\?\\%S#%S&%S&%S#%S",
"\\\\?\\%s#%s&%s&%s#%s",
root,
vidstr,
pidstr,
mistr,
extra);
mbstowcs(sym, buffer, CAMERA_DATA_STRING_SIZE);
return true;
}
@@ -805,6 +808,14 @@ void camhook_init(struct camhook_config_cam *config_cam)
// fill before applying hooks
for (size_t i = 0; i < config_cam->num_devices; ++i) {
// Check if this camera is disabled first
if (config_cam->disable_camera[i]) {
// If so, pretend this camera is already assigned and move on
num_addressed_cams++;
num_located_cams++;
continue;
}
// If not, try to hook the camera
fill_cam_struct(&camData[i], config_cam->device_id[i]);
}
@@ -826,7 +837,9 @@ void camhook_init(struct camhook_config_cam *config_cam)
NULL, "Mf.dll", camhook_mf_syms, lengthof(camhook_mf_syms));
log_info("Inserted cam hooks for %d cams", (int) num_setup);
} else {
// If the user has manually disabled all cams, don't print this in the
// log
} else if (num_addressed_cams != config_cam->num_devices) {
log_info("No cams detected, not hooking");
}
}

View File

@@ -7,8 +7,19 @@
#define CAMHOOK_CONFIG_CAM_DISABLE_EMU_KEY "cam.disable_emu"
#define CAMHOOK_CONFIG_CAM_DEFAULT_DISABLE_EMU_VALUE false
// the following two arrays are based on CAMHOOK_CONFIG_CAM_MAX
// the following four arrays are based on CAMHOOK_CONFIG_CAM_MAX
// please insert more elements if more cams are added
const char *camhook_config_disable_camera[CAMHOOK_CONFIG_CAM_MAX] = {
"cam.disable_camera1",
"cam.disable_camera2",
};
const int camhook_config_disable_camera_default_values[CAMHOOK_CONFIG_CAM_MAX] =
{
false,
false,
};
const char *camhook_config_device_id_keys[CAMHOOK_CONFIG_CAM_MAX] = {
"cam.device_id1",
"cam.device_id2",
@@ -28,6 +39,11 @@ void camhook_config_cam_init(struct cconfig *config, size_t num_cams)
"Disables the camera emulation");
for (size_t i = 0; i < num_cams; ++i) {
cconfig_util_set_bool(
config,
camhook_config_disable_camera[i],
camhook_config_disable_camera_default_values[i],
"Disable camera");
cconfig_util_set_str(
config,
camhook_config_device_id_keys[i],
@@ -56,6 +72,17 @@ void camhook_config_cam_get(
CAMHOOK_CONFIG_CAM_DEFAULT_DISABLE_EMU_VALUE);
}
for (size_t i = 0; i < num_cams; ++i) {
if (!cconfig_util_get_bool(
config,
camhook_config_disable_camera[i],
&config_cam->disable_camera[i],
camhook_config_disable_camera_default_values[i])) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
camhook_config_disable_camera[i],
camhook_config_disable_camera_default_values[i]);
}
if (!cconfig_util_get_str(
config,
camhook_config_device_id_keys[i],

View File

@@ -11,6 +11,7 @@ struct camhook_config_cam {
bool disable_emu;
size_t num_devices;
char device_id[CAMHOOK_CONFIG_CAM_MAX][MAX_PATH];
bool disable_camera[CAMHOOK_CONFIG_CAM_MAX];
};
void camhook_config_cam_init(struct cconfig *config, size_t num_cams);

View File

@@ -0,0 +1,6 @@
libs += d3d9-util
libs_d3d9-util := \
src_d3d9-util := \
dxerr9.c \

2830
src/main/d3d9-util/dxerr.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
// Source:
// https://github.com/Alexpux/mingw-w64/blob/master/mingw-w64-crt/libsrc/dxerr9.c
/*
dxerr9.c - DirectX 9 Error Functions
Written by Filip Navara <xnavara@volny.cz>
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#define DXGetErrorString DXGetErrorString9A
#define DXGetErrorDescription DXGetErrorDescription9A
#define DXTrace DXTraceA
#define DXERROR9(v, n, d) {v, n, d},
#define DXERROR9LAST(v, n, d) \
{ \
v, n, d \
}
#include "dxerr.c"

View File

@@ -0,0 +1,67 @@
// Source:
// https://github.com/Alexpux/mingw-w64/blob/master/mingw-w64-headers/direct-x/include/dxerr9.h
/*
* Copyright (C) 2004 Robert Reif
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __WINE_DXERR9_H
#define __WINE_DXERR9_H
#include <windows.h>
#ifdef __cplusplus
extern "C" {
#endif /* defined(__cplusplus) */
const char *WINAPI DXGetErrorString9A(HRESULT hr);
const WCHAR *WINAPI DXGetErrorString9W(HRESULT hr);
#define DXGetErrorString9 __MINGW_NAME_AW(DXGetErrorString9)
const char *WINAPI DXGetErrorDescription9A(HRESULT hr);
const WCHAR *WINAPI DXGetErrorDescription9W(HRESULT hr);
#define DXGetErrorDescription9 __MINGW_NAME_AW(DXGetErrorDescription9)
HRESULT WINAPI DXTraceA(
const char *strFile,
DWORD dwLine,
HRESULT hr,
const char *strMsg,
WINBOOL bPopMsgBox);
HRESULT WINAPI DXTraceW(
const char *strFile,
DWORD dwLine,
HRESULT hr,
const WCHAR *strMsg,
WINBOOL bPopMsgBox);
#define DXTrace __MINGW_NAME_AW(DXTrace)
#if defined(DEBUG) || defined(_DEBUG)
#define DXTRACE_MSG(str) DXTrace(__FILE__, (DWORD) __LINE__, 0, str, FALSE)
#define DXTRACE_ERR(str, hr) DXTrace(__FILE__, (DWORD) __LINE__, hr, str, TRUE)
#define DXTRACE_ERR_NOMSGBOX(str, hr) \
DXTrace(__FILE__, (DWORD) __LINE__, hr, str, FALSE)
#else
#define DXTRACE_MSG(str) __MSABI_LONG(0)
#define DXTRACE_ERR(str, hr) (hr)
#define DXTRACE_ERR_NOMSGBOX(str, hr) (hr)
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif /* defined(__cplusplus) */
#endif /* __WINE_DXERR9_H */

View File

@@ -0,0 +1,23 @@
#ifndef D3D9_UTIL_H
#define D3D9_UTIL_H
#include <stdbool.h>
#include <stdint.h>
struct d3d9_util_vertex {
float x;
float y;
float z;
uint32_t color;
uint32_t unknown;
float tu;
float tv;
};
inline bool
d3d9_util_vertex_in_range(float v, float lower_bound_inc, float upper_bound_inc)
{
return v >= lower_bound_inc && v <= upper_bound_inc;
}
#endif

View File

@@ -0,0 +1,9 @@
dlls += ddrio-async
ldflags_ddrio-async:= \
libs_ddrio-async := \
util \
src_ddrio-async := \
ddrio.c \

View File

@@ -0,0 +1,11 @@
LIBRARY ddrio-async
EXPORTS
ddr_io_set_loggers
ddr_io_fini
ddr_io_init
ddr_io_read_pad
ddr_io_set_lights_extio
ddr_io_set_lights_p3io
ddr_io_set_lights_hdxs_panel
ddr_io_set_lights_hdxs_rgb

View File

@@ -0,0 +1,268 @@
#define LOG_MODULE "ddrio-async"
#include <windows.h>
#include <stdatomic.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include "bemanitools/ddrio.h"
#include "util/log.h"
#include "util/thread.h"
#include "util/time.h"
typedef void (*ddr_io_set_loggers_t)(
log_formatter_t misc,
log_formatter_t info,
log_formatter_t warning,
log_formatter_t fatal);
typedef bool (*ddr_io_init_t)(
thread_create_t thread_create,
thread_join_t thread_join,
thread_destroy_t thread_destroy);
typedef uint32_t (*ddr_io_read_pad_t)(void);
typedef void (*ddr_io_set_lights_extio_t)(uint32_t extio_lights);
typedef void (*ddr_io_set_lights_p3io_t)(uint32_t p3io_lights);
typedef void (*ddr_io_set_lights_hdxs_panel_t)(uint32_t hdxs_lights);
typedef void (*ddr_io_set_lights_hdxs_rgb_t)(uint8_t idx, uint8_t r, uint8_t g, uint8_t b);
typedef void (*ddr_io_fini_t)(void);
static HMODULE _child_ddr_io_module;
static ddr_io_set_loggers_t _child_ddr_io_set_loggers;
static ddr_io_init_t _child_ddr_io_init;
static ddr_io_read_pad_t _child_ddr_io_read_pad;
static ddr_io_set_lights_extio_t _child_ddr_io_set_lights_extio;
static ddr_io_set_lights_p3io_t _child_ddr_io_set_lights_p3io;
static ddr_io_set_lights_hdxs_panel_t _child_ddr_io_set_lights_hdxs_panel;
static ddr_io_set_lights_hdxs_rgb_t _child_ddr_io_set_lights_hdxs_rgb;
static ddr_io_fini_t _child_ddr_io_fini;
static log_formatter_t _log_formatter_misc;
static log_formatter_t _log_formatter_info;
static log_formatter_t _log_formatter_warning;
static log_formatter_t _log_formatter_fatal;
static _Atomic(bool) _io_thread_proc_loop;
static _Atomic(bool) _io_thread_proc_running;
static _Atomic(uint32_t) _child_ddr_io_data_pad;
static _Atomic(uint32_t) _child_ddr_io_data_extio_lights;
static _Atomic(uint32_t) _child_ddr_io_data_p3io_lights;
static int _io_thread_proc(void *ctx)
{
uint64_t time_start;
uint64_t time_end;
uint64_t loop_counter;
uint64_t total_time;
uint32_t prev_child_ddr_io_data_extio_lights;
uint32_t prev_child_ddr_io_data_p3io_lights;
uint32_t local_tmp;
atomic_store_explicit(
&_io_thread_proc_running,
true,
memory_order_seq_cst);
log_info("IO thread running");
prev_child_ddr_io_data_extio_lights = atomic_load_explicit(
&_child_ddr_io_data_extio_lights, memory_order_seq_cst);
prev_child_ddr_io_data_p3io_lights = atomic_load_explicit(
&_child_ddr_io_data_p3io_lights, memory_order_seq_cst);
time_start = time_get_counter();
loop_counter = 0;
while (atomic_load_explicit(&_io_thread_proc_loop, memory_order_seq_cst)) {
local_tmp = _child_ddr_io_read_pad();
atomic_store_explicit(
&_child_ddr_io_data_pad,
local_tmp,
memory_order_relaxed);
// Only update outputs when they change gives this loop a major performance boost
// The write calls on a p3io for the outputs are very expensive (~12 ms) as they
// are executed over the ACIO protocol compared to only the input read
// calls (~4 ms) which have a dedicated IOCTL call/endpoint
local_tmp = atomic_load_explicit(
&_child_ddr_io_data_extio_lights,
memory_order_relaxed);
if (local_tmp != prev_child_ddr_io_data_extio_lights) {
_child_ddr_io_set_lights_extio(local_tmp);
prev_child_ddr_io_data_extio_lights = local_tmp;
}
local_tmp = atomic_load_explicit(
&_child_ddr_io_data_p3io_lights,
memory_order_relaxed);
if (local_tmp != prev_child_ddr_io_data_p3io_lights) {
_child_ddr_io_set_lights_p3io(local_tmp);
prev_child_ddr_io_data_p3io_lights = local_tmp;
}
// Don't hog the CPU
SwitchToThread();
loop_counter++;
}
time_end = time_get_counter();
total_time = time_get_elapsed_us(time_end - time_start);
log_info("IO thread performance: total iterations %lld, avg. loop cycle time %f us",
loop_counter, ((double) total_time) / loop_counter);
atomic_store_explicit(
&_io_thread_proc_running,
false,
memory_order_seq_cst);
log_info("IO thread shut down");
return 0;
}
static void* _load_function(HMODULE module, const char* name)
{
void* ptr;
ptr = GetProcAddress(module, name);
if (ptr == NULL) {
log_fatal("Could not find function %s in ddr3io child library", name);
}
return ptr;
}
void ddr_io_set_loggers(
log_formatter_t misc,
log_formatter_t info,
log_formatter_t warning,
log_formatter_t fatal)
{
_log_formatter_misc = misc;
_log_formatter_info = info;
_log_formatter_warning = warning;
_log_formatter_fatal = fatal;
log_to_external(misc, info, warning, fatal);
}
bool ddr_io_init(
thread_create_t thread_create,
thread_join_t thread_join,
thread_destroy_t thread_destroy)
{
log_info("Loading ddrio-async-child.dll as child ddrio library...");
_child_ddr_io_module = LoadLibraryA("ddrio-async-child.dll");
if (_child_ddr_io_module == NULL) {
log_warning("Loading ddrio-async-child.dll failed");
return false;
}
_child_ddr_io_set_loggers = _load_function(_child_ddr_io_module, "ddr_io_set_loggers");
_child_ddr_io_init = _load_function(_child_ddr_io_module, "ddr_io_init");
_child_ddr_io_read_pad = _load_function(_child_ddr_io_module, "ddr_io_read_pad");
_child_ddr_io_set_lights_extio = _load_function(_child_ddr_io_module, "ddr_io_set_lights_extio");
_child_ddr_io_set_lights_p3io = _load_function(_child_ddr_io_module, "ddr_io_set_lights_p3io");
_child_ddr_io_set_lights_hdxs_panel = _load_function(_child_ddr_io_module, "ddr_io_set_lights_hdxs_panel");
_child_ddr_io_set_lights_hdxs_rgb = _load_function(_child_ddr_io_module, "ddr_io_set_lights_hdxs_rgb");
_child_ddr_io_fini = _load_function(_child_ddr_io_module, "ddr_io_fini");
_child_ddr_io_set_loggers(
_log_formatter_misc,
_log_formatter_info,
_log_formatter_warning,
_log_formatter_fatal);
log_info("Calling child ddr_io_init...");
if (!_child_ddr_io_init(thread_create, thread_join, thread_destroy)) {
log_warning("Child ddr_io_init failed");
FreeLibrary(_child_ddr_io_module);
return false;
}
atomic_store_explicit(
&_io_thread_proc_loop,
true,
memory_order_seq_cst);
if (!thread_create(_io_thread_proc, NULL, 16384, 0)) {
log_warning("Creating IO thread failed");
_child_ddr_io_fini();
FreeLibrary(_child_ddr_io_module);
return false;
}
return true;
}
uint32_t ddr_io_read_pad(void)
{
return atomic_load_explicit(&_child_ddr_io_data_pad, memory_order_relaxed);
}
void ddr_io_set_lights_extio(uint32_t extio_lights)
{
atomic_store_explicit(
&_child_ddr_io_data_extio_lights,
extio_lights,
memory_order_relaxed);
}
void ddr_io_set_lights_p3io(uint32_t p3io_lights)
{
atomic_store_explicit(
&_child_ddr_io_data_p3io_lights,
p3io_lights,
memory_order_relaxed);
}
void ddr_io_set_lights_hdxs_panel(uint32_t lights)
{
// Not implemented for now
}
void ddr_io_set_lights_hdxs_rgb(uint8_t idx, uint8_t r, uint8_t g, uint8_t b)
{
// Not implemented for now
}
void ddr_io_fini(void)
{
atomic_store_explicit(
&_io_thread_proc_loop,
false,
memory_order_seq_cst);
log_info("Shutting down IO thread and waiting for it to finish...");
while (atomic_load_explicit(&_io_thread_proc_running, memory_order_seq_cst)) {
Sleep(1);
}
log_info("IO thread finished");
_child_ddr_io_fini();
FreeLibrary(_child_ddr_io_module);
}

View File

@@ -0,0 +1,16 @@
dlls += ddrio-p3io
ldflags_ddrio-p3io:= \
-lsetupapi \
libs_ddrio-p3io := \
cconfig \
extio \
extiodrv \
p3io \
p3iodrv \
util \
src_ddrio-p3io := \
config.c \
ddrio.c \

View File

@@ -0,0 +1,35 @@
#include "cconfig/cconfig-util.h"
#include "util/log.h"
#include "config.h"
#define DDRIO_P3IO_CONFIG_EXTIO_PORT_KEY "ddrio.p3io.extio_port"
#define DDRIO_P3IO_CONFIG_EXTIO_PORT_VALUE "COM1"
void ddrio_p3io_config_init(struct cconfig *config)
{
cconfig_util_set_str(
config,
DDRIO_P3IO_CONFIG_EXTIO_PORT_KEY,
DDRIO_P3IO_CONFIG_EXTIO_PORT_VALUE,
"COM port the EXTIO is connected to, default COM1");
}
void ddrio_p3io_config_get(
struct ddrio_p3io_config *config_ddrio_p3io, struct cconfig *config)
{
if (!cconfig_util_get_str(
config,
DDRIO_P3IO_CONFIG_EXTIO_PORT_KEY,
config_ddrio_p3io->extio_port,
sizeof(config_ddrio_p3io->extio_port) - 1,
DDRIO_P3IO_CONFIG_EXTIO_PORT_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%s'",
DDRIO_P3IO_CONFIG_EXTIO_PORT_KEY,
DDRIO_P3IO_CONFIG_EXTIO_PORT_VALUE);
}
}

View File

@@ -0,0 +1,17 @@
#ifndef DDRIO_P3IO_CONFIG_H
#define DDRIO_P3IO_CONFIG_H
#include <windows.h>
#include "cconfig/cconfig.h"
struct ddrio_p3io_config {
char extio_port[12];
};
void ddrio_p3io_config_init(struct cconfig *config);
void ddrio_p3io_config_get(
struct ddrio_p3io_config *config_ddrio_p3io, struct cconfig *config);
#endif

View File

@@ -0,0 +1,11 @@
LIBRARY ddrio-p3io
EXPORTS
ddr_io_set_loggers
ddr_io_fini
ddr_io_init
ddr_io_read_pad
ddr_io_set_lights_extio
ddr_io_set_lights_p3io
ddr_io_set_lights_hdxs_panel
ddr_io_set_lights_hdxs_rgb

427
src/main/ddrio-p3io/ddrio.c Normal file
View File

@@ -0,0 +1,427 @@
#define LOG_MODULE "ddrio-p3io"
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "bemanitools/ddrio.h"
#include "cconfig/cconfig-main.h"
#include "extiodrv/device.h"
#include "extiodrv/extio.h"
#include "p3iodrv/ddr.h"
#include "p3iodrv/device.h"
#include "util/log.h"
#include "util/thread.h"
#include "config.h"
static struct ddrio_p3io_config _ddr_io_p3io_config;
static HANDLE _ddr_io_p3io_handle;
static HANDLE _ddr_io_extio_handle;
static HRESULT _ddr_io_p3io_scan_and_open(HANDLE *handle)
{
HRESULT hr;
char path[MAX_PATH];
log_info("Scanning for p3io...");
hr = p3iodrv_device_scan(path);
if (FAILED(hr)) {
log_warning("Cannot find a connected p3io: %lX", hr);
return hr;
}
log_info("Opening p3io: %s", path);
hr = p3iodrv_device_open(path, handle);
if (FAILED(hr)) {
log_warning("Opening p3io failed: %lX", hr);
return hr;
}
return hr;
}
static HRESULT _ddr_io_p3io_print_version(HANDLE handle)
{
HRESULT hr;
char version[P3IODRV_VERSION_MAX_LEN];
memset(version, 0, P3IODRV_VERSION_MAX_LEN);
hr = p3iodrv_device_read_version(handle, version);
if (FAILED(hr)) {
log_warning("Getting p3io version failed: %lX", hr);
return hr;
}
log_info("P3IO version: %s", version);
return hr;
}
static HRESULT _ddr_io_ddr_p3io_print_version(HANDLE handle)
{
HRESULT hr;
char str[4];
uint32_t major;
uint32_t minor;
uint32_t patch;
hr = p3iodrv_ddr_get_version(handle, str, &major, &minor, &patch);
if (FAILED(hr)) {
log_warning("Getting version failed: %lX", hr);
return hr;
}
log_info("DDR version: %s %d.%d.%d", str, major, minor, patch);
return hr;
}
static HRESULT _ddr_io_ddr_p3io_print_cabinet_type(HANDLE handle)
{
HRESULT hr;
enum p3io_cab_type type;
hr = p3iodrv_ddr_get_cab_type(handle, &type);
if (FAILED(hr)) {
log_warning("Getting cab type failed: %lX", hr);
return hr;
}
log_info("Cabinet type: %d", type);
return hr;
}
static HRESULT _ddr_io_ddr_p3io_print_dip_switches(HANDLE handle)
{
HRESULT hr;
uint8_t dip_sw;
hr = p3iodrv_ddr_get_dipsw(handle, &dip_sw);
if (FAILED(hr)) {
log_warning("Getting dip switches failed");
return hr;
}
log_info("Dip switches: 0x%X", dip_sw);
return hr;
}
static HRESULT _ddr_io_ddr_p3io_print_video_freq(HANDLE handle)
{
HRESULT hr;
enum p3io_video_freq video_freq;
hr = p3iodrv_ddr_get_video_freq(handle, &video_freq);
if (FAILED(hr)) {
log_warning("Getting video freq failed");
return hr;
}
log_info("Video freq: 0x%X", video_freq);
return hr;
}
static HRESULT _ddr_io_ddr_p3io_print_debug_info(HANDLE handle)
{
return _ddr_io_p3io_print_version(handle) &&
_ddr_io_ddr_p3io_print_version(handle) &&
_ddr_io_ddr_p3io_print_cabinet_type(handle) &&
_ddr_io_ddr_p3io_print_dip_switches(handle) &&
_ddr_io_ddr_p3io_print_video_freq(handle);
}
static HRESULT _ddr_io_p3io_init(HANDLE *handle)
{
HRESULT hr;
log_info("Initializing DDR P3IO...");
hr = _ddr_io_p3io_scan_and_open(handle);
if (FAILED(hr)) {
return hr;
}
hr = p3iodrv_ddr_init(*handle);
if (FAILED(hr)) {
return hr;
}
hr = _ddr_io_ddr_p3io_print_debug_info(*handle);
if (FAILED(hr)) {
return hr;
}
return hr;
}
static HRESULT _ddr_io_p3io_close(HANDLE *handle)
{
HRESULT hr;
log_info("Closing p3io...");
hr = p3iodrv_device_close(handle);
if (FAILED(hr)) {
log_warning("Closing p3io failed: %lX", hr);
return hr;
}
return hr;
}
static HRESULT _ddr_io_extio_init(HANDLE *handle)
{
log_info("Initializing EXTIO...");
return extiodrv_device_open(_ddr_io_p3io_config.extio_port, handle);
}
static HRESULT _ddr_io_extio_close(HANDLE *handle)
{
log_info("Closing EXTIO...");
return extiodrv_device_close(handle);
}
static HRESULT _ddr_io_flush_and_reset(HANDLE p3io_handle, HANDLE extio_handle)
{
HRESULT hr;
struct p3io_ddr_jamma jamma;
struct p3io_ddr_output output;
struct extiodrv_extio_pad_lights pad_lights[2];
bool neons;
log_assert(p3io_handle != INVALID_HANDLE_VALUE);
log_assert(extio_handle != INVALID_HANDLE_VALUE);
log_info("Flushing inputs and outputs");
memset(&output, 0, sizeof(output));
memset(&pad_lights, 0, sizeof(pad_lights));
neons = false;
hr = p3iodrv_ddr_get_jamma(p3io_handle, &jamma);
if (FAILED(hr)) {
log_warning("Reading jamma failed");
return hr;
}
hr = p3iodrv_ddr_set_outputs(p3io_handle, &output);
if (FAILED(hr)) {
log_warning("Settings outputs failed");
return hr;
}
hr = extiodrv_extio_transfer(
extio_handle, EXTIODRV_EXTIO_SENSOR_READ_MODE_ALL, pad_lights, neons);
if (FAILED(hr)) {
log_warning("EXTIO transfer failed");
return hr;
}
return hr;
}
void ddr_io_set_loggers(
log_formatter_t misc,
log_formatter_t info,
log_formatter_t warning,
log_formatter_t fatal)
{
log_to_external(misc, info, warning, fatal);
}
static void _ddr_io_config_init(struct ddrio_p3io_config *config_ddrio_p3io)
{
struct cconfig *config;
config = cconfig_init();
ddrio_p3io_config_init(config);
if (!cconfig_main_config_init(
config,
"--ddrio-p3io-config",
"ddrio-p3io.conf",
"--help",
"-h",
"ddrio-p3io",
CCONFIG_CMD_USAGE_OUT_STDOUT)) {
cconfig_finit(config);
exit(EXIT_FAILURE);
}
ddrio_p3io_config_get(config_ddrio_p3io, config);
cconfig_finit(config);
}
bool ddr_io_init(
thread_create_t thread_create,
thread_join_t thread_join,
thread_destroy_t thread_destroy)
{
HRESULT hr;
_ddr_io_config_init(&_ddr_io_p3io_config);
hr = _ddr_io_p3io_init(&_ddr_io_p3io_handle);
if (FAILED(hr)) {
return false;
}
hr = _ddr_io_extio_init(&_ddr_io_extio_handle);
if (FAILED(hr)) {
return false;
}
hr = _ddr_io_flush_and_reset(_ddr_io_p3io_handle, _ddr_io_extio_handle);
if (FAILED(hr)) {
return false;
}
return true;
}
uint32_t ddr_io_read_pad(void)
{
HRESULT hr;
struct p3io_ddr_jamma jamma;
hr = p3iodrv_ddr_get_jamma(_ddr_io_p3io_handle, &jamma);
if (FAILED(hr)) {
log_warning("Reading jamma failed");
return 0;
}
return _byteswap_ulong(*((uint32_t *) &jamma));
}
void ddr_io_set_lights_extio(uint32_t extio_lights)
{
HRESULT hr;
struct extiodrv_extio_pad_lights pad_lights[EXTIO_PAD_LIGHT_MAX_PLAYERS];
bool neons;
pad_lights[0].up = (extio_lights & (1 << LIGHT_P1_UP)) > 0;
pad_lights[0].down = (extio_lights & (1 << LIGHT_P1_DOWN)) > 0;
pad_lights[0].left = (extio_lights & (1 << LIGHT_P1_LEFT)) > 0;
pad_lights[0].right = (extio_lights & (1 << LIGHT_P1_RIGHT)) > 0;
pad_lights[1].up = (extio_lights & (1 << LIGHT_P2_UP)) > 0;
pad_lights[1].down = (extio_lights & (1 << LIGHT_P2_DOWN)) > 0;
pad_lights[1].left = (extio_lights & (1 << LIGHT_P2_LEFT)) > 0;
pad_lights[1].right = (extio_lights & (1 << LIGHT_P2_RIGHT)) > 0;
neons = (extio_lights & (1 << LIGHT_NEONS)) > 0;
hr = extiodrv_extio_transfer(
_ddr_io_extio_handle,
EXTIODRV_EXTIO_SENSOR_READ_MODE_ALL,
pad_lights,
neons);
if (FAILED(hr)) {
log_warning("EXTIO transfer failed: %lX", hr);
}
}
void ddr_io_set_lights_p3io(uint32_t p3io_lights)
{
HRESULT hr;
struct p3io_ddr_output output;
output.cabinet.top_p1_lower =
(p3io_lights & (1 << LIGHT_P1_LOWER_LAMP)) > 0 ? 1 : 0;
output.cabinet.top_p1_upper =
(p3io_lights & (1 << LIGHT_P1_UPPER_LAMP)) > 0 ? 1 : 0;
output.cabinet.top_p2_lower =
(p3io_lights & (1 << LIGHT_P2_LOWER_LAMP)) > 0 ? 1 : 0;
output.cabinet.top_p2_upper =
(p3io_lights & (1 << LIGHT_P2_UPPER_LAMP)) > 0 ? 1 : 0;
output.cabinet.p1_menu_buttons =
(p3io_lights & (1 << LIGHT_P1_MENU)) > 0 ? 1 : 0;
output.cabinet.p2_menu_buttons =
(p3io_lights & (1 << LIGHT_P2_MENU)) > 0 ? 1 : 0;
hr = p3iodrv_ddr_set_outputs(_ddr_io_p3io_handle, &output);
if (FAILED(hr)) {
log_warning("Settings outputs failed: %lX", hr);
}
}
void ddr_io_set_lights_hdxs_panel(uint32_t lights)
{
// Unused
(void) lights;
}
void ddr_io_set_lights_hdxs_rgb(uint8_t idx, uint8_t r, uint8_t g, uint8_t b)
{
// Unused
(void) idx;
(void) r;
(void) g;
(void) b;
}
void ddr_io_fini(void)
{
HRESULT hr;
hr = _ddr_io_flush_and_reset(_ddr_io_p3io_handle, _ddr_io_extio_handle);
if (FAILED(hr)) {
log_warning("Flusing IO failed: %lX", hr);
return;
}
hr = _ddr_io_p3io_close(&_ddr_io_p3io_handle);
if (FAILED(hr)) {
log_warning("Closing P3IO failed: %lX", hr);
// continue
}
hr = _ddr_io_extio_close(&_ddr_io_extio_handle);
if (FAILED(hr)) {
log_warning("Closing EXTIO failed: %lX", hr);
// continue
}
}

View File

@@ -0,0 +1,8 @@
exes += ddriotest \
libs_ddriotest := \
ddrio \
util \
src_ddriotest := \
main.c \

303
src/main/ddriotest/main.c Normal file
View File

@@ -0,0 +1,303 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "bemanitools/ddrio.h"
#include "util/log.h"
#include "util/thread.h"
int main(int argc, char **argv)
{
enum log_level log_level;
log_level = LOG_LEVEL_FATAL;
for (int i = 0; i < argc; i++) {
if (!strcmp(argv[i], "-v")) {
log_level = LOG_LEVEL_WARNING;
} else if (!strcmp(argv[i], "-vv")) {
log_level = LOG_LEVEL_INFO;
} else if (!strcmp(argv[i], "-vvv")) {
log_level = LOG_LEVEL_MISC;
}
}
log_to_writer(log_writer_stderr, NULL);
log_set_level(log_level);
ddr_io_set_loggers(
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
if (!ddr_io_init(crt_thread_create, crt_thread_join, crt_thread_destroy)) {
fprintf(stderr, "Initializing ddrio failed\n");
return -1;
}
fprintf(
stderr,
">>> Initializing ddrio successful, press enter to continue <<<\n");
if (getchar() != '\n') {
return 0;
}
// inputs
uint32_t pad = 0;
// outputs
uint32_t extio_lights = 0;
uint32_t p3io_lights = 0;
bool loop = true;
uint8_t cnt = 0;
while (loop) {
ddr_io_set_lights_extio(extio_lights);
ddr_io_set_lights_p3io(p3io_lights);
pad = ddr_io_read_pad();
system("cls");
printf("Counter: %d\n", cnt);
printf("Player 1 Player 2\n");
printf("\n");
printf("Pad\n");
printf(
"Up: %d Up: %d\n",
(pad & (1 << DDR_P1_UP)) > 0,
(pad & (1 << DDR_P2_UP)) > 0);
printf(
"Down: %d Down: %d\n",
(pad & (1 << DDR_P1_DOWN)) > 0,
(pad & (1 << DDR_P2_DOWN)) > 0);
printf(
"Left: %d Left: %d\n",
(pad & (1 << DDR_P1_LEFT)) > 0,
(pad & (1 << DDR_P2_LEFT)) > 0);
printf(
"Right: %d Right: %d\n",
(pad & (1 << DDR_P1_RIGHT)) > 0,
(pad & (1 << DDR_P2_RIGHT)) > 0);
printf("\n");
printf("Menu\n");
printf(
"Start: %d Start: %d\n",
(pad & (1 << DDR_P1_START)) > 0,
(pad & (1 << DDR_P2_START)) > 0);
printf(
"Up: %d Up: %d\n",
(pad & (1 << DDR_P1_MENU_UP)) > 0,
(pad & (1 << DDR_P2_MENU_UP)) > 0);
printf(
"Down: %d Down: %d\n",
(pad & (1 << DDR_P1_MENU_DOWN)) > 0,
(pad & (1 << DDR_P2_MENU_DOWN)) > 0);
printf(
"Left: %d Left: %d\n",
(pad & (1 << DDR_P1_MENU_LEFT)) > 0,
(pad & (1 << DDR_P2_MENU_LEFT)) > 0);
printf(
"Right: %d Right: %d\n",
(pad & (1 << DDR_P1_MENU_RIGHT)) > 0,
(pad & (1 << DDR_P2_MENU_RIGHT)) > 0);
printf("\n");
printf("Operator\n");
printf(
"Test: %d Service: %d Coin: %d\n",
(pad & (1 << DDR_TEST)) > 0,
(pad & (1 << DDR_SERVICE)) > 0,
(pad & (1 << DDR_COIN)) > 0);
if ((pad & (1 << DDR_P1_UP)) > 0) {
extio_lights |= (1 << LIGHT_P1_UP);
} else {
extio_lights &= ~(1 << LIGHT_P1_UP);
}
if ((pad & (1 << DDR_P1_DOWN)) > 0) {
extio_lights |= (1 << LIGHT_P1_DOWN);
} else {
extio_lights &= ~(1 << LIGHT_P1_DOWN);
}
if ((pad & (1 << DDR_P1_LEFT)) > 0) {
extio_lights |= (1 << LIGHT_P1_LEFT);
} else {
extio_lights &= ~(1 << LIGHT_P1_LEFT);
}
if ((pad & (1 << DDR_P1_RIGHT)) > 0) {
extio_lights |= (1 << LIGHT_P1_RIGHT);
} else {
extio_lights &= ~(1 << LIGHT_P1_RIGHT);
}
if ((pad & (1 << DDR_P2_UP)) > 0) {
extio_lights |= (1 << LIGHT_P2_UP);
} else {
extio_lights &= ~(1 << LIGHT_P2_UP);
}
if ((pad & (1 << DDR_P2_DOWN)) > 0) {
extio_lights |= (1 << LIGHT_P2_DOWN);
} else {
extio_lights &= ~(1 << LIGHT_P2_DOWN);
}
if ((pad & (1 << DDR_P2_LEFT)) > 0) {
extio_lights |= (1 << LIGHT_P2_LEFT);
} else {
extio_lights &= ~(1 << LIGHT_P2_LEFT);
}
if ((pad & (1 << DDR_P2_RIGHT)) > 0) {
extio_lights |= (1 << LIGHT_P2_RIGHT);
} else {
extio_lights &= ~(1 << LIGHT_P2_RIGHT);
}
if ((pad & (1 << DDR_P1_START)) > 0 ||
(pad & (1 << DDR_P1_MENU_UP)) > 0 ||
(pad & (1 << DDR_P1_MENU_DOWN)) > 0 ||
(pad & (1 << DDR_P1_MENU_LEFT)) > 0 ||
(pad & (1 << DDR_P1_MENU_RIGHT)) > 0) {
p3io_lights |= (1 << LIGHT_P1_MENU);
} else {
p3io_lights &= ~(1 << LIGHT_P1_MENU);
}
if ((pad & (1 << DDR_P2_START)) > 0 ||
(pad & (1 << DDR_P2_MENU_UP)) > 0 ||
(pad & (1 << DDR_P2_MENU_DOWN)) > 0 ||
(pad & (1 << DDR_P2_MENU_LEFT)) > 0 ||
(pad & (1 << DDR_P2_MENU_RIGHT)) > 0) {
p3io_lights |= (1 << LIGHT_P2_MENU);
} else {
p3io_lights &= ~(1 << LIGHT_P2_MENU);
}
/* avoid CPU banging */
Sleep(1);
++cnt;
/* process menu */
if ((GetAsyncKeyState(VK_ESCAPE) & 0x8000) != 0) {
system("cls");
Sleep(5);
printf(
"Menu options:\n"
" 0: Exit menu and continue loop\n"
" 1: Exit\n"
" 2: Set neon state\n"
" 3: Top lamp state\n"
" 4: Set all lights on\n"
" 5: Set all lights off\n"
"Waiting for input: ");
char c = getchar();
switch (c) {
case '1': {
loop = false;
break;
}
case '2': {
int state;
int n;
printf("Enter neon state (0/1): ");
n = scanf("%d", &state);
if (n > 0) {
extio_lights |= (1 << LIGHT_NEONS);
} else {
extio_lights &= ~(1 << LIGHT_NEONS);
}
break;
}
case '3': {
char buf[4];
int n;
printf("Enter top lamp state, chain of 0/1s: ");
n = scanf("%8s", buf);
if (n > 0) {
if (buf[0] == '1') {
p3io_lights |= (1 << LIGHT_P1_UPPER_LAMP);
} else {
p3io_lights &= ~(1 << LIGHT_P1_UPPER_LAMP);
}
if (buf[1] == '1') {
p3io_lights |= (1 << LIGHT_P1_LOWER_LAMP);
} else {
p3io_lights &= ~(1 << LIGHT_P1_LOWER_LAMP);
}
if (buf[2] == '1') {
p3io_lights |= (1 << LIGHT_P2_UPPER_LAMP);
} else {
p3io_lights &= ~(1 << LIGHT_P2_UPPER_LAMP);
}
if (buf[3] == '1') {
p3io_lights |= (1 << LIGHT_P2_LOWER_LAMP);
} else {
p3io_lights &= ~(1 << LIGHT_P2_LOWER_LAMP);
}
}
break;
}
case '4': {
extio_lights |= (1 << LIGHT_NEONS);
p3io_lights |= (1 << LIGHT_P1_MENU);
p3io_lights |= (1 << LIGHT_P2_MENU);
p3io_lights |= (1 << LIGHT_P1_UPPER_LAMP);
p3io_lights |= (1 << LIGHT_P1_LOWER_LAMP);
p3io_lights |= (1 << LIGHT_P2_UPPER_LAMP);
p3io_lights |= (1 << LIGHT_P2_LOWER_LAMP);
break;
}
case '5': {
extio_lights &= ~(1 << LIGHT_NEONS);
p3io_lights &= ~(1 << LIGHT_P1_MENU);
p3io_lights &= ~(1 << LIGHT_P2_MENU);
p3io_lights &= ~(1 << LIGHT_P1_UPPER_LAMP);
p3io_lights &= ~(1 << LIGHT_P1_LOWER_LAMP);
p3io_lights &= ~(1 << LIGHT_P2_UPPER_LAMP);
p3io_lights &= ~(1 << LIGHT_P2_LOWER_LAMP);
break;
}
case '0':
default:
break;
}
}
}
system("cls");
ddr_io_fini();
return 0;
}

4
src/main/extio/Module.mk Normal file
View File

@@ -0,0 +1,4 @@
libs += extio
src_extio := \
cmd.c \

16
src/main/extio/cmd.c Normal file
View File

@@ -0,0 +1,16 @@
#include "cmd.h"
uint8_t extio_cmd_checksum(const struct extio_cmd_write *write)
{
const uint8_t *data;
uint32_t checksum;
data = (const uint8_t *) write;
checksum = 0;
checksum += data[0];
checksum += data[1];
checksum += data[2];
return (uint8_t) (checksum & 0x7F);
}

49
src/main/extio/cmd.h Normal file
View File

@@ -0,0 +1,49 @@
#ifndef EXTIO_CMD_H
#define EXTIO_CMD_H
#include <stdint.h>
#define EXTIO_PAD_LIGHT_MAX_PLAYERS 2
enum extio_status {
EXTIO_STATUS_OK = 0x11,
};
#pragma pack(push, 1)
struct extio_cmd_pad_light {
uint8_t unknown : 3;
uint8_t right : 1;
uint8_t left : 1;
uint8_t down : 1;
uint8_t up : 1;
uint8_t unknown_80 : 1;
};
struct extio_cmd_write {
struct extio_cmd_pad_light pad_lights[EXTIO_PAD_LIGHT_MAX_PLAYERS];
uint8_t unknown3 : 3;
uint8_t sensor_read_mode : 3;
uint8_t neons : 1;
uint8_t unknown4 : 1;
uint8_t checksum;
};
struct extio_cmd_read {
uint8_t status;
};
_Static_assert(
sizeof(struct extio_cmd_write) == 4,
"struct extio_cmd_write is the wrong size");
_Static_assert(
sizeof(struct extio_cmd_read) == 1,
"struct extio_cmd_read is the wrong size");
#pragma pack(pop)
uint8_t extio_cmd_checksum(const struct extio_cmd_write *write);
#endif

View File

@@ -0,0 +1,5 @@
libs += extiodrv
src_extiodrv := \
device.c \
extio.c \

182
src/main/extiodrv/device.c Normal file
View File

@@ -0,0 +1,182 @@
#define LOG_MODULE "extiodrv-device"
#include "device.h"
#include "util/log.h"
HRESULT extiodrv_device_open(const char *port, HANDLE *handle)
{
HRESULT hr;
COMMTIMEOUTS ct;
DCB dcb;
log_assert(port);
log_assert(handle);
log_info("Opening extio on %s", port);
*handle = CreateFile(
port,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_WRITE_THROUGH | FILE_ATTRIBUTE_NORMAL,
NULL);
if (*handle == INVALID_HANDLE_VALUE) {
hr = HRESULT_FROM_WIN32(GetLastError());
log_warning("Failed to open %s: %lX", port, hr);
goto early_fail;
}
if (!SetCommMask(*handle, EV_RXCHAR)) {
hr = HRESULT_FROM_WIN32(GetLastError());
log_warning("SetCommMask failed: %lX", hr);
goto fail;
}
if (!SetupComm(*handle, 0x4000u, 0x4000u)) {
hr = HRESULT_FROM_WIN32(GetLastError());
log_warning("SetupComm failed: %lX", hr);
goto fail;
}
if (!PurgeComm(
*handle,
PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR)) {
hr = HRESULT_FROM_WIN32(GetLastError());
log_warning("PurgeComm failed: %lX", hr);
goto fail;
}
ct.ReadTotalTimeoutConstant = 0;
ct.WriteTotalTimeoutConstant = 0;
ct.ReadIntervalTimeout = -1;
ct.ReadTotalTimeoutMultiplier = 10;
ct.WriteTotalTimeoutMultiplier = 100;
if (!SetCommTimeouts(*handle, &ct)) {
hr = HRESULT_FROM_WIN32(GetLastError());
log_warning("SetCommTimeouts failed: %lX", hr);
goto fail;
}
dcb.DCBlength = sizeof(dcb);
if (!GetCommState(*handle, &dcb)) {
hr = HRESULT_FROM_WIN32(GetLastError());
log_warning("GetCommState failed: %lX", hr);
goto fail;
}
dcb.BaudRate = 38400;
dcb.fBinary = TRUE;
dcb.fParity = FALSE;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fDsrSensitivity = FALSE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
dcb.fErrorChar = FALSE;
dcb.fNull = FALSE;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.fAbortOnError = FALSE;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.XonChar = 17;
dcb.XoffChar = 19;
dcb.XonLim = 100;
dcb.XoffLim = 100;
if (!SetCommState(*handle, &dcb)) {
hr = HRESULT_FROM_WIN32(GetLastError());
log_warning("SetCommState failed: %lX", hr);
goto fail;
}
log_info("[%p] Opened extio device on %s", *handle, port);
return S_OK;
fail:
CloseHandle(*handle);
*handle = INVALID_HANDLE_VALUE;
early_fail:
return hr;
}
HRESULT extiodrv_device_close(HANDLE *handle)
{
HRESULT hr;
log_assert(handle);
if (CloseHandle(*handle) == FALSE) {
hr = HRESULT_FROM_WIN32(GetLastError());
return hr;
}
*handle = INVALID_HANDLE_VALUE;
return S_OK;
}
HRESULT extiodrv_device_read(
HANDLE handle, void *bytes, size_t nbytes, size_t *read_bytes)
{
HRESULT hr;
DWORD dw_read_bytes;
log_assert(handle != INVALID_HANDLE_VALUE);
log_assert(bytes);
log_assert(read_bytes);
if (!ClearCommError(handle, NULL, NULL)) {
hr = HRESULT_FROM_WIN32(GetLastError());
log_warning("[%p] ClearCommError failed: %lX", handle, hr);
return hr;
}
if (!ReadFile(handle, bytes, nbytes, &dw_read_bytes, NULL)) {
hr = HRESULT_FROM_WIN32(GetLastError());
log_warning("[%p] ReadFile failed: %lX", handle, hr);
return hr;
}
*read_bytes = dw_read_bytes;
return S_OK;
}
HRESULT extiodrv_device_write(
HANDLE handle, const void *bytes, size_t nbytes, size_t *written_bytes)
{
HRESULT hr;
DWORD dw_written_bytes;
log_assert(handle != INVALID_HANDLE_VALUE);
log_assert(bytes);
log_assert(written_bytes);
if (!WriteFile(handle, bytes, nbytes, &dw_written_bytes, NULL)) {
hr = HRESULT_FROM_WIN32(GetLastError());
log_warning("[%p] WriteFile failed: %lX", handle, hr);
return hr;
}
*written_bytes = dw_written_bytes;
return S_OK;
}

View File

@@ -0,0 +1,57 @@
#ifndef EXTIODRV_DEVICE_H
#define EXTIODRV_DEVICE_H
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
/**
* Open an EXTIO device connected to a com port.
*
* @param port Com port the device is connected to, e.g. "COM1"
* @param handle Pointer to a HANDLE variable to return the handle to when
* succesfully opened
* @return S_OK on success with the handle returned in handle, other HRESULT
* value on error.
*/
HRESULT extiodrv_device_open(const char *port, HANDLE *handle);
/**
* Close an opened EXTIO device
*
* @param handle Pointer to a handle variable that stores a valid and opened
* EXTIO handle.
* @return S_OK on success and the handle value is set to INVALID_HANDLE_VALUE,
* other HRESULT value on error.
*/
HRESULT extiodrv_device_close(HANDLE *handle);
/**
* Read data from the EXTIO device. This call blocks until data is available.
*
* @param handle A valid handle to an opened EXTIO device.
* @param bytes Pointer to a buffer to read the data into
* @param nbytes (Maximum) number of bytes to read
* @param read_bytes Pointer to a variable to store the resulting read size to
* @return S_OK on success with read_bytes populated with the number of bytes
* read, other HRESULT value on error.
*/
HRESULT extiodrv_device_read(
HANDLE handle, void *bytes, size_t nbytes, size_t *read_bytes);
/**
* WRite data to the EXTIO device. This call blocks until the data is written.
*
* @param handle A valid handle to an opened EXTIO device.
* @param bytes Pointer to a buffer with data to write to the device
* @param nbytes (Maximum) number of bytes to write
* @param written_bytes Pointer to a variable to store the resulting write size
* to
* @return S_OK on success with written_bytes populated with the number of bytes
* written, other HRESULT value on error.
*/
HRESULT extiodrv_device_write(
HANDLE handle, const void *bytes, size_t nbytes, size_t *written_bytes);
#endif

110
src/main/extiodrv/extio.c Normal file
View File

@@ -0,0 +1,110 @@
#define LOG_MODULE "extiodrv-extio"
#include "extio.h"
#include "util/log.h"
// static uint8_t _extiodrv_extio_sensor_read_mode_map[5] = {
// 1, // all
// 2, // up
// 3, // down
// 4, // left
// 5, // right
// };
HRESULT extiodrv_extio_transfer(
HANDLE handle,
enum extiodrv_extio_sensor_read_mode sensor_read_mode,
const struct extiodrv_extio_pad_lights
pad_lights[EXTIO_PAD_LIGHT_MAX_PLAYERS],
bool neons)
{
HRESULT hr;
struct extio_cmd_write write;
struct extio_cmd_read read;
size_t bytes_written;
size_t bytes_read;
const uint8_t *raw;
log_assert(handle != INVALID_HANDLE_VALUE);
memset(&write, 0, sizeof(write));
// TODO this doesn't seem to work, yet
// write.sensor_read_mode =
// 0;//_extiodrv_extio_sensor_read_mode_map[sensor_read_mode]; 0 = all 1 =
// mess? 2 = mess? 3 = mess? 4 = mess? 5 = mess? 6 = right sensor only 7 =
// right sensor only 8 = right sensor only
write.sensor_read_mode = 0;
for (uint8_t i = 0; i < EXTIO_PAD_LIGHT_MAX_PLAYERS; i++) {
write.pad_lights[i].up = pad_lights[i].up ? 1 : 0;
write.pad_lights[i].down = pad_lights[i].down ? 1 : 0;
write.pad_lights[i].left = pad_lights[i].left ? 1 : 0;
write.pad_lights[i].right = pad_lights[i].right ? 1 : 0;
}
write.neons = neons ? 1 : 0;
// This MUST be set but only on the p1 packet
// Not setting it or also setting it on the p2 packet results in the EXTIO
// not responding at all
write.pad_lights[0].unknown_80 = 1;
write.checksum = extio_cmd_checksum(&write);
raw = (uint8_t *) &write;
log_misc("Raw write paket: %X %X %X %X", raw[0], raw[1], raw[2], raw[3]);
hr = extiodrv_device_write(handle, &write, sizeof(write), &bytes_written);
if (FAILED(hr)) {
log_warning("Writing extio device failed");
return hr;
}
if (bytes_written != sizeof(write)) {
log_warning(
"Writing extio device failed, expected bytes %d != actual bytes %d",
(uint32_t) sizeof(write),
(uint32_t) bytes_written);
return HRESULT_FROM_WIN32(ERROR_BAD_LENGTH);
}
// Read loop to keep reading until a full message is read
// There are various occasions, especially if polling from the host side is
// faster than the device can put the response to the wire. this can result
// in empty reads
while (true) {
hr = extiodrv_device_read(handle, &read, sizeof(read), &bytes_read);
if (FAILED(hr)) {
log_warning("Reading extio device failed");
return hr;
}
if (bytes_read < sizeof(read)) {
log_misc("Empty read, retry read");
continue;
}
if (bytes_read != sizeof(read)) {
log_warning(
"Reading extio device failed, expected bytes %d != actual "
"bytes %d",
(uint32_t) sizeof(read),
(uint32_t) bytes_read);
return HRESULT_FROM_WIN32(ERROR_BAD_LENGTH);
}
break;
}
if (read.status != EXTIO_STATUS_OK) {
log_warning("Status not ok: 0x%X", read.status);
return HRESULT_FROM_WIN32(ERROR_GEN_FAILURE);
}
return S_OK;
}

45
src/main/extiodrv/extio.h Normal file
View File

@@ -0,0 +1,45 @@
#ifndef EXTIODRV_EXTIO_H
#define EXTIODRV_EXTIO_H
#include <windows.h>
#include <stdbool.h>
#include "extio/cmd.h"
#include "device.h"
enum extiodrv_extio_sensor_read_mode {
EXTIODRV_EXTIO_SENSOR_READ_MODE_ALL = 0,
EXTIODRV_EXTIO_SENSOR_READ_MODE_UP = 1,
EXTIODRV_EXTIO_SENSOR_READ_MODE_DOWN = 2,
EXTIODRV_EXTIO_SENSOR_READ_MODE_LEFT = 3,
EXTIODRV_EXTIO_SENSOR_READ_MODE_RIGHT = 4
};
struct extiodrv_extio_pad_lights {
bool up;
bool down;
bool left;
bool right;
};
/**
* Execute a data transfer (write + read) to the EXTIO device
*
* @param handle A valid and opened handle to an EXTIO device
* @param sensor_read_mode The sensor read mode to set on the EXTIO device.
* This only needs to be set once that input reads return the configured
* sensor read setting.
* @param pad_lights Pad light ouptut state to set
* @param neons Neon output state to set
* @return S_OK on success, other HRESULT value on error
*/
HRESULT extiodrv_extio_transfer(
HANDLE handle,
enum extiodrv_extio_sensor_read_mode sensor_read_mode,
const struct extiodrv_extio_pad_lights
pad_lights[EXTIO_PAD_LIGHT_MAX_PLAYERS],
bool neons);
#endif

View File

@@ -0,0 +1,9 @@
exes += extiotest \
libs_extiotest := \
extiodrv \
extio \
util \
src_extiotest := \
main.c \

55
src/main/extiotest/main.c Normal file
View File

@@ -0,0 +1,55 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "extiodrv/extio.h"
#include "util/log.h"
int main(int argc, char **argv)
{
HRESULT hr;
const char *port;
HANDLE handle;
struct extiodrv_extio_pad_lights pad_lights[EXTIO_PAD_LIGHT_MAX_PLAYERS];
if (argc < 2) {
fprintf(stderr, "Basic functional test of EXTIO\n");
fprintf(stderr, "Usage: %s COM_PORT\n", argv[0]);
fprintf(stderr, " COM_PORT: For example COM1\n");
}
log_to_writer(log_writer_stderr, NULL);
log_set_level(LOG_LEVEL_MISC);
port = argv[1];
hr = extiodrv_device_open(port, &handle);
if (FAILED(hr)) {
fprintf(stderr, "Opening extio at port '%s' failed: %lX\n", port, hr);
return -1;
}
memset(&pad_lights, 0, sizeof(pad_lights));
hr = extiodrv_extio_transfer(
handle, EXTIODRV_EXTIO_SENSOR_READ_MODE_ALL, pad_lights, false);
if (FAILED(hr)) {
fprintf(stderr, "Extio transfer failed: %lX\n", hr);
return -1;
}
hr = extiodrv_device_close(&handle);
if (FAILED(hr)) {
fprintf(stderr, "Closing extio failed: %lX", hr);
return -1;
}
return 0;
}

View File

@@ -80,6 +80,9 @@ static HRESULT(STDCALL *real_SetViewport)(
static HRESULT(STDCALL *real_SetVertexShader)(
IDirect3DDevice9 *self, IDirect3DVertexShader9 *pShader);
static HRESULT(STDCALL *real_SetScissorRect)(
IDirect3DDevice9 *self, const RECT *pRect);
/* ------------------------------------------------------------------------------------------------------------------
*/
@@ -154,6 +157,9 @@ my_SetViewport(IDirect3DDevice9 *self, const D3DVIEWPORT9 *pViewport);
static HRESULT STDCALL
my_SetVertexShader(IDirect3DDevice9 *self, IDirect3DVertexShader9 *pShader);
static HRESULT STDCALL
my_SetScissorRect(IDirect3DDevice9 *self, const RECT *pRect);
/* ------------------------------------------------------------------------------------------------------------------
*/
@@ -220,6 +226,9 @@ hook_d3d9_irp_handler_real_dev_set_viewport(struct hook_d3d9_irp *irp);
static HRESULT
hook_d3d9_irp_handler_real_dev_set_vertex_shader(struct hook_d3d9_irp *irp);
static HRESULT
hook_d3d9_irp_handler_real_dev_set_scissor_rect(struct hook_d3d9_irp *irp);
/* ------------------------------------------------------------------------------------------------------------------
*/
@@ -249,6 +258,8 @@ static const hook_d3d9_irp_handler_t hook_d3d9_irp_real_handlers[] = {
hook_d3d9_irp_handler_real_dev_set_viewport,
[HOOK_D3D9_IRP_OP_DEV_SET_VERTEX_SHADER] =
hook_d3d9_irp_handler_real_dev_set_vertex_shader,
[HOOK_D3D9_IRP_OP_DEV_SET_SCISSOR_RECT] =
hook_d3d9_irp_handler_real_dev_set_scissor_rect,
};
static const hook_d3d9_irp_handler_t *hook_d3d9_handlers;
@@ -570,6 +581,23 @@ my_Reset(IDirect3DDevice9 *self, D3DPRESENT_PARAMETERS *pp)
return hr;
}
static HRESULT STDCALL
my_SetScissorRect(IDirect3DDevice9 *self, const RECT *pRect)
{
struct hook_d3d9_irp irp;
HRESULT hr;
memset(&irp, 0, sizeof(irp));
irp.op = HOOK_D3D9_IRP_OP_DEV_SET_SCISSOR_RECT;
irp.args.dev_set_scissor_rect.self = self;
irp.args.dev_set_scissor_rect.pRect = pRect;
hr = hook_d3d9_irp_invoke_next(&irp);
return hr;
}
/* ------------------------------------------------------------------------------------------------------------------
*/
@@ -748,6 +776,9 @@ hook_d3d9_irp_handler_real_dev_create_device(struct hook_d3d9_irp *irp)
real_SetVertexShader = api_vtbl->SetVertexShader;
api_vtbl->SetVertexShader = my_SetVertexShader;
real_SetScissorRect = api_vtbl->SetScissorRect;
api_vtbl->SetScissorRect = my_SetScissorRect;
*irp->args.ctx_create_device.pdev = (IDirect3DDevice9 *) api_proxy;
return hr;
@@ -848,6 +879,16 @@ hook_d3d9_irp_handler_real_dev_set_vertex_shader(struct hook_d3d9_irp *irp)
irp->args.dev_set_vertex_shader.pShader);
}
static HRESULT
hook_d3d9_irp_handler_real_dev_set_scissor_rect(struct hook_d3d9_irp *irp)
{
log_assert(irp);
return real_SetScissorRect(
irp->args.dev_set_scissor_rect.self,
irp->args.dev_set_scissor_rect.pRect);
}
/* ------------------------------------------------------------------------------------------------------------------
*/

View File

@@ -36,6 +36,7 @@ enum hook_d3d9_irp_op {
HOOK_D3D9_IRP_OP_DEV_RESET = 12,
HOOK_D3D9_IRP_OP_DEV_SET_VIEWPORT = 13,
HOOK_D3D9_IRP_OP_DEV_SET_VERTEX_SHADER = 14,
HOOK_D3D9_IRP_OP_DEV_SET_SCISSOR_RECT = 15,
};
/**
@@ -188,6 +189,14 @@ struct hook_d3d9_irp {
IDirect3DDevice9 *self;
IDirect3DVertexShader9 *pShader;
} dev_set_vertex_shader;
/**
* Params of IDIrect3DDevice9_SetScissorRect
*/
struct {
IDirect3DDevice9 *self;
const RECT *pRect;
} dev_set_scissor_rect;
} args;
size_t next_handler;

View File

@@ -0,0 +1,8 @@
libs += iidxhook-d3d9
libs_iidxhook-d3d9 := \
util \
d3d9-util \
src_iidxhook-d3d9 := \
bb-scale-hd.c \

View File

@@ -0,0 +1,163 @@
#define LOG_MODULE "iidxhook-d3d9-bb-scale-hd"
#include <windows.h>
#include "d3d9-util/vertex.h"
#include "bb-scale-hd.h"
#include "util.h"
#include "util/log.h"
static bool iidxhook_d3d9_bb_scale_initialized;
static uint16_t iidxhook_d3d9_bb_scale_hd_width;
static uint16_t iidxhook_d3d9_bb_scale_hd_height;
void iidxhook_d3d9_bb_scale_hd_init(uint16_t width, uint16_t height)
{
iidxhook_d3d9_bb_scale_hd_width = width;
iidxhook_d3d9_bb_scale_hd_height = height;
iidxhook_d3d9_bb_scale_initialized = true;
log_info("Initialized, width %d, height %d", width, height);
}
static bool iidxhook_d3d9_bb_scale_hd_in_range_of_2d_coords(
struct d3d9_util_vertex *vertex, float x, float y, float error_margin)
{
return vertex->x >= x - error_margin && vertex->x <= x + error_margin &&
vertex->y >= y - error_margin && vertex->y <= y + error_margin;
}
static bool iidxhook_d3d9_bb_scale_hd_match_2d_plane(
struct d3d9_util_vertex *vertices,
float origin_x,
float origin_y,
float size_x,
float size_y,
float error_margin)
{
return
// top left
iidxhook_d3d9_bb_scale_hd_in_range_of_2d_coords(
&vertices[0], origin_x, origin_y, error_margin) &&
// top right
iidxhook_d3d9_bb_scale_hd_in_range_of_2d_coords(
&vertices[1], origin_x + size_x, origin_y, error_margin) &&
// bottom right
iidxhook_d3d9_bb_scale_hd_in_range_of_2d_coords(
&vertices[2], origin_x + size_x, origin_y + size_y, error_margin) &&
// bottom left
iidxhook_d3d9_bb_scale_hd_in_range_of_2d_coords(
&vertices[3], origin_x, origin_y + size_y, error_margin);
}
static void iidxhook_d3d9_bb_scale_hd_set_plane(
struct d3d9_util_vertex *vertices,
float origin_x,
float origin_y,
float size_x,
float size_y)
{
// top left
vertices[0].x = origin_x;
vertices[0].y = origin_y;
// top right
vertices[1].x = origin_x + size_x;
vertices[1].y = origin_y;
// bottom right
vertices[2].x = origin_x + size_x;
vertices[2].y = origin_y + size_y;
// bottom left
vertices[3].x = origin_x;
vertices[3].y = origin_y + size_y;
}
HRESULT iidxhook_d3d9_bb_scale_hd_d3d9_irp_handler(struct hook_d3d9_irp *irp)
{
log_assert(irp);
if (!iidxhook_d3d9_bb_scale_initialized) {
return hook_d3d9_irp_invoke_next(irp);
}
if (irp->op == HOOK_D3D9_IRP_OP_CTX_CREATE_DEVICE) {
// Scale the backbuffer accordingly
// The game renders to an intermediate texture by default to provide the
// SD vs. HD feature already
irp->args.ctx_create_device.pp->BackBufferWidth =
iidxhook_d3d9_bb_scale_hd_width;
irp->args.ctx_create_device.pp->BackBufferHeight =
iidxhook_d3d9_bb_scale_hd_height;
return hook_d3d9_irp_invoke_next(irp);
} else if (irp->op == HOOK_D3D9_IRP_OP_DEV_DRAW_PRIMITIVE_UP) {
if (irp->args.dev_draw_primitive_up.primitive_type ==
D3DPT_TRIANGLEFAN &&
irp->args.dev_draw_primitive_up.primitive_count == 2 &&
irp->args.dev_draw_primitive_up.stride == 28) {
struct d3d9_util_vertex *vertices =
(struct d3d9_util_vertex *)
irp->args.dev_draw_primitive_up.data;
// The engine draws everything to a separate texture as the primary
// render target Depending on the game mode selected, SD vs. HD/HD*,
// the texture's size is either 640x480 or 1280x720 After drawing
// the scene is finished (after EndScene), the game blends the
// texture with the game's rendered output to the actual frame
// buffer
if (iidxhook_d3d9_bb_scale_hd_match_2d_plane(
vertices, 0, 0, 640, 480, 1.0) ||
iidxhook_d3d9_bb_scale_hd_match_2d_plane(
vertices, 0, 0, 1280, 720, 1.0)) {
// Note: Original plane is not at origin 0.0/0.0?
// Example for SD plane:
// -0.500000/-0.500000 639.500000/-0.500000
// 639.500000/479.500000 -0.500000/479.500000 Patch to set it to
// 0.0/0.0
// Scale the 2D output plane primitive to the right resolution
// (upscale or downscale) The render parameter for the blending
// operation will automatically scale the selected source
// texture, the intermediate render buffer with the game's final
// frame, to the actual frame buffer once the DrawPrimitiveUP
// call completed
iidxhook_d3d9_bb_scale_hd_set_plane(
vertices,
0.0,
0.0,
iidxhook_d3d9_bb_scale_hd_width,
iidxhook_d3d9_bb_scale_hd_height);
}
}
return hook_d3d9_irp_invoke_next(irp);
} else if (irp->op == HOOK_D3D9_IRP_OP_DEV_RESET) {
// Gets called when changing the "definition type" in the operator
// menu. needs to be patched to keep the right back buffer size
irp->args.dev_reset.pp->BackBufferWidth =
iidxhook_d3d9_bb_scale_hd_width;
irp->args.dev_reset.pp->BackBufferHeight =
iidxhook_d3d9_bb_scale_hd_height;
return hook_d3d9_irp_invoke_next(irp);
} else if (irp->op == HOOK_D3D9_IRP_OP_DEV_SET_SCISSOR_RECT) {
// Blending to the frame buffer applies scissors which needs to be
// patched to match the final frame buffer's size
RECT *rect = (RECT *) irp->args.dev_set_scissor_rect.pRect;
// Only adjust scissoring when applied to full frame
// Otherwise, this also scissors various UI elements
if (rect->left == 0 && rect->left == 0 && rect->right == 1280 &&
rect->bottom == 720) {
rect->right = iidxhook_d3d9_bb_scale_hd_width;
rect->bottom = iidxhook_d3d9_bb_scale_hd_height;
}
return hook_d3d9_irp_invoke_next(irp);
} else {
return hook_d3d9_irp_invoke_next(irp);
}
}

View File

@@ -0,0 +1,13 @@
#ifndef IIDXHOOK_D3D9_HD_H
#define IIDXHOOK_D3D9_HD_H
#include <stdbool.h>
#include <stdint.h>
#include "hook/d3d9.h"
void iidxhook_d3d9_bb_scale_hd_init(uint16_t width, uint16_t height);
HRESULT iidxhook_d3d9_bb_scale_hd_d3d9_irp_handler(struct hook_d3d9_irp *irp);
#endif

View File

@@ -0,0 +1,22 @@
#ifndef IIDXHOOK_D3D9_UTIL_H
#define IIDXHOOK_D3D9_UTIL_H
#include <windows.h>
#include "d3d9-util/dxerr9.h"
#include "util/log.h"
inline void
iidxhook_d3d9_util_check_and_handle_failure(HRESULT hr, const char *msg)
{
if (FAILED(hr)) {
log_fatal(
"%s\nDX error: %s, DX error description: %s",
msg,
DXGetErrorString9(hr),
DXGetErrorDescription9(hr));
}
}
#endif

View File

@@ -45,8 +45,9 @@ void iidxhook_config_gfx_init(struct cconfig *config)
config,
IIDXHOOK_CONFIG_GFX_BGVIDEO_UV_FIX_KEY,
IIDXHOOK_CONFIG_GFX_DEFAULT_BGVIDEO_UV_FIX_VALUE,
"Fix stretched BG videos on newer GPUs. Might appear on Red and "
"newer");
"Fix stretched BG videos on newer GPUs. Might appear on SIRIUS "
"and older. On 9th and 10th style this issue may only affect "
"older BGAs (from 1st-3rd style)");
cconfig_util_set_bool(
config,

View File

@@ -580,14 +580,14 @@ iidxhook_util_d3d9_iidx13_fix_song_select_bg(struct hook_d3d9_irp *irp)
}
static void
iidxhook_util_d3d9_iidx11_to_17_fix_uvs_bg_videos(struct hook_d3d9_irp *irp)
iidxhook_util_d3d9_iidx09_to_17_fix_uvs_bg_videos(struct hook_d3d9_irp *irp)
{
log_assert(irp);
log_assert(irp->op == HOOK_D3D9_IRP_OP_DEV_DRAW_PRIMITIVE_UP);
/* same code taken from the d3d8 module. but, this just fixes the quad
seam issue as there are no reports of streched bg videos */
if (iidxhook_util_d3d9_config.iidx11_to_17_fix_uvs_bg_videos &&
if (iidxhook_util_d3d9_config.iidx09_to_17_fix_uvs_bg_videos &&
irp->args.dev_draw_primitive_up.primitive_type == D3DPT_TRIANGLEFAN &&
irp->args.dev_draw_primitive_up.primitive_count == 2 &&
irp->args.dev_draw_primitive_up.stride == 28) {
@@ -632,52 +632,100 @@ iidxhook_util_d3d9_iidx11_to_17_fix_uvs_bg_videos(struct hook_d3d9_irp *irp)
/* different versions have different themes and position the bg
video on slightly different positions (good job...) */
if (/* single */
((vertices[0].x >= 164.0f && vertices[0].x <= 168.0f &&
iidxhook_util_d3d9_float_equal(vertices[0].y, 0.0f, 0.1f)) &&
(vertices[1].x >= 472.0f && vertices[1].x <= 476.0f &&
iidxhook_util_d3d9_float_equal(vertices[1].y, 0.0f, 0.1f)) &&
(vertices[2].x >= 472.0f && vertices[2].x <= 476.0f &&
(vertices[0].x >= 164.0f && vertices[0].x <= 168.0f &&
iidxhook_util_d3d9_float_equal(vertices[0].y, 0.0f, 0.1f) &&
vertices[1].x >= 472.0f && vertices[1].x <= 476.1f &&
iidxhook_util_d3d9_float_equal(vertices[1].y, 0.0f, 0.1f) &&
vertices[2].x >= 472.0f && vertices[2].x <= 476.1f &&
((iidxhook_util_d3d9_float_equal(
vertices[2].y, 415.0f, 0.1f)) ||
iidxhook_util_d3d9_float_equal(
vertices[2].y, 416.0f, 0.1f)) &&
(vertices[3].x >= 164.0f && vertices[3].x <= 168.0f &&
iidxhook_util_d3d9_float_equal(
vertices[3].y, 416.0f, 0.1f))) ||
vertices[3].x >= 164.0f && vertices[3].x <= 168.0f &&
((iidxhook_util_d3d9_float_equal(
vertices[3].y, 415.0f, 0.1f)) ||
(iidxhook_util_d3d9_float_equal(
vertices[3].y, 416.0f, 0.1f)))) ||
/* double top left */
((iidxhook_util_d3d9_float_equal(vertices[0].x, 6.0f, 0.1f) &&
vertices[0].y >= 24.0f && vertices[0].y <= 28.0f) &&
(iidxhook_util_d3d9_float_equal(vertices[1].x, 147.0f, 0.1f) &&
vertices[1].y >= 24.0f && vertices[1].y <= 28.0f) &&
(iidxhook_util_d3d9_float_equal(vertices[2].x, 147.0f, 0.1f) &&
vertices[2].y >= 212.0f && vertices[2].y <= 216.0f) &&
(iidxhook_util_d3d9_float_equal(vertices[3].x, 6.0f, 0.1f) &&
vertices[3].y >= 212.0f && vertices[3].y <= 216.0f)) ||
((iidxhook_util_d3d9_float_equal(vertices[0].x, 6.0f, 0.1f) ||
iidxhook_util_d3d9_float_equal(vertices[0].x, 11.0f, 0.1f)) &&
vertices[0].y >= 23.9f && vertices[0].y <= 28.0f &&
(iidxhook_util_d3d9_float_equal(vertices[1].x, 137.0f, 0.1f) ||
iidxhook_util_d3d9_float_equal(
vertices[1].x, 147.0f, 0.1f)) &&
vertices[1].y >= 23.9f && vertices[1].y <= 28.0f &&
(iidxhook_util_d3d9_float_equal(vertices[2].x, 137.0f, 0.1f) ||
iidxhook_util_d3d9_float_equal(
vertices[2].x, 147.0f, 0.1f)) &&
(iidxhook_util_d3d9_float_equal(vertices[2].y, 192.0f, 0.1f) ||
(vertices[2].y >= 212.0f && vertices[2].y <= 216.0f)) &&
(iidxhook_util_d3d9_float_equal(vertices[3].x, 6.0f, 0.1f) ||
iidxhook_util_d3d9_float_equal(vertices[3].x, 11.0f, 0.1f)) &&
(iidxhook_util_d3d9_float_equal(vertices[3].y, 192.0f, 0.1f) ||
(vertices[3].y >= 212.0f && vertices[3].y <= 216.0f))) ||
/* double bottom left */
((iidxhook_util_d3d9_float_equal(vertices[0].x, 6.0f, 0.1f) &&
vertices[0].y >= 216.0f && vertices[0].y <= 220.0f) &&
(iidxhook_util_d3d9_float_equal(vertices[1].x, 147.0f, 0.1f) &&
vertices[1].y >= 216.0f && vertices[1].y <= 220.0f) &&
(iidxhook_util_d3d9_float_equal(vertices[2].x, 147.0f, 0.1) &&
vertices[2].y >= 404.0f && vertices[2].y <= 408.0f) &&
(iidxhook_util_d3d9_float_equal(vertices[3].x, 6.0f, 0.1f) &&
vertices[3].y >= 404.0f && vertices[3].y <= 408.0f)) ||
((iidxhook_util_d3d9_float_equal(vertices[0].x, 6.0f, 0.1f) ||
iidxhook_util_d3d9_float_equal(vertices[0].x, 11.0f, 0.1f)) &&
(iidxhook_util_d3d9_float_equal(vertices[0].y, 200.0f, 0.1f) ||
iidxhook_util_d3d9_float_equal(vertices[0].y, 206.0f, 0.1f) ||
(vertices[0].y >= 216.0f && vertices[0].y <= 220.0f)) &&
(iidxhook_util_d3d9_float_equal(vertices[1].x, 137.0f, 0.1f) ||
iidxhook_util_d3d9_float_equal(
vertices[1].x, 147.0f, 0.1f)) &&
(iidxhook_util_d3d9_float_equal(vertices[1].y, 200.0f, 0.1f) ||
iidxhook_util_d3d9_float_equal(vertices[1].y, 206.0f, 0.1f) ||
(vertices[1].y >= 216.0f && vertices[1].y <= 220.0f)) &&
(iidxhook_util_d3d9_float_equal(vertices[2].x, 137.0f, 0.1f) ||
iidxhook_util_d3d9_float_equal(
vertices[2].x, 147.0f, 0.1f)) &&
(iidxhook_util_d3d9_float_equal(vertices[2].y, 368.0f, 0.1f) ||
iidxhook_util_d3d9_float_equal(vertices[2].y, 394.0f, 0.1f) ||
(vertices[2].y >= 404.0f && vertices[2].y <= 408.0f)) &&
(iidxhook_util_d3d9_float_equal(vertices[3].x, 6.0f, 0.1f) ||
iidxhook_util_d3d9_float_equal(vertices[3].x, 11.0f, 0.1f)) &&
(iidxhook_util_d3d9_float_equal(vertices[3].y, 368.0f, 0.1f) ||
iidxhook_util_d3d9_float_equal(vertices[3].y, 394.0f, 0.1f) ||
(vertices[3].y >= 404.0f && vertices[3].y <= 408.0f))) ||
/* double top right */
((vertices[0].x >= 493.0f && vertices[0].x <= 494.0f &&
vertices[0].y >= 24.0f && vertices[0].y <= 28.0f) &&
(vertices[1].x >= 634.0f && vertices[1].x <= 635.0f &&
vertices[1].y >= 24.0f && vertices[1].y <= 28.0f) &&
(vertices[2].x >= 634.0f && vertices[2].x <= 635.0f &&
vertices[2].y >= 212.0f && vertices[2].y <= 216.0f) &&
(vertices[3].x >= 493.0f && vertices[3].x <= 494.0f &&
vertices[3].y >= 212.0f && vertices[3].y <= 216.0f)) ||
(((vertices[0].x >= 493.0f && vertices[0].x <= 494.0f) ||
iidxhook_util_d3d9_float_equal(
vertices[0].x, 500.0f, 0.1f)) &&
vertices[0].y >= 23.9f && vertices[0].y <= 28.0f &&
(iidxhook_util_d3d9_float_equal(vertices[1].x, 626.0f, 0.1f) ||
(vertices[1].x >= 634.0f && vertices[1].x <= 635.0f)) &&
vertices[1].y >= 23.9f && vertices[1].y <= 28.0f &&
(iidxhook_util_d3d9_float_equal(vertices[2].x, 626.0f, 0.1f) ||
(vertices[2].x >= 634.0f && vertices[2].x <= 635.0f)) &&
(iidxhook_util_d3d9_float_equal(vertices[2].y, 192.0f, 0.1f) ||
(vertices[2].y >= 212.0f && vertices[2].y <= 216.0f)) &&
((vertices[3].x >= 493.0f && vertices[3].x <= 494.0f) ||
iidxhook_util_d3d9_float_equal(
vertices[3].x, 500.0f, 0.1f)) &&
(iidxhook_util_d3d9_float_equal(vertices[3].y, 192.0f, 0.1f) ||
(vertices[3].y >= 212.0f && vertices[3].y <= 216.0f))) ||
/* double bottom right */
((vertices[0].x >= 493.0f && vertices[0].x <= 494.0f &&
vertices[0].y >= 216.0f && vertices[0].y <= 220.0f) &&
(vertices[1].x >= 634.0f && vertices[1].x <= 635.0f &&
vertices[1].y >= 216.0f && vertices[1].y <= 220.0f) &&
(vertices[2].x >= 634.0f && vertices[2].x <= 635.0f &&
vertices[2].y >= 404.0f && vertices[2].y <= 408.0f) &&
(vertices[3].x >= 493.0f && vertices[3].x <= 494.0f &&
vertices[3].y >= 404.0f && vertices[3].y <= 408.0f))) {
(((vertices[0].x >= 493.0f && vertices[0].x <= 494.0f) ||
iidxhook_util_d3d9_float_equal(
vertices[0].x, 500.0f, 0.1f)) &&
(iidxhook_util_d3d9_float_equal(vertices[0].y, 200.0f, 0.1f) ||
iidxhook_util_d3d9_float_equal(vertices[0].y, 206.0f, 0.1f) ||
(vertices[0].y >= 216.0f && vertices[0].y <= 220.0f)) &&
(iidxhook_util_d3d9_float_equal(vertices[1].x, 626.0f, 0.1f) ||
(vertices[1].x >= 634.0f && vertices[1].x <= 635.0f)) &&
(iidxhook_util_d3d9_float_equal(vertices[1].y, 200.0f, 0.1f) ||
iidxhook_util_d3d9_float_equal(vertices[1].y, 206.0f, 0.1f) ||
(vertices[1].y >= 216.0f && vertices[1].y <= 220.0f)) &&
(iidxhook_util_d3d9_float_equal(vertices[2].x, 626.0f, 0.1f) ||
(vertices[2].x >= 634.0f && vertices[2].x <= 635.0f)) &&
(iidxhook_util_d3d9_float_equal(vertices[2].y, 368.0f, 0.1f) ||
iidxhook_util_d3d9_float_equal(vertices[2].y, 394.0f, 0.1f) ||
(vertices[2].y >= 404.0f && vertices[2].y <= 408.0f)) &&
((vertices[3].x >= 493.0f && vertices[3].x <= 494.0f) ||
iidxhook_util_d3d9_float_equal(
vertices[3].x, 500.0f, 0.1f)) &&
(iidxhook_util_d3d9_float_equal(vertices[3].y, 368.0f, 0.1f) ||
iidxhook_util_d3d9_float_equal(vertices[3].y, 394.0f, 0.1f) ||
(vertices[3].y >= 404.0f && vertices[3].y <= 408.0f)))) {
/* fix UVs
1.0f / 512 fixes the diagonal seam connecting the two
triangles which is visible on some GPUs (why? idk)
@@ -695,7 +743,7 @@ iidxhook_util_d3d9_iidx11_to_17_fix_uvs_bg_videos(struct hook_d3d9_irp *irp)
}
static void
iidxhook_uti_d3d9_fix_iidx9_to_13_viewport_size(struct hook_d3d9_irp *irp)
iidxhook_uti_d3d9_fix_iidx09_to_13_viewport_size(struct hook_d3d9_irp *irp)
{
log_assert(irp);
log_assert(irp->op == HOOK_D3D9_IRP_OP_GET_CLIENT_RECT);
@@ -967,7 +1015,7 @@ iidxhook_util_d3d9_log_config(const struct iidxhook_util_d3d9_config *config)
"pci_vid: %X\n"
"pci_pid: %X\n"
"iidx09_to_19_monitor_check_cb: %p\n"
"iidx11_to_17_fix_uvs_bg_videos: %d\n"
"iidx09_to_17_fix_uvs_bg_videos: %d\n"
"iidx12_fix_song_select_bg: %d\n"
"iidx13_fix_song_select_bg: %d\n"
"iidx14_to_19_nvidia_fix: %d\n"
@@ -985,7 +1033,7 @@ iidxhook_util_d3d9_log_config(const struct iidxhook_util_d3d9_config *config)
config->pci_vid,
config->pci_pid,
config->iidx09_to_19_monitor_check_cb,
config->iidx11_to_17_fix_uvs_bg_videos,
config->iidx09_to_17_fix_uvs_bg_videos,
config->iidx12_fix_song_select_bg,
config->iidx13_fix_song_select_bg,
config->iidx14_to_19_nvidia_fix,
@@ -1050,7 +1098,7 @@ void iidxhook_util_d3d9_init_config(struct iidxhook_util_d3d9_config *config)
config->pci_vid = 0;
config->pci_pid = 0;
config->iidx09_to_19_monitor_check_cb = NULL;
config->iidx11_to_17_fix_uvs_bg_videos = false;
config->iidx09_to_17_fix_uvs_bg_videos = false;
config->iidx12_fix_song_select_bg = false;
config->iidx13_fix_song_select_bg = false;
config->iidx14_to_19_nvidia_fix = false;
@@ -1109,7 +1157,7 @@ iidxhook_util_d3d9_irp_handler(struct hook_d3d9_irp *irp)
hr = hook_d3d9_irp_invoke_next(irp);
if (hr == S_OK) {
iidxhook_uti_d3d9_fix_iidx9_to_13_viewport_size(irp);
iidxhook_uti_d3d9_fix_iidx09_to_13_viewport_size(irp);
}
return hr;
@@ -1161,7 +1209,7 @@ iidxhook_util_d3d9_irp_handler(struct hook_d3d9_irp *irp)
return hook_d3d9_irp_invoke_next(irp);
case HOOK_D3D9_IRP_OP_DEV_DRAW_PRIMITIVE_UP:
iidxhook_util_d3d9_iidx11_to_17_fix_uvs_bg_videos(irp);
iidxhook_util_d3d9_iidx09_to_17_fix_uvs_bg_videos(irp);
return hook_d3d9_irp_invoke_next(irp);

View File

@@ -102,7 +102,7 @@ struct iidxhook_util_d3d9_config {
* the background videos or seeing a quad seam (see implementation for
* further details).
*/
bool iidx11_to_17_fix_uvs_bg_videos;
bool iidx09_to_17_fix_uvs_bg_videos;
/**
* Ported from d3d8 module to enable this when using d3d8to9.

View File

@@ -87,7 +87,7 @@ static void iidxhook1_setup_d3d9_hooks(
d3d9_config.framerate_limit = config_gfx->frame_rate_limit;
d3d9_config.iidx12_fix_song_select_bg =
config_iidxhook1->happy_sky_ms_bg_fix;
d3d9_config.iidx11_to_17_fix_uvs_bg_videos = config_gfx->bgvideo_uv_fix;
d3d9_config.iidx09_to_17_fix_uvs_bg_videos = config_gfx->bgvideo_uv_fix;
d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width;
d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height;
d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter;

View File

@@ -84,7 +84,7 @@ static void iidxhook2_setup_d3d9_hooks(
d3d9_config.framerate_limit = config_gfx->frame_rate_limit;
d3d9_config.iidx13_fix_song_select_bg =
config_iidxhook2->distorted_ms_bg_fix;
d3d9_config.iidx11_to_17_fix_uvs_bg_videos = config_gfx->bgvideo_uv_fix;
d3d9_config.iidx09_to_17_fix_uvs_bg_videos = config_gfx->bgvideo_uv_fix;
d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width;
d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height;
d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter;

View File

@@ -80,7 +80,7 @@ iidxhook3_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx)
d3d9_config.pci_pid = config_gfx->pci_id_pid;
/* Required for GOLD (and newer?) to not crash with NVIDIA cards */
d3d9_config.iidx11_to_17_fix_uvs_bg_videos = true;
d3d9_config.iidx09_to_17_fix_uvs_bg_videos = true;
d3d9_config.iidx14_to_19_nvidia_fix = true;
d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width;

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