diff --git a/Package.mk b/Package.mk index 9d907b1..5647e9b 100644 --- a/Package.mk +++ b/Package.mk @@ -5,7 +5,7 @@ $(BUILD_DIR_ZIP)/chuni.zip: $(V)cp $(BUILD_DIR_32)/subprojects/capnhook/inject/inject.exe \ $(BUILD_DIR_32)/chunihook/chunihook.dll \ $(DIST_DIR)/chuni/segatools.ini \ - $(DIST_DIR)/chuni/start.bat \ + $(DIST_DIR)/chuni/launch.bat \ $(BUILD_DIR_ZIP)/chuni $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -20,7 +20,7 @@ $(BUILD_DIR_ZIP)/cxb.zip: $(V)cp $(BUILD_DIR_32)/subprojects/capnhook/inject/inject.exe \ $(BUILD_DIR_32)/cxbhook/cxbhook.dll \ $(DIST_DIR)/cxb/segatools.ini \ - $(DIST_DIR)/cxb/start.bat \ + $(DIST_DIR)/cxb/launch.bat \ $(BUILD_DIR_ZIP)/cxb $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -35,7 +35,7 @@ $(BUILD_DIR_ZIP)/diva.zip: $(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \ $(BUILD_DIR_64)/divahook/divahook.dll \ $(DIST_DIR)/diva/segatools.ini \ - $(DIST_DIR)/diva/start.bat \ + $(DIST_DIR)/diva/launch.bat \ $(BUILD_DIR_ZIP)/diva $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -50,7 +50,7 @@ $(BUILD_DIR_ZIP)/carol.zip: $(V)cp $(BUILD_DIR_32)/subprojects/capnhook/inject/inject.exe \ $(BUILD_DIR_32)/carolhook/carolhook.dll \ $(DIST_DIR)/carol/segatools.ini \ - $(DIST_DIR)/carol/start.bat \ + $(DIST_DIR)/carol/launch.bat \ $(BUILD_DIR_ZIP)/carol $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -65,7 +65,7 @@ $(BUILD_DIR_ZIP)/idz.zip: $(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \ $(BUILD_DIR_64)/idzhook/idzhook.dll \ $(DIST_DIR)/idz/segatools.ini \ - $(DIST_DIR)/idz/start.bat \ + $(DIST_DIR)/idz/launch.bat \ $(BUILD_DIR_ZIP)/idz $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -80,7 +80,7 @@ $(BUILD_DIR_ZIP)/fgo.zip: $(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \ $(BUILD_DIR_64)/fgohook/fgohook.dll \ $(DIST_DIR)/fgo/segatools.ini \ - $(DIST_DIR)/fgo/start.bat \ + $(DIST_DIR)/fgo/launch.bat \ $(BUILD_DIR_ZIP)/fgo $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -96,7 +96,7 @@ $(BUILD_DIR_ZIP)/idac.zip: $(BUILD_DIR_64)/idachook/idachook.dll \ $(DIST_DIR)/idac/segatools.ini \ $(DIST_DIR)/idac/config_hook.json \ - $(DIST_DIR)/idac/start.bat \ + $(DIST_DIR)/idac/launch.bat \ $(BUILD_DIR_ZIP)/idac $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -112,7 +112,7 @@ $(BUILD_DIR_ZIP)/swdc.zip: $(BUILD_DIR_64)/swdchook/swdchook.dll \ $(DIST_DIR)/swdc/segatools.ini \ $(DIST_DIR)/swdc/config_hook.json \ - $(DIST_DIR)/swdc/start.bat \ + $(DIST_DIR)/swdc/launch.bat \ $(BUILD_DIR_ZIP)/swdc $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -127,7 +127,7 @@ $(BUILD_DIR_ZIP)/mercury.zip: $(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \ $(BUILD_DIR_64)/mercuryhook/mercuryhook.dll \ $(DIST_DIR)/mercury/segatools.ini \ - $(DIST_DIR)/mercury/start.bat \ + $(DIST_DIR)/mercury/launch.bat \ $(BUILD_DIR_ZIP)/mercury $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -141,7 +141,7 @@ $(BUILD_DIR_ZIP)/chusan.zip: $(V)mkdir -p $(BUILD_DIR_ZIP)/chusan/DEVICE $(V)cp $(DIST_DIR)/chusan/segatools.ini \ $(DIST_DIR)/chusan/config_hook.json \ - $(DIST_DIR)/chusan/start.bat \ + $(DIST_DIR)/chusan/launch.bat \ $(BUILD_DIR_ZIP)/chusan $(V)cp $(BUILD_DIR_32)/chusanhook/chusanhook.dll \ $(BUILD_DIR_ZIP)/chusan/chusanhook_x86.dll @@ -164,7 +164,7 @@ $(BUILD_DIR_ZIP)/mu3.zip: $(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \ $(BUILD_DIR_64)/mu3hook/mu3hook.dll \ $(DIST_DIR)/mu3/segatools.ini \ - $(DIST_DIR)/mu3/start.bat \ + $(DIST_DIR)/mu3/launch.bat \ $(BUILD_DIR_ZIP)/mu3 $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -179,7 +179,7 @@ $(BUILD_DIR_ZIP)/mai2.zip: $(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \ $(BUILD_DIR_64)/mai2hook/mai2hook.dll \ $(DIST_DIR)/mai2/segatools.ini \ - $(DIST_DIR)/mai2/start.bat \ + $(DIST_DIR)/mai2/launch.bat \ $(BUILD_DIR_ZIP)/mai2 $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -195,7 +195,7 @@ $(BUILD_DIR_ZIP)/cm.zip: $(BUILD_DIR_64)/cmhook/cmhook.dll \ $(DIST_DIR)/cm/config_hook.json \ $(DIST_DIR)/cm/segatools.ini \ - $(DIST_DIR)/cm/start.bat \ + $(DIST_DIR)/cm/launch.bat \ $(BUILD_DIR_ZIP)/cm $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -211,7 +211,7 @@ $(BUILD_DIR_ZIP)/tokyo.zip: $(BUILD_DIR_64)/tokyohook/tokyohook.dll \ $(DIST_DIR)/tokyo/config_hook.json \ $(DIST_DIR)/tokyo/segatools.ini \ - $(DIST_DIR)/tokyo/start.bat \ + $(DIST_DIR)/tokyo/launch.bat \ $(BUILD_DIR_ZIP)/tokyo $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -224,7 +224,7 @@ $(BUILD_DIR_ZIP)/kemono.zip: $(V)mkdir -p $(BUILD_DIR_ZIP)/kemono $(V)mkdir -p $(BUILD_DIR_ZIP)/kemono/DEVICE $(V)cp $(DIST_DIR)/kemono/segatools.ini \ - $(DIST_DIR)/kemono/start.bat \ + $(DIST_DIR)/kemono/launch.bat \ $(BUILD_DIR_ZIP)/kemono $(V)cp $(BUILD_DIR_32)/kemonohook/kemonohook.dll \ $(BUILD_DIR_ZIP)/kemono/kemonohook_x86.dll diff --git a/board/led15070.c b/board/led15070.c index c2d62a5..43a015d 100644 --- a/board/led15070.c +++ b/board/led15070.c @@ -103,19 +103,30 @@ HRESULT led15070_hook_init( io_led_set_fet_output_t _led_set_fet_output, io_led_dc_update_t _led_dc_update, io_led_gs_update_t _led_gs_update, - unsigned int first_port, - unsigned int num_boards) + unsigned int port_no[2]) { + unsigned int num_boards = 0; + assert(cfg != NULL); + assert(_led_init != NULL); if (!cfg->enable) { return S_FALSE; } - if (cfg->port_no != 0) { - first_port = cfg->port_no; + for (int i = 0; i < led15070_nboards; i++) + { + if (cfg->port_no[i] != 0) { + port_no[i] = cfg->port_no[i]; + } + + if (port_no[i] != 0) { + num_boards++; + } } + assert(num_boards != 0); + led_init = _led_init; led_set_fet_output = _led_set_fet_output; led_dc_update = _led_dc_update; @@ -131,10 +142,7 @@ HRESULT led15070_hook_init( InitializeCriticalSection(&v->lock); - // TODO: IMPROVE! - first_port = i == 1 ? first_port + 2 : first_port; - - uart_init(&v->boarduart, first_port); + uart_init(&v->boarduart, port_no[i]); v->boarduart.baud.BaudRate = 115200; v->boarduart.written.bytes = v->written_bytes; v->boarduart.written.nbytes = sizeof(v->written_bytes); @@ -238,7 +246,7 @@ static HRESULT led15070_handle_irp_locked(int board, struct irp *irp) } for (;;) { -#if 0 +#if defined(LOG_LED15070) dprintf("TX Buffer:\n"); dump_iobuf(&boarduart->written); #endif @@ -257,7 +265,7 @@ static HRESULT led15070_handle_irp_locked(int board, struct irp *irp) return hr; } -#if 0 +#if defined(LOG_LED15070) dprintf("Deframe Buffer:\n"); dump_iobuf(&req_iobuf); #endif @@ -385,7 +393,9 @@ static HRESULT led15070_req_reset(int board, const struct led15070_req_any *req) static HRESULT led15070_req_set_input(int board, const struct led15070_req_any *req) { +#if defined(LOG_LED15070) dprintf("LED 15070: Set input (board %u)\n", board); +#endif if (!led15070_per_board_vars[board].enable_response) return S_OK; @@ -408,9 +418,10 @@ static HRESULT led15070_req_set_input(int board, const struct led15070_req_any * static HRESULT led15070_req_set_normal_12bit(int board, const struct led15070_req_any *req) { uint8_t idx = req->payload[0]; - +#if defined(LOG_LED15070) dprintf("LED 15070: Set LED - Normal 12bit (board %u, index %u)\n", board, idx); +#endif // TODO: Data for this command. Seen with Carol @@ -435,9 +446,10 @@ static HRESULT led15070_req_set_normal_12bit(int board, const struct led15070_re static HRESULT led15070_req_set_normal_8bit(int board, const struct led15070_req_any *req) { uint8_t idx = req->payload[0]; - - // dprintf("LED 15070: Set LED - Normal 8bit (board %u, index %u)\n", - // board, idx); +#if defined(LOG_LED15070) + dprintf("LED 15070: Set LED - Normal 8bit (board %u, index %u)\n", + board, idx); +#endif led15070_per_board_vars[board].gs[idx][0] = req->payload[1]; // R led15070_per_board_vars[board].gs[idx][1] = req->payload[2]; // G @@ -468,8 +480,10 @@ static HRESULT led15070_req_set_multi_flash_8bit(int board, const struct led1507 uint8_t idx_skip = req->payload[2]; // TODO: useful? - // dprintf("LED 15070: Set LED - Multi flash 8bit (board %u, start %u, end %u, skip %u)\n", - // board, idx_start, idx_end, idx_skip); +#if defined(LOG_LED15070) + dprintf("LED 15070: Set LED - Multi flash 8bit (board %u, start %u, end %u, skip %u)\n", + board, idx_start, idx_end, idx_skip); +#endif if (idx_skip > 0 && idx_skip <= (idx_end - idx_start + 1)) { idx_start += idx_skip; @@ -508,9 +522,10 @@ static HRESULT led15070_req_set_multi_fade_8bit(int board, const struct led15070 uint8_t idx_start = req->payload[0]; uint8_t idx_end = req->payload[1]; uint8_t idx_skip = req->payload[2]; - - // dprintf("LED 15070: Set LED - Multi fade 8bit (board %u, start %u, end %u, skip %u)\n", - // board, idx_start, idx_end, idx_skip); +#if defined(LOG_LED15070) + dprintf("LED 15070: Set LED - Multi fade 8bit (board %u, start %u, end %u, skip %u)\n", + board, idx_start, idx_end, idx_skip); +#endif if (idx_skip > 0 && idx_skip <= (idx_end - idx_start + 1)) { idx_start += idx_skip; @@ -545,7 +560,9 @@ static HRESULT led15070_req_set_multi_fade_8bit(int board, const struct led15070 static HRESULT led15070_req_set_palette_7_normal_led(int board, const struct led15070_req_any *req) { +#if defined(LOG_LED15070) dprintf("LED 15070: Set palette - 7 Normal LED (board %u)\n", board); +#endif if (!led15070_per_board_vars[board].enable_response) return S_OK; @@ -567,7 +584,9 @@ static HRESULT led15070_req_set_palette_7_normal_led(int board, const struct led static HRESULT led15070_req_set_palette_6_flash_led(int board, const struct led15070_req_any *req) { +#if defined(LOG_LED15070) dprintf("LED 15070: Set palette - 6 Flash LED (board %u)\n", board); +#endif if (!led15070_per_board_vars[board].enable_response) return S_OK; @@ -589,7 +608,9 @@ static HRESULT led15070_req_set_palette_6_flash_led(int board, const struct led1 static HRESULT led15070_req_set_15dc_out(int board, const struct led15070_req_any *req) { +#if defined(LOG_LED15070) dprintf("LED 15070: Set 15DC out (board %u)\n", board); +#endif if (!led15070_per_board_vars[board].enable_response) return S_OK; @@ -611,7 +632,9 @@ static HRESULT led15070_req_set_15dc_out(int board, const struct led15070_req_an static HRESULT led15070_req_set_15gs_out(int board, const struct led15070_req_any *req) { +#if defined(LOG_LED15070) dprintf("LED 15070: Set 15GS out (board %u)\n", board); +#endif if (!led15070_per_board_vars[board].enable_response) return S_OK; @@ -633,7 +656,9 @@ static HRESULT led15070_req_set_15gs_out(int board, const struct led15070_req_an static HRESULT led15070_req_set_psc_max(int board, const struct led15070_req_any *req) { +#if defined(LOG_LED15070) dprintf("LED 15070: Set PSC max (board %u)\n", board); +#endif if (!led15070_per_board_vars[board].enable_response) return S_OK; @@ -655,14 +680,16 @@ static HRESULT led15070_req_set_psc_max(int board, const struct led15070_req_any static HRESULT led15070_req_set_fet_output(int board, const struct led15070_req_any *req) { +#if defined(LOG_LED15070) dprintf("LED 15070: Set FET output (board %u)\n", board); +#endif led15070_per_board_vars[board].fet[0] = req->payload[0]; // R or FET0 intensity led15070_per_board_vars[board].fet[1] = req->payload[1]; // G or FET1 intensity led15070_per_board_vars[board].fet[2] = req->payload[2]; // B or FET2 intensity if (led_set_fet_output) - led_set_fet_output((const uint8_t*)led15070_per_board_vars[board].fet); + led_set_fet_output(board, (const uint8_t*)led15070_per_board_vars[board].fet); if (!led15070_per_board_vars[board].enable_response) return S_OK; @@ -685,8 +712,9 @@ static HRESULT led15070_req_set_fet_output(int board, const struct led15070_req_ static HRESULT led15070_req_set_gs_palette(int board, const struct led15070_req_any *req) { uint8_t idx = req->payload[0]; - +#if defined(LOG_LED15070) dprintf("LED 15070: Set GS palette (board %u, index %u)\n", board, idx); +#endif led15070_per_board_vars[board].gs_palette[idx][0] = req->payload[1]; // R led15070_per_board_vars[board].gs_palette[idx][1] = req->payload[2]; // G @@ -712,10 +740,12 @@ static HRESULT led15070_req_set_gs_palette(int board, const struct led15070_req_ static HRESULT led15070_req_dc_update(int board, const struct led15070_req_any *req) { - // dprintf("LED 15070: DC update (board %u)\n", board); +#if defined(LOG_LED15070) + dprintf("LED 15070: DC update (board %u)\n", board); +#endif if (led_dc_update) - led_dc_update((const uint8_t*)led15070_per_board_vars[board].dc); + led_dc_update(board, (const uint8_t*)led15070_per_board_vars[board].dc); if (!led15070_per_board_vars[board].enable_response) return S_OK; @@ -737,10 +767,12 @@ static HRESULT led15070_req_dc_update(int board, const struct led15070_req_any * static HRESULT led15070_req_gs_update(int board, const struct led15070_req_any *req) { - // dprintf("LED 15070: GS update (board %u)\n", board); +#if defined(LOG_LED15070) + dprintf("LED 15070: GS update (board %u)\n", board); +#endif if (led_gs_update) - led_gs_update((const uint8_t*)led15070_per_board_vars[board].gs); + led_gs_update(board, (const uint8_t*)led15070_per_board_vars[board].gs); if (!led15070_per_board_vars[board].enable_response) return S_OK; @@ -762,7 +794,9 @@ static HRESULT led15070_req_gs_update(int board, const struct led15070_req_any * static HRESULT led15070_req_rotate(int board, const struct led15070_req_any *req) { +#if defined(LOG_LED15070) dprintf("LED 15070: Rotate (board %u)\n", board); +#endif if (!led15070_per_board_vars[board].enable_response) return S_OK; @@ -787,9 +821,10 @@ static HRESULT led15070_req_set_dc_data(int board, const struct led15070_req_any uint8_t idx_start = req->payload[0]; uint8_t idx_end = req->payload[1]; uint8_t idx_skip = req->payload[2]; - - // dprintf("LED 15070: Set DC data (board %u, start %u, end %u, skip %u)\n", - // board, idx_start, idx_end, idx_skip); +#if defined(LOG_LED15070) + dprintf("LED 15070: Set DC data (board %u, start %u, end %u, skip %u)\n", + board, idx_start, idx_end, idx_skip); +#endif if (idx_skip > 0 && idx_skip <= (idx_end - idx_start + 1)) { idx_start += idx_skip; @@ -829,9 +864,10 @@ static HRESULT led15070_req_eeprom_write(int board, const struct led15070_req_an uint8_t addr = req->payload[0]; uint8_t data = req->payload[1]; - +#if defined(LOG_LED15070) dprintf("LED 15070: EEPROM write (board %u, address %02x, data %02x)\n", board, addr, data); +#endif if (addr > 0x07) { dprintf("LED 15070: Error -- Invalid EEPROM write address %02x\n", @@ -919,8 +955,9 @@ static HRESULT led15070_req_eeprom_read(int board, const struct led15070_req_any uint8_t addr = req->payload[0]; uint8_t data = 0; - +#if defined(LOG_LED15070) dprintf("LED 15070: EEPROM read (board %u, address %02x)\n", board, addr); +#endif if (addr > 0x07) { dprintf("LED 15070: Error -- Invalid EEPROM read address %02x\n", @@ -1002,7 +1039,9 @@ static HRESULT led15070_req_eeprom_read(int board, const struct led15070_req_any static HRESULT led15070_req_ack_on(int board, const struct led15070_req_any *req) { +#if defined(LOG_LED15070) dprintf("LED 15070: Acknowledge commands ON (board %u)\n", board); +#endif led15070_per_board_vars[board].enable_response = true; @@ -1023,7 +1062,9 @@ static HRESULT led15070_req_ack_on(int board, const struct led15070_req_any *req static HRESULT led15070_req_ack_off(int board, const struct led15070_req_any *req) { +#if defined(LOG_LED15070) dprintf("LED 15070: Acknowledge commands OFF (board %u)\n", board); +#endif led15070_per_board_vars[board].enable_response = false; @@ -1044,7 +1085,9 @@ static HRESULT led15070_req_ack_off(int board, const struct led15070_req_any *re static HRESULT led15070_req_board_info(int board) { +#if defined(LOG_LED15070) dprintf("LED 15070: Get board info (board %u)\n", board); +#endif struct led15070_resp_board_info resp; @@ -1067,7 +1110,9 @@ static HRESULT led15070_req_board_info(int board) static HRESULT led15070_req_board_status(int board) { +#if defined(LOG_LED15070) dprintf("LED 15070: Get board status (board %u)\n", board); +#endif struct led15070_resp_any resp; @@ -1091,7 +1136,9 @@ static HRESULT led15070_req_board_status(int board) static HRESULT led15070_req_fw_sum(int board) { +#if defined(LOG_LED15070) dprintf("LED 15070: Get firmware checksum (board %u)\n", board); +#endif struct led15070_resp_any resp; @@ -1113,7 +1160,9 @@ static HRESULT led15070_req_fw_sum(int board) static HRESULT led15070_req_protocol_ver(int board) { +#if defined(LOG_LED15070) dprintf("LED 15070: Get protocol version (board %u)\n", board); +#endif struct led15070_resp_any resp; @@ -1187,7 +1236,7 @@ static HRESULT led15070_eeprom_open(int board, wchar_t *path, HANDLE *handle) HRESULT hr; BOOL ok; -#if 0 +#if defined(LOG_LED15070) dprintf("LED 15070: Opening EEPROM file '%S' handle (board %u)\n", path, board); #endif @@ -1233,7 +1282,7 @@ static HRESULT led15070_eeprom_close(int board, wchar_t *path, HANDLE *handle) HRESULT hr; BOOL ok; -#if 0 +#if defined(LOG_LED15070) dprintf("LED 15070: Closing EEPROM file '%S' handle (board %u)\n", path, board); #endif diff --git a/board/led15070.h b/board/led15070.h index a2ad863..ae237b4 100644 --- a/board/led15070.h +++ b/board/led15070.h @@ -7,7 +7,7 @@ struct led15070_config { bool enable; - unsigned int port_no; + unsigned int port_no[2]; char board_number[8]; uint8_t fw_ver; uint16_t fw_sum; @@ -15,9 +15,9 @@ struct led15070_config { }; typedef HRESULT (*io_led_init_t)(void); -typedef void (*io_led_set_fet_output_t)(const uint8_t *rgb); -typedef void (*io_led_dc_update_t)(const uint8_t *rgb); -typedef void (*io_led_gs_update_t)(const uint8_t *rgb); +typedef void (*io_led_set_fet_output_t)(uint8_t board, const uint8_t *rgb); +typedef void (*io_led_dc_update_t)(uint8_t board, const uint8_t *rgb); +typedef void (*io_led_gs_update_t)(uint8_t board, const uint8_t *rgb); HRESULT led15070_hook_init( const struct led15070_config *cfg, @@ -25,5 +25,4 @@ HRESULT led15070_hook_init( io_led_set_fet_output_t _led_set_fet_output, io_led_dc_update_t _led_dc_update, io_led_gs_update_t _led_gs_update, - unsigned int first_port, - unsigned int num_boards); + unsigned int port_no[2]); diff --git a/board/led15093.c b/board/led15093.c index a070a24..31ccb4e 100644 --- a/board/led15093.c +++ b/board/led15093.c @@ -107,9 +107,13 @@ static uint8_t led15093_host_adr = 1; static io_led_init_t led_init; static io_led_set_leds_t set_leds; -HRESULT led15093_hook_init(const struct led15093_config *cfg, io_led_init_t _led_init, - io_led_set_leds_t _set_leds, unsigned int first_port, unsigned int num_boards, uint8_t board_adr, uint8_t host_adr) +HRESULT led15093_hook_init( + const struct led15093_config *cfg, + io_led_init_t _led_init, + io_led_set_leds_t _set_leds, + unsigned int port_no[2]) { + unsigned int num_boards = 0; assert(cfg != NULL); assert(_led_init != NULL); @@ -119,14 +123,24 @@ HRESULT led15093_hook_init(const struct led15093_config *cfg, io_led_init_t _led return S_FALSE; } - if (cfg->port_no != 0) { - first_port = cfg->port_no; + for (int i = 0; i < led15093_nboards; i++) + { + if (cfg->port_no[i] != 0) { + port_no[i] = cfg->port_no[i]; + } + + if (port_no[i] != 0) { + num_boards++; + } } + assert(num_boards != 0); + + led15093_board_adr = num_boards; + led15093_host_adr = num_boards == 2 ? 1 : 2; + led_init = _led_init; set_leds = _set_leds; - led15093_board_adr = board_adr; - led15093_host_adr = host_adr; memcpy(led15093_board_num, cfg->board_number, sizeof(led15093_board_num)); memcpy(led15093_chip_num, cfg->chip_number, sizeof(led15093_chip_num)); @@ -140,7 +154,7 @@ HRESULT led15093_hook_init(const struct led15093_config *cfg, io_led_init_t _led InitializeCriticalSection(&vb->lock); - uart_init(&vb->boarduart, first_port + i); + uart_init(&vb->boarduart, port_no[i]); if (cfg->high_baudrate) { vb->boarduart.baud.BaudRate = 460800; } else { @@ -209,7 +223,6 @@ static HRESULT led15093_handle_irp_locked(int board, struct irp *irp) _led15093_per_board_vars *v = &led15093_per_board_vars[board]; struct uart *boarduart = &led15093_per_board_vars[board].boarduart; - /* if (irp->op == IRP_OP_OPEN) { // Unfortunately the LED board UART gets opened and closed repeatedly @@ -236,30 +249,6 @@ static HRESULT led15093_handle_irp_locked(int board, struct irp *irp) } } } - */ - - if (irp->op == IRP_OP_OPEN) { - dprintf("LED 15093: Starting backend DLL\n"); - // int res = led_init(); - hr = led_init(); - - /* - if (res != 0) { - dprintf("LED 15093: Backend error, LED board disconnected: " - "%d\n", - res); - - return E_FAIL; - } - */ - if (FAILED(hr)) { - dprintf("LED 15093: Backend error, LED board disconnected: " - "%x\n", - (int) hr); - - return hr; - } - } hr = uart_handle_irp(boarduart, irp); @@ -688,16 +677,6 @@ static HRESULT led15093_req_set_imm_led(int board, const struct led15093_req_set return E_INVALIDARG; } - /* - if (board == 0) { - dprintf("board %d: red: %d, green: %d, blue: %d\n", board, req->data[0x96], req->data[0x97], req->data[0x98]); - } - else if (board == 1) - { - dprintf("board %d: red: %d, green: %d, blue: %d\n", board, req->data[0xb4], req->data[0xb5], req->data[0xb6]); - } - */ - // Return the current LED data, remove const qualifier set_leds(board, (uint8_t *) req->data); diff --git a/board/led15093.h b/board/led15093.h index 869a11b..5ff930b 100644 --- a/board/led15093.h +++ b/board/led15093.h @@ -8,7 +8,7 @@ struct led15093_config { bool enable; bool high_baudrate; - unsigned int port_no; + unsigned int port_no[2]; char board_number[8]; char chip_number[5]; char boot_chip_number[5]; @@ -20,5 +20,5 @@ typedef HRESULT (*io_led_init_t)(void); typedef void (*io_led_set_leds_t)(uint8_t board, uint8_t *rgb); HRESULT led15093_hook_init(const struct led15093_config *cfg, io_led_init_t _led_init, - io_led_set_leds_t _set_leds, unsigned int first_port, unsigned int num_boards, uint8_t board_adr, uint8_t host_adr); + io_led_set_leds_t _set_leds, unsigned int port_no[2]); diff --git a/carolhook/touch.c b/carolhook/touch.c index 70c2e92..cf94355 100644 --- a/carolhook/touch.c +++ b/carolhook/touch.c @@ -196,7 +196,7 @@ static void touch_scan_auto(const bool is_pressed, const uint16_t mouse_x, const flg = resp.touches[0].x1 != last_x1 || resp.touches[0].x2 != last_x2 || resp.touches[0].y1 != last_y1 || resp.touches[0].y2 != last_y2; -#if 1 +#if 0 if (flg) dprintf("Touch: Mouse down! x %02X %02X y: %02X %02X\n", resp.touches[0].x1, resp.touches[0].x2, resp.touches[0].y1, resp.touches[0].y2); #endif diff --git a/chunihook/config.c b/chunihook/config.c index 2ad959e..d711fec 100644 --- a/chunihook/config.c +++ b/chunihook/config.c @@ -56,7 +56,8 @@ void led15093_config_load(struct led15093_config *cfg, const wchar_t *filename) memset(cfg->boot_chip_number, ' ', sizeof(cfg->boot_chip_number)); cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename); - cfg->port_no = 0; + cfg->port_no[0] = GetPrivateProfileIntW(L"led15093", L"portNo1", 0, filename); + cfg->port_no[1] = GetPrivateProfileIntW(L"led15093", L"portNo2", 0, filename); cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaud", 0, filename); cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0x90, filename); cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xadf7, filename); diff --git a/chunihook/dllmain.c b/chunihook/dllmain.c index d421e23..a3fa8ab 100644 --- a/chunihook/dllmain.c +++ b/chunihook/dllmain.c @@ -114,8 +114,9 @@ static DWORD CALLBACK chuni_pre_startup(void) { dprintf("IO DLL doesn't support led_init/led_set_leds, cannot start LED15093 hook\n"); } else { + unsigned int led_port_no[2] = {10, 11}; hr = led15093_hook_init(&chuni_hook_cfg.led15093, - chuni_dll.led_init, chuni_dll.led_set_leds, 10, 2, 2, 1); + chuni_dll.led_init, chuni_dll.led_set_leds, led_port_no); if (FAILED(hr)) { goto fail; diff --git a/chuniio/chuniio.c b/chuniio/chuniio.c index 614dc47..a2c0336 100644 --- a/chuniio/chuniio.c +++ b/chuniio/chuniio.c @@ -174,6 +174,20 @@ HRESULT chuni_io_led_init(void) } void chuni_io_led_set_colors(uint8_t board, uint8_t *rgb) -{ +{ +#if 0 + if (board == 0) { + dprintf("CHUNI LED: Left Air 1: red: %d, green: %d, blue: %d\n", rgb[0x96], rgb[0x97], rgb[0x98]); + dprintf("CHUNI LED: Left Air 2: red: %d, green: %d, blue: %d\n", rgb[0x99], rgb[0x9A], rgb[0x9B]); + dprintf("CHUNI LED: Left Air 3: red: %d, green: %d, blue: %d\n", rgb[0x9C], rgb[0x9D], rgb[0x9E]); + } + else if (board == 1) + { + dprintf("CHUNI LED: Right Air 1: red: %d, green: %d, blue: %d\n", rgb[0xB4], rgb[0xB5], rgb[0xB6]); + dprintf("CHUNI LED: Right Air 2: red: %d, green: %d, blue: %d\n", rgb[0xB7], rgb[0xB8], rgb[0xB9]); + dprintf("CHUNI LED: Right Air 3: red: %d, green: %d, blue: %d\n", rgb[0xBA], rgb[0xBB], rgb[0xBC]); + } +#endif + led_output_update(board, rgb); } diff --git a/chusanhook/config.c b/chusanhook/config.c index 0ec8c61..691e8f7 100644 --- a/chusanhook/config.c +++ b/chusanhook/config.c @@ -96,7 +96,8 @@ void led15093_config_load(struct led15093_config *cfg, const wchar_t *filename) memset(cfg->boot_chip_number, ' ', sizeof(cfg->boot_chip_number)); cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename); - cfg->port_no = 0; + cfg->port_no[0] = GetPrivateProfileIntW(L"led15093", L"portNo1", 0, filename); + cfg->port_no[1] = GetPrivateProfileIntW(L"led15093", L"portNo2", 0, filename); cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaud", 0, filename); cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0x90, filename); cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xadf7, filename); diff --git a/chusanhook/dllmain.c b/chusanhook/dllmain.c index 9a2f5da..6ba4cd4 100644 --- a/chusanhook/dllmain.c +++ b/chusanhook/dllmain.c @@ -22,27 +22,23 @@ COM4: 837-15396 "Gen 3" Aime Reader */ -#include - #include #include - -#include "amex/amex.h" +#include #include "board/sg-reader.h" #include "board/vfd.h" +#include "chuniio/chuniio.h" #include "chusanhook/config.h" #include "chusanhook/io4.h" #include "chusanhook/slider.h" -#include "chuniio/chuniio.h" - -#include "hook/process.h" - #include "gfxhook/d3d9.h" #include "gfxhook/gfx.h" +#include "hook/process.h" + #include "hooklib/serial.h" #include "hooklib/spike.h" @@ -55,8 +51,7 @@ static HMODULE chusan_hook_mod; static process_entry_t chusan_startup; static struct chusan_hook_config chusan_hook_cfg; -static DWORD CALLBACK chusan_pre_startup(void) -{ +static DWORD CALLBACK chusan_pre_startup(void) { HMODULE d3dc; HMODULE dbghelp; HRESULT hr; @@ -88,7 +83,7 @@ static DWORD CALLBACK chusan_pre_startup(void) chusan_hook_config_load(&chusan_hook_cfg, get_config_path()); /* Hook Win32 APIs */ - + dvd_hook_init(&chusan_hook_cfg.dvd, chusan_hook_mod); gfx_hook_init(&chusan_hook_cfg.gfx); gfx_d3d9_hook_init(&chusan_hook_cfg.gfx, chusan_hook_mod); @@ -96,6 +91,16 @@ static DWORD CALLBACK chusan_pre_startup(void) /* Initialize emulation hooks */ + struct dipsw_config new_dipsw_config[8] = { + {L"Delivery Server", L"Server", L"Client"}, + {L"Monitor Type", L"60FPS", L"120FPS"}, + {L"Cabinet Type", L"CVT", L"SP"}, + }; + + // Set the system dip switch configuration + memcpy(chusan_hook_cfg.platform.system.dipsw_config, new_dipsw_config, + sizeof(new_dipsw_config)); + hr = platform_hook_init( &chusan_hook_cfg.platform, "SDHD", @@ -124,27 +129,7 @@ static DWORD CALLBACK chusan_pre_startup(void) goto fail; } - bool *dipsw = &chusan_hook_cfg.platform.system.dipsw[0]; - bool is_cvt = dipsw[2]; - - for (int i = 0; i < 3; i++) { - switch (i) { - case 0: - dprintf("DipSw: NetInstall: %s\n", dipsw[0] ? "Server" : "Client"); - break; - - case 1: - dprintf("DipSw: Monitor Type: %dFPS\n", dipsw[1] ? 60 : 120); - break; - - case 2: - dprintf("DipSw: Cab Type: %s\n", is_cvt ? "CVT" : "SP"); - - break; - } - } - - unsigned int first_port = is_cvt ? 2 : 20; + bool is_cvt = chusan_hook_cfg.platform.system.dipsw[2]; if (!is_cvt) { hr = vfd_hook_init(&chusan_hook_cfg.vfd, 2); @@ -154,19 +139,31 @@ static DWORD CALLBACK chusan_pre_startup(void) } } - if ( chuni_dll.led_init == NULL || chuni_dll.led_set_leds == NULL ) - { - dprintf("IO DLL doesn't support led_init/led_set_leds, cannot start LED15093 hook\n"); + unsigned int led_port_no[2]; + + if (is_cvt) { + led_port_no[0] = 2; + led_port_no[1] = 3; } else { - hr = led15093_hook_init(&chusan_hook_cfg.led15093, - chuni_dll.led_init, chuni_dll.led_set_leds, first_port, 2, 2, 1); + led_port_no[0] = 20; + led_port_no[1] = 21; + } + + if (chuni_dll.led_init == NULL || chuni_dll.led_set_leds == NULL) { + dprintf( + "IO DLL doesn't support led_init/led_set_leds, cannot start " + "LED15093 hook\n"); + } else { + hr = led15093_hook_init(&chusan_hook_cfg.led15093, chuni_dll.led_init, + chuni_dll.led_set_leds, led_port_no); if (FAILED(hr)) { goto fail; } } - hr = sg_reader_hook_init(&chusan_hook_cfg.aime, 4, is_cvt ? 2: 3, chusan_hook_mod); + hr = sg_reader_hook_init(&chusan_hook_cfg.aime, 4, is_cvt ? 2 : 3, + chusan_hook_mod); if (FAILED(hr)) { goto fail; @@ -186,8 +183,7 @@ fail: ExitProcess(EXIT_FAILURE); } -BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx) -{ +BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx) { HRESULT hr; if (cause != DLL_PROCESS_ATTACH) { @@ -199,7 +195,7 @@ BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx) hr = process_hijack_startup(chusan_pre_startup, &chusan_startup); if (!SUCCEEDED(hr)) { - dprintf("Failed to hijack process startup: %x\n", (int) hr); + dprintf("Failed to hijack process startup: %x\n", (int)hr); } return SUCCEEDED(hr); diff --git a/cmhook/dllmain.c b/cmhook/dllmain.c index 03ace58..29d93af 100644 --- a/cmhook/dllmain.c +++ b/cmhook/dllmain.c @@ -63,6 +63,14 @@ static DWORD CALLBACK cm_pre_startup(void) /* Initialize emulation hooks */ + struct dipsw_config new_dipsw_config[8] = { + {L"Delivery Server", L"Client", L"Server"}, + }; + + // Set the system dip switch configuration + memcpy(cm_hook_cfg.platform.system.dipsw_config, new_dipsw_config, + sizeof(new_dipsw_config)); + hr = platform_hook_init( &cm_hook_cfg.platform, "SDED", diff --git a/dist/carol/start.bat b/dist/carol/launch.bat similarity index 80% rename from dist/carol/start.bat rename to dist/carol/launch.bat index 0fab950..4e75aa0 100644 --- a/dist/carol/start.bat +++ b/dist/carol/launch.bat @@ -2,10 +2,10 @@ pushd %~dp0 -taskkill /f /im aimeReaderHost.exe > nul 2>&1 - start /min inject -d -k carolhook.dll aimeReaderHost.exe -p 10 + inject -d -k carolhook.dll carol_nu.exe + taskkill /f /im aimeReaderHost.exe > nul 2>&1 echo. diff --git a/dist/chuni/start.bat b/dist/chuni/launch.bat similarity index 96% rename from dist/chuni/start.bat rename to dist/chuni/launch.bat index 0c942e9..a1c54ef 100644 --- a/dist/chuni/start.bat +++ b/dist/chuni/launch.bat @@ -3,7 +3,9 @@ pushd %~dp0 start /min inject -d -k chunihook.dll aimeReaderHost.exe -p 12 + inject -d -k chunihook.dll chuniApp.exe + taskkill /f /im aimeReaderHost.exe > nul 2>&1 echo. diff --git a/dist/chusan/start.bat b/dist/chusan/launch.bat similarity index 100% rename from dist/chusan/start.bat rename to dist/chusan/launch.bat diff --git a/dist/cm/start.bat b/dist/cm/launch.bat similarity index 100% rename from dist/cm/start.bat rename to dist/cm/launch.bat diff --git a/dist/cxb/start.bat b/dist/cxb/launch.bat similarity index 100% rename from dist/cxb/start.bat rename to dist/cxb/launch.bat diff --git a/dist/cxb/segatools.ini b/dist/cxb/segatools.ini index 1fe70c8..40589de 100644 --- a/dist/cxb/segatools.ini +++ b/dist/cxb/segatools.ini @@ -60,7 +60,7 @@ enable=1 subnet=192.168.150.0 billingCa=../DEVICE/ca.crt billingPub=../DEVICE/billing.pub -billingType=2 +billingType=0 [eeprom] ; See above diff --git a/dist/diva/start.bat b/dist/diva/launch.bat similarity index 100% rename from dist/diva/start.bat rename to dist/diva/launch.bat diff --git a/dist/fgo/start.bat b/dist/fgo/launch.bat similarity index 100% rename from dist/fgo/start.bat rename to dist/fgo/launch.bat diff --git a/dist/fgo/segatools.ini b/dist/fgo/segatools.ini index e9c7c20..4e846ee 100644 --- a/dist/fgo/segatools.ini +++ b/dist/fgo/segatools.ini @@ -41,7 +41,7 @@ portNo=17 ; 837-15093-06 LED board emulation setting. enable=1 ; COM port number for the LED board. Has to be the same as the FTDI port. -portNo=17 +portNo1=17 ; ----------------------------------------------------------------------------- ; Network settings diff --git a/dist/idac/start.bat b/dist/idac/launch.bat similarity index 100% rename from dist/idac/start.bat rename to dist/idac/launch.bat diff --git a/dist/idz/start.bat b/dist/idz/launch.bat similarity index 87% rename from dist/idz/start.bat rename to dist/idz/launch.bat index d64aa9b..4f6ea5e 100644 --- a/dist/idz/start.bat +++ b/dist/idz/launch.bat @@ -2,7 +2,7 @@ pushd %~dp0 -start /min "AM Daemon" inject -d -k idzhook.dll amdaemon.exe -c configDHCP_Final_Common.json configDHCP_Final_JP.json configDHCP_Final_JP_ST1.json configDHCP_Final_JP_ST2.json configDHCP_Final_EX.json configDHCP_Final_EX_ST1.json configDHCP_Final_EX_ST2.json +start "AM Daemon" /min inject -d -k idzhook.dll amdaemon.exe -c configDHCP_Final_Common.json configDHCP_Final_JP.json configDHCP_Final_JP_ST1.json configDHCP_Final_JP_ST2.json configDHCP_Final_EX.json configDHCP_Final_EX_ST1.json configDHCP_Final_EX_ST2.json rem Set dipsw1=0 and uncomment the ServerBox for in store battle? rem inject -k idzhook.dll ServerBoxD8_Nu_x64.exe diff --git a/dist/kemono/start.bat b/dist/kemono/launch.bat similarity index 100% rename from dist/kemono/start.bat rename to dist/kemono/launch.bat diff --git a/dist/mai2/start.bat b/dist/mai2/launch.bat similarity index 100% rename from dist/mai2/start.bat rename to dist/mai2/launch.bat diff --git a/dist/mai2/segatools.ini b/dist/mai2/segatools.ini index c253334..dde853f 100644 --- a/dist/mai2/segatools.ini +++ b/dist/mai2/segatools.ini @@ -69,6 +69,15 @@ freeplay=0 ; this to 1 on exactly one machine and set this to 0 on all others. dipsw1=1 +; ----------------------------------------------------------------------------- +; LED settings +; ----------------------------------------------------------------------------- + +[led15070] +; Enable emulation of the 837-15070-04 controlled lights, which handle the +; cabinet and button LEDs. +enable=1 + ; ----------------------------------------------------------------------------- ; Misc. hook settings ; ----------------------------------------------------------------------------- @@ -126,11 +135,22 @@ coin=0x72 ; Uncomment and complete the following sequence of settings to configure a ; custom keybinding. [button] -;1p_btn1=0x53 -;1p_btn2=0x53 -;1p_btn3=0x53 +enable=1 +;p1Btn1=0x53 +;p1Btn2=0x53 +;p1Btn3=0x53 ; ... etc ... -;2p_btn1=0x53 -;2p_btn2=0x53 -;2p_btn3=0x53 +;p2Btn1=0x53 +;p2Btn2=0x53 +;p2Btn3=0x53 ; ... etc ... + +[touch] +p1Enable=1 +;p1DebugInput=0 +p2Enable=1 +;p2DebugInput=0 +;p1TouchA1=0x53 +;p1TouchA2=0x53 +; ... etc ... +;p1TouchE8=0x53 diff --git a/dist/mercury/start.bat b/dist/mercury/launch.bat similarity index 55% rename from dist/mercury/start.bat rename to dist/mercury/launch.bat index a9a3f22..4a64365 100644 --- a/dist/mercury/start.bat +++ b/dist/mercury/launch.bat @@ -1,10 +1,8 @@ @echo off pushd %~dp0 -taskkill /f /im amdaemon.exe > nul 2>&1 - REM USA -start "AM Daemon" /min inject -d -k mercuryhook.dll amdaemon.exe -f -c config.json config_lan_install_client.json config_lan_install_server.json config_video_clone.json config_video_dual.json config_video_clone_flip.json config_video_dual_flip.json config_region_exp.json config_region_chn.json config_region_usa.json +REM start "AM Daemon" /min inject -d -k mercuryhook.dll amdaemon.exe -f -c config.json config_lan_install_client.json config_lan_install_server.json config_video_clone.json config_video_dual.json config_video_clone_flip.json config_video_dual_flip.json config_region_exp.json config_region_chn.json config_region_usa.json REM JP start "AM Daemon" /min inject -d -k mercuryhook.dll amdaemon.exe -f -c config.json config_lan_install_client.json config_lan_install_server.json config_video_clone.json config_video_dual.json config_video_clone_flip.json config_video_dual_flip.json config_region_exp.json config_region_chn.json config_region_jpn.json diff --git a/dist/mercury/segatools.ini b/dist/mercury/segatools.ini index 4e24489..5e10634 100644 --- a/dist/mercury/segatools.ini +++ b/dist/mercury/segatools.ini @@ -5,7 +5,7 @@ [vfs] ; Insert the path to the game AMFS directory here (contains ICF1 and ICF2) amfs= -; Insert the path to the game Option directory here (contains Axxx directories) +; Insert the path to the game Option directory here (unused in Mercury) option= ; Create an empty directory somewhere and insert the path here. ; This directory may be shared between multiple SEGA games. diff --git a/dist/mu3/start.bat b/dist/mu3/launch.bat similarity index 100% rename from dist/mu3/start.bat rename to dist/mu3/launch.bat diff --git a/dist/swdc/start.bat b/dist/swdc/launch.bat similarity index 100% rename from dist/swdc/start.bat rename to dist/swdc/launch.bat diff --git a/dist/tokyo/start.bat b/dist/tokyo/launch.bat similarity index 100% rename from dist/tokyo/start.bat rename to dist/tokyo/launch.bat diff --git a/doc/chunihook.md b/doc/chunihook.md index 57e19b0..7b68a20 100644 --- a/doc/chunihook.md +++ b/doc/chunihook.md @@ -44,7 +44,7 @@ option=../../option 1. In the `[dns]` section, set `default=` to your computer's hostname or LAN IP. Do not put `127.0.0.1` here, the game specifically checks for and rejects loopback addresses. This setting controls the address of the network services server -1. Right click `start.bat` in `app/bin` and run it as Administrator. I think you need to run it as +1. Right click `launch.bat` in `app/bin` and run it as Administrator. I think you need to run it as admin at least once, but once you have done that you can run the game as a regular user 1. A sequence of several start-up screens will be displayed. You should also see a bunch of debug output in a command line window; if you're seeing hex dumps here then that's a good sign. There diff --git a/doc/config/common.md b/doc/config/common.md index 2796ded..89c48c6 100644 --- a/doc/config/common.md +++ b/doc/config/common.md @@ -11,7 +11,7 @@ The default file path for config file is `./segatools.ini`. You can modify environment variable `SEGATOOLS_CONFIG_PATH` to another path. -For example, You can have another `start.bat` with following code in it, +For example, You can have another `launch.bat` with following code in it, Then you can copy `segatools.ini` to `another_config.ini` but with different dns host in it ```bat set SEGATOOLS_CONFIG_PATH=.\another_config.ini @@ -420,18 +420,22 @@ 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: +integer `modelType` setting, but they are combined here for convenience. -- `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 +`platformId` is one of the following: +- `AAV`: Nu 1/1.1/2 +- `AAW`: NuSX 1/1.1 +- `ACA`: ALLS UX/HX/MX + +`modelType` is one of the following: +- `1`: Server (SV) +- `2`: Satalite (ST) +- `3`: Live (LV) +- `4`: Terminal (TN) + +It's safe to assume that every game you'll be playing with these tools will be a Satalite. +Some games care, others don't. Some even change how they run based on this value (Wonderland Wars +will boot into terminal mode if `modelType` is 4). ### `region` @@ -468,15 +472,9 @@ the billing transactions. 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 REV. 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 +Sets the billing type, a single bit value that flags the cabinet as a rental if set to `1`, or `0` otherwise. +Certian games that were only sold officially as full purchases (that is, non-rentals) must have this value set to 0. +NOTE: Crossbeats erroniously displays Billing modes A/B1/B2, but this value comes from the `modelType` and NOT this value! ### `systemFlag` diff --git a/doc/idzhook.md b/doc/idzhook.md index e23c18c..1686458 100644 --- a/doc/idzhook.md +++ b/doc/idzhook.md @@ -65,7 +65,7 @@ felicaGen=0 and fill it with 20 digits, for example `01234567891234567890`. Make sure to save the file. -1. Right click `start.bat` in `package` and run it as Administrator. After the +1. Right click `launch.bat` in `package` and run it as Administrator. After the first run you may be able to run the game as a normal user. 1. Once you're at the title screen, press 2 or 3 a few times to add some credits, then _hold_ the Enter key for a few seconds to scan a card and start diff --git a/fgohook/config.c b/fgohook/config.c index 30dbf86..766240c 100644 --- a/fgohook/config.c +++ b/fgohook/config.c @@ -48,7 +48,8 @@ void led15093_config_load(struct led15093_config *cfg, const wchar_t *filename) memset(cfg->boot_chip_number, ' ', sizeof(cfg->boot_chip_number)); cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename); - cfg->port_no = GetPrivateProfileIntW(L"led15093", L"portNo", 0, filename); + cfg->port_no[0] = GetPrivateProfileIntW(L"led15093", L"portNo1", 0, filename); + cfg->port_no[1] = GetPrivateProfileIntW(L"led15093", L"portNo2", 0, filename); cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaud", 0, filename); cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0xA0, filename); cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xAA53, filename); diff --git a/fgohook/dllmain.c b/fgohook/dllmain.c index e82423f..a65cbcd 100644 --- a/fgohook/dllmain.c +++ b/fgohook/dllmain.c @@ -133,8 +133,9 @@ static DWORD CALLBACK fgo_pre_startup(void) goto fail; } + unsigned int led_port_no[2] = {17, 0}; hr = led15093_hook_init(&fgo_hook_cfg.led15093, - fgo_dll.led_init, fgo_dll.led_set_leds, 17, 1, 1, 2); + fgo_dll.led_init, fgo_dll.led_set_leds, led_port_no); if (FAILED(hr)) { goto fail; diff --git a/hooklib/meson.build b/hooklib/meson.build index e6908d6..b0ad6c2 100644 --- a/hooklib/meson.build +++ b/hooklib/meson.build @@ -4,7 +4,7 @@ hooklib_lib = static_library( implicit_include_directories : false, dependencies : [ capnhook.get_variable('hook_dep'), - Ws2_32_lib + ws2_32_lib ], sources : [ 'cursor.c', diff --git a/hooklib/reg.c b/hooklib/reg.c index bc18dbb..d4a3bc3 100644 --- a/hooklib/reg.c +++ b/hooklib/reg.c @@ -308,7 +308,7 @@ static void reg_hook_init(void) reg_hook_initted = true; InitializeCriticalSection(®_hook_lock); - dprintf("Reg hook init\n"); + dprintf("Reg: hook init.\n"); reg_hook_insert_hooks(NULL); diff --git a/idachook/config.c b/idachook/config.c index 279aba7..0e8dc88 100644 --- a/idachook/config.c +++ b/idachook/config.c @@ -23,7 +23,8 @@ void led15070_config_load(struct led15070_config *cfg, const wchar_t *filename) wchar_t tmpstr[16]; cfg->enable = GetPrivateProfileIntW(L"led15070", L"enable", 1, filename); - cfg->port_no = GetPrivateProfileIntW(L"led15070", L"portNo", 0, filename); + cfg->port_no[0] = GetPrivateProfileIntW(L"led15070", L"portNo1", 0, filename); + cfg->port_no[1] = GetPrivateProfileIntW(L"led15070", L"portNo2", 0, filename); cfg->fw_ver = GetPrivateProfileIntW(L"led15070", L"fwVer", 0x90, filename); /* TODO: Unknown, no firmware file available */ cfg->fw_sum = GetPrivateProfileIntW(L"led15070", L"fwSum", 0x0000, filename); diff --git a/idachook/dllmain.c b/idachook/dllmain.c index 0e955e8..448ea5b 100644 --- a/idachook/dllmain.c +++ b/idachook/dllmain.c @@ -60,6 +60,18 @@ static DWORD CALLBACK idac_pre_startup(void) /* Initialize emulation hooks */ + struct dipsw_config new_dipsw_config[8] = { + {L"Delivery Server", L"Server", L"Client"}, + {L"Cabinet Type", L"SWDC CVT", L"DZero CVT"}, + {L"Single Seat", L"ON", L"OFF"}, + {L"Seat Setting 1", L"ON", L"OFF"}, + {L"Seat Setting 2", L"ON", L"OFF"}, + }; + + // Set the system dip switch configuration + memcpy(idac_hook_cfg.platform.system.dipsw_config, new_dipsw_config, + sizeof(new_dipsw_config)); + hr = platform_hook_init( &idac_hook_cfg.platform, "SDGT", @@ -70,13 +82,21 @@ static DWORD CALLBACK idac_pre_startup(void) goto fail; } + bool *dipsw = &idac_hook_cfg.platform.system.dipsw[0]; + bool is_swdc_cvt = dipsw[1]; + + if (!dipsw[2]) { + // the next two bit are the seat number most significant bit first + dprintf("System: Seat Number: %d\n", ((dipsw[4] << 1) | dipsw[3]) + 1); + } + hr = idac_dll_init(&idac_hook_cfg.dll, idac_hook_mod); if (FAILED(hr)) { goto fail; } - hr = sg_reader_hook_init(&idac_hook_cfg.aime, 3, 3, idac_hook_mod); + hr = sg_reader_hook_init(&idac_hook_cfg.aime, 3, is_swdc_cvt ? 3 : 2, idac_hook_mod); if (FAILED(hr)) { goto fail; @@ -94,8 +114,9 @@ static DWORD CALLBACK idac_pre_startup(void) goto fail; } + unsigned int led_port_no[2] = {2, 0}; hr = led15070_hook_init(&idac_hook_cfg.led15070, idac_dll.led_init, - idac_dll.led_set_fet_output, NULL, idac_dll.led_gs_update, 2, 1); + idac_dll.led_set_fet_output, NULL, idac_dll.led_gs_update, led_port_no); if (FAILED(hr)) { goto fail; diff --git a/idachook/idac-dll.h b/idachook/idac-dll.h index 88ac299..92aa664 100644 --- a/idachook/idac-dll.h +++ b/idachook/idac-dll.h @@ -12,9 +12,9 @@ struct idac_dll { void (*get_shifter)(uint8_t *gear); void (*get_analogs)(struct idac_io_analog_state *out); HRESULT (*led_init)(void); - void (*led_set_fet_output)(const uint8_t *rgb); - void (*led_gs_update)(const uint8_t *rgb); - void (*led_set_leds)(const uint8_t *rgb); + void (*led_set_fet_output)(uint8_t board, const uint8_t *rgb); + void (*led_gs_update)(uint8_t board, const uint8_t *rgb); + void (*led_set_leds)(uint8_t board, const uint8_t *rgb); HRESULT (*ffb_init)(void); void (*ffb_toggle)(bool active); void (*ffb_constant_force)(uint8_t direction, uint8_t force); diff --git a/idachook/io4.c b/idachook/io4.c index 1e4d990..3861ef8 100644 --- a/idachook/io4.c +++ b/idachook/io4.c @@ -159,7 +159,7 @@ static HRESULT idac_io4_write_gpio(uint8_t* payload, size_t len) lights_data & IDAC_IO_LED_LEFT ? 0xFF : 0x00, }; - idac_dll.led_set_leds(rgb_out); + idac_dll.led_set_leds(0, rgb_out); return S_OK; } diff --git a/idacio/dllmain.c b/idacio/dllmain.c index 6a5dba8..fe8246e 100644 --- a/idacio/dllmain.c +++ b/idacio/dllmain.c @@ -127,7 +127,7 @@ HRESULT idac_io_led_init(void) return S_OK; } -void idac_io_led_set_fet_output(const uint8_t *rgb) +void idac_io_led_set_fet_output(uint8_t board, const uint8_t *rgb) { #if 0 dprintf("IDAC LED: LEFT SEAT LED: %02X\n", rgb[0]); @@ -137,7 +137,7 @@ void idac_io_led_set_fet_output(const uint8_t *rgb) return; } -void idac_io_led_gs_update(const uint8_t *rgb) +void idac_io_led_gs_update(uint8_t board, const uint8_t *rgb) { #if 0 for (int i = 0; i < 9; i++) { @@ -149,7 +149,7 @@ void idac_io_led_gs_update(const uint8_t *rgb) return; } -void idac_io_led_set_leds(const uint8_t *rgb) +void idac_io_led_set_leds(uint8_t board, const uint8_t *rgb) { #if 0 dprintf("IDAC LED: START: %02X\n", rgb[0]); diff --git a/idacio/idacio.h b/idacio/idacio.h index 513c9d1..bc58a34 100644 --- a/idacio/idacio.h +++ b/idacio/idacio.h @@ -127,7 +127,7 @@ HRESULT idac_io_led_init(void); Minimum API version: 0x0101 */ -void idac_io_led_set_fet_output(const uint8_t *rgb); +void idac_io_led_set_fet_output(uint8_t board, const uint8_t *rgb); /* Update the RGB LEDs. rgb is a pointer to an array up to 32 * 4 = 128 bytes. @@ -144,7 +144,7 @@ void idac_io_led_set_fet_output(const uint8_t *rgb); Minimum API version: 0x0101 */ -void idac_io_led_gs_update(const uint8_t *rgb); +void idac_io_led_gs_update(uint8_t board, const uint8_t *rgb); /* Update the cabinet button LEDs. rgb is a pointer to an array up to 6 bytes. @@ -160,7 +160,7 @@ void idac_io_led_gs_update(const uint8_t *rgb); Minimum API version: 0x0101 */ -void idac_io_led_set_leds(const uint8_t *rgb); +void idac_io_led_set_leds(uint8_t board, const uint8_t *rgb); /* Initialize FFB emulation. This function will be called before any other idac_io_ffb_*() function calls. diff --git a/idzhook/config.c b/idzhook/config.c index 0378cbe..6bbc0ed 100644 --- a/idzhook/config.c +++ b/idzhook/config.c @@ -27,7 +27,8 @@ void led15070_config_load(struct led15070_config *cfg, const wchar_t *filename) wchar_t tmpstr[16]; cfg->enable = GetPrivateProfileIntW(L"led15070", L"enable", 1, filename); - cfg->port_no = GetPrivateProfileIntW(L"led15070", L"portNo", 0, filename); + cfg->port_no[0] = GetPrivateProfileIntW(L"led15070", L"portNo1", 0, filename); + cfg->port_no[1] = GetPrivateProfileIntW(L"led15070", L"portNo2", 0, filename); cfg->fw_ver = GetPrivateProfileIntW(L"led15070", L"fwVer", 0x90, filename); /* TODO: Unknown, no firmware file available */ cfg->fw_sum = GetPrivateProfileIntW(L"led15070", L"fwSum", 0x0000, filename); diff --git a/idzhook/dllmain.c b/idzhook/dllmain.c index edf6cbb..534f4d0 100644 --- a/idzhook/dllmain.c +++ b/idzhook/dllmain.c @@ -128,8 +128,9 @@ static DWORD CALLBACK idz_pre_startup(void) goto fail; } + unsigned int led_port_no[2] = {11, 0}; hr = led15070_hook_init(&idz_hook_cfg.led15070, idz_dll.led_init, - idz_dll.led_set_fet_output, NULL, idz_dll.led_gs_update, 11, 1); + idz_dll.led_set_fet_output, NULL, idz_dll.led_gs_update, led_port_no); if (FAILED(hr)) { goto fail; diff --git a/idzhook/idz-dll.h b/idzhook/idz-dll.h index e827f8e..4084d84 100644 --- a/idzhook/idz-dll.h +++ b/idzhook/idz-dll.h @@ -12,9 +12,9 @@ struct idz_dll { void (*jvs_read_shifter)(uint8_t *gear); void (*jvs_read_coin_counter)(uint16_t *total); HRESULT (*led_init)(void); - void (*led_set_fet_output)(const uint8_t *rgb); - void (*led_gs_update)(const uint8_t *rgb); - void (*led_set_leds)(const uint8_t *rgb); + void (*led_set_fet_output)(uint8_t board, const uint8_t *rgb); + void (*led_gs_update)(uint8_t board, const uint8_t *rgb); + void (*led_set_leds)(uint8_t board, const uint8_t *rgb); HRESULT (*ffb_init)(void); void (*ffb_toggle)(bool active); void (*ffb_constant_force)(uint8_t direction, uint8_t force); diff --git a/idzhook/jvs.c b/idzhook/jvs.c index 3531d55..2ded71c 100644 --- a/idzhook/jvs.c +++ b/idzhook/jvs.c @@ -192,5 +192,5 @@ static void idz_jvs_write_gpio(void *ctx, uint32_t state) state & IDZ_IO_LED_LEFT ? 0xFF : 0x00, }; - idz_dll.led_set_leds(rgb_out); + idz_dll.led_set_leds(0, rgb_out); } diff --git a/idzio/dllmain.c b/idzio/dllmain.c index 39d08fc..322d194 100644 --- a/idzio/dllmain.c +++ b/idzio/dllmain.c @@ -130,7 +130,7 @@ HRESULT idz_io_led_init(void) return S_OK; } -void idz_io_led_set_fet_output(const uint8_t *rgb) +void idz_io_led_set_fet_output(uint8_t board, const uint8_t *rgb) { #if 0 dprintf("IDZ LED: LEFT SEAT LED: %02X\n", rgb[0]); @@ -140,7 +140,7 @@ void idz_io_led_set_fet_output(const uint8_t *rgb) return; } -void idz_io_led_gs_update(const uint8_t *rgb) +void idz_io_led_gs_update(uint8_t board, const uint8_t *rgb) { #if 0 for (int i = 0; i < 9; i++) { @@ -152,7 +152,7 @@ void idz_io_led_gs_update(const uint8_t *rgb) return; } -void idz_io_led_set_leds(const uint8_t *rgb) +void idz_io_led_set_leds(uint8_t board, const uint8_t *rgb) { #if 0 dprintf("IDZ LED: START: %02X\n", rgb[0]); diff --git a/idzio/idzio.h b/idzio/idzio.h index 8fd01d8..db64c44 100644 --- a/idzio/idzio.h +++ b/idzio/idzio.h @@ -138,7 +138,7 @@ HRESULT idz_io_led_init(void); Minimum API version: 0x0101 */ -void idz_io_led_set_fet_output(const uint8_t *rgb); +void idz_io_led_set_fet_output(uint8_t board, const uint8_t *rgb); /* Update the RGB LEDs. rgb is a pointer to an array up to 32 * 4 = 128 bytes. @@ -155,7 +155,7 @@ void idz_io_led_set_fet_output(const uint8_t *rgb); Minimum API version: 0x0101 */ -void idz_io_led_gs_update(const uint8_t *rgb); +void idz_io_led_gs_update(uint8_t board, const uint8_t *rgb); /* Update the cabinet button LEDs. rgb is a pointer to an array up to 6 bytes. @@ -171,7 +171,7 @@ void idz_io_led_gs_update(const uint8_t *rgb); Minimum API version: 0x0101 */ -void idz_io_led_set_leds(const uint8_t *rgb); +void idz_io_led_set_leds(uint8_t board, const uint8_t *rgb); /* Initialize FFB emulation. This function will be called before any other idz_io_ffb_*() function calls. diff --git a/kemonohook/config.c b/kemonohook/config.c index ec00aa1..c008d88 100644 --- a/kemonohook/config.c +++ b/kemonohook/config.c @@ -65,7 +65,8 @@ void led15093_config_load(struct led15093_config *cfg, const wchar_t *filename) memset(cfg->boot_chip_number, ' ', sizeof(cfg->boot_chip_number)); cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename); - cfg->port_no = GetPrivateProfileIntW(L"led15093", L"portNo", 0, filename); + cfg->port_no[0] = GetPrivateProfileIntW(L"led15093", L"portNo1", 0, filename); + cfg->port_no[1] = GetPrivateProfileIntW(L"led15093", L"portNo2", 1, filename); cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaud", 0, filename); cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0xA0, filename); cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xAA53, filename); diff --git a/kemonohook/dllmain.c b/kemonohook/dllmain.c index 83a4290..3373489 100644 --- a/kemonohook/dllmain.c +++ b/kemonohook/dllmain.c @@ -1,28 +1,21 @@ -#include - #include +#include #include "board/io4.h" #include "board/sg-reader.h" #include "board/vfd.h" - +#include "hook/iohook.h" #include "hook/process.h" #include "hook/table.h" -#include "hook/iohook.h" - #include "hooklib/printer.h" #include "hooklib/serial.h" #include "hooklib/spike.h" - #include "kemonohook/config.h" #include "kemonohook/hooks.h" #include "kemonohook/jvs.h" #include "kemonohook/kemono-dll.h" - #include "platform/platform.h" - #include "unityhook/hook.h" - #include "util/dprintf.h" #include "util/env.h" @@ -47,29 +40,38 @@ static DWORD CALLBACK kemono_pre_startup(void) { // 2.02 does not call printer update functions uint16_t ret; - fwdlusb_updateFirmware_main(1, "UnityApp\\Parade_Data\\StreamingAssets\\Printer\\E0223100-014E-C300-MAINAPP.BIN", &ret); - if (ret != 0){ + fwdlusb_updateFirmware_main( + 1, + "UnityApp\\Parade_Data\\StreamingAssets\\Printer\\E0223100-014E-C300-" + "MAINAPP.BIN", + &ret); + if (ret != 0) { goto fail; } - fwdlusb_updateFirmware_dsp(2, "UnityApp\\Parade_Data\\StreamingAssets\\Printer\\E0223200-0101-C300-DSPAPP.BIN", &ret); - if (ret != 0){ + fwdlusb_updateFirmware_dsp( + 2, + "UnityApp\\Parade_Data\\StreamingAssets\\Printer\\E0223200-0101-C300-" + "DSPAPP.BIN", + &ret); + if (ret != 0) { goto fail; } - fwdlusb_updateFirmware_param(3, "UnityApp\\Parade_Data\\StreamingAssets\\Printer\\D0460700-0101-C300-PARAM.BIN", &ret); - if (ret != 0){ + fwdlusb_updateFirmware_param( + 3, + "UnityApp\\Parade_Data\\StreamingAssets\\Printer\\D0460700-0101-C300-" + "PARAM.BIN", + &ret); + if (ret != 0) { goto fail; } printer_hook_init(&kemono_hook_cfg.printer, 0, kemono_hook_mod); - printer_set_dimensions(720, 1028); // printer doesn't call setimageformat + printer_set_dimensions(720, 1028); // printer doesn't call setimageformat /* Initialize emulation hooks */ - hr = platform_hook_init( - &kemono_hook_cfg.platform, - "SDFL", - "AAW1", - kemono_hook_mod); + hr = platform_hook_init(&kemono_hook_cfg.platform, "SDFL", "AAW1", + kemono_hook_mod); if (FAILED(hr)) { goto fail; @@ -93,7 +95,9 @@ static DWORD CALLBACK kemono_pre_startup(void) { goto fail; } - hr = led15093_hook_init(&kemono_hook_cfg.led15093, kemono_dll.led_init, kemono_dll.led_set_leds, 10, 1, 1, 2); + unsigned int led_port_no[2] = {10, 0}; + hr = led15093_hook_init(&kemono_hook_cfg.led15093, kemono_dll.led_init, + kemono_dll.led_set_leds, led_port_no); if (FAILED(hr)) { goto fail; @@ -106,7 +110,8 @@ static DWORD CALLBACK kemono_pre_startup(void) { There seems to be an issue with other DLL hooks if `LoadLibraryW` is hooked earlier in the `kemonohook` initialization. */ - unity_hook_init(&kemono_hook_cfg.unity, kemono_hook_mod, kemono_extra_hooks_load); + unity_hook_init(&kemono_hook_cfg.unity, kemono_hook_mod, + kemono_extra_hooks_load); /* Initialize debug helpers */ @@ -118,7 +123,7 @@ static DWORD CALLBACK kemono_pre_startup(void) { return kemono_startup(); - fail: +fail: ExitProcess(EXIT_FAILURE); } @@ -134,7 +139,7 @@ BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx) { hr = process_hijack_startup(kemono_pre_startup, &kemono_startup); if (!SUCCEEDED(hr)) { - dprintf("Failed to hijack process startup: %x\n", (int) hr); + dprintf("Failed to hijack process startup: %x\n", (int)hr); } return SUCCEEDED(hr); diff --git a/mai2hook/config.c b/mai2hook/config.c index 27e19ec..5435ada 100644 --- a/mai2hook/config.c +++ b/mai2hook/config.c @@ -12,24 +12,71 @@ #include "platform/config.h" void mai2_dll_config_load( - struct mai2_dll_config *cfg, - const wchar_t *filename) + struct mai2_dll_config *cfg, + const wchar_t *filename) { assert(cfg != NULL); assert(filename != NULL); GetPrivateProfileStringW( - L"mai2io", - L"path", - L"", - cfg->path, - _countof(cfg->path), - filename); + L"mai2io", + L"path", + L"", + cfg->path, + _countof(cfg->path), + filename); +} + +void touch_config_load( + struct touch_config *cfg, + const wchar_t *filename) +{ + assert(cfg != NULL); + assert(filename != NULL); + + cfg->enable_1p = GetPrivateProfileIntW(L"touch", L"p1Enable", 1, filename); + cfg->enable_2p = GetPrivateProfileIntW(L"touch", L"p2Enable", 1, filename); +} + +void led15070_config_load(struct led15070_config *cfg, const wchar_t *filename) +{ + assert(cfg != NULL); + assert(filename != NULL); + + wchar_t tmpstr[16]; + + cfg->enable = GetPrivateProfileIntW(L"led15070", L"enable", 1, filename); + cfg->port_no[0] = GetPrivateProfileIntW(L"led15070", L"portNo1", 0, filename); + cfg->port_no[1] = GetPrivateProfileIntW(L"led15070", L"portNo2", 0, filename); + cfg->fw_ver = GetPrivateProfileIntW(L"led15070", L"fwVer", 0x90, filename); + cfg->fw_sum = GetPrivateProfileIntW(L"led15070", L"fwSum", 0x00, filename); + + GetPrivateProfileStringW( + L"led15070", + L"boardNumber", + L"15070-04", + tmpstr, + _countof(tmpstr), + filename); + + size_t n = wcstombs(cfg->board_number, tmpstr, sizeof(cfg->board_number)); + for (int i = n; i < sizeof(cfg->board_number); i++) + { + cfg->board_number[i] = ' '; + } + + GetPrivateProfileStringW( + L"led15070", + L"eepromPath", + L"DEVICE", + cfg->eeprom_path, + _countof(cfg->eeprom_path), + filename); } void mai2_hook_config_load( - struct mai2_hook_config *cfg, - const wchar_t *filename) + struct mai2_hook_config *cfg, + const wchar_t *filename) { assert(cfg != NULL); assert(filename != NULL); @@ -40,5 +87,7 @@ void mai2_hook_config_load( io4_config_load(&cfg->io4, filename); vfd_config_load(&cfg->vfd, filename); mai2_dll_config_load(&cfg->dll, filename); + touch_config_load(&cfg->touch, filename); + led15070_config_load(&cfg->led15070, filename); unity_config_load(&cfg->unity, filename); } diff --git a/mai2hook/config.h b/mai2hook/config.h index 7e86822..1055b81 100644 --- a/mai2hook/config.h +++ b/mai2hook/config.h @@ -10,6 +10,10 @@ #include "platform/config.h" +#include "mai2hook/touch.h" + +#include "board/led15070.h" + #include "unityhook/config.h" struct mai2_hook_config { @@ -19,13 +23,23 @@ struct mai2_hook_config { struct io4_config io4; struct vfd_config vfd; struct mai2_dll_config dll; + struct touch_config touch; + struct led15070_config led15070; struct unity_config unity; }; void mai2_dll_config_load( - struct mai2_dll_config *cfg, - const wchar_t *filename); + struct mai2_dll_config *cfg, + const wchar_t *filename); + +void touch_config_load( + struct touch_config *cfg, + const wchar_t *filename); + +void led15070_config_load( + struct led15070_config *cfg, + const wchar_t *filename); void mai2_hook_config_load( - struct mai2_hook_config *cfg, - const wchar_t *filename); + struct mai2_hook_config *cfg, + const wchar_t *filename); diff --git a/mai2hook/dllmain.c b/mai2hook/dllmain.c index 193467f..cecc01e 100644 --- a/mai2hook/dllmain.c +++ b/mai2hook/dllmain.c @@ -66,17 +66,54 @@ static DWORD CALLBACK mai2_pre_startup(void) /* Initialize emulation hooks */ + struct dipsw_config new_dipsw_config[8] = { + {L"Delivery Server", L"Server", L"Client"}, + }; + + // Set the system dip switch configuration + memcpy(mai2_hook_cfg.platform.system.dipsw_config, new_dipsw_config, + sizeof(new_dipsw_config)); + hr = platform_hook_init( - &mai2_hook_cfg.platform, - "SDEZ", - "ACA1", - mai2_hook_mod); + &mai2_hook_cfg.platform, + "SDEZ", + "ACA1", + mai2_hook_mod); if (FAILED(hr)) { goto fail; } - hr = sg_reader_hook_init(&mai2_hook_cfg.aime, 1, 1, mai2_hook_mod); + /* Initialize DLLs */ + + hr = mai2_dll_init(&mai2_hook_cfg.dll, mai2_hook_mod); + + if (FAILED(hr)) { + goto fail; + } + + // Touch Panel uses COM3 and COM4 + + hr = touch_hook_init(&mai2_hook_cfg.touch); + + if (FAILED(hr)) { + goto fail; + } + + // LED board uses COM21 and COM23 + unsigned int led_port_no[2] = {21, 23}; + hr = led15070_hook_init(&mai2_hook_cfg.led15070, + mai2_dll.led_init, + mai2_dll.led_set_fet_output, + mai2_dll.led_dc_update, + mai2_dll.led_gs_update, + led_port_no); + + if (FAILED(hr)) { + goto fail; + } + + hr = sg_reader_hook_init(&mai2_hook_cfg.aime, 1, 3, mai2_hook_mod); if (FAILED(hr)) { goto fail; @@ -88,12 +125,6 @@ static DWORD CALLBACK mai2_pre_startup(void) goto fail; } - hr = mai2_dll_init(&mai2_hook_cfg.dll, mai2_hook_mod); - - if (FAILED(hr)) { - goto fail; - } - hr = mai2_io4_hook_init(&mai2_hook_cfg.io4); if (FAILED(hr)) { diff --git a/mai2hook/mai2-dll.c b/mai2hook/mai2-dll.c index dd172c3..121750e 100644 --- a/mai2hook/mai2-dll.c +++ b/mai2hook/mai2-dll.c @@ -21,7 +21,28 @@ const struct dll_bind_sym mai2_dll_syms[] = { }, { .sym = "mai2_io_get_gamebtns", .off = offsetof(struct mai2_dll, get_gamebtns), - } + }, { + .sym = "mai2_io_touch_init", + .off = offsetof(struct mai2_dll, touch_init), + }, { + .sym = "mai2_io_touch_set_sens", + .off = offsetof(struct mai2_dll, touch_set_sens), + }, { + .sym = "mai2_io_touch_update", + .off = offsetof(struct mai2_dll, touch_update), + }, { + .sym = "mai2_io_led_init", + .off = offsetof(struct mai2_dll, led_init), + }, { + .sym = "mai2_io_led_set_fet_output", + .off = offsetof(struct mai2_dll, led_set_fet_output), + }, { + .sym = "mai2_io_led_dc_update", + .off = offsetof(struct mai2_dll, led_dc_update), + }, { + .sym = "mai2_io_led_gs_update", + .off = offsetof(struct mai2_dll, led_gs_update), + }, }; struct mai2_dll mai2_dll; @@ -67,7 +88,7 @@ HRESULT mai2_dll_init(const struct mai2_dll_config *cfg, HINSTANCE self) if (get_api_version != NULL) { mai2_dll.api_version = get_api_version(); } else { - mai2_dll.api_version = 0x0100; + mai2_dll.api_version = 0x0101; dprintf("Custom IO DLL does not expose mai2_io_get_api_version, " "assuming API version 1.0.\n" "Please ask the developer to update their DLL.\n"); diff --git a/mai2hook/mai2-dll.h b/mai2hook/mai2-dll.h index 6e53454..599d44a 100644 --- a/mai2hook/mai2-dll.h +++ b/mai2hook/mai2-dll.h @@ -10,6 +10,13 @@ struct mai2_dll { HRESULT (*poll)(void); void (*get_opbtns)(uint8_t *opbtn); void (*get_gamebtns)(uint16_t *player1, uint16_t *player2); + HRESULT (*touch_init)(mai2_io_touch_callback_t callback); + void (*touch_set_sens)(uint8_t *bytes); + void (*touch_update)(bool player1, bool player2); + HRESULT (*led_init)(void); + void (*led_set_fet_output)(uint8_t board, const uint8_t *rgb); + void (*led_dc_update)(uint8_t board, const uint8_t *rgb); + void (*led_gs_update)(uint8_t board, const uint8_t *rgb); }; struct mai2_dll_config { diff --git a/mai2hook/mai2hook.def b/mai2hook/mai2hook.def index 2d0ac8b..50e4058 100644 --- a/mai2hook/mai2hook.def +++ b/mai2hook/mai2hook.def @@ -15,4 +15,11 @@ EXPORTS mai2_io_get_gamebtns mai2_io_get_opbtns mai2_io_init - mai2_io_poll \ No newline at end of file + mai2_io_poll + mai2_io_touch_init + mai2_io_touch_set_sens + mai2_io_touch_update + mai2_io_led_init + mai2_io_led_set_fet_output + mai2_io_led_dc_update + mai2_io_led_gs_update diff --git a/mai2hook/meson.build b/mai2hook/meson.build index eba0c19..ed47793 100644 --- a/mai2hook/meson.build +++ b/mai2hook/meson.build @@ -23,6 +23,8 @@ shared_library( 'dllmain.c', 'io4.c', 'io4.h', + 'touch.c', + 'touch.h', 'mai2-dll.c', 'mai2-dll.h', ], diff --git a/mai2hook/touch.c b/mai2hook/touch.c new file mode 100644 index 0000000..305d005 --- /dev/null +++ b/mai2hook/touch.c @@ -0,0 +1,259 @@ +#include +#include + +#include "hooklib/fdshark.h" +#include "hooklib/reg.h" + +#include "mai2hook/mai2-dll.h" +#include "mai2hook/touch.h" + +#include "util/dprintf.h" +#include "util/dump.h" + + +static HRESULT read_reg_touch_1p(void *bytes, uint32_t *nbytes) +{ + return reg_hook_read_wstr(bytes, nbytes, L"COM3"); +} + +static HRESULT read_reg_touch_2p(void *bytes, uint32_t *nbytes) +{ + return reg_hook_read_wstr(bytes, nbytes, L"COM4"); +} + +static const struct reg_hook_val touch_reg_key[] = { + { + .name = L"\\Device\\RealTouchBoard0", + .read = read_reg_touch_1p, + .type = REG_SZ, + }, + { + .name = L"\\Device\\RealTouchBoard1", + .read = read_reg_touch_2p, + .type = REG_SZ, + }, +}; + +const char *sensor_map[34] = { + "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", // 0x41 - 0x48 + "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", // 0x49 - 0x50 + "C1", "C2", // 0x51 - 0x52 + "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", // 0x53 - 0x5A + "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8" // 0x5B - 0x62 +}; + +const char *sensor_to_str(uint8_t sensor) +{ + if (sensor < 0x41 || sensor > 0x62) + { + return "Invalid"; + } + + return sensor_map[sensor - 0x41]; +} + +static CRITICAL_SECTION touch_1p_lock; +static struct uart touch_1p_uart; +static uint8_t touch_1p_written_bytes[64]; +static uint8_t touch_1p_readable_bytes[64]; +static bool touch_1p_status = false; + +static CRITICAL_SECTION touch_2p_lock; +static struct uart touch_2p_uart; +static uint8_t touch_2p_written_bytes[64]; +static uint8_t touch_2p_readable_bytes[64]; +static bool touch_2p_status = false; + +HRESULT touch_hook_init(const struct touch_config *cfg) +{ + assert(cfg != NULL); + + if (!cfg->enable_1p && !cfg->enable_2p) + { + return S_FALSE; + } + + HRESULT hr = reg_hook_push_key(HKEY_LOCAL_MACHINE, L"HARDWARE\\DEVICEMAP\\SERIALCOMM", touch_reg_key, _countof(touch_reg_key)); + + if (FAILED(hr)) + { + return hr; + } + + if (cfg->enable_1p) + { + dprintf("Mai2 touch 1P: Init.\n"); + + InitializeCriticalSection(&touch_1p_lock); + uart_init(&touch_1p_uart, 3); + touch_1p_uart.written.bytes = touch_1p_written_bytes; + touch_1p_uart.written.nbytes = sizeof(touch_1p_written_bytes); + touch_1p_uart.readable.bytes = touch_1p_readable_bytes; + touch_1p_uart.readable.nbytes = sizeof(touch_1p_readable_bytes); + } + + if (cfg->enable_2p) + { + dprintf("Mai2 touch 2P: Init.\n"); + + InitializeCriticalSection(&touch_2p_lock); + uart_init(&touch_2p_uart, 4); + touch_2p_uart.written.bytes = touch_2p_written_bytes; + touch_2p_uart.written.nbytes = sizeof(touch_2p_written_bytes); + touch_2p_uart.readable.bytes = touch_2p_readable_bytes; + touch_2p_uart.readable.nbytes = sizeof(touch_2p_readable_bytes); + } + + return iohook_push_handler(touch_handle_irp); +} + +static HRESULT touch_handle_irp(struct irp *irp) +{ + HRESULT hr; + + assert(irp != NULL); + + if (uart_match_irp(&touch_1p_uart, irp)) + { + EnterCriticalSection(&touch_1p_lock); + hr = touch_handle_irp_locked(irp, &touch_1p_uart); + LeaveCriticalSection(&touch_1p_lock); + } + else if (uart_match_irp(&touch_2p_uart, irp)) + { + EnterCriticalSection(&touch_2p_lock); + hr = touch_handle_irp_locked(irp, &touch_2p_uart); + LeaveCriticalSection(&touch_2p_lock); + } + else + { + return iohook_invoke_next(irp); + } + + return hr; +} + +static HRESULT touch_handle_irp_locked(struct irp *irp, struct uart *uart) +{ + HRESULT hr; + + if (irp->op == IRP_OP_OPEN) + { + dprintf("Mai2 touch port %d: Starting backend\n", uart->port_no); + hr = mai2_dll.touch_init(touch_auto_scan); + + if (FAILED(hr)) + { + dprintf("Mai2 touch port %d: Backend error: %x\n", uart->port_no, (int)hr); + return hr; + } + } + + hr = uart_handle_irp(uart, irp); + + if (FAILED(hr) || irp->op != IRP_OP_WRITE) + { + return hr; + } + +#if defined(LOG_MAI2_TOUCH) + dprintf("Mai2 touch port %d WRITE:\n", uart->port_no); + dump_iobuf(&uart->written); +#endif + uint8_t port_no = uart->port_no; + uint8_t *src = uart->written.bytes; + uint8_t *dest = uart->readable.bytes; + + switch (src[3]) + { + case commandRSET: + dprintf("Mai2 touch port %d: Reset\n", port_no); + break; + + case commandHALT: // Enter Conditioning mode and stop sending touch data. + dprintf("Mai2 touch port %d: Halt\n", port_no); + assert(mai2_dll.touch_update != NULL); + if (port_no == 3) + { + EnterCriticalSection(&touch_1p_lock); + touch_1p_status = false; + mai2_dll.touch_update(touch_1p_status, touch_2p_status); + LeaveCriticalSection(&touch_1p_lock); + } + else + { + EnterCriticalSection(&touch_2p_lock); + touch_2p_status = false; + mai2_dll.touch_update(touch_1p_status, touch_2p_status); + LeaveCriticalSection(&touch_2p_lock); + } + break; + + case commandSTAT: // Exit Conditioning mode and resume sending touch data. + dprintf("Mai2 touch port %d: Stat\n", port_no); + assert(mai2_dll.touch_update != NULL); + if (port_no == 3) + { + EnterCriticalSection(&touch_1p_lock); + touch_1p_status = true; + mai2_dll.touch_update(touch_1p_status, touch_2p_status); + LeaveCriticalSection(&touch_1p_lock); + } + else + { + EnterCriticalSection(&touch_2p_lock); + touch_2p_status = true; + mai2_dll.touch_update(touch_1p_status, touch_2p_status); + LeaveCriticalSection(&touch_2p_lock); + } + break; + + case commandRatio: +#if defined(LOG_MAI2_TOUCH) + dprintf("Mai2 touch side %c: set sensor %s ratio to %d\n", src[1], sensor_to_str(src[2]), src[4]); +#endif + dest[0] = res_start; + dest[1] = src[1]; // L,R + dest[2] = src[2]; // sensor + dest[3] = commandRatio; + dest[4] = src[4]; // Ratio + dest[5] = res_end; + uart->readable.pos = 6; + // The Ratio is fixed at 0x72 and does not need to be sent to mai2io for processing. + break; + + case commandSens: +#if defined(LOG_MAI2_TOUCH) + dprintf("Mai2 touch side %c: set sensor %s sensitivity to %d\n", src[1], sensor_to_str(src[2]), src[4]); +#endif + dest[0] = res_start; + dest[1] = src[1]; // L,R + dest[2] = src[2]; // sensor + dest[3] = commandSens; + dest[4] = src[4]; // Sensitivity + dest[5] = res_end; + uart->readable.pos = 6; + mai2_dll.touch_set_sens(dest); + break; + + default: + dprintf("Mai2 touch port %d: Unknow %02x\n", port_no, src[3]); + break; + } +#if defined(LOG_MAI2_TOUCH) + dprintf("Mai2 touch port %d READ:\n", uart->port_no); + dump_iobuf(&uart->readable); +#endif + uart->written.pos = 0; + + return hr; +} + +static void touch_auto_scan(const uint8_t player, const uint8_t state[7]) +{ + struct uart *touch_uart = player == 1 ? &touch_1p_uart : &touch_2p_uart; + touch_uart->readable.bytes[0] = res_start; + memcpy(&touch_uart->readable.bytes[1], state, 7); + touch_uart->readable.bytes[8] = res_end; + touch_uart->readable.pos = 9; +} diff --git a/mai2hook/touch.h b/mai2hook/touch.h new file mode 100644 index 0000000..f6fc72a --- /dev/null +++ b/mai2hook/touch.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include + +#include "hooklib/uart.h" + +struct touch_config +{ + bool enable_1p; + bool enable_2p; +}; + +enum +{ + commandRSET = 0x45, // E + commandHALT = 0x4C, // L + commandSTAT = 0x41, // A + commandRatio = 0x72, // r + commandSens = 0x6B, // k + req_start = 0x7b, // { + req_end = 0x7d, // } + res_start = 0x28, // ( + res_end = 0x29, // ) +}; + +extern const char *sensor_map[34]; +const char *sensor_to_str(uint8_t sensor); + +HRESULT touch_hook_init(const struct touch_config *cfg); +static HRESULT touch_handle_irp(struct irp *irp); +static HRESULT touch_handle_irp_locked(struct irp *irp, struct uart *uart); + +/* Called in mai2io to send touch data. + Similar to chuni slider_res_auto_scan, but the host does not require periodic updates. + Touch data is sent only when there is a change. */ +static void touch_auto_scan(const uint8_t player, const uint8_t state[7]); diff --git a/mai2io/config.c b/mai2io/config.c index 3578338..c6c9913 100644 --- a/mai2io/config.c +++ b/mai2io/config.c @@ -6,6 +6,7 @@ #include #include "mai2io/config.h" +#include "mai2hook/touch.h" /* Maimai DX Default key binding @@ -15,9 +16,24 @@ Maimai DX Default key binding static const int mai2_io_1p_default[] = {'W', 'E', 'D', 'C', 'X', 'Z', 'A', 'Q', '3'}; static const int mai2_io_2p_default[] = {0x68, 0x69, 0x66, 0x63, 0x62, 0x61, 0x64, 0x67, 0x54}; +static const int mai2_io_1p_touch_default[] = { + 'T', 'Y', 'H', 'N', 'B', 'V', 'F', 'R', + 'T', 'Y', 'H', 'N', 'B', 'V', 'F', 'R', + 'G', 'G', + 'T', 'Y', 'H', 'N', 'B', 'V', 'F', 'R', + 'T', 'Y', 'H', 'N', 'B', 'V', 'F', 'R', +}; +static const int mai2_io_2p_touch_default[] = { + 'I', 'O', 'L', VK_OEM_PERIOD, VK_OEM_COMMA, 'M', 'J', 'U', + 'I', 'O', 'L', VK_OEM_PERIOD, VK_OEM_COMMA, 'M', 'J', 'U', + 'K', 'K', + 'I', 'O', 'L', VK_OEM_PERIOD, VK_OEM_COMMA, 'M', 'J', 'U', + 'I', 'O', 'L', VK_OEM_PERIOD, VK_OEM_COMMA, 'M', 'J', 'U', +}; + void mai2_io_config_load( - struct mai2_io_config *cfg, - const wchar_t *filename) + struct mai2_io_config *cfg, + const wchar_t *filename) { wchar_t key[16]; int i; @@ -28,22 +44,41 @@ void mai2_io_config_load( cfg->vk_test = GetPrivateProfileIntW(L"io4", L"test", VK_F1, filename); cfg->vk_service = GetPrivateProfileIntW(L"io4", L"service", VK_F2, filename); cfg->vk_coin = GetPrivateProfileIntW(L"io4", L"coin", VK_F3, filename); + cfg->vk_btn_enable = GetPrivateProfileIntW(L"button", L"enable", 1, filename); - for (i = 0 ; i < 9 ; i++) { - swprintf_s(key, _countof(key), L"1p_btn%i", i + 1); + for (i = 0; i < 9; i++) + { + swprintf_s(key, _countof(key), L"p1Btn%i", i + 1); cfg->vk_1p_btn[i] = GetPrivateProfileIntW( - L"button", - key, - mai2_io_1p_default[i], - filename); + L"button", + key, + mai2_io_1p_default[i], + filename); + + swprintf_s(key, _countof(key), L"p2Btn%i", i + 1); + cfg->vk_2p_btn[i] = GetPrivateProfileIntW( + L"button", + key, + mai2_io_2p_default[i], + filename); } - for (i = 0 ; i < 9 ; i++) { - swprintf_s(key, _countof(key), L"2p_btn%i", i + 1); - cfg->vk_2p_btn[i] = GetPrivateProfileIntW( - L"button", - key, - mai2_io_2p_default[i], - filename); + cfg->debug_input_1p = GetPrivateProfileIntW(L"touch", L"p1DebugInput", 0, filename); + cfg->debug_input_2p = GetPrivateProfileIntW(L"touch", L"p2DebugInput", 0, filename); + for (i = 0; i < 34; i++) + { + swprintf_s(key, _countof(key), L"p1Touch%S", sensor_map[i]); + cfg->vk_1p_touch[i] = GetPrivateProfileIntW( + L"touch", + key, + mai2_io_1p_touch_default[i], + filename); + + swprintf_s(key, _countof(key), L"p2Touch%S", sensor_map[i]); + cfg->vk_2p_touch[i] = GetPrivateProfileIntW( + L"touch", + key, + mai2_io_2p_touch_default[i], + filename); } } diff --git a/mai2io/config.h b/mai2io/config.h index 568b832..ce765ed 100644 --- a/mai2io/config.h +++ b/mai2io/config.h @@ -9,8 +9,13 @@ struct mai2_io_config { uint8_t vk_test; uint8_t vk_service; uint8_t vk_coin; + bool vk_btn_enable; uint8_t vk_1p_btn[9]; uint8_t vk_2p_btn[9]; + bool debug_input_1p; + bool debug_input_2p; + uint8_t vk_1p_touch[34]; + uint8_t vk_2p_touch[34]; }; void mai2_io_config_load( diff --git a/mai2io/mai2io.c b/mai2io/mai2io.c index ffdbfcf..57404cb 100644 --- a/mai2io/mai2io.c +++ b/mai2io/mai2io.c @@ -1,10 +1,11 @@ -#include +#include "mai2io/mai2io.h" #include -#include +#include -#include "mai2io/mai2io.h" +#include "mai2hook/touch.h" #include "mai2io/config.h" +#include "util/dprintf.h" #include "util/env.h" static uint8_t mai2_opbtn; @@ -12,21 +13,21 @@ static uint16_t mai2_player1_btn; static uint16_t mai2_player2_btn; static struct mai2_io_config mai2_io_cfg; static bool mai2_io_coin; +mai2_io_touch_callback_t _callback; +static HANDLE mai2_io_touch_1p_thread; +static bool mai2_io_touch_1p_stop_flag; +static HANDLE mai2_io_touch_2p_thread; +static bool mai2_io_touch_2p_stop_flag; -uint16_t mai2_io_get_api_version(void) -{ - return 0x0100; -} +uint16_t mai2_io_get_api_version(void) { return 0x0101; } -HRESULT mai2_io_init(void) -{ +HRESULT mai2_io_init(void) { mai2_io_config_load(&mai2_io_cfg, get_config_path()); return S_OK; } -HRESULT mai2_io_poll(void) -{ +HRESULT mai2_io_poll(void) { mai2_opbtn = 0; mai2_player1_btn = 0; mai2_player2_btn = 0; @@ -47,8 +48,13 @@ HRESULT mai2_io_poll(void) } else { mai2_io_coin = false; } + // If sinmai has enabled DebugInput, there is no need to input buttons + // through hook amdaemon. + if (!mai2_io_cfg.vk_btn_enable) { + return S_OK; + } - //Player 1 + // Player 1 if (GetAsyncKeyState(mai2_io_cfg.vk_1p_btn[0])) { mai2_player1_btn |= MAI2_IO_GAMEBTN_1; } @@ -85,7 +91,7 @@ HRESULT mai2_io_poll(void) mai2_player1_btn |= MAI2_IO_GAMEBTN_SELECT; } - //Player 2 + // Player 2 if (GetAsyncKeyState(mai2_io_cfg.vk_2p_btn[0])) { mai2_player2_btn |= MAI2_IO_GAMEBTN_1; } @@ -125,20 +131,137 @@ HRESULT mai2_io_poll(void) return S_OK; } -void mai2_io_get_opbtns(uint8_t *opbtn) -{ +void mai2_io_get_opbtns(uint8_t *opbtn) { if (opbtn != NULL) { *opbtn = mai2_opbtn; } } -void mai2_io_get_gamebtns(uint16_t *player1, uint16_t *player2) -{ +void mai2_io_get_gamebtns(uint16_t *player1, uint16_t *player2) { if (player1 != NULL) { *player1 = mai2_player1_btn; } - if (player2 != NULL ){ + if (player2 != NULL) { *player2 = mai2_player2_btn; } } + +HRESULT mai2_io_touch_init(mai2_io_touch_callback_t callback) { + _callback = callback; + return S_OK; +} + +void mai2_io_touch_set_sens(uint8_t *bytes) { +#if 0 + dprintf("Mai2 touch side %c: set sensor %s sensitivity to %d\n", bytes[1], sensor_to_str(bytes[2]), bytes[4]); +#endif + return; +} + +void mai2_io_touch_update(bool player1, bool player2) { + if (mai2_io_cfg.debug_input_1p) { + if (player1 && mai2_io_touch_1p_thread == NULL) { + mai2_io_touch_1p_thread = (HANDLE)_beginthreadex( + NULL, 0, mai2_io_touch_1p_thread_proc, _callback, 0, NULL); + } else if (!player1 && mai2_io_touch_1p_thread != NULL) { + mai2_io_touch_1p_stop_flag = true; + + WaitForSingleObject(mai2_io_touch_1p_thread, INFINITE); + CloseHandle(mai2_io_touch_1p_thread); + mai2_io_touch_1p_thread = NULL; + + mai2_io_touch_1p_stop_flag = false; + } + } + + if (mai2_io_cfg.debug_input_2p) { + if (player2 && mai2_io_touch_2p_thread == NULL) { + mai2_io_touch_2p_thread = (HANDLE)_beginthreadex( + NULL, 0, mai2_io_touch_2p_thread_proc, _callback, 0, NULL); + } else if (!player2 && mai2_io_touch_2p_thread != NULL) { + mai2_io_touch_2p_stop_flag = true; + + WaitForSingleObject(mai2_io_touch_2p_thread, INFINITE); + CloseHandle(mai2_io_touch_2p_thread); + mai2_io_touch_2p_thread = NULL; + + mai2_io_touch_2p_stop_flag = false; + } + } +} + +static unsigned int __stdcall mai2_io_touch_1p_thread_proc(void *ctx) { + mai2_io_touch_callback_t callback = ctx; + + while (!mai2_io_touch_1p_stop_flag) { + uint8_t state[7] = {0, 0, 0, 0, 0, 0, 0}; + + for (int i = 0; i < 34; i++) { + if (GetAsyncKeyState(mai2_io_cfg.vk_1p_touch[i])) { + int byteIndex = i / 5; + int bitIndex = i % 5; + state[byteIndex] |= (1 << bitIndex); + } + } + callback(1, state); + Sleep(1); + } + return 0; +} + +static unsigned int __stdcall mai2_io_touch_2p_thread_proc(void *ctx) { + mai2_io_touch_callback_t callback = ctx; + + while (!mai2_io_touch_2p_stop_flag) { + uint8_t state[7] = {0, 0, 0, 0, 0, 0, 0}; + + for (int i = 0; i < 34; i++) { + if (GetAsyncKeyState(mai2_io_cfg.vk_2p_touch[i])) { + int byteIndex = i / 5; + int bitIndex = i % 5; + state[byteIndex] |= (1 << bitIndex); + } + } + callback(2, state); + Sleep(1); + } + return 0; +} + +HRESULT mai2_io_led_init(void) { return S_OK; } + +void mai2_io_led_set_fet_output(uint8_t board, const uint8_t *rgb) { +#if 0 + uint8_t player = board + 1; + dprintf("MAI2 LED %dP: BodyLed brightness: %d%%\n", player, + (rgb[0] * 100) / 255); + dprintf("MAI2 LED %dP: ExtLed brightness: %d%%\n", player, + (rgb[1] * 100) / 255); + dprintf("MAI2 LED %dP: SideLed brightness: %d%%\n", player, + (rgb[2] * 100) / 255); +#endif + return; +} + +void mai2_io_led_dc_update(uint8_t board, const uint8_t *rgb) { +#if 0 + uint8_t player = board + 1; + for (int i = 0; i < 10; i++) { + dprintf("Mai2 LED %dP: LED %d: %02X %02X %02X Speed: %02X\n", player + i, rgb[i * 4], rgb[i * 4 + 1], rgb[i * 4 + 2], rgb[i * 4 + 3]); + } +#endif + return; +} + +void mai2_io_led_gs_update(uint8_t board, const uint8_t *rgb) { +#if 0 + uint8_t player = board + 1; + for (int i = 0; i < 8; i++) { + dprintf("Mai2 LED %dP: LED %d: %02X %02X %02X Speed: %02X\n", player, i, + rgb[i * 4], rgb[i * 4 + 1], rgb[i * 4 + 2], rgb[i * 4 + 3]); + } +#endif + return; +} diff --git a/mai2io/mai2io.h b/mai2io/mai2io.h index 084228c..9c0a7f0 100644 --- a/mai2io/mai2io.h +++ b/mai2io/mai2io.h @@ -3,6 +3,7 @@ #include #include +#include enum { MAI2_IO_OPBTN_TEST = 0x01, @@ -66,3 +67,126 @@ void mai2_io_get_opbtns(uint8_t *opbtn); Minimum API version: 0x0100 */ void mai2_io_get_gamebtns(uint16_t *player1, uint16_t *player2); + +/* Callback function used by mai2_io_touch_1p/2p_thread_proc. + + The 'player'(1 or 2) parameter indicates which player the touch data is for. + + The 'state' represents a complete response packet. + The format of the state array is as follows: + uint8_t state[7] = { + bytes[0] - bit(0 , 0 , 0 , A5, A4, A3, A2, A1) + bytes[1] - bit(0 , 0 , 0 , B2, B1, A8, A7, A6) + bytes[2] - bit(0 , 0 , 0 , B7, B6, B5, B4, B3) + bytes[3] - bit(0 , 0 , 0 , D2, D1, C2, C1, B8) + bytes[4] - bit(0 , 0 , 0 , D7, D6, D5, D4, D3) + bytes[5] - bit(0 , 0 , 0 , E4, E3, E2, E1, D8) + bytes[6] - bit(0 , 0 , 0 , 0 , E8, E7, E6, E5) + } + The 7 bytes are the touch data, with each byte storing the touch state in the lower 5 bits. + A value of 1 indicates that the corresponding touch area is pressed. + The touch areas are ordered from A1 to E8, and the binary values are stored from low to high. */ + +typedef void (*mai2_io_touch_callback_t)(const uint8_t player, const uint8_t state[7]); + +/** + * @brief Initializes the touch input callback function + * + * This function accepts a callback function as a parameter and stores it in the global variable `_callback` + * for later handling of touch input events. + * + * @param callback The touch input callback function that takes two parameters: player number and the touch state array. + * @return HRESULT Returns the result of the operation, S_OK on success. + */ + +HRESULT mai2_io_touch_init(mai2_io_touch_callback_t callback); + +/* Send sensitivity setting data to the touch device. + Format: + bytes[0] - Header + bytes[1] - Target device, ASCII characters 'L' or 'R' + bytes[2] - Target touch point + bytes[3] - commandRatio identifier + bytes[4] - Ratio value to be set, within a fixed range + bytes[5] - Footer + + Example function, not actually used. The sensitivity range can be determined + based on the Ratio set within the game. */ + +void mai2_io_touch_set_sens(uint8_t *bytes); + +/** + * @brief Updates the touch input acceptance state + * + * This function determines whether the game is ready to accept touch input based on the states of player 1 and player 2. + * If the game is ready, it creates or stops the corresponding threads to handle touch data for each player. + * Whether or not threads are created for each player is controlled by `mai2_io_cfg.debug_input_1p` and `mai2_io_cfg.debug_input_2p` configuration. + * + * @param player1 If `true`, indicates the game is ready to accept touch data from player 1, `false` means the game is not ready. + * @param player2 If `true`, indicates the game is ready to accept touch data from player 2, `false` means the game is not ready. + */ + +void mai2_io_touch_update(bool player1, bool player2); + +/** + * @brief Player touch input handling thread + * + * This function runs in a separate thread, continuously monitoring player touch status and passing the state data + * to the main thread via a callback function. Each time a touch input is detected, it updates the `state` array and calls the callback. + * The thread stops when `mai2_io_touch_1p/2p_stop_flag` is `true`. + * + * @param ctx The callback function context, of type `mai2_io_touch_callback_t`, used to handle the touch input events. + * @return The thread's return value, typically `0`. + */ + +static unsigned int __stdcall mai2_io_touch_1p_thread_proc(void *ctx); + +static unsigned int __stdcall mai2_io_touch_2p_thread_proc(void *ctx); + +/* Initialize LED emulation. This function will be called before any + other mai2_io_led_*() function calls. + + All subsequent calls may originate from arbitrary threads and some may + overlap with each other. Ensuring synchronization inside your IO DLL is + your responsibility. + + Minimum API version: 0x0101 */ + +HRESULT mai2_io_led_init(void); + +/* Update the FET outputs. rgb is a pointer to an array up to 3 bytes. + + maimai DX uses two boards. Board 0 is for the player 1 side (left) and board 1 + is for the player 2 side (right). + + Set the brightness of the white light on the machine's outer shell. + The program will continuously send changed values to request the blinking effect. + + [0]: BodyLed + [1]: ExtLed + [2]: SideLed + + The LED is truned on when the byte is 255 and turned off when the byte is 0. + + Minimum API version: 0x0101 */ + +void mai2_io_led_set_fet_output(uint8_t board, const uint8_t *rgb); + +/* The effect of this command is unknown, it is triggered after LED_15070_CMD_EEPROM_READ. */ + +void mai2_io_led_dc_update(uint8_t board, const uint8_t *rgb); + +/* Update the RGB LEDs. rgb is a pointer to an array up to 8 * 4 = 32 bytes. + + maimai DX uses two boards. Board 0 is for the player 1 side (left) and board 1 + is for the player 2 side (right). + + The LEDs are laid out as follows: + [0-7]: 8 button LED + + Each rgb value is comprised for 4 bytes in the order of R, G, B, Speed. + Speed is a value from 0 to 255, where 0 is the fastest speed and 255 is the slowest. + + Minimum API version: 0x0101 */ + +void mai2_io_led_gs_update(uint8_t board, const uint8_t *rgb); diff --git a/mai2io/meson.build b/mai2io/meson.build index cdbfd35..3d06b9f 100644 --- a/mai2io/meson.build +++ b/mai2io/meson.build @@ -3,6 +3,9 @@ mai2io_lib = static_library( name_prefix : '', include_directories : inc, implicit_include_directories : false, + dependencies : [ + capnhook.get_variable('hook_dep'), + ], sources : [ 'mai2io.c', 'mai2io.h', diff --git a/mercuryhook/dllmain.c b/mercuryhook/dllmain.c index 64b5707..37030d3 100644 --- a/mercuryhook/dllmain.c +++ b/mercuryhook/dllmain.c @@ -64,6 +64,14 @@ static DWORD CALLBACK mercury_pre_startup(void) /* Initialize emulation hooks */ + struct dipsw_config new_dipsw_config[8] = { + {L"Delivery Server", L"Server", L"Client"}, + }; + + // Set the system dip switch configuration + memcpy(mercury_hook_cfg.platform.system.dipsw_config, new_dipsw_config, + sizeof(new_dipsw_config)); + hr = platform_hook_init( &mercury_hook_cfg.platform, "SDFE", diff --git a/meson.build b/meson.build index 40a99c4..aada974 100644 --- a/meson.build +++ b/meson.build @@ -46,6 +46,9 @@ endif if get_option('log_all') or get_option('log_io3') add_project_arguments('-DLOG_IO3', language: 'c') endif +if get_option('log_all') or get_option('log_led15070') + add_project_arguments('-DLOG_LED15070', language: 'c') +endif if get_option('log_all') or get_option('log_led15093') add_project_arguments('-DLOG_LED15093', language: 'c') endif @@ -61,6 +64,9 @@ endif if get_option('log_all') or get_option('log_carol_touch') add_project_arguments('-DLOG_CAROL_TOUCH', language: 'c') endif +if get_option('log_all') or get_option('log_mai2_touch') + add_project_arguments('-DLOG_MAI2_TOUCH', language: 'c') +endif if get_option('log_all') or get_option('log_chuni_slider') add_project_arguments('-DLOG_CHUNI_SLIDER', language: 'c') endif @@ -83,7 +89,7 @@ dxguid_lib = cc.find_library('dxguid') xinput_lib = cc.find_library('xinput') pathcch_lib = cc.find_library('pathcch') imagehlp_lib = cc.find_library('imagehlp') -Ws2_32_lib = cc.find_library('Ws2_32') +ws2_32_lib = cc.find_library('ws2_32') inc = include_directories('.') capnhook = subproject('capnhook') diff --git a/meson_options.txt b/meson_options.txt index fb39b10..de9aefc 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -13,6 +13,11 @@ option('log_io3', value : false, description : 'Enable debug logging for JVS' ) +option('log_led15070', + type : 'boolean', + value : false, + description : 'Enable debug logging for the 15070 LED board emulation' +) option('log_led15093', type : 'boolean', value : false, @@ -38,6 +43,11 @@ option('log_carol_touch', value : false, description : 'Enable debug logging for the Carlo Touchscreen' ) +option('log_mai2_touch', + type : 'boolean', + value : false, + description : 'Enable debug logging for the mai2 TouchPanel' +) option('log_chuni_slider', type : 'boolean', value : false, diff --git a/mu3hook/config.c b/mu3hook/config.c index 93957ea..6c52446 100644 --- a/mu3hook/config.c +++ b/mu3hook/config.c @@ -41,7 +41,8 @@ void led15093_config_load(struct led15093_config *cfg, const wchar_t *filename) memset(cfg->boot_chip_number, ' ', sizeof(cfg->boot_chip_number)); cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename); - cfg->port_no = GetPrivateProfileIntW(L"led15093", L"portNo", 0, filename); + cfg->port_no[0] = GetPrivateProfileIntW(L"led15093", L"portNo1", 0, filename); + cfg->port_no[1] = GetPrivateProfileIntW(L"led15093", L"portNo2", 0, filename); cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaud", 0, filename); cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0xA0, filename); cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xAA53, filename); diff --git a/mu3hook/dllmain.c b/mu3hook/dllmain.c index e4336e9..1b57e5d 100644 --- a/mu3hook/dllmain.c +++ b/mu3hook/dllmain.c @@ -65,6 +65,14 @@ static DWORD CALLBACK mu3_pre_startup(void) /* Initialize emulation hooks */ + struct dipsw_config new_dipsw_config[8] = { + {L"Delivery Server", L"Server", L"Client"}, + }; + + // Set the system dip switch configuration + memcpy(mu3_hook_cfg.platform.system.dipsw_config, new_dipsw_config, + sizeof(new_dipsw_config)); + hr = platform_hook_init( &mu3_hook_cfg.platform, "SDDT", @@ -81,8 +89,9 @@ static DWORD CALLBACK mu3_pre_startup(void) goto fail; } + unsigned int led_port_no[2] = {3, 0}; hr = led15093_hook_init(&mu3_hook_cfg.led15093, - mu3_dll.led_init, mu3_dll.led_set_leds, 3, 1, 1, 2); + mu3_dll.led_init, mu3_dll.led_set_leds, led_port_no); if (FAILED(hr)) { return hr; diff --git a/platform/epay.c b/platform/epay.c index 0faf145..4a231c2 100644 --- a/platform/epay.c +++ b/platform/epay.c @@ -189,7 +189,7 @@ HRESULT epay_hook_init(const struct epay_config *cfg) { thinca_stub->impl1->unk220 = thinca_unk; thinca_stub->impl1->unk228 = thinca_unk; - dprintf("Epay: Init\n"); + dprintf("Epay: Init.\n"); return hr; } diff --git a/platform/system.c b/platform/system.c index dbc832f..5879032 100644 --- a/platform/system.c +++ b/platform/system.c @@ -1,40 +1,36 @@ -#include +#include "platform/system.h" +#include #include -#include #include +#include #include -#include "platform/system.h" #include "platform/vfs.h" - +#include "util/crc.h" #include "util/dprintf.h" #include "util/str.h" -#include "util/crc.h" #define DATA_SIZE 503 #define BLOCK_SIZE (sizeof(uint32_t) + 4 + 1 + DATA_SIZE) #pragma pack(push, 1) -typedef struct -{ +typedef struct { uint32_t checksum; char padding[6]; uint8_t freeplay; char data[DATA_SIZE - 2]; } CreditBlock; -typedef struct -{ +typedef struct { uint32_t checksum; char padding[4]; uint8_t dip_switches; char data[DATA_SIZE]; } DipSwBlock; -typedef struct -{ +typedef struct { CreditBlock credit_block; DipSwBlock dip_switch_block; char *data; @@ -50,16 +46,15 @@ static struct vfs_config vfs_config; static void system_read_sysfile(const wchar_t *sys_file); static void system_save_sysfile(const wchar_t *sys_file); -HRESULT system_init(const struct system_config *cfg, const struct vfs_config *vfs_cfg) -{ +HRESULT system_init(const struct system_config *cfg, + const struct vfs_config *vfs_cfg) { HRESULT hr; wchar_t sys_file_path[MAX_PATH]; assert(cfg != NULL); assert(vfs_cfg != NULL); - if (!cfg->enable) - { + if (!cfg->enable) { return S_FALSE; } @@ -78,13 +73,13 @@ HRESULT system_init(const struct system_config *cfg, const struct vfs_config *vf return S_OK; } -static void system_read_sysfile(const wchar_t *sys_file) -{ +static void system_read_sysfile(const wchar_t *sys_file) { FILE *f = _wfopen(sys_file, L"r"); - if (f == NULL) - { - dprintf("System: First run detected, system settings can only be applied AFTER the first run\n"); + if (f == NULL) { + dprintf( + "System: First run detected, system settings can only be applied " + "AFTER the first run\n"); return; } @@ -92,8 +87,7 @@ static void system_read_sysfile(const wchar_t *sys_file) long file_size = ftell(f); fseek(f, 0, SEEK_SET); - if (file_size != 0x6000) - { + if (file_size != 0x6000) { dprintf("System: Invalid sysfile.dat file size\n"); fclose(f); @@ -106,11 +100,11 @@ static void system_read_sysfile(const wchar_t *sys_file) // copy the credit_block and dip_switch_block from the sysfile.dat memcpy(&system_info.credit_block, system_info.data, BLOCK_SIZE); - memcpy(&system_info.dip_switch_block, system_info.data + 0x2800, BLOCK_SIZE); + memcpy(&system_info.dip_switch_block, system_info.data + 0x2800, + BLOCK_SIZE); } -static void system_save_sysfile(const wchar_t *sys_file) -{ +static void system_save_sysfile(const wchar_t *sys_file) { char block[BLOCK_SIZE]; uint8_t system = 0; uint8_t freeplay = 0; @@ -118,24 +112,28 @@ static void system_save_sysfile(const wchar_t *sys_file) // open the sysfile.dat for writing in bytes mode FILE *f = _wfopen(sys_file, L"rb+"); - if (f == NULL) - { + if (f == NULL) { return; } // write the system_config.system to the dip_switch_block - for (int i = 0; i < 8; i++) - { - if (system_config.dipsw[i]) - { - // print which system is enabled + for (int i = 0; i < 8; i++) { + // print the dip switch configuration with labels if present + if (system_config.dipsw_config[i].label[0] != L'\0') { + dprintf("System: %ls: %ls\n", system_config.dipsw_config[i].label, + system_config.dipsw[i] ? system_config.dipsw_config[i].on + : system_config.dipsw_config[i].off); + } else if (system_config.dipsw[i]) { dprintf("System: DipSw%d=1 set\n", i + 1); + } + + // set the system variable to the dip switch configuration + if (system_config.dipsw[i]) { system |= (1 << i); } } - if (system_config.freeplay) - { + if (system_config.freeplay) { // print that freeplay is enabled dprintf("System: Freeplay enabled\n"); freeplay = 1; @@ -149,10 +147,10 @@ static void system_save_sysfile(const wchar_t *sys_file) // calculate the new checksum, skip the old crc32 value // which is at the beginning of the block, thats's why the +4 // conver the struct to chars in order for the crc32 calculation to work - system_info.credit_block.checksum = crc32( - (char *)&system_info.credit_block + 4, BLOCK_SIZE - 4, 0); - system_info.dip_switch_block.checksum = crc32( - (char *)&system_info.dip_switch_block + 4, BLOCK_SIZE - 4, 0); + system_info.credit_block.checksum = + crc32((char *)&system_info.credit_block + 4, BLOCK_SIZE - 4, 0); + system_info.dip_switch_block.checksum = + crc32((char *)&system_info.dip_switch_block + 4, BLOCK_SIZE - 4, 0); // build the new credit block memcpy(block, (char *)&system_info.credit_block, BLOCK_SIZE); diff --git a/platform/system.h b/platform/system.h index ba0f2a6..e69ce90 100644 --- a/platform/system.h +++ b/platform/system.h @@ -7,10 +7,20 @@ #include "platform/vfs.h" + +struct dipsw_config +{ + wchar_t label[MAX_PATH]; + wchar_t on[MAX_PATH]; + wchar_t off[MAX_PATH]; +}; + + struct system_config { bool enable; bool freeplay; bool dipsw[8]; + struct dipsw_config dipsw_config[8]; }; HRESULT system_init(const struct system_config *cfg, const struct vfs_config *vfs_cfg); diff --git a/swdchook/config.c b/swdchook/config.c index fcfa251..e64654e 100644 --- a/swdchook/config.c +++ b/swdchook/config.c @@ -23,7 +23,8 @@ void led15070_config_load(struct led15070_config *cfg, const wchar_t *filename) wchar_t tmpstr[16]; cfg->enable = GetPrivateProfileIntW(L"led15070", L"enable", 1, filename); - cfg->port_no = GetPrivateProfileIntW(L"led15070", L"portNo", 0, filename); + cfg->port_no[0] = GetPrivateProfileIntW(L"led15070", L"portNo1", 0, filename); + cfg->port_no[1] = GetPrivateProfileIntW(L"led15070", L"portNo2", 0, filename); cfg->fw_ver = GetPrivateProfileIntW(L"led15070", L"fwVer", 0x90, filename); /* TODO: Unknown, no firmware file available */ cfg->fw_sum = GetPrivateProfileIntW(L"led15070", L"fwSum", 0xdead, filename); diff --git a/swdchook/dllmain.c b/swdchook/dllmain.c index d83798c..5932a69 100644 --- a/swdchook/dllmain.c +++ b/swdchook/dllmain.c @@ -100,8 +100,9 @@ static DWORD CALLBACK swdc_pre_startup(void) } /* Not working, different board -04 instead of -02? */ + unsigned int led_port_no[2] = {2, 0}; hr = led15070_hook_init(&swdc_hook_cfg.led15070, swdc_dll.led_init, - swdc_dll.led_set_fet_output, NULL, swdc_dll.led_gs_update, 2, 1); + swdc_dll.led_set_fet_output, NULL, swdc_dll.led_gs_update, led_port_no); if (FAILED(hr)) { goto fail; diff --git a/swdchook/io4.c b/swdchook/io4.c index be1d4b9..679a646 100644 --- a/swdchook/io4.c +++ b/swdchook/io4.c @@ -203,7 +203,7 @@ static HRESULT swdc_io4_write_gpio(uint8_t* payload, size_t len) lights_data & SWDC_IO_LED_LEFT ? 0xFF : 0x00, }; - swdc_dll.led_set_leds(rgb_out); + swdc_dll.led_set_leds(0, rgb_out); return S_OK; } diff --git a/swdchook/swdc-dll.h b/swdchook/swdc-dll.h index 1b81e26..7539d1c 100644 --- a/swdchook/swdc-dll.h +++ b/swdchook/swdc-dll.h @@ -11,9 +11,9 @@ struct swdc_dll { void (*get_gamebtns)(uint16_t *gamebtn); void (*get_analogs)(struct swdc_io_analog_state *out); HRESULT (*led_init)(void); - void (*led_set_fet_output)(const uint8_t *rgb); - void (*led_gs_update)(const uint8_t *rgb); - void (*led_set_leds)(const uint8_t *rgb); + void (*led_set_fet_output)(uint8_t board, const uint8_t *rgb); + void (*led_gs_update)(uint8_t board, const uint8_t *rgb); + void (*led_set_leds)(uint8_t board, const uint8_t *rgb); HRESULT (*ffb_init)(void); void (*ffb_toggle)(bool active); void (*ffb_constant_force)(uint8_t direction, uint8_t force); diff --git a/swdcio/dllmain.c b/swdcio/dllmain.c index 8057e23..a35b8e8 100644 --- a/swdcio/dllmain.c +++ b/swdcio/dllmain.c @@ -119,7 +119,7 @@ HRESULT swdc_io_led_init(void) return S_OK; } -void swdc_io_led_set_fet_output(const uint8_t *rgb) +void swdc_io_led_set_fet_output(uint8_t board, const uint8_t *rgb) { #if 0 dprintf("SWDC LED: LEFT SEAT LED: %02X\n", rgb[0]); @@ -129,7 +129,7 @@ void swdc_io_led_set_fet_output(const uint8_t *rgb) return; } -void swdc_io_led_gs_update(const uint8_t *rgb) +void swdc_io_led_gs_update(uint8_t board, const uint8_t *rgb) { #if 0 for (int i = 0; i < 9; i++) { @@ -141,7 +141,7 @@ void swdc_io_led_gs_update(const uint8_t *rgb) return; } -void swdc_io_led_set_leds(const uint8_t *rgb) +void swdc_io_led_set_leds(uint8_t board, const uint8_t *rgb) { #if 0 dprintf("SWDC LED: START: %02X\n", rgb[0]); diff --git a/swdcio/swdcio.h b/swdcio/swdcio.h index 6843634..9d069f3 100644 --- a/swdcio/swdcio.h +++ b/swdcio/swdcio.h @@ -123,7 +123,7 @@ HRESULT swdc_io_led_init(void); Minimum API version: 0x0101 */ -void swdc_io_led_set_fet_output(const uint8_t *rgb); +void swdc_io_led_set_fet_output(uint8_t board, const uint8_t *rgb); /* Update the RGB LEDs. rgb is a pointer to an array up to 32 * 4 = 128 bytes. @@ -140,7 +140,7 @@ void swdc_io_led_set_fet_output(const uint8_t *rgb); Minimum API version: 0x0101 */ -void swdc_io_led_gs_update(const uint8_t *rgb); +void swdc_io_led_gs_update(uint8_t board, const uint8_t *rgb); /* Update the cabinet button LEDs. rgb is a pointer to an array up to 6 bytes. @@ -156,7 +156,7 @@ void swdc_io_led_gs_update(const uint8_t *rgb); Minimum API version: 0x0101 */ -void swdc_io_led_set_leds(const uint8_t *rgb); +void swdc_io_led_set_leds(uint8_t board, const uint8_t *rgb); /* Initialize FFB emulation. This function will be called before any other swdc_io_ffb_*() function calls. diff --git a/tokyohook/config.c b/tokyohook/config.c index 304cbc2..3ab387a 100644 --- a/tokyohook/config.c +++ b/tokyohook/config.c @@ -40,7 +40,8 @@ void led15093_config_load(struct led15093_config *cfg, const wchar_t *filename) memset(cfg->boot_chip_number, ' ', sizeof(cfg->boot_chip_number)); cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename); - cfg->port_no = GetPrivateProfileIntW(L"led15093", L"portNo", 0, filename); + cfg->port_no[0] = GetPrivateProfileIntW(L"led15093", L"portNo1", 0, filename); + cfg->port_no[1] = GetPrivateProfileIntW(L"led15093", L"portNo2", 0, filename); cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaud", 0, filename); cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0x90, filename); cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xAED9, filename); diff --git a/tokyohook/dllmain.c b/tokyohook/dllmain.c index 19a1517..9c3a262 100644 --- a/tokyohook/dllmain.c +++ b/tokyohook/dllmain.c @@ -50,6 +50,16 @@ static DWORD CALLBACK tokyo_pre_startup(void) /* Initialize emulation hooks */ + struct dipsw_config new_dipsw_config[8] = { + {L"Delivery Server", L"Server", L"Client"}, + {L"Cabinet ID Setting", L"ON", L"OFF"}, + {L"Cabinet ID Setting", L"ON", L"OFF"}, + }; + + // Set the system dip switch configuration + memcpy(tokyo_hook_cfg.platform.system.dipsw_config, new_dipsw_config, + sizeof(new_dipsw_config)); + hr = platform_hook_init( &tokyo_hook_cfg.platform, "SDFV", @@ -60,14 +70,35 @@ static DWORD CALLBACK tokyo_pre_startup(void) goto fail; } + bool *dipsw = &tokyo_hook_cfg.platform.system.dipsw[0]; + unsigned int cabinet_id = 0; + + if (dipsw[0] == 1 && dipsw[1] == 0 && dipsw[2] == 0) { + cabinet_id = 1; // Server 1 + } else if (dipsw[0] == 0 && dipsw[1] == 1 && dipsw[2] == 0) { + cabinet_id = 2; // Client 2 + } else if (dipsw[0] == 0 && dipsw[1] == 0 && dipsw[2] == 1) { + cabinet_id = 3; // Client 3 + } else if (dipsw[0] == 0 && dipsw[1] == 1 && dipsw[2] == 1) { + cabinet_id = 4; // Client 4 + } else { + dprintf("Error: Invalid dip switch configuration!\n"); + } + + // Print the correct Cabinet ID if valid + if (cabinet_id > 0) { + dprintf("System: Cabinet ID %d\n", cabinet_id); + } + hr = tokyo_dll_init(&tokyo_hook_cfg.dll, tokyo_hook_mod); if (FAILED(hr)) { goto fail; } + unsigned int led_port_no[2] = {1, 0}; hr = led15093_hook_init(&tokyo_hook_cfg.led15093, - tokyo_dll.led_init, tokyo_dll.led_set_leds, 1, 1, 1, 2); + tokyo_dll.led_init, tokyo_dll.led_set_leds, led_port_no); if (FAILED(hr)) { return hr;