naomi: emulate midi ffb drive board response

needed for driving simulator
This commit is contained in:
Flyinghead 2022-04-27 14:28:58 +02:00
parent 15ca7e82bd
commit fc9e1e401b
9 changed files with 99 additions and 32 deletions

View File

@ -18,6 +18,7 @@ InterruptInfo* MCIRE;
InterruptInfo* SCIEB;
InterruptInfo* SCIPD;
InterruptInfo* SCIRE;
std::deque<u8> 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()
{

View File

@ -1,5 +1,6 @@
#pragma once
#include "types.h"
#include <deque>
#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<u8> midiSendBuffer;
extern CommonData_struct* CommonData;
extern DSPData_struct* DSPData;

View File

@ -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);

View File

@ -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);
}
}
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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,
};

View File

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