diff --git a/core/hw/aica/aica.cpp b/core/hw/aica/aica.cpp index 1e5d13cab..b8066f364 100644 --- a/core/hw/aica/aica.cpp +++ b/core/hw/aica/aica.cpp @@ -18,6 +18,7 @@ InterruptInfo* MCIRE; InterruptInfo* SCIEB; InterruptInfo* SCIPD; InterruptInfo* SCIRE; +std::deque midiSendBuffer; //Interrupts //arm side @@ -235,6 +236,15 @@ template void WriteAicaReg<>(u32 reg, u8 data); template void WriteAicaReg<>(u32 reg, u16 data); template void WriteAicaReg<>(u32 reg, u32 data); +void aica_midiSend(u8 data) +{ + midiSendBuffer.push_back(data); + SCIPD->MIDI_IN = 1; + update_arm_interrupts(); + MCIPD->MIDI_IN = 1; + UpdateSh4Ints(); +} + //misc :p s32 libAICA_Init() { diff --git a/core/hw/aica/aica.h b/core/hw/aica/aica.h index e08de778a..a74cd8c98 100644 --- a/core/hw/aica/aica.h +++ b/core/hw/aica/aica.h @@ -1,5 +1,6 @@ #pragma once #include "types.h" +#include #define SCIEB_addr 0x289C #define SCIPD_addr (0x289C+4) @@ -299,6 +300,7 @@ extern InterruptInfo* MCIRE; extern InterruptInfo* SCIEB; extern InterruptInfo* SCIPD; extern InterruptInfo* SCIRE; +extern std::deque midiSendBuffer; extern CommonData_struct* CommonData; extern DSPData_struct* DSPData; diff --git a/core/hw/aica/aica_if.h b/core/hw/aica/aica_if.h index 37821ef46..5c59a709d 100644 --- a/core/hw/aica/aica_if.h +++ b/core/hw/aica/aica_if.h @@ -14,6 +14,7 @@ void aica_Init(); void aica_Reset(bool hard); void aica_Term(); void aica_setMidiReceiver(void (*handler)(u8 data)); +void aica_midiSend(u8 data); void aica_sb_Init(); void aica_sb_Reset(bool hard); diff --git a/core/hw/aica/sgc_if.cpp b/core/hw/aica/sgc_if.cpp index 61d38cc29..2bd3d4787 100755 --- a/core/hw/aica/sgc_if.cpp +++ b/core/hw/aica/sgc_if.cpp @@ -1338,10 +1338,23 @@ void ReadCommonReg(u32 reg,bool byte) { case 0x2808: case 0x2809: - CommonData->MIEMP = 1; - CommonData->MOEMP = 1; + if (!midiSendBuffer.empty()) + { + if (!byte || reg == 0x2808) + { + CommonData->MIBUF = midiSendBuffer.front(); + midiSendBuffer.pop_front(); + } + CommonData->MIEMP = 0; + CommonData->MIFUL = 1; + } + else + { + CommonData->MIEMP = 1; + CommonData->MIFUL = 0; + } CommonData->MIOVF = 0; - CommonData->MIFUL = 0; + CommonData->MOEMP = 1; CommonData->MOFUL = 0; break; case 0x2810: // EG, SGC, LP @@ -1627,6 +1640,9 @@ void channel_serialize(Serializer& ser) ser << beepCounter; ser << cdda_sector; ser << cdda_index; + ser << (u32)midiSendBuffer.size(); + for (u8 b : midiSendBuffer) + ser << b; } void channel_deserialize(Deserializer& deser) @@ -1761,4 +1777,16 @@ void channel_deserialize(Deserializer& deser) deser.skip(4 * 64); // mxlr deser.skip(4); // samples_gen } + midiSendBuffer.clear(); + if (deser.version() >= Deserializer::V28) + { + u32 size; + deser >> size; + for (u32 i = 0; i < size; i++) + { + u8 b; + deser >> b; + midiSendBuffer.push_back(b); + } + } } diff --git a/core/hw/naomi/naomi.cpp b/core/hw/naomi/naomi.cpp index 00630562e..c923e3724 100644 --- a/core/hw/naomi/naomi.cpp +++ b/core/hw/naomi/naomi.cpp @@ -748,13 +748,34 @@ void naomi_Deserialize(Deserializer& deser) } } -static void initFFBMidiReceiver(u8 data) +static void midiSend(u8 b1, u8 b2, u8 b3) { + aica_midiSend(b1); + aica_midiSend(b2); + aica_midiSend(b3); + aica_midiSend((b1 ^ b2 ^ b3) & 0x7f); +} + +static void forceFeedbackMidiReceiver(u8 data) +{ + static float position = 8192.f; + static float torque; + position = std::min(16383.f, std::max(0.f, position + torque)); if (data & 0x80) midiTxBufIndex = 0; midiTxBuf[midiTxBufIndex] = data; if (midiTxBufIndex == 3 && ((midiTxBuf[0] ^ midiTxBuf[1] ^ midiTxBuf[2]) & 0x7f) == midiTxBuf[3]) { + if (midiTxBuf[0] == 0x84) + torque = ((midiTxBuf[1] << 7) | midiTxBuf[2]) - 0x80; + else if (midiTxBuf[0] == 0xff) + { + torque = 0; + position = 8192; + } + // required: b1 & 0x1f == 0x10 && b1 & 0x40 == 0 + midiSend(0x90, ((int)position >> 7) & 0x7f, (int)position & 0x7f); + // decoding from FFB Arcade Plugin (by Boomslangnz) // https://github.com/Boomslangnz/FFBArcadePlugin/blob/master/Game%20Files/Demul.cpp if (midiTxBuf[0] == 0x85 && midiTxBuf[1] == 0x3f) @@ -763,7 +784,7 @@ static void initFFBMidiReceiver(u8 data) midiTxBufIndex = (midiTxBufIndex + 1) % ARRAY_SIZE(midiTxBuf); } -void initdFFBInit() +void initMidiForceFeedback() { - aica_setMidiReceiver(initFFBMidiReceiver); + aica_setMidiReceiver(forceFeedbackMidiReceiver); } diff --git a/core/hw/naomi/naomi.h b/core/hw/naomi/naomi.h index 60ea8ded4..3c3b3f0c4 100644 --- a/core/hw/naomi/naomi.h +++ b/core/hw/naomi/naomi.h @@ -26,7 +26,7 @@ extern u32 reg_dimm_parameterl; extern u32 reg_dimm_parameterh; extern u32 reg_dimm_status; -void initdFFBInit(); +void initMidiForceFeedback(); u32 libExtDevice_ReadMem_A0_006(u32 addr, u32 size); void libExtDevice_WriteMem_A0_006(u32 addr, u32 data, u32 size); diff --git a/core/hw/naomi/naomi_cart.cpp b/core/hw/naomi/naomi_cart.cpp index 6007d592f..2600e5559 100644 --- a/core/hw/naomi/naomi_cart.cpp +++ b/core/hw/naomi/naomi_cart.cpp @@ -587,13 +587,17 @@ void naomi_cart_LoadRom(const char* file, LoadProgress *progress) || gameId == "INITIAL D CYCRAFT") { card_reader::initialDCardReader.init(); - initdFFBInit(); + initMidiForceFeedback(); } else if (gameId == "MAXIMUM SPEED") { maxSpeedNetPipe.init(); configure_maxspeed_flash(config::NetworkEnable, config::ActAsServer); } + else if (gameId == "SAMPLE GAME MAX LONG NAME-") // Driving Simulator + { + initMidiForceFeedback(); + } } else NOTICE_LOG(NAOMI, "NAOMI GAME ID [%s]", naomi_game_id); diff --git a/core/serialize.h b/core/serialize.h index 0ca8c552d..6df6e19fa 100644 --- a/core/serialize.h +++ b/core/serialize.h @@ -41,29 +41,30 @@ public: VLAST_LIBRETRO = V13_LIBRETRO, V5 = 800, - V6 = 801, - V7 = 802, - V8 = 803, - V9 = 804, - V10 = 805, - V11 = 806, - V12 = 807, - V13 = 808, - V14 = 809, - V15 = 810, - V16 = 811, - V17 = 812, - V18 = 813, - V19 = 814, - V20 = 815, - V21 = 816, - V22 = 817, - V23 = 818, - V24 = 819, - V25 = 820, - V26 = 821, - V27 = 822, - Current = V27, + V6, + V7, + V8, + V9, + V10, + V11, + V12, + V13, + V14, + V15, + V16, + V17, + V18, + V19, + V20, + V21, + V22, + V23, + V24, + V25, + V26, + V27, + V28, + Current = V28, Next = Current + 1, }; diff --git a/tests/src/serialize_test.cpp b/tests/src/serialize_test.cpp index 833fe2690..9c5ebb460 100644 --- a/tests/src/serialize_test.cpp +++ b/tests/src/serialize_test.cpp @@ -31,7 +31,7 @@ TEST_F(SerializeTest, SizeTest) std::vector data(30000000); Serializer ser(data.data(), data.size()); dc_serialize(ser); - ASSERT_EQ(28191595u, ser.size()); + ASSERT_EQ(28191599u, ser.size()); }