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)