diff --git a/Src/Model3/SoundBoard.cpp b/Src/Model3/SoundBoard.cpp
index 1490e4a..a674cb1 100644
--- a/Src/Model3/SoundBoard.cpp
+++ b/Src/Model3/SoundBoard.cpp
@@ -1,7 +1,7 @@
/**
** Supermodel
** A Sega Model 3 Arcade Emulator.
- ** Copyright 2011 Bart Trzynadlowski
+ ** Copyright 2011 Bart Trzynadlowski, Nik Henson
**
** This file is part of Supermodel.
**
@@ -500,7 +500,8 @@ bool CSoundBoard::Init(const UINT8 *soundROMPtr, const UINT8 *sampleROMPtr)
// Initialize SCSPs
SCSP_SetBuffers(audioL, audioR, 44100/60);
SCSP_SetCB(SCSP68KRunCallback, SCSP68KIRQCallback);
- SCSP_Init(2);
+ if (OKAY != SCSP_Init(2))
+ return FAIL;
SCSP_SetRAM(0, ram1);
SCSP_SetRAM(1, ram2);
diff --git a/Src/Model3/SoundBoard.h b/Src/Model3/SoundBoard.h
index 88bea14..9b9df55 100644
--- a/Src/Model3/SoundBoard.h
+++ b/Src/Model3/SoundBoard.h
@@ -31,6 +31,7 @@
#include "Types.h"
#include "CPU/Bus.h"
#include "Model3/DSB.h"
+#include "OSD/Thread.h"
/*
* CSoundBoardConfig:
diff --git a/Src/OSD/SDL/Thread.cpp b/Src/OSD/SDL/Thread.cpp
index fa3e776..7a43e01 100755
--- a/Src/OSD/SDL/Thread.cpp
+++ b/Src/OSD/SDL/Thread.cpp
@@ -1,10 +1,37 @@
+/**
+ ** Supermodel
+ ** A Sega Model 3 Arcade Emulator.
+ ** Copyright 2011 Bart Trzynadlowski, Nik Henson
+ **
+ ** This file is part of Supermodel.
+ **
+ ** Supermodel is free software: you can redistribute it and/or modify it under
+ ** the terms of the GNU General Public License as published by the Free
+ ** Software Foundation, either version 3 of the License, or (at your option)
+ ** any later version.
+ **
+ ** Supermodel is distributed in the hope that it will be useful, but WITHOUT
+ ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ ** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ ** more details.
+ **
+ ** You should have received a copy of the GNU General Public License along
+ ** with Supermodel. If not, see .
+ **/
+
+/*
+ * Thread.cpp
+ *
+ * SDL-based implementation of threading primitives.
+ */
+
#include "Supermodel.h"
-
+
#ifdef SUPERMODEL_OSX
-#include
+#include
#include
#else
-#include
+#include
#include
#endif
diff --git a/Src/OSD/Thread.h b/Src/OSD/Thread.h
index 0821043..a8900d4 100755
--- a/Src/OSD/Thread.h
+++ b/Src/OSD/Thread.h
@@ -1,3 +1,30 @@
+/**
+ ** Supermodel
+ ** A Sega Model 3 Arcade Emulator.
+ ** Copyright 2011 Bart Trzynadlowski, Nik Henson
+ **
+ ** This file is part of Supermodel.
+ **
+ ** Supermodel is free software: you can redistribute it and/or modify it under
+ ** the terms of the GNU General Public License as published by the Free
+ ** Software Foundation, either version 3 of the License, or (at your option)
+ ** any later version.
+ **
+ ** Supermodel is distributed in the hope that it will be useful, but WITHOUT
+ ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ ** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ ** more details.
+ **
+ ** You should have received a copy of the GNU General Public License along
+ ** with Supermodel. If not, see .
+ **/
+
+/*
+ * Thread.h
+ *
+ * Header file for threading primitives.
+ */
+
#ifndef INCLUDED_THREADS_H
#define INCLUDED_THREADS_H
@@ -7,10 +34,10 @@ class CCondVar;
typedef int (*ThreadStart)(void *startParam);
-/*
- * CThread
- *
- * Class that represents an O/S thread.
+/*
+ * CThread
+ *
+ * Class that represents an O/S thread.
*/
class CThread
{
@@ -122,7 +149,7 @@ public:
};
/*
- * CSemaphore
+ * CCondVar
*
* Class that represents a condition variable.
*/
diff --git a/Src/Sound/SCSP.cpp b/Src/Sound/SCSP.cpp
index 58a67b6..01cb3ca 100644
--- a/Src/Sound/SCSP.cpp
+++ b/Src/Sound/SCSP.cpp
@@ -1,7 +1,7 @@
/**
** Supermodel
** A Sega Model 3 Arcade Emulator.
- ** Copyright 2011 Bart Trzynadlowski
+ ** Copyright 2011 Bart Trzynadlowski, Nik Henson
**
** This file is part of Supermodel.
**
@@ -116,6 +116,7 @@ unsigned int RevR,RevW;
#define DWORD UINT32
#endif
+static CMutex *MIDILock; // for safe access to the MIDI FIFOs
static int (*Run68kCB)(int cycles);
static void (*Int68kCB)(int irq);
static void (*RetIntCB)();
@@ -332,14 +333,31 @@ void CheckPendingIRQ()
return;
}
*/
+
+ /*
+ * MIDI FIFO critical section
+ *
+ * NOTE: I don't think a mutex is really needed here, so I've disabled
+ * this critical section.
+ */
+ //if (g_Config.multiThreaded)
+ // MIDILock->Lock();
+
if(MidiW!=MidiR)
{
+ //if (g_Config.multiThreaded)
+ // MIDILock->Unlock();
+
//SCSP.data[0x20/2]|=0x8; //Hold midi line while there are commands pending
Int68kCB(IrqMidi);
//printf("68K: MIDI IRQ\n");
//ErrorLogMessage("Midi");
return;
}
+
+ //if (g_Config.multiThreaded)
+ // MIDILock->Unlock();
+
if(!pend)
return;
if(pend&0x40)
@@ -535,7 +553,7 @@ void SCSP_StopSlot(_SLOT *slot,int keyoff)
#define log2(n) (log((float) n)/log((float) 2))
-void SCSP_Init(int n)
+bool SCSP_Init(int n)
{
if(n==2)
{
@@ -712,10 +730,30 @@ void SCSP_Init(int n)
#endif
LFO_Init();
+ buffertmpl = NULL;
+ buffertmpr = NULL;
buffertmpl=(signed int*) malloc(44100*sizeof(signed int));
+ if (NULL == buffertmpl)
+ return ErrorLog("Insufficient memory for internal SCSP buffers.");
buffertmpr=(signed int*) malloc(44100*sizeof(signed int));
+ if (NULL == buffertmpl)
+ {
+ free(buffertmpl);
+ return ErrorLog("Insufficient memory for internal SCSP buffers.");
+ }
memset(buffertmpl,0,44100*sizeof(signed int));
memset(buffertmpr,0,44100*sizeof(signed int));
+
+ // MIDI FIFO mutex
+ MIDILock = CThread::CreateMutex();
+ if (NULL == MIDILock)
+ {
+ free(buffertmpl);
+ free(buffertmpr);
+ return ErrorLog("Unable to create MIDI mutex!");
+ }
+
+ return OKAY;
}
void SCSP_SetRAM(int n,unsigned char *r)
@@ -887,6 +925,13 @@ void SCSP_UpdateRegR(int reg)
{
unsigned short v=SCSP->data[0x5/2];
v&=0xff00;
+
+ /*
+ * MIDI FIFO critical section!
+ */
+ if (g_Config.multiThreaded)
+ MIDILock->Lock();
+
v|=MidiStack[MidiR];
//printf("read MIDI\n");
if(MidiR!=MidiW)
@@ -894,11 +939,13 @@ void SCSP_UpdateRegR(int reg)
++MidiR;
MidiR&=MIDI_STACK_SIZE_MASK;
//Int68kCB(IrqMidi);
-
}
MidiInFill--;
SCSP->data[0x5/2]=v;
+
+ if (g_Config.multiThreaded)
+ MIDILock->Unlock();
}
break;
case 8:
@@ -1870,46 +1917,100 @@ void SCSP_SetCB(int (*Run68k)(int cycles),void (*Int68k)(int irq))
void SCSP_MidiIn(BYTE val)
{
+ /*
+ * MIDI FIFO critical section
+ */
+ if (g_Config.multiThreaded)
+ MIDILock->Lock();
+
//DebugLog("Midi Buffer push %02X",val);
-
MidiStack[MidiW++]=val;
MidiW&=MIDI_STACK_SIZE_MASK;
MidiInFill++;
//Int68kCB(IrqMidi);
// SCSP.data[0x20/2]|=0x8;
+
+ if (g_Config.multiThreaded)
+ MIDILock->Unlock();
}
void SCSP_MidiOutW(BYTE val)
{
+ /*
+ * MIDI FIFO critical section
+ */
+ if (g_Config.multiThreaded)
+ MIDILock->Lock();
+
//printf("68K: MIDI out\n");
//DebugLog("Midi Out Buffer push %02X",val);
MidiStack[MidiOutW++]=val;
MidiOutW&=7;
++MidiOutFill;
+
+ if (g_Config.multiThreaded)
+ MIDILock->Unlock();
}
unsigned char SCSP_MidiOutR()
{
unsigned char val;
- if(MidiOutR==MidiOutW)
+
+ if(MidiOutR==MidiOutW) // I don't think this needs to be a critical section...
return 0xff;
+
+ /*
+ * MIDI FIFO critical section
+ */
+ if (g_Config.multiThreaded)
+ MIDILock->Lock();
val=MidiStack[MidiOutR++];
//DebugLog("Midi Out Buffer pop %02X",val);
MidiOutR&=7;
--MidiOutFill;
+
+ if (g_Config.multiThreaded)
+ MIDILock->Unlock();
+
return val;
}
unsigned char SCSP_MidiOutFill()
{
- return MidiOutFill;
+ unsigned char v;
+
+ /*
+ * MIDI FIFO critical section
+ */
+ if (g_Config.multiThreaded)
+ MIDILock->Lock();
+
+ v = MidiOutFill;
+
+ if (g_Config.multiThreaded)
+ MIDILock->Unlock();
+
+ return v;
}
unsigned char SCSP_MidiInFill()
{
- return MidiInFill;
+ unsigned char v;
+
+ /*
+ * MIDI FIFO critical section
+ */
+ if (g_Config.multiThreaded)
+ MIDILock->Lock();
+
+ v = MidiInFill;
+
+ if (g_Config.multiThreaded)
+ MIDILock->Unlock();
+
+ return v;
}
void SCSP_RTECheck()
@@ -2218,4 +2319,8 @@ void SCSP_Deinit(void)
#endif
free(buffertmpl);
free(buffertmpr);
+ delete MIDILock;
+ buffertmpl = NULL;
+ buffertmpr = NULL;
+ MIDILock = NULL;
}
diff --git a/Src/Sound/SCSP.h b/Src/Sound/SCSP.h
index 15c5185..8c68cdc 100644
--- a/Src/Sound/SCSP.h
+++ b/Src/Sound/SCSP.h
@@ -44,7 +44,22 @@ UINT8 SCSP_MidiOutFill();
UINT8 SCSP_MidiInFill();
void SCSP_CpuRunScanline();
UINT8 SCSP_MidiOutR();
-void SCSP_Init(int n);
+
+/*
+ * SCSP_Init(n):
+ *
+ * Initializes the SCSPs, allocates internal memory, and creates a mutex for
+ * MIDI FIFO access. Call SCSP_SetCB() and SCSP_SetBuffers() before calling
+ * this.
+ *
+ * Parameters:
+ * n Number of SCSPs to create. Always use 2!
+ *
+ * Returns:
+ * FAIL if an error occured (prints own error messages), OKAY otherwise.
+ */
+bool SCSP_Init(int n);
+
void SCSP_SetRAM(int n,UINT8 *r);
void SCSP_RTECheck();
int SCSP_IRQCB(int);