#include #include #include #include #include "idmac/idmac.h" #include "idmac/jvs.h" #include "hook/table.h" #include "hook/iohook.h" #include "util/dprintf.h" #include "util/str.h" #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) static uint8_t dipsw = 0; static HANDLE idmac_fd; 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[] = { { .name = "iDmacDrvOpen", .ordinal = 1, .patch = hook_iDmacDrvOpen, .link = (void **) &next_iDmacDrvOpen, },{ .name = "iDmacDrvClose", .ordinal = 2, .patch = hook_iDmacDrvClose, .link = (void **) &next_iDmacDrvClose, },{ .name = "iDmacDrvDmaRead", .ordinal = 3, .patch = hook_iDmacDrvDmaRead, .link = (void **) &next_iDmacDrvDmaRead, },{ .name = "iDmacDrvDmaWrite", .ordinal = 4, .patch = hook_iDmacDrvDmaWrite, .link = (void **) &next_iDmacDrvDmaWrite, },{ .name = "iDmacDrvRegisterRead", .ordinal = 5, .patch = hook_iDmacDrvRegisterRead, .link = (void **) &next_iDmacDrvRegisterRead, },{ .name = "iDmacDrvRegisterWrite", .ordinal = 6, .patch = hook_iDmacDrvRegisterWrite, .link = (void **) &next_iDmacDrvRegisterWrite, },{ .name = "iDmacDrvRegisterBufferRead", .ordinal = 7, .patch = hook_iDmacDrvRegisterBufferRead, .link = (void **) &next_iDmacDrvRegisterBufferRead, },{ .name = "iDmacDrvRegisterBufferWrite", .ordinal = 8, .patch = hook_iDmacDrvRegisterBufferWrite, .link = (void **) &next_iDmacDrvRegisterBufferWrite, },{ .name = "iDmacDrvMemoryRead", .ordinal = 9, .patch = hook_iDmacDrvMemoryRead, .link = (void **) &next_iDmacDrvMemoryRead, },{ .name = "iDmacDrvMemoryWrite", .ordinal = 10, .patch = hook_iDmacDrvMemoryWrite, .link = (void **) &next_iDmacDrvMemoryWrite, },{ .name = "iDmacDrvMemoryBufferRead", .ordinal = 11, .patch = hook_iDmacDrvMemoryBufferRead, .link = (void **) &next_iDmacDrvMemoryBufferRead, },{ .name = "iDmacDrvMemoryBufferWrite", .ordinal = 12, .patch = hook_iDmacDrvMemoryBufferWrite, .link = (void **) &next_iDmacDrvMemoryBufferWrite, },{ .name = "iDmacDrvMemoryReadExt", .ordinal = 13, .patch = hook_iDmacDrvMemoryReadExt, .link = (void **) &next_iDmacDrvMemoryReadExt, },{ .name = "iDmacDrvMemoryWriteExt", .ordinal = 14, .patch = hook_iDmacDrvMemoryWriteExt, .link = (void **) &next_iDmacDrvMemoryWriteExt, }, }; void idmac_hook_table_apply(HMODULE target) { hook_table_apply( target, "iDmacDrv64.dll", idmac_hooks, _countof(idmac_hooks) ); hook_table_apply( target, "iDmacDrv32.dll", idmac_hooks, _countof(idmac_hooks) ); } HRESULT idmac_hook_init(const struct idmac_config *cfg, struct idmac_hardware *hardware) { HRESULT hr; assert(cfg != NULL); dprintf("iDmac: Init\n"); 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; } hr = fastio_hook_init(hardware->fastio_main, hardware->fastio_sub); if (FAILED(hr)) { return hr; } 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; } 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; } static DWORD hook_iDmacDrvClose(HANDLE dev_handle, DWORD *lp) { dprintf("hook_iDmacDrvClose: Close handle %p\n", dev_handle); return 0; } static int hook_iDmacDrvDmaRead(HANDLE a1, void *lp, int ucb, unsigned int *err) { dprintf("hook_iDmacDrvDmaRead: Read %d bytes\n", ucb); return 0; } static int hook_iDmacDrvDmaWrite(HANDLE a1, void *lp, int ucb, unsigned int *err) { dprintf("hook_iDmacDrvDmaWrite: Write %d bytes\n", ucb); return 0; } static int hook_iDmacDrvRegisterRead(HANDLE a1, DWORD register_id, DWORD* register_val, unsigned int *err) { //dprintf("hook_iDmacDrvRegisterRead: This code should not run!\n"); *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 fastio_digital_read(NULL, 0, (uint32_t *)register_val); break; case 0x4124: break; // Analog 1 case 0x4128: break; // Analog 2 case 0x412C: break; // Analog 3 case 0x4140: fastio_coins_in(NULL, 0, 1, (uint32_t *)register_val); break; // Coin slot 1 case 0x4144: fastio_coins_in(NULL, 0, 2, (uint32_t *)register_val); 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; } static int hook_iDmacDrvRegisterWrite(HANDLE a1, DWORD register_id, int a3, DWORD *lp) { //dprintf("hook_iDmacDrvRegisterWrite: Write %d to register %04lX\n", a3, register_id); return 0; } 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; } 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; } static int hook_iDmacDrvMemoryRead(HANDLE a1, DWORD BytesReturned, LPVOID lp, DWORD *a4) { //dprintf("hook_iDmacDrvMemoryRead: This code should not run!\n"); return 0; } static int hook_iDmacDrvMemoryWrite(HANDLE a1, DWORD BytesReturned, int a3, DWORD *lp) { //dprintf("hook_iDmacDrvMemoryWrite: This code should not run!\n"); return 0; } 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; } 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; } 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; } 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; }