maple: raise interrupt on vblank when maple bus is occupied

Raise a maple interrupt at the next vblank when the host occupies the
maple bus to read the lightgun position. Fixes RevolveR single shot
issue since the game is waiting for the interrupt.
Issue #1369
This commit is contained in:
Flyinghead 2024-01-28 15:21:40 +01:00
parent b2d96d77d7
commit ecce9157bd
4 changed files with 35 additions and 20 deletions

View File

@ -10,6 +10,7 @@
MapleInputState mapleInputState[4]; MapleInputState mapleInputState[4];
extern bool maple_ddt_pending_reset; extern bool maple_ddt_pending_reset;
extern std::vector<std::pair<u32, std::vector<u32>>> mapleDmaOut; extern std::vector<std::pair<u32, std::vector<u32>>> mapleDmaOut;
extern bool SDCKBOccupied;
void (*MapleConfigMap::UpdateVibration)(u32 port, float power, float inclination, u32 duration_ms); void (*MapleConfigMap::UpdateVibration)(u32 port, float power, float inclination, u32 duration_ms);
@ -414,6 +415,7 @@ void mcfg_DestroyDevices(bool full)
void mcfg_SerializeDevices(Serializer& ser) void mcfg_SerializeDevices(Serializer& ser)
{ {
ser << maple_ddt_pending_reset; ser << maple_ddt_pending_reset;
ser << SDCKBOccupied;
ser << (u32)mapleDmaOut.size(); ser << (u32)mapleDmaOut.size();
for (const auto& pair : mapleDmaOut) for (const auto& pair : mapleDmaOut)
{ {
@ -446,6 +448,8 @@ void mcfg_DeserializeDevices(Deserializer& deser)
deser.skip<bool>(); // EEPROM_loaded deser.skip<bool>(); // EEPROM_loaded
} }
deser >> maple_ddt_pending_reset; deser >> maple_ddt_pending_reset;
if (deser.version() >= Deserializer::V47)
deser >> SDCKBOccupied;
mapleDmaOut.clear(); mapleDmaOut.clear();
if (deser.version() >= Deserializer::V23) if (deser.version() >= Deserializer::V23)
{ {

View File

@ -32,6 +32,7 @@ int maple_schid;
static void maple_DoDma(); static void maple_DoDma();
static void maple_handle_reconnect(); static void maple_handle_reconnect();
static int maple_schd(int tag, int cycles, int jitter, void *arg);
//really hackish //really hackish
//misses delay , and stop/start implementation //misses delay , and stop/start implementation
@ -40,30 +41,39 @@ static void maple_handle_reconnect();
bool maple_ddt_pending_reset; bool maple_ddt_pending_reset;
// pending DMA xfers // pending DMA xfers
std::vector<std::pair<u32, std::vector<u32>>> mapleDmaOut; std::vector<std::pair<u32, std::vector<u32>>> mapleDmaOut;
bool SDCKBOccupied;
void maple_vblank() void maple_vblank()
{ {
if (SB_MDEN & 1) if (SB_MDEN & 1)
{ {
if (SB_MDTSEL == 1) if (SDCKBOccupied)
{ {
if (maple_ddt_pending_reset) maple_schd(0, 0, 0, nullptr);
{ SDCKBOccupied = false;
DEBUG_LOG(MAPLE, "DDT vblank ; reset pending");
}
else
{
DEBUG_LOG(MAPLE, "DDT vblank");
SB_MDST = 1;
maple_DoDma();
// if trigger reset is manual, mark it as pending
if ((SB_MSYS >> 12) & 1)
maple_ddt_pending_reset = true;
}
} }
else else
{ {
maple_ddt_pending_reset = false; if (SB_MDTSEL == 1)
{
if (maple_ddt_pending_reset)
{
DEBUG_LOG(MAPLE, "DDT vblank ; reset pending");
}
else
{
DEBUG_LOG(MAPLE, "DDT vblank");
SB_MDST = 1;
maple_DoDma();
// if trigger reset is manual, mark it as pending
if ((SB_MSYS >> 12) & 1)
maple_ddt_pending_reset = true;
}
}
else
{
maple_ddt_pending_reset = false;
}
} }
} }
if (settings.platform.isConsole()) if (settings.platform.isConsole())
@ -152,7 +162,6 @@ static void maple_DoDma()
const bool swap_msb = (SB_MMSEL == 0); const bool swap_msb = (SB_MMSEL == 0);
u32 xfer_count = 0; u32 xfer_count = 0;
bool last = false; bool last = false;
bool occupy = false;
while (!last) while (!last)
{ {
u32 header_1 = ReadMem32_nommu(addr); u32 header_1 = ReadMem32_nommu(addr);
@ -245,7 +254,7 @@ static void maple_DoDma()
{ {
u32 bus = (header_1 >> 16) & 3; u32 bus = (header_1 >> 16) & 3;
if (MapleDevices[bus][5]) { if (MapleDevices[bus][5]) {
occupy = MapleDevices[bus][5]->get_lightgun_pos(); SDCKBOccupied = SDCKBOccupied || MapleDevices[bus][5]->get_lightgun_pos();
xfer_count++; xfer_count++;
} }
addr += 1 * 4; addr += 1 * 4;
@ -253,6 +262,7 @@ static void maple_DoDma()
break; break;
case MP_SDCKBOccupyCancel: case MP_SDCKBOccupyCancel:
SDCKBOccupied = false;
addr += 1 * 4; addr += 1 * 4;
break; break;
@ -273,7 +283,7 @@ static void maple_DoDma()
// Maple bus max speed: 2 Mb/s, actual speed: 1 Mb/s // Maple bus max speed: 2 Mb/s, actual speed: 1 Mb/s
//printf("Maple XFER size %d bytes - %.2f ms\n", xfer_count, xfer_count * 1000.0f / (128 * 1024)); //printf("Maple XFER size %d bytes - %.2f ms\n", xfer_count, xfer_count * 1000.0f / (128 * 1024));
if (!occupy) if (!SDCKBOccupied)
sh4_sched_request(maple_schid, std::min((u64)xfer_count * (SH4_MAIN_CLOCK / (256 * 1024)), (u64)SH4_MAIN_CLOCK)); sh4_sched_request(maple_schid, std::min((u64)xfer_count * (SH4_MAIN_CLOCK / (256 * 1024)), (u64)SH4_MAIN_CLOCK));
} }

View File

@ -72,7 +72,8 @@ public:
V44, V44,
V45, V45,
V46, V46,
Current = V46, V47,
Current = V47,
Next = Current + 1, Next = Current + 1,
}; };

View File

@ -32,7 +32,7 @@ TEST_F(SerializeTest, SizeTest)
std::vector<char> data(30000000); std::vector<char> data(30000000);
Serializer ser(data.data(), data.size()); Serializer ser(data.data(), data.size());
dc_serialize(ser); dc_serialize(ser);
ASSERT_EQ(28191437u, ser.size()); ASSERT_EQ(28191438u, ser.size());
} }