mirror of
https://gitea.tendokyu.moe/TeamTofuShop/taitools.git
synced 2026-10-05 21:28:12 +03:00
idmac: status good
This commit is contained in:
+25
-261
@@ -60,21 +60,6 @@ emulates an IC card in its proximity. A variety of different IC cards can be
|
||||
emulated; the exact choice of card that is emulated depends on the presence or
|
||||
absence of the configured card ID files.
|
||||
|
||||
## `[amvideo]`
|
||||
|
||||
Controls the `amvideo.dll` stub built into Taitools. This is a DLL that is
|
||||
normally present on the SEGA operating system image which is responsible for
|
||||
changing screen resolution and orientation.
|
||||
|
||||
### `enable`
|
||||
|
||||
Default: `1`
|
||||
|
||||
Enable stub `amvideo.dll`. Disable to use a real `amvideo.dll` build. Note that
|
||||
you must have the correct registry settings installed and you must use the
|
||||
version of `amvideo.dll` that matches your GPU vendor (since these DLLs make
|
||||
use of vendor-specific APIs).
|
||||
|
||||
## `[clock]`
|
||||
|
||||
Controls hooks for Windows time-of-day APIs.
|
||||
@@ -143,122 +128,6 @@ Default: Empty string (i.e. use value from `default` setting)
|
||||
|
||||
Overrides the target of the `aime.naominet.jp` host lookup.
|
||||
|
||||
## `[ds]`
|
||||
|
||||
Controls emulation of the "DS (Dallas Semiconductor) EEPROM" chip on the AMEX
|
||||
PCIe board. This is a small (32 byte) EEPROM that contains serial number and
|
||||
region code information. It is not normally written to outside of inital
|
||||
factory provisioning of a Sega Nu.
|
||||
|
||||
### `enable`
|
||||
|
||||
Default: `1`
|
||||
|
||||
Enable DS EEPROM emulation. Disable to use the DS EEPROM chip on a real AMEX.
|
||||
|
||||
### `region`
|
||||
|
||||
Default: `1`
|
||||
|
||||
AMEX Board region code. This appears to be a bit mask?
|
||||
|
||||
- `1`: Japan
|
||||
- `2`: USA? (Dead code, not used)
|
||||
- `4`: Export
|
||||
- `8`: China
|
||||
|
||||
### `serialNo`
|
||||
|
||||
Default `AAVE-01A99999999`
|
||||
|
||||
"MAIN ID" serial number. First three characters are hardware series:
|
||||
|
||||
- `AAV`: Nu-series
|
||||
- `AAW`: NuSX-series
|
||||
- `ACA`: ALLS-series
|
||||
|
||||
## `[eeprom]`
|
||||
|
||||
Controls emulation of the bulk EEPROM on the AMEX PCIe board. This chip stores
|
||||
status and configuration information.
|
||||
|
||||
### `enable`
|
||||
|
||||
Default: `1`
|
||||
|
||||
Enable bulk EEPROM emulation. Disable to use the bulk EEPROM chip on a real
|
||||
AMEX.
|
||||
|
||||
### `path`
|
||||
|
||||
Default: `DEVICE\eeprom.bin`
|
||||
|
||||
Path to the storage file for EEPROM emulation. This file is automatically
|
||||
created and initialized with a suitable number of zero bytes if it does not
|
||||
already exist.
|
||||
|
||||
## `[gpio]`
|
||||
|
||||
Configure emulation of the AMEX PCIe GPIO (General Purpose Input Output)
|
||||
controller.
|
||||
|
||||
### `enable`
|
||||
|
||||
Default: `1`
|
||||
|
||||
Enable GPIO emulation. Disable to use the GPIO controller on a real AMEX.
|
||||
|
||||
### `sw1`
|
||||
|
||||
Default `0x70` (`VK_F1`)
|
||||
|
||||
Keyboard binding for Nu chassis SW1 button (alternative Test)
|
||||
|
||||
### `sw2`
|
||||
|
||||
Default `0x71` (`VK_F2`)
|
||||
|
||||
Keyboard binding for Nu chassis SW2 button (alternative Service)
|
||||
|
||||
### `dipsw1` .. `dipsw8`
|
||||
|
||||
Defaults: `1`, `0`, `0`, `0`, `0`, `0`, `0`, `0`
|
||||
|
||||
Nu chassis DIP switch settings:
|
||||
|
||||
- Switch 1: Game-specific, but usually controls the "distribution server"
|
||||
setting. Exactly one arcade machine on a cabinet router must be set to the
|
||||
Server setting.
|
||||
- `0`: Client
|
||||
- `1`: Server
|
||||
- Switch 2,3: Game-specific.
|
||||
- Used by Mario&Sonic to configure cabinet ID, possibly other games.
|
||||
- Switch 4: Screen orientation. Only used by the Nu system startup program.
|
||||
- `0`: YOKO/Horizontal
|
||||
- `1`: TATE/Vertical
|
||||
- Switch 5,6,7: Screen resolution. Only used by the Nu system startup program.
|
||||
- `000`: No change
|
||||
- `100`: 640x480
|
||||
- `010`: 1024x600
|
||||
- `110`: 1024x768
|
||||
- `001`: 1280x720
|
||||
- `101`: 1280x1024
|
||||
- `110`: 1360x768
|
||||
- `111`: 1920x1080
|
||||
- Switch 8: Game-specific. Not used in any shipping game.
|
||||
|
||||
## `[hwmon]`
|
||||
|
||||
Configure stub implementation of the platform hardware monitor driver. The
|
||||
real implementation of this driver monitors CPU temperatures by reading from
|
||||
Intel Model Specific Registers, which is an action that is only permitted from
|
||||
kernel mode.
|
||||
|
||||
### `enable`
|
||||
|
||||
Default `1`
|
||||
|
||||
Enable hwmon emulation. Disable to use the real hwmon driver.
|
||||
|
||||
## `[jvs]`
|
||||
|
||||
@@ -270,96 +139,6 @@ Default `1`
|
||||
|
||||
Enable JVS port emulation. Disable to use the JVS port on a real AMEX.
|
||||
|
||||
## `[keychip]`
|
||||
|
||||
Configure keychip emulation.
|
||||
|
||||
### `enable`
|
||||
|
||||
Enable keychip emulation. Disable to use a real keychip.
|
||||
|
||||
### `id`
|
||||
|
||||
Default: `A69E-01A88888888`
|
||||
|
||||
Keychip serial number. Keychip serials observed in the wild follow this
|
||||
pattern: `A6xE-01Ayyyyyyyy`.
|
||||
|
||||
### `gameId`
|
||||
|
||||
Default: (Varies depending on game)
|
||||
|
||||
Override the game's four-character model code. Changing this from the game's
|
||||
expected value will probably just cause a system error.
|
||||
|
||||
### `platformId`
|
||||
|
||||
Default: (Varies depending on game)
|
||||
|
||||
Override the game's four-character platform code (e.g. `AAV2` for Nu 2). This
|
||||
is actually supposed to be a separate three-character `platformId` and
|
||||
integer `modelType` setting, but they are combined here for convenience. Valid
|
||||
values include:
|
||||
|
||||
- `AAV0`: Nu 1 (Project DIVA)
|
||||
- `AAV1`: Nu 1.1 (Chunithm)
|
||||
- `AAV2`: Nu 2 (Initial D Zero)
|
||||
- `AAW0`: NuSX 1
|
||||
- `AAW1`: NuSX 1.1
|
||||
- `ACA0`: ALLS UX
|
||||
- `ACA1`: ALLS HX
|
||||
- `ACA2`: ALLS UX (without dedicated GPU)
|
||||
- `ACA4`: ALLS MX
|
||||
|
||||
### `region`
|
||||
|
||||
Default: `1`
|
||||
|
||||
Override the keychip's region code. Most games seem to pay attention to the
|
||||
DS EEPROM region code and not the keychip region code, and this seems to be
|
||||
a bit mask that controls which Nu PCB region codes this keychip is authorized
|
||||
for. So it probably only affects the system software and not the game software.
|
||||
Bit values are:
|
||||
|
||||
- 1: JPN: Japan
|
||||
- 2: USA (unused)
|
||||
- 3: EXP: Export (for Asian markets)
|
||||
- 4: CHS: China (Simplified Chinese?)
|
||||
|
||||
### `billingType`
|
||||
|
||||
Default: `1`
|
||||
|
||||
Set the billing "type" for the keychip. The type determins what kind of revenue share,
|
||||
if any, the game maker has with SEGA. Some games may be picky and require types other
|
||||
then 1 (ex. Crossbeats requires billing type 2), so this option is provided if this
|
||||
is an issue. Billing types are:
|
||||
|
||||
- 0: No billing?
|
||||
- 1: Billing type A
|
||||
- 2: Billing type B1
|
||||
- 3: Billing type B2
|
||||
|
||||
### `systemFlag`
|
||||
|
||||
Default: `0x64`
|
||||
|
||||
An 8-bit bitfield of unclear meaning. The least significant bit indicates a
|
||||
developer dongle, I think? Changing this doesn't seem to have any effect on
|
||||
anything other than Project DIVA.
|
||||
|
||||
Other values observed in the wild:
|
||||
|
||||
- `0x04`: SDCH, SDCA
|
||||
- `0x20`: SDCA
|
||||
|
||||
### `subnet`
|
||||
|
||||
Default `192.168.100.0`
|
||||
|
||||
The LAN IP range that the game will expect. The prefix length is hardcoded into
|
||||
the game program: for some games this is `/24`, for others it is `/20`.
|
||||
|
||||
## `[netenv]`
|
||||
|
||||
Configure network environment virtualization. This module helps bypass various
|
||||
@@ -396,46 +175,6 @@ Default: `01:02:03:04:05:06`
|
||||
The MAC address of the virtualized Ethernet adapter. The exact value shouldn't
|
||||
ever matter.
|
||||
|
||||
## `[pcbid]`
|
||||
|
||||
Configure Windows host name virtualization. The ALLS-series platform no longer
|
||||
has an AMEX board, so the MAIN ID serial number is stored in the Windows
|
||||
hostname.
|
||||
|
||||
### `enable`
|
||||
|
||||
Default: `1`
|
||||
|
||||
Enable Windows host name virtualization. This is only needed for ALLS-platform
|
||||
games (since the ALLS lacks an AMEX and therefore has no DS EEPROM, so it needs
|
||||
another way to store the PCB serial), but it does no harm on games that run on
|
||||
earlier hardware.
|
||||
|
||||
### `serialNo`
|
||||
|
||||
Default: `ACAE01A99999999`
|
||||
|
||||
Set the Windows host name. This should be an ALLS MAIN ID, without the
|
||||
hyphen (which is not a valid character in a Windows host name).
|
||||
|
||||
## `[sram]`
|
||||
|
||||
Configure emulation of the AMEX PCIe battery-backed SRAM. This stores
|
||||
bookkeeping state and settings. This file is automatically created and
|
||||
initialized with a suitable number of zero bytes if it does not already exist.
|
||||
|
||||
### `enable`
|
||||
|
||||
Default `1`
|
||||
|
||||
Enable SRAM emulation. Disable to use the SRAM on a real AMEX.
|
||||
|
||||
### `path`
|
||||
|
||||
Default `DEVICE\sram.bin`
|
||||
|
||||
Path to the storage file for SRAM emulation.
|
||||
|
||||
## `[vfs]`
|
||||
|
||||
Configure Windows path redirection hooks.
|
||||
@@ -468,3 +207,28 @@ Default: Empty string
|
||||
Configure the location of the "Option" data mount point. This mount point is
|
||||
optional (hence the name, probably) and contains directories which contain
|
||||
minor over-the-air content updates.
|
||||
|
||||
## `[idmac]`
|
||||
### `dipsw_override`
|
||||
|
||||
Default: 0
|
||||
|
||||
Weather the value of `dipsw` will override the dipswitch value set by the DLL.
|
||||
Only useful for debugging. Leave disabled.
|
||||
|
||||
### `dipsw`
|
||||
|
||||
Default: 0
|
||||
|
||||
Controls the value of the 4-switch dipswitch on the DMAC's daughter board. Each
|
||||
bit is one of the switches, with LSB being switch 1. Ignored if `dipsw_override`
|
||||
is 0.
|
||||
|
||||
### `hook_dll`
|
||||
|
||||
Default: 0
|
||||
|
||||
If 1, hook the iDmacDrvxx.dll functions, otherwise create a fake device. Set to
|
||||
1 if you're using the stub included with this hook as a substitute for the real
|
||||
DLL. Both hooking methods lead to the same place, so it doesn't matter too much
|
||||
what you use.
|
||||
|
||||
@@ -23,5 +23,9 @@ void idmac_config_load(struct idmac_config *cfg, const wchar_t *filename)
|
||||
assert(cfg != NULL);
|
||||
assert(filename != NULL);
|
||||
|
||||
cfg->dipsw = GetPrivateProfileIntW(L"idmac", L"dipsw_override", 0, filename) << 4;
|
||||
cfg->dipsw |= GetPrivateProfileIntW(L"idmac", L"dipsw", 0, filename);
|
||||
cfg->hook_dll = GetPrivateProfileIntW(L"idmac", L"hook_dll", 0, filename);
|
||||
|
||||
jvs_config_load(&cfg->jvs, filename);
|
||||
}
|
||||
|
||||
+205
-70
@@ -1,58 +1,66 @@
|
||||
#include <windows.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <winioctl.h>
|
||||
|
||||
#include "idmac/idmac.h"
|
||||
#include "idmac/jvs.h"
|
||||
|
||||
#include "hook/table.h"
|
||||
#include "hook/table.h"
|
||||
#include "hook/iohook.h"
|
||||
#include "util/dprintf.h"
|
||||
#include "util/str.h"
|
||||
|
||||
enum IDAMC_IOCTL {
|
||||
DMA_READ = 0xC3502000,
|
||||
DMA_WRITE = 0xC3502004,
|
||||
REGISTER_READ = 0xC3502008,
|
||||
REGISTER_WRITE = 0xC350200C,
|
||||
REGISTER_BUFFER_READ = 0xC3502012,
|
||||
REGISTER_BUFFER_WRITE = 0xC3502016,
|
||||
MEMORY_READ = 0xC3502018,
|
||||
MEMORY_WRITE = 0xC350201C,
|
||||
MEMORY_READ_EXT = 0xC3502080,
|
||||
MEMORY_WRITE_EXT = 0xC3502084,
|
||||
MEMORY_BUFFER_READ = 0xC3502020,
|
||||
MEMORY_BUFFER_WRITE = 0xC3502024,
|
||||
};
|
||||
#define IDMAC_IOCTL_DMA_READ CTL_CODE(0xC350, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IDMAC_IOCTL_DMA_WRITE CTL_CODE(0xC350, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IDMAC_IOCTL_REGISTER_READ CTL_CODE(0xC350, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IDMAC_IOCTL_REGISTER_WRITE CTL_CODE(0xC350, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IDMAC_IOCTL_REGISTER_BUFFER_READ CTL_CODE(0xC350, 0x804, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||
#define IDMAC_IOCTL_REGISTER_BUFFER_WRITE CTL_CODE(0xC350, 0x805, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||
#define IDMAC_IOCTL_MEMORY_READ CTL_CODE(0xC350, 0x806, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IDMAC_IOCTL_MEMORY_WRITE CTL_CODE(0xC350, 0x807, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IDMAC_IOCTL_MEMORY_BUFFER_READ CTL_CODE(0xC350, 0x808, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IDMAC_IOCTL_MEMORY_BUFFER_WRITE CTL_CODE(0xC350, 0x809, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IDMAC_IOCTL_MEMORY_READ_EXT CTL_CODE(0xC350, 0x820, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IDMAC_IOCTL_MEMORY_WRITE_EXT CTL_CODE(0xC350, 0x821, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
DWORD hook_iDmacDrvOpen(int dev_num, DWORD *dev_handle, DWORD *other_ptr);
|
||||
DWORD hook_iDmacDrvClose(HANDLE a1, DWORD *lp);
|
||||
int hook_iDmacDrvDmaRead(HANDLE a1, LPVOID lp, UINT_PTR ucb, unsigned int *a4);
|
||||
int hook_iDmacDrvDmaWrite(HANDLE a1, void *lp, UINT_PTR ucb, unsigned int *a4);
|
||||
int hook_iDmacDrvRegisterRead(HANDLE a1, DWORD register_id, DWORD* lp, unsigned int *a4);
|
||||
int hook_iDmacDrvRegisterWrite(HANDLE a1, DWORD register_id, int a3, DWORD *lp);
|
||||
int hook_iDmacDrvRegisterBufferRead(HANDLE a1, DWORD BytesReturned, LPVOID lp, UINT_PTR ucb, DWORD *a5);
|
||||
int hook_iDmacDrvRegisterBufferWrite(HANDLE a1, DWORD BytesReturned, void *lp, UINT_PTR ucb, DWORD *a5);
|
||||
int hook_iDmacDrvMemoryRead(HANDLE a1, DWORD BytesReturned, LPVOID lp, DWORD *a4);
|
||||
int hook_iDmacDrvMemoryWrite(HANDLE a1, DWORD BytesReturned, int a3, DWORD *lp);
|
||||
int hook_iDmacDrvMemoryBufferRead(HANDLE a1, DWORD BytesReturned, LPVOID lp, UINT_PTR ucb, DWORD *a5);
|
||||
int hook_iDmacDrvMemoryBufferWrite(HANDLE a1, unsigned int a2, void *lp, UINT_PTR ucb, DWORD *a5);
|
||||
int hook_iDmacDrvMemoryReadExt(HANDLE a1, DWORD BytesReturned, unsigned int a3, LPVOID lp, int nOutBufferSize, DWORD *a6);
|
||||
int hook_iDmacDrvMemoryWriteExt(HANDLE a1, int a2, unsigned int a3, void *Source, rsize_t DestinationSize, unsigned int *lp);
|
||||
static uint8_t dipsw = 0;
|
||||
static HANDLE idmac_fd;
|
||||
|
||||
DWORD (*next_iDmacDrvOpen)(int dev_num, DWORD *dev_handle, DWORD *other_ptr);
|
||||
DWORD (*next_iDmacDrvClose)(HANDLE a1, DWORD *lp);
|
||||
int (*next_iDmacDrvDmaRead)(HANDLE a1, LPVOID lp, UINT_PTR ucb, unsigned int *a4);
|
||||
int (*next_iDmacDrvDmaWrite)(HANDLE a1, void *lp, UINT_PTR ucb, unsigned int *a4);
|
||||
int (*next_iDmacDrvRegisterRead)(HANDLE a1, DWORD BytesReturned, LPVOID lp, unsigned int *a4);
|
||||
int (*next_iDmacDrvRegisterWrite)(HANDLE a1, DWORD BytesReturned, int a3, DWORD *lp);
|
||||
int (*next_iDmacDrvRegisterBufferRead)(HANDLE a1, DWORD BytesReturned, LPVOID lp, UINT_PTR ucb, DWORD *a5);
|
||||
int (*next_iDmacDrvRegisterBufferWrite)(HANDLE a1, DWORD BytesReturned, void *lp, UINT_PTR ucb, DWORD *a5);
|
||||
int (*next_iDmacDrvMemoryRead)(HANDLE a1, DWORD BytesReturned, LPVOID lp, DWORD *a4);
|
||||
int (*next_iDmacDrvMemoryWrite)(HANDLE a1, DWORD BytesReturned, int a3, DWORD *lp);
|
||||
int (*next_iDmacDrvMemoryBufferRead)(HANDLE a1, DWORD BytesReturned, LPVOID lp, UINT_PTR ucb, DWORD *a5);
|
||||
int (*next_iDmacDrvMemoryBufferWrite)(HANDLE a1, unsigned int a2, void *lp, UINT_PTR ucb, DWORD *a5);
|
||||
int (*next_iDmacDrvMemoryReadExt)(HANDLE a1, DWORD BytesReturned, unsigned int a3, LPVOID lp, int nOutBufferSize, DWORD *a6);
|
||||
int (*next_iDmacDrvMemoryWriteExt)(HANDLE a1, int a2, unsigned int a3, void *Source, rsize_t DestinationSize, unsigned int *lp);
|
||||
static HRESULT idmac_handle_irp(struct irp *irp);
|
||||
static HRESULT idmac_handle_open(struct irp *irp);
|
||||
static HRESULT idmac_handle_close(struct irp *irp);
|
||||
static HRESULT idmac_handle_ioctl(struct irp *irp);
|
||||
|
||||
static DWORD hook_iDmacDrvOpen(int dev_num, DWORD *dev_handle, DWORD *err);
|
||||
static DWORD hook_iDmacDrvClose(HANDLE a1, DWORD *lp);
|
||||
static int hook_iDmacDrvDmaRead(HANDLE a1, void *lp, int ucb, unsigned int *err);
|
||||
static int hook_iDmacDrvDmaWrite(HANDLE a1, void *lp, int ucb, unsigned int *err);
|
||||
static int hook_iDmacDrvRegisterRead(HANDLE a1, DWORD register_id, DWORD* lp, unsigned int *err);
|
||||
static int hook_iDmacDrvRegisterWrite(HANDLE a1, DWORD register_id, int a3, DWORD *lp);
|
||||
static int hook_iDmacDrvRegisterBufferRead(HANDLE a1, DWORD BytesReturned, LPVOID lp, UINT_PTR ucb, DWORD *a5);
|
||||
static int hook_iDmacDrvRegisterBufferWrite(HANDLE a1, DWORD BytesReturned, void *lp, UINT_PTR ucb, DWORD *a5);
|
||||
static int hook_iDmacDrvMemoryRead(HANDLE a1, DWORD BytesReturned, LPVOID lp, DWORD *a4);
|
||||
static int hook_iDmacDrvMemoryWrite(HANDLE a1, DWORD BytesReturned, int a3, DWORD *lp);
|
||||
static int hook_iDmacDrvMemoryBufferRead(HANDLE a1, DWORD BytesReturned, LPVOID lp, UINT_PTR ucb, DWORD *a5);
|
||||
static int hook_iDmacDrvMemoryBufferWrite(HANDLE a1, unsigned int a2, void *lp, UINT_PTR ucb, DWORD *a5);
|
||||
static int hook_iDmacDrvMemoryReadExt(HANDLE a1, DWORD BytesReturned, unsigned int a3, LPVOID lp, int nOutBufferSize, DWORD *a6);
|
||||
static int hook_iDmacDrvMemoryWriteExt(HANDLE a1, int a2, unsigned int a3, void *Source, rsize_t DestinationSize, unsigned int *lp);
|
||||
|
||||
static DWORD (*next_iDmacDrvOpen)(int dev_num, DWORD *dev_handle, DWORD *err);
|
||||
static DWORD (*next_iDmacDrvClose)(HANDLE a1, DWORD *lp);
|
||||
static int (*next_iDmacDrvDmaRead)(HANDLE a1, void *lp, int ucb, unsigned int *err);
|
||||
static int (*next_iDmacDrvDmaWrite)(HANDLE a1, void *lp, int ucb, unsigned int *err);
|
||||
static int (*next_iDmacDrvRegisterRead)(HANDLE a1, DWORD BytesReturned, LPVOID lp, unsigned int *err);
|
||||
static int (*next_iDmacDrvRegisterWrite)(HANDLE a1, DWORD BytesReturned, int a3, DWORD *lp);
|
||||
static int (*next_iDmacDrvRegisterBufferRead)(HANDLE a1, DWORD BytesReturned, LPVOID lp, UINT_PTR ucb, DWORD *a5);
|
||||
static int (*next_iDmacDrvRegisterBufferWrite)(HANDLE a1, DWORD BytesReturned, void *lp, UINT_PTR ucb, DWORD *a5);
|
||||
static int (*next_iDmacDrvMemoryRead)(HANDLE a1, DWORD BytesReturned, LPVOID lp, DWORD *a4);
|
||||
static int (*next_iDmacDrvMemoryWrite)(HANDLE a1, DWORD BytesReturned, int a3, DWORD *lp);
|
||||
static int (*next_iDmacDrvMemoryBufferRead)(HANDLE a1, DWORD BytesReturned, LPVOID lp, UINT_PTR ucb, DWORD *a5);
|
||||
static int (*next_iDmacDrvMemoryBufferWrite)(HANDLE a1, unsigned int a2, void *lp, UINT_PTR ucb, DWORD *a5);
|
||||
static int (*next_iDmacDrvMemoryReadExt)(HANDLE a1, DWORD BytesReturned, unsigned int a3, LPVOID lp, int nOutBufferSize, DWORD *a6);
|
||||
static int (*next_iDmacDrvMemoryWriteExt)(HANDLE a1, int a2, unsigned int a3, void *Source, rsize_t DestinationSize, unsigned int *lp);
|
||||
|
||||
static const struct hook_symbol idmac_hooks[] = {
|
||||
{
|
||||
@@ -144,7 +152,7 @@ void idmac_hook_table_apply(HMODULE target)
|
||||
);
|
||||
}
|
||||
|
||||
HRESULT idmac_hook_init(const struct idmac_config *cfg, jvs_provider_t jvs)
|
||||
HRESULT idmac_hook_init(const struct idmac_config *cfg, struct idmac_hardware *hardware)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
@@ -152,7 +160,13 @@ HRESULT idmac_hook_init(const struct idmac_config *cfg, jvs_provider_t jvs)
|
||||
|
||||
dprintf("iDmac: Init\n");
|
||||
|
||||
hr = jvs_hook_init(&cfg->jvs, jvs);
|
||||
dipsw = hardware->dipsw & 0x0F;
|
||||
|
||||
if (cfg->dipsw >> 4) {
|
||||
dipsw = cfg->dipsw & 0x0F;
|
||||
}
|
||||
|
||||
hr = jvs_hook_init(&cfg->jvs, hardware->jvs);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
@@ -160,97 +174,218 @@ HRESULT idmac_hook_init(const struct idmac_config *cfg, jvs_provider_t jvs)
|
||||
|
||||
idmac_hook_table_apply(NULL);
|
||||
|
||||
hr = iohook_open_nul_fd(&idmac_fd);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = iohook_push_handler(idmac_handle_irp);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
DWORD hook_iDmacDrvOpen(int dev_num, DWORD *dev_handle, DWORD *other_ptr)
|
||||
static HRESULT idmac_handle_irp(struct irp *irp)
|
||||
{
|
||||
assert(irp != NULL);
|
||||
|
||||
if (irp->op != IRP_OP_OPEN && irp->fd != idmac_fd) {
|
||||
return iohook_invoke_next(irp);
|
||||
}
|
||||
|
||||
switch (irp->op) {
|
||||
case IRP_OP_OPEN: return idmac_handle_open(irp);
|
||||
case IRP_OP_CLOSE: return idmac_handle_close(irp);
|
||||
case IRP_OP_IOCTL: return idmac_handle_ioctl(irp);
|
||||
default: return HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION);
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT idmac_handle_open(struct irp *irp)
|
||||
{
|
||||
if (!wstr_ieq(irp->open_filename, L"\\\\.\\iDmacDrv0")) {
|
||||
return iohook_invoke_next(irp);
|
||||
}
|
||||
|
||||
dprintf("iDmac: Opened handle\n");
|
||||
irp->fd = idmac_fd;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT idmac_handle_close(struct irp *irp)
|
||||
{
|
||||
dprintf("iDmac: Closed handle\n");
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT idmac_handle_ioctl(struct irp *irp)
|
||||
{
|
||||
switch (irp->ioctl) {
|
||||
/*case IDMAC_IOCTL_DMA_READ:
|
||||
return hook_iDmacDrvDmaRead(irp);
|
||||
|
||||
case IDMAC_IOCTL_DMA_WRITE:
|
||||
return hook_iDmacDrvDmaWrite(irp);
|
||||
|
||||
case IDMAC_IOCTL_REGISTER_READ:
|
||||
return hook_iDmacDrvRegisterRead(irp);
|
||||
|
||||
case IDMAC_IOCTL_REGISTER_WRITE:
|
||||
return hook_iDmacDrvRegisterWrite(irp);
|
||||
|
||||
case IDMAC_IOCTL_REGISTER_BUFFER_READ:
|
||||
return hook_iDmacDrvRegisterBufferRead(irp);
|
||||
|
||||
case IDMAC_IOCTL_REGISTER_BUFFER_WRITE:
|
||||
return hook_iDmacDrvRegisterBufferWrite(irp);
|
||||
|
||||
case IDMAC_IOCTL_MEMORY_READ:
|
||||
return hook_iDmacDrvMemoryRead(irp);
|
||||
|
||||
case IDMAC_IOCTL_MEMORY_WRITE:
|
||||
return hook_iDmacDrvMemoryWrite(irp);
|
||||
|
||||
case IDMAC_IOCTL_MEMORY_BUFFER_READ:
|
||||
return hook_iDmacDrvMemoryBufferRead(irp);
|
||||
|
||||
case IDMAC_IOCTL_MEMORY_BUFFER_WRITE:
|
||||
return hook_iDmacDrvMemoryBufferWrite(irp);
|
||||
|
||||
case IDMAC_IOCTL_MEMORY_READ_EXT:
|
||||
return hook_iDmacDrvMemoryReadExt(irp);
|
||||
|
||||
case IDMAC_IOCTL_MEMORY_WRITE_EXT:
|
||||
return hook_iDmacDrvMemoryWriteExt(irp);*/
|
||||
|
||||
default:
|
||||
dprintf("iDmac: Unknown ioctl %#08x, write %i read %i\n",
|
||||
irp->ioctl,
|
||||
(int) irp->write.nbytes,
|
||||
(int) irp->read.nbytes);
|
||||
|
||||
return HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION);
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD hook_iDmacDrvOpen(int dev_num, DWORD *dev_handle, DWORD *err)
|
||||
{
|
||||
dprintf("hook_iDmacDrvOpen: Open device #%X\n", dev_num);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD hook_iDmacDrvClose(HANDLE dev_handle, DWORD *lp)
|
||||
static DWORD hook_iDmacDrvClose(HANDLE dev_handle, DWORD *lp)
|
||||
{
|
||||
dprintf("hook_iDmacDrvClose: Close handle %p\n", dev_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hook_iDmacDrvDmaRead(HANDLE a1, LPVOID lp, UINT_PTR ucb, unsigned int *a4)
|
||||
static int hook_iDmacDrvDmaRead(HANDLE a1, void *lp, int ucb, unsigned int *err)
|
||||
{
|
||||
//dprintf("hook_iDmacDrvDmaRead: This code should not run!\n");
|
||||
dprintf("hook_iDmacDrvDmaRead: Read %d bytes\n", ucb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hook_iDmacDrvDmaWrite(HANDLE a1, void *lp, UINT_PTR ucb, unsigned int *a4)
|
||||
static int hook_iDmacDrvDmaWrite(HANDLE a1, void *lp, int ucb, unsigned int *err)
|
||||
{
|
||||
//dprintf("hook_iDmacDrvDmaWrite: This code should not run!\n");
|
||||
dprintf("hook_iDmacDrvDmaWrite: Write %d bytes\n", ucb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hook_iDmacDrvRegisterRead(HANDLE a1, DWORD register_id, DWORD* lp, unsigned int *a4)
|
||||
static int hook_iDmacDrvRegisterRead(HANDLE a1, DWORD register_id, DWORD* register_val, unsigned int *err)
|
||||
{
|
||||
//dprintf("hook_iDmacDrvRegisterRead: This code should not run!\n");
|
||||
if (register_id == 0x4140) { // get coin slot 1
|
||||
*lp = 0;
|
||||
}
|
||||
if (register_id == 0x4144) { // get coin slot 2
|
||||
*lp = 0;
|
||||
}
|
||||
if (register_id == 0x4120 && (GetAsyncKeyState(VK_DELETE) & 0x8000)) { // get keys
|
||||
*lp = 0x40;
|
||||
*register_val = 0;
|
||||
*err = 0;
|
||||
|
||||
switch (register_id) {
|
||||
case 0x0400: break;
|
||||
|
||||
case 0x4000: *register_val = -2; break; // Status
|
||||
case 0x4004: *register_val = -2; break; // Status
|
||||
|
||||
case 0x4120: // JVS Buttons
|
||||
if (GetAsyncKeyState(VK_DELETE) & 0x8000) {
|
||||
*register_val = 0x40; // Test
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x4124: break; // Analog 1
|
||||
case 0x4128: break; // Analog 2
|
||||
case 0x412C: break; // Analog 3
|
||||
|
||||
case 0x4140: break; // Coin slot 1
|
||||
case 0x4144: break; // Coin slot 2
|
||||
|
||||
case 0x41A0: break;
|
||||
case 0x41A4: break;
|
||||
case 0x41A8: break;
|
||||
case 0x41AC: break;
|
||||
|
||||
case 0x41C0: break;
|
||||
case 0x41C4: break;
|
||||
|
||||
default:
|
||||
dprintf("iDmac: Requested register %04lX\n", register_id);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hook_iDmacDrvRegisterWrite(HANDLE a1, DWORD register_id, int a3, DWORD *lp)
|
||||
static int hook_iDmacDrvRegisterWrite(HANDLE a1, DWORD register_id, int a3, DWORD *lp)
|
||||
{
|
||||
//dprintf("hook_iDmacDrvRegisterWrite: This code should not run!\n");
|
||||
//dprintf("hook_iDmacDrvRegisterWrite: Write %d to register %04lX\n", a3, register_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hook_iDmacDrvRegisterBufferRead(HANDLE a1, DWORD BytesReturned, LPVOID lp, UINT_PTR ucb, DWORD *a5)
|
||||
static int hook_iDmacDrvRegisterBufferRead(HANDLE a1, DWORD BytesReturned, LPVOID lp, UINT_PTR ucb, DWORD *a5)
|
||||
{
|
||||
//dprintf("hook_iDmacDrvRegisterBufferRead: This code should not run!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hook_iDmacDrvRegisterBufferWrite(HANDLE a1, DWORD BytesReturned, void *lp, UINT_PTR ucb, DWORD *a5)
|
||||
static int hook_iDmacDrvRegisterBufferWrite(HANDLE a1, DWORD BytesReturned, void *lp, UINT_PTR ucb, DWORD *a5)
|
||||
{
|
||||
//dprintf("hook_iDmacDrvRegisterBufferWrite: This code should not run!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hook_iDmacDrvMemoryRead(HANDLE a1, DWORD BytesReturned, LPVOID lp, DWORD *a4)
|
||||
static int hook_iDmacDrvMemoryRead(HANDLE a1, DWORD BytesReturned, LPVOID lp, DWORD *a4)
|
||||
{
|
||||
//dprintf("hook_iDmacDrvMemoryRead: This code should not run!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hook_iDmacDrvMemoryWrite(HANDLE a1, DWORD BytesReturned, int a3, DWORD *lp)
|
||||
static int hook_iDmacDrvMemoryWrite(HANDLE a1, DWORD BytesReturned, int a3, DWORD *lp)
|
||||
{
|
||||
//dprintf("hook_iDmacDrvMemoryWrite: This code should not run!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hook_iDmacDrvMemoryBufferRead(HANDLE a1, DWORD BytesReturned, LPVOID lp, UINT_PTR ucb, DWORD *a5)
|
||||
static int hook_iDmacDrvMemoryBufferRead(HANDLE a1, DWORD BytesReturned, LPVOID lp, UINT_PTR ucb, DWORD *a5)
|
||||
{
|
||||
//dprintf("hook_iDmacDrvMemoryBufferRead: This code should not run!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hook_iDmacDrvMemoryBufferWrite(HANDLE a1, unsigned int a2, void *lp, UINT_PTR ucb, DWORD *a5)
|
||||
static int hook_iDmacDrvMemoryBufferWrite(HANDLE a1, unsigned int a2, void *lp, UINT_PTR ucb, DWORD *a5)
|
||||
{
|
||||
//dprintf("hook_iDmacDrvMemoryBufferWrite: This code should not run!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hook_iDmacDrvMemoryReadExt(HANDLE a1, DWORD BytesReturned, unsigned int a3, LPVOID lp, int nOutBufferSize, DWORD *a6)
|
||||
static int hook_iDmacDrvMemoryReadExt(HANDLE a1, DWORD BytesReturned, unsigned int a3, LPVOID lp, int nOutBufferSize, DWORD *a6)
|
||||
{
|
||||
//dprintf("hook_iDmacDrvMemoryReadExt: This code should not run!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hook_iDmacDrvMemoryWriteExt(HANDLE a1, int a2, unsigned int a3, void *Source, rsize_t DestinationSize, unsigned int *lp)
|
||||
static int hook_iDmacDrvMemoryWriteExt(HANDLE a1, int a2, unsigned int a3, void *Source, rsize_t DestinationSize, unsigned int *lp)
|
||||
{
|
||||
//dprintf("hook_iDmacDrvMemoryWriteExt: This code should not run!\n");
|
||||
return 0;
|
||||
|
||||
+16
-1
@@ -1,15 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "idmac/jvs.h"
|
||||
|
||||
#pragma pack(push,1)
|
||||
|
||||
struct idmac_config {
|
||||
uint8_t dipsw;
|
||||
bool hook_dll;
|
||||
struct jvs_config jvs;
|
||||
};
|
||||
|
||||
struct idmac_hardware {
|
||||
uint8_t dipsw;
|
||||
jvs_provider_t dongle;
|
||||
jvs_provider_t jvs;
|
||||
jvs_provider_t fastio_main;
|
||||
jvs_provider_t fastio_sub;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
HRESULT idmac_hook_init(
|
||||
const struct idmac_config *cfg,
|
||||
jvs_provider_t jvs);
|
||||
struct idmac_hardware *hardware);
|
||||
|
||||
void idmac_hook_table_apply(HMODULE target);
|
||||
|
||||
+14
-5
@@ -16,6 +16,7 @@
|
||||
#include "gfxhook/d3d11.h"
|
||||
#include "gfxhook/dxgi.h"
|
||||
|
||||
#include "sivahook/fastio.h"
|
||||
#include "sivahook/reader.h"
|
||||
#include "sivahook/config.h"
|
||||
#include "sivahook/siva-dll.h"
|
||||
@@ -45,10 +46,10 @@ static DWORD CALLBACK siva_pre_startup(void)
|
||||
/* Hook Win32 APIs */
|
||||
serial_hook_init();
|
||||
|
||||
//gfx_hook_init(&siva_hook_cfg.gfx);
|
||||
//gfx_d3d9_hook_init(&siva_hook_cfg.gfx, siva_hook_mod);
|
||||
//gfx_d3d11_hook_init(&siva_hook_cfg.gfx, siva_hook_mod);
|
||||
//gfx_dxgi_hook_init(&siva_hook_cfg.gfx, siva_hook_mod);
|
||||
gfx_hook_init(&siva_hook_cfg.gfx);
|
||||
gfx_d3d9_hook_init(&siva_hook_cfg.gfx, siva_hook_mod);
|
||||
gfx_d3d11_hook_init(&siva_hook_cfg.gfx, siva_hook_mod);
|
||||
gfx_dxgi_hook_init(&siva_hook_cfg.gfx, siva_hook_mod);
|
||||
|
||||
/* Initialize emulation hooks */
|
||||
|
||||
@@ -73,7 +74,15 @@ static DWORD CALLBACK siva_pre_startup(void)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hr = idmac_hook_init(&siva_hook_cfg.idmac, siva_reader_init);
|
||||
struct idmac_hardware idhw = {
|
||||
.dipsw = 0b0000,
|
||||
.dongle = NULL,
|
||||
.jvs = siva_reader_init,
|
||||
.fastio_main = siva_fastio_init,
|
||||
.fastio_sub = NULL,
|
||||
};
|
||||
|
||||
hr = idmac_hook_init(&siva_hook_cfg.idmac, &idhw);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
#include <windows.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "jvs/jvs-bus.h"
|
||||
#include "idmac/jvs.h"
|
||||
#include "board/io3.h"
|
||||
|
||||
#include "sivahook/fastio.h"
|
||||
#include "sivahook/siva-dll.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
static void fastio_jvs_read_switches(void *ctx, struct io3_switch_state *out);
|
||||
static void fastio_jvs_read_coin_counter(
|
||||
void *ctx,
|
||||
uint8_t slot_no,
|
||||
uint16_t *out);
|
||||
|
||||
static const struct io3_ops siva_jvs_fastio_ops = {
|
||||
.read_switches = fastio_jvs_read_switches,
|
||||
.read_coin_counter = fastio_jvs_read_coin_counter,
|
||||
};
|
||||
|
||||
static struct io3 siva_jvs_fastio;
|
||||
|
||||
HRESULT siva_fastio_init(struct jvs_node **out)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
assert(out != NULL);
|
||||
|
||||
dprintf("Siva Nesica Fastio: Init\n");
|
||||
|
||||
io3_init(&siva_jvs_fastio, NULL, &siva_jvs_fastio_ops, NULL);
|
||||
*out = io3_to_jvs_node(&siva_jvs_fastio);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void fastio_jvs_read_switches(void *ctx, struct io3_switch_state *out) {}
|
||||
static void fastio_jvs_read_coin_counter(
|
||||
void *ctx,
|
||||
uint8_t slot_no,
|
||||
uint16_t *out)
|
||||
{}
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include <windows.h>
|
||||
|
||||
#include "jvs/jvs-bus.h"
|
||||
|
||||
HRESULT siva_fastio_init(struct jvs_node **out);
|
||||
@@ -30,5 +30,7 @@ shared_library(
|
||||
'touch.h',
|
||||
'reader.c',
|
||||
'reader.h',
|
||||
'fastio.c',
|
||||
'fastio.h',
|
||||
],
|
||||
)
|
||||
|
||||
+6
-6
@@ -10,15 +10,15 @@
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
static void carol_jvs_read_switches(void *ctx, struct io3_switch_state *out);
|
||||
static void carol_jvs_read_coin_counter(
|
||||
static void reader_jvs_read_switches(void *ctx, struct io3_switch_state *out);
|
||||
static void reader_jvs_read_coin_counter(
|
||||
void *ctx,
|
||||
uint8_t slot_no,
|
||||
uint16_t *out);
|
||||
|
||||
static const struct io3_ops siva_jvs_reader_ops = {
|
||||
.read_switches = carol_jvs_read_switches,
|
||||
.read_coin_counter = carol_jvs_read_coin_counter,
|
||||
.read_switches = reader_jvs_read_switches,
|
||||
.read_coin_counter = reader_jvs_read_coin_counter,
|
||||
};
|
||||
|
||||
static struct io3 siva_jvs_reader;
|
||||
@@ -37,8 +37,8 @@ HRESULT siva_reader_init(struct jvs_node **out)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void carol_jvs_read_switches(void *ctx, struct io3_switch_state *out) {}
|
||||
static void carol_jvs_read_coin_counter(
|
||||
static void reader_jvs_read_switches(void *ctx, struct io3_switch_state *out) {}
|
||||
static void reader_jvs_read_coin_counter(
|
||||
void *ctx,
|
||||
uint8_t slot_no,
|
||||
uint16_t *out)
|
||||
|
||||
Reference in New Issue
Block a user