diff --git a/doc/config/common.md b/doc/config/common.md index e0616a8..71b1356 100644 --- a/doc/config/common.md +++ b/doc/config/common.md @@ -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. diff --git a/idmac/config.c b/idmac/config.c index e1da790..39f785d 100644 --- a/idmac/config.c +++ b/idmac/config.c @@ -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); } diff --git a/idmac/idmac.c b/idmac/idmac.c index 1cc2aab..a5b8ad0 100644 --- a/idmac/idmac.c +++ b/idmac/idmac.c @@ -1,58 +1,66 @@ #include #include #include +#include #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; diff --git a/idmac/idmac.h b/idmac/idmac.h index 2006902..e482b33 100644 --- a/idmac/idmac.h +++ b/idmac/idmac.h @@ -1,15 +1,30 @@ #pragma once #include +#include #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); diff --git a/sivahook/dllmain.c b/sivahook/dllmain.c index e9170aa..04667b6 100644 --- a/sivahook/dllmain.c +++ b/sivahook/dllmain.c @@ -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; diff --git a/sivahook/fastio.c b/sivahook/fastio.c new file mode 100644 index 0000000..5ee2eaf --- /dev/null +++ b/sivahook/fastio.c @@ -0,0 +1,45 @@ +#include +#include + +#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) + {} \ No newline at end of file diff --git a/sivahook/fastio.h b/sivahook/fastio.h new file mode 100644 index 0000000..8124462 --- /dev/null +++ b/sivahook/fastio.h @@ -0,0 +1,6 @@ +#pragma once +#include + +#include "jvs/jvs-bus.h" + +HRESULT siva_fastio_init(struct jvs_node **out); diff --git a/sivahook/meson.build b/sivahook/meson.build index 1ff4b85..0239b0c 100644 --- a/sivahook/meson.build +++ b/sivahook/meson.build @@ -30,5 +30,7 @@ shared_library( 'touch.h', 'reader.c', 'reader.h', + 'fastio.c', + 'fastio.h', ], ) diff --git a/sivahook/reader.c b/sivahook/reader.c index bb0de7e..57c051a 100644 --- a/sivahook/reader.c +++ b/sivahook/reader.c @@ -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)