diff --git a/Config/Games.xml b/Config/Games.xml index 264f94e1..4be8a2ef 100644 --- a/Config/Games.xml +++ b/Config/Games.xml @@ -1217,7 +1217,7 @@ Magical Truck Adventure - Japan + Export Sega 1998 @@ -1233,8 +1233,8 @@ - - + + @@ -1288,7 +1288,7 @@ --> Magical Truck Adventure - Japan + Export Sega 1998 @@ -1306,8 +1306,8 @@ - - + + diff --git a/Src/Model3/Model3.cpp b/Src/Model3/Model3.cpp index 4c1de836..a685f69d 100644 --- a/Src/Model3/Model3.cpp +++ b/Src/Model3/Model3.cpp @@ -978,9 +978,9 @@ UINT8 CModel3::Read8(UINT32 addr) switch (addr & 0xf) { case 0x0: // MIDI data port - return 0x00; // Something to do with region locked in magtruck (0=locked, 1=unlocked). /!\ no effect if rom patch is activated! + return SoundBoard.ReadMIDIPort(); case 0x4: // MIDI control port - return 0x83; // magtruck country check + return SoundBoard.CheckMIDIStatus(); default: return 0; } @@ -1428,7 +1428,7 @@ void CModel3::Write8(UINT32 addr, UINT8 data) else if ((addr & 0xF) == 4) // MIDI control port { midiCtrlPort = data; - if ((data & 0x20) == 0) + if ((data & 0x01) == 0) IRQ.Deassert(0x40); } break; @@ -2124,17 +2124,19 @@ void CModel3::RunMainBoardFrame(void) /* * Sound: * - * Bit 0x20 of the MIDI control port appears to enable periodic interrupts, - * which are used to send MIDI commands. Often games will write 0x27, send - * a series of commands, and write 0x06 to stop. Other games, like Star - * Wars Trilogy and Sega Rally 2, will enable interrupts at the beginning - * by writing 0x37 and will disable/enable interrupts to control command - * output. + * The PPC communicates with the soundboard via an Intel 8251 compatible + * USART device, which transmits/receives data to/from the master SCSP MIDI + * input/output lines. Setting bit 0 (0x01) when writing to the control + * port enables data transmission; when it is enabled, a sound IRQ (0x40) + * is triggered when the USART device is ready to transmit data. + * + * Most games disable sound IRQs once they have finished sending commands + * by writing 0x06 to the control port, clearing bit 0 to disable data + * transmission. Sega Rally 2 and Star Wars Trilogy instead disable sound + * IRQs by masking them via the IRQ controller. */ //printf("\t-- BEGIN (Ctrl=%02X, IRQEn=%02X, IRQPend=%02X) --\n", midiCtrlPort, IRQ.ReadIRQEnable()&0x40, IRQ.ReadIRQState()); - int irqCount = 0; - while ((midiCtrlPort & 0x20)) - //while (midiCtrlPort == 0x27) // 27 triggers IRQ sequence, 06 stops it + while (midiCtrlPort & 0x01 && SoundBoard.CheckMIDIStatus() & 0x01) // don't send any more commands if the FIFO buffer is full { // Don't waste time firing MIDI interrupts if game has disabled them if ((IRQ.ReadIRQEnable() & 0x40) == 0) @@ -2144,12 +2146,6 @@ void CModel3::RunMainBoardFrame(void) IRQ.Assert(0x40); ppc_execute(1000); // give PowerPC time to acknowledge IR dispCycles -= 1000; - - ++irqCount; - if (irqCount > 128) - { - break; - } } IRQ.Assert(0x0D); diff --git a/Src/Model3/SoundBoard.cpp b/Src/Model3/SoundBoard.cpp index 1bf712cc..6f77f9c9 100644 --- a/Src/Model3/SoundBoard.cpp +++ b/Src/Model3/SoundBoard.cpp @@ -330,6 +330,12 @@ int SCSP68KRunCallback(int numCycles) Sound Board Interface ******************************************************************************/ +UINT8 CSoundBoard::ReadMIDIPort(void) +{ + UINT8 result = SCSP_MidiOutR(); + return result; +} + void CSoundBoard::WriteMIDIPort(UINT8 data) { SCSP_MidiIn(data); @@ -337,6 +343,17 @@ void CSoundBoard::WriteMIDIPort(UINT8 data) DSB->SendCommand(data); } +UINT8 CSoundBoard::CheckMIDIStatus(void) +{ + UINT8 status = 0x80; + if (SCSP_MidiInFill() < 256) // MIDI input buffer not full + status |= 1; + if (SCSP_MidiOutFill() > 0) // MIDI output buffer not empty + status |= 2; + + return status; +} + #ifdef SUPERMODEL_LOG_AUDIO static INT16 ClampINT16(float x) { diff --git a/Src/Model3/SoundBoard.h b/Src/Model3/SoundBoard.h index 6d79431c..27eff050 100644 --- a/Src/Model3/SoundBoard.h +++ b/Src/Model3/SoundBoard.h @@ -74,6 +74,16 @@ class CSoundBoard: public IBus void Write16(UINT32 addr, UINT16 data); void Write32(UINT32 addr, UINT32 data); + /* + * ReadMIDIPort(void): + * + * Reads from the sound board MIDI port. + * + * Returns: + * Data read from MIDI port. + */ + UINT8 ReadMIDIPort(void); + /* * WriteMIDIPort(data): * @@ -84,6 +94,16 @@ class CSoundBoard: public IBus */ void WriteMIDIPort(UINT8 data); + /* + * CheckMIDIStatus(void): + * + * Checks status of MIDI input/output buffers. + * + * Returns: + * Status of MIDI input/output buffers. + */ + UINT8 CheckMIDIStatus(void); + /* * SaveState(SaveState): * diff --git a/Src/Sound/SCSP.cpp b/Src/Sound/SCSP.cpp index 03834d5b..3173ae16 100644 --- a/Src/Sound/SCSP.cpp +++ b/Src/Sound/SCSP.cpp @@ -1757,8 +1757,8 @@ void SCSP_MidiOutW(BYTE val) //printf("68K: MIDI out\n"); //DebugLog("Midi Out Buffer push %02X",val); - MidiStack[MidiOutW++]=val; - MidiOutW&=31; + MidiOutStack[MidiOutW++]=val; + MidiOutW &= 3; ++MidiOutFill; if (s_multiThreaded) @@ -1779,9 +1779,9 @@ unsigned char SCSP_MidiOutR() if (s_multiThreaded) MIDILock->Lock(); - val=MidiStack[MidiOutR++]; + val=MidiOutStack[MidiOutR++]; //DebugLog("Midi Out Buffer pop %02X",val); - MidiOutR&=31; + MidiOutR&=3; --MidiOutFill; if (s_multiThreaded)