From bec007d52a49259acf3d74fdd36d52dd08f71f36 Mon Sep 17 00:00:00 2001 From: icex2 Date: Tue, 28 Nov 2023 15:31:03 +0100 Subject: [PATCH] fix(p3ioemu): Incorrect dispatching of unknown p3io commands Using ddrhook1, this caused DDR X to crash on startup when the P3io client sends the currently unknown command 2B. Handling it with the incorrect p3io command struct, any following reading attempts from the P3IO by the game fail. Handle the 2B case explicitly with a generic response that worked previously before the restructuring of the code. Apply the same to any further unknown commands with improved logging warning about this. --- src/main/p3io/cmd.h | 12 ++++++++++++ src/main/p3ioemu/emu.c | 32 +++++++++++++++++++++++++------- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/main/p3io/cmd.h b/src/main/p3io/cmd.h index 5359ec4..49b42cc 100644 --- a/src/main/p3io/cmd.h +++ b/src/main/p3io/cmd.h @@ -161,6 +161,11 @@ struct p3io_req_rs232_write { uint8_t bytes[128]; }; +struct p3io_req_unknown_generic { + struct p3io_hdr hdr; + uint8_t unknown; +}; + struct p3io_req_raw { uint8_t data[P3IO_MAX_MESSAGE_SIZE]; }; @@ -182,6 +187,7 @@ union p3io_req_any { struct p3io_req_rs232_open_close rs232_open_close; struct p3io_req_rs232_read rs232_read; struct p3io_req_rs232_write rs232_write; + struct p3io_req_unknown_generic unknown_generic; struct p3io_req_raw raw; }; @@ -266,6 +272,11 @@ struct p3io_resp_rs232_write { uint8_t nbytes; }; +struct p3io_resp_unknown_generic { + struct p3io_hdr hdr; + uint8_t unknown; +}; + struct p3io_resp_raw { uint8_t data[P3IO_MAX_MESSAGE_SIZE]; }; @@ -286,6 +297,7 @@ union p3io_resp_any { struct p3io_resp_rs232_open_close rs232_open_close; struct p3io_resp_rs232_read rs232_read; struct p3io_resp_rs232_write rs232_write; + struct p3io_resp_unknown_generic unknown_generic; struct p3io_resp_raw raw; }; diff --git a/src/main/p3ioemu/emu.c b/src/main/p3ioemu/emu.c index c72f9d8..dbf2c8a 100644 --- a/src/main/p3ioemu/emu.c +++ b/src/main/p3ioemu/emu.c @@ -49,6 +49,8 @@ static void p3io_cmd_get_video_freq( const struct p3io_req_get_video_freq *req, struct p3io_resp_get_video_freq *resp); static void +p3io_cmd_unknown_2b(const struct p3io_req_unknown_2b *req, struct p3io_resp_unknown_2b *resp); +static void p3io_cmd_init(const struct p3io_req_init *req, struct p3io_resp_init *resp); static void p3io_cmd_get_coinstock( const struct p3io_req_coin_stock *req, struct p3io_resp_coin_stock *resp); @@ -56,7 +58,7 @@ static void p3io_cmd_set_coin_counter( const struct p3io_req_set_coin_counter *req, struct p3io_resp_set_coin_counter *resp); static void -p3io_cmd_unknown(const union p3io_req_any *req, struct p3io_resp_raw *resp); +p3io_cmd_unknown(const struct p3io_req_unknown_generic *req, struct p3io_resp_unknown_generic *resp); void p3io_emu_init(const struct p3io_ops *ops, void *ctx) { @@ -268,6 +270,11 @@ static HRESULT p3io_cmd_dispatch(const union p3io_req_any *req) break; + case P3IO_CMD_UNKNOWN_2B: + p3io_cmd_unknown_2b(&req->unknown_2b, &resp.unknown_2b); + + break; + case P3IO_CMD_INIT: p3io_cmd_init(&req->init, &resp.init); @@ -301,7 +308,7 @@ static HRESULT p3io_cmd_dispatch(const union p3io_req_any *req) break; default: - p3io_cmd_unknown(req, &resp.raw); + p3io_cmd_unknown(&req->unknown_generic, &resp.unknown_generic); break; } @@ -511,6 +518,16 @@ static void p3io_cmd_get_video_freq( } } +static void +p3io_cmd_unknown_2b(const struct p3io_req_unknown_2b *req, struct p3io_resp_unknown_2b *resp) +{ + log_misc("Unknown 2b"); + + p3io_resp_hdr_init(&resp->hdr, sizeof(*resp), &req->hdr); + + resp->unknown = 0; +} + static void p3io_cmd_init(const struct p3io_req_init *req, struct p3io_resp_init *resp) { @@ -557,15 +574,16 @@ static void p3io_cmd_set_coin_counter( } static void -p3io_cmd_unknown(const union p3io_req_any *req, struct p3io_resp_raw *resp) +p3io_cmd_unknown(const struct p3io_req_unknown_generic *req, struct p3io_resp_unknown_generic *resp) { - log_warning("Unsupported P3IO command: %02x", req->hdr.cmd); + log_warning("Unsupported P3IO command, sending default response (might not work/crash though): %02x", + req->hdr.cmd); - p3io_resp_hdr_init( - (struct p3io_hdr *) &resp->data, sizeof(*resp), &req->hdr); + p3io_resp_hdr_init(&resp->hdr, sizeof(*resp), &req->hdr); // Not always applicable/correct as there are several commands not // responding with any data, but fine for the majority of (unsupported) // commands - resp->data[sizeof(struct p3io_hdr) + 0] = 0; + // Remark: This might also lead to unpredictable behaviour or crashes + resp->unknown = 0; }