USIO: Support up to 4 players for Tekken Tag Tournament 2 Pair Play mode

This commit is contained in:
brian218 2023-09-06 23:10:30 +08:00 committed by Megamouse
parent 52495c17d6
commit 009d8e13da
3 changed files with 62 additions and 46 deletions

View File

@ -186,7 +186,7 @@ void usb_device_usio::translate_input_taiko()
std::lock_guard lock(pad::g_pad_mutex);
const auto handler = pad::get_current_handler();
std::vector<u8> input_buf(96);
std::vector<u8> input_buf(0x60);
constexpr le_t<u16> c_hit = 0x1800;
le_t<u16> digital_input = 0;
@ -204,6 +204,7 @@ void usb_device_usio::translate_input_taiko()
}
const usz offset = player * 8ULL;
auto& status = m_io_status[0];
const auto& cfg = ::at32(g_cfg_usio.players, pad_number);
cfg->handle_input(pad, false, [&](usio_btn btn, u16 /*value*/, bool pressed)
@ -212,15 +213,15 @@ void usb_device_usio::translate_input_taiko()
{
case usio_btn::test:
if (player != 0) break;
if (pressed && !test_key_pressed) // Solve the need to hold the Test key
test_on = !test_on;
test_key_pressed = pressed;
if (pressed && !status.test_key_pressed) // Solve the need to hold the Test key
status.test_on = !status.test_on;
status.test_key_pressed = pressed;
break;
case usio_btn::coin:
if (player != 0) break;
if (pressed && !coin_key_pressed) // Ensure only one coin is inserted each time the Coin key is pressed
coin_counter++;
coin_key_pressed = pressed;
if (pressed && !status.coin_key_pressed) // Ensure only one coin is inserted each time the Coin key is pressed
status.coin_counter++;
status.coin_key_pressed = pressed;
break;
case usio_btn::service:
if (player == 0 && pressed)
@ -258,14 +259,16 @@ void usb_device_usio::translate_input_taiko()
break;
}
});
if (player == 0 && status.test_on)
digital_input |= 0x80;
};
for (usz i = 0; i < g_cfg_usio.players.size(); i++)
translate_from_pad(i, i);
digital_input |= test_on ? 0x80 : 0x00;
std::memcpy(input_buf.data(), &digital_input, sizeof(u16));
std::memcpy(input_buf.data() + 16, &coin_counter, sizeof(u16));
std::memcpy(input_buf.data() + 16, &m_io_status[0].coin_counter, sizeof(u16));
response = std::move(input_buf);
}
@ -275,8 +278,8 @@ void usb_device_usio::translate_input_tekken()
std::lock_guard lock(pad::g_pad_mutex);
const auto handler = pad::get_current_handler();
std::vector<u8> input_buf(256);
le_t<u64> digital_input = 0;
std::vector<u8> input_buf(0x180);
le_t<u64> digital_input[2]{};
le_t<u16> digital_input_lm = 0;
auto translate_from_pad = [&](usz pad_number, usz player)
@ -292,7 +295,9 @@ void usb_device_usio::translate_input_tekken()
return;
}
const usz shift = player * 24ULL;
const usz shift = (player % 2) * 24ULL;
auto& status = m_io_status[player / 2];
auto& input = digital_input[player / 2];
const auto& cfg = ::at32(g_cfg_usio.players, pad_number);
cfg->handle_input(pad, false, [&](usio_btn btn, u16 /*value*/, bool pressed)
@ -300,27 +305,27 @@ void usb_device_usio::translate_input_tekken()
switch (btn)
{
case usio_btn::test:
if (player != 0)
if (player % 2 != 0)
break;
if (pressed && !test_key_pressed) // Solve the need to hold the Test button
test_on = !test_on;
test_key_pressed = pressed;
if (pressed && !status.test_key_pressed) // Solve the need to hold the Test button
status.test_on = !status.test_on;
status.test_key_pressed = pressed;
break;
case usio_btn::coin:
if (player != 0)
if (player % 2 != 0)
break;
if (pressed && !coin_key_pressed) // Ensure only one coin is inserted each time the Coin button is pressed
coin_counter++;
coin_key_pressed = pressed;
if (pressed && !status.coin_key_pressed) // Ensure only one coin is inserted each time the Coin button is pressed
status.coin_counter++;
status.coin_key_pressed = pressed;
break;
case usio_btn::service:
if (player == 0 && pressed)
digital_input |= 0x4000;
if (player % 2 == 0 && pressed)
input |= 0x4000;
break;
case usio_btn::enter:
if (pressed)
{
digital_input |= 0x800000ULL << shift;
input |= 0x800000ULL << shift;
if (player == 0)
digital_input_lm |= 0x800;
}
@ -328,7 +333,7 @@ void usb_device_usio::translate_input_tekken()
case usio_btn::up:
if (pressed)
{
digital_input |= 0x200000ULL << shift;
input |= 0x200000ULL << shift;
if (player == 0)
digital_input_lm |= 0x200;
}
@ -336,7 +341,7 @@ void usb_device_usio::translate_input_tekken()
case usio_btn::down:
if (pressed)
{
digital_input |= 0x100000ULL << shift;
input |= 0x100000ULL << shift;
if (player == 0)
digital_input_lm |= 0x400;
}
@ -344,7 +349,7 @@ void usb_device_usio::translate_input_tekken()
case usio_btn::left:
if (pressed)
{
digital_input |= 0x80000ULL << shift;
input |= 0x80000ULL << shift;
if (player == 0)
digital_input_lm |= 0x2000;
}
@ -352,7 +357,7 @@ void usb_device_usio::translate_input_tekken()
case usio_btn::right:
if (pressed)
{
digital_input |= 0x40000ULL << shift;
input |= 0x40000ULL << shift;
if (player == 0)
digital_input_lm |= 0x4000;
}
@ -360,47 +365,52 @@ void usb_device_usio::translate_input_tekken()
case usio_btn::tekken_button1:
if (pressed)
{
digital_input |= 0x20000ULL << shift;
input |= 0x20000ULL << shift;
if (player == 0)
digital_input_lm |= 0x100;
}
break;
case usio_btn::tekken_button2:
if (pressed)
digital_input |= 0x10000ULL << shift;
input |= 0x10000ULL << shift;
break;
case usio_btn::tekken_button3:
if (pressed)
digital_input |= 0x40000000ULL << shift;
input |= 0x40000000ULL << shift;
break;
case usio_btn::tekken_button4:
if (pressed)
digital_input |= 0x20000000ULL << shift;
input |= 0x20000000ULL << shift;
break;
case usio_btn::tekken_button5:
if (pressed)
digital_input |= 0x80000000ULL << shift;
input |= 0x80000000ULL << shift;
break;
default:
break;
}
});
if (player % 2 == 0 && status.test_on)
{
input |= 0x80;
if (player == 0)
digital_input_lm |= 0x1000;
}
};
for (usz i = 0; i < g_cfg_usio.players.size(); i++)
translate_from_pad(i, i);
if (test_on)
for (usz i = 0; i < 2; i++)
{
digital_input |= 0x80;
digital_input_lm |= 0x1000;
std::memcpy(input_buf.data() - i * 0x80 + 0x100, &digital_input[i], sizeof(u64));
std::memcpy(input_buf.data() - i * 0x80 + 0x100 + 0x10, &m_io_status[i].coin_counter, sizeof(u16));
}
std::memcpy(input_buf.data() + 128, &digital_input, sizeof(u64));
std::memcpy(input_buf.data() + 128 + 16, &coin_counter, sizeof(u16));
std::memcpy(input_buf.data(), &digital_input_lm, sizeof(u16));
input_buf[2] = 0b00010000; // DIP Switches, 8 in total
input_buf[2] = 0b00010000; // DIP switches, 8 in total
response = std::move(input_buf);
}
@ -489,7 +499,7 @@ void usb_device_usio::usio_read(u8 channel, u16 reg, u16 size)
// Get Buffer, rarely gives a reply on real HW
// First U16 seems to be a timestamp of sort
// Purpose seems related to connectivity check
response = {0x7E, 0xE4, 0x00, 0x00, 0x74, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
response = {0x7E, 0xE4, 0x00, 0x00, 0x74, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
break;
}
case 0x0080:
@ -522,7 +532,7 @@ void usb_device_usio::usio_read(u8 channel, u16 reg, u16 size)
// Seems to contain a few extra bytes of info in addition to the firmware string
// Firmware
// "NBGI.;USIO01;Ver1.00;JPN,Multipurpose with PPG."
constexpr std::array<u8, 0x100> info {0x4E, 0x42, 0x47, 0x49, 0x2E, 0x3B, 0x55, 0x53, 0x49, 0x4F, 0x30, 0x31, 0x3B, 0x56, 0x65, 0x72, 0x31, 0x2E, 0x30, 0x30, 0x3B, 0x4A, 0x50, 0x4E, 0x2C, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x70, 0x75, 0x72, 0x70, 0x6F, 0x73, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x50, 0x50, 0x47, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x42, 0x47, 0x49, 0x2E, 0x3B, 0x55, 0x53, 0x49, 0x4F, 0x30, 0x31, 0x3B, 0x56, 0x65, 0x72, 0x31, 0x2E, 0x30, 0x30, 0x3B, 0x4A, 0x50, 0x4E, 0x2C, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x70, 0x75, 0x72, 0x70, 0x6F, 0x73, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x50, 0x50, 0x47, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x13, 0x00, 0x30, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x75, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
constexpr std::array<u8, 0x180> info {0x4E, 0x42, 0x47, 0x49, 0x2E, 0x3B, 0x55, 0x53, 0x49, 0x4F, 0x30, 0x31, 0x3B, 0x56, 0x65, 0x72, 0x31, 0x2E, 0x30, 0x30, 0x3B, 0x4A, 0x50, 0x4E, 0x2C, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x70, 0x75, 0x72, 0x70, 0x6F, 0x73, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x50, 0x50, 0x47, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x42, 0x47, 0x49, 0x31, 0x3B, 0x55, 0x53, 0x49, 0x4F, 0x30, 0x31, 0x3B, 0x56, 0x65, 0x72, 0x31, 0x2E, 0x30, 0x30, 0x3B, 0x4A, 0x50, 0x4E, 0x2C, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x70, 0x75, 0x72, 0x70, 0x6F, 0x73, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x50, 0x50, 0x47, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x13, 0x00, 0x30, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x75, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x42, 0x47, 0x49, 0x32, 0x3B, 0x55, 0x53, 0x49, 0x4F, 0x30, 0x31, 0x3B, 0x56, 0x65, 0x72, 0x31, 0x2E, 0x30, 0x30, 0x3B, 0x4A, 0x50, 0x4E, 0x2C, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x70, 0x75, 0x72, 0x70, 0x6F, 0x73, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x50, 0x50, 0x47, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x13, 0x00, 0x30, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x75, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
response = {info.begin() + (reg - 0x1800), info.end()};
break;
}

View File

@ -21,11 +21,17 @@ private:
void usio_read(u8 channel, u16 reg, u16 size);
private:
bool test_on = false;
bool test_key_pressed = false;
bool coin_key_pressed = false;
bool is_used = false;
le_t<u16> coin_counter = 0;
const std::string usio_backup_path = rpcs3::utils::get_hdd1_dir() + "/caches/usiobackup.bin";
std::vector<u8> response;
struct io_status
{
bool test_on = false;
bool test_key_pressed = false;
bool coin_key_pressed = false;
le_t<u16> coin_counter = 0;
};
std::array<io_status, 2> m_io_status;
};

View File

@ -50,9 +50,9 @@ struct cfg_usio final : public emulated_pad_config<usio_btn>
cfg_pad_btn<usio_btn> tekken_button5{this, "Tekken Button 5", usio_btn::tekken_button5, pad_button::R1};
};
struct cfg_usios final : public emulated_pads_config<cfg_usio, 2>
struct cfg_usios final : public emulated_pads_config<cfg_usio, 4>
{
cfg_usios() : emulated_pads_config<cfg_usio, 2>("usio") {};
cfg_usios() : emulated_pads_config<cfg_usio, 4>("usio") {};
};
extern cfg_usios g_cfg_usio;