- Added mutex for MIDI FIFO access to SCSP.cpp.

This commit is contained in:
Bart Trzynadlowski 2011-09-14 07:38:56 +00:00
parent d200dff89e
commit 5bf4a6d52b
6 changed files with 194 additions and 18 deletions

View file

@ -1,7 +1,7 @@
/** /**
** Supermodel ** Supermodel
** A Sega Model 3 Arcade Emulator. ** A Sega Model 3 Arcade Emulator.
** Copyright 2011 Bart Trzynadlowski ** Copyright 2011 Bart Trzynadlowski, Nik Henson
** **
** This file is part of Supermodel. ** This file is part of Supermodel.
** **
@ -500,7 +500,8 @@ bool CSoundBoard::Init(const UINT8 *soundROMPtr, const UINT8 *sampleROMPtr)
// Initialize SCSPs // Initialize SCSPs
SCSP_SetBuffers(audioL, audioR, 44100/60); SCSP_SetBuffers(audioL, audioR, 44100/60);
SCSP_SetCB(SCSP68KRunCallback, SCSP68KIRQCallback); SCSP_SetCB(SCSP68KRunCallback, SCSP68KIRQCallback);
SCSP_Init(2); if (OKAY != SCSP_Init(2))
return FAIL;
SCSP_SetRAM(0, ram1); SCSP_SetRAM(0, ram1);
SCSP_SetRAM(1, ram2); SCSP_SetRAM(1, ram2);

View file

@ -31,6 +31,7 @@
#include "Types.h" #include "Types.h"
#include "CPU/Bus.h" #include "CPU/Bus.h"
#include "Model3/DSB.h" #include "Model3/DSB.h"
#include "OSD/Thread.h"
/* /*
* CSoundBoardConfig: * CSoundBoardConfig:

View file

@ -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 <http://www.gnu.org/licenses/>.
**/
/*
* Thread.cpp
*
* SDL-based implementation of threading primitives.
*/
#include "Supermodel.h" #include "Supermodel.h"
#ifdef SUPERMODEL_OSX #ifdef SUPERMODEL_OSX
#include <SDL/SDL.h> #include <SDL/SDL.h>
#include <SDL/SDL_thread.h> #include <SDL/SDL_thread.h>
#else #else
#include <SDL.h> #include <SDL.h>
#include <SDL_thread.h> #include <SDL_thread.h>
#endif #endif

View file

@ -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 <http://www.gnu.org/licenses/>.
**/
/*
* Thread.h
*
* Header file for threading primitives.
*/
#ifndef INCLUDED_THREADS_H #ifndef INCLUDED_THREADS_H
#define INCLUDED_THREADS_H #define INCLUDED_THREADS_H
@ -7,10 +34,10 @@ class CCondVar;
typedef int (*ThreadStart)(void *startParam); typedef int (*ThreadStart)(void *startParam);
/* /*
* CThread * CThread
* *
* Class that represents an O/S thread. * Class that represents an O/S thread.
*/ */
class CThread class CThread
{ {
@ -122,7 +149,7 @@ public:
}; };
/* /*
* CSemaphore * CCondVar
* *
* Class that represents a condition variable. * Class that represents a condition variable.
*/ */

View file

@ -1,7 +1,7 @@
/** /**
** Supermodel ** Supermodel
** A Sega Model 3 Arcade Emulator. ** A Sega Model 3 Arcade Emulator.
** Copyright 2011 Bart Trzynadlowski ** Copyright 2011 Bart Trzynadlowski, Nik Henson
** **
** This file is part of Supermodel. ** This file is part of Supermodel.
** **
@ -116,6 +116,7 @@ unsigned int RevR,RevW;
#define DWORD UINT32 #define DWORD UINT32
#endif #endif
static CMutex *MIDILock; // for safe access to the MIDI FIFOs
static int (*Run68kCB)(int cycles); static int (*Run68kCB)(int cycles);
static void (*Int68kCB)(int irq); static void (*Int68kCB)(int irq);
static void (*RetIntCB)(); static void (*RetIntCB)();
@ -332,14 +333,31 @@ void CheckPendingIRQ()
return; 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(MidiW!=MidiR)
{ {
//if (g_Config.multiThreaded)
// MIDILock->Unlock();
//SCSP.data[0x20/2]|=0x8; //Hold midi line while there are commands pending //SCSP.data[0x20/2]|=0x8; //Hold midi line while there are commands pending
Int68kCB(IrqMidi); Int68kCB(IrqMidi);
//printf("68K: MIDI IRQ\n"); //printf("68K: MIDI IRQ\n");
//ErrorLogMessage("Midi"); //ErrorLogMessage("Midi");
return; return;
} }
//if (g_Config.multiThreaded)
// MIDILock->Unlock();
if(!pend) if(!pend)
return; return;
if(pend&0x40) if(pend&0x40)
@ -535,7 +553,7 @@ void SCSP_StopSlot(_SLOT *slot,int keyoff)
#define log2(n) (log((float) n)/log((float) 2)) #define log2(n) (log((float) n)/log((float) 2))
void SCSP_Init(int n) bool SCSP_Init(int n)
{ {
if(n==2) if(n==2)
{ {
@ -712,10 +730,30 @@ void SCSP_Init(int n)
#endif #endif
LFO_Init(); LFO_Init();
buffertmpl = NULL;
buffertmpr = NULL;
buffertmpl=(signed int*) malloc(44100*sizeof(signed int)); 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)); 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(buffertmpl,0,44100*sizeof(signed int));
memset(buffertmpr,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) void SCSP_SetRAM(int n,unsigned char *r)
@ -887,6 +925,13 @@ void SCSP_UpdateRegR(int reg)
{ {
unsigned short v=SCSP->data[0x5/2]; unsigned short v=SCSP->data[0x5/2];
v&=0xff00; v&=0xff00;
/*
* MIDI FIFO critical section!
*/
if (g_Config.multiThreaded)
MIDILock->Lock();
v|=MidiStack[MidiR]; v|=MidiStack[MidiR];
//printf("read MIDI\n"); //printf("read MIDI\n");
if(MidiR!=MidiW) if(MidiR!=MidiW)
@ -894,11 +939,13 @@ void SCSP_UpdateRegR(int reg)
++MidiR; ++MidiR;
MidiR&=MIDI_STACK_SIZE_MASK; MidiR&=MIDI_STACK_SIZE_MASK;
//Int68kCB(IrqMidi); //Int68kCB(IrqMidi);
} }
MidiInFill--; MidiInFill--;
SCSP->data[0x5/2]=v; SCSP->data[0x5/2]=v;
if (g_Config.multiThreaded)
MIDILock->Unlock();
} }
break; break;
case 8: case 8:
@ -1870,46 +1917,100 @@ void SCSP_SetCB(int (*Run68k)(int cycles),void (*Int68k)(int irq))
void SCSP_MidiIn(BYTE val) void SCSP_MidiIn(BYTE val)
{ {
/*
* MIDI FIFO critical section
*/
if (g_Config.multiThreaded)
MIDILock->Lock();
//DebugLog("Midi Buffer push %02X",val); //DebugLog("Midi Buffer push %02X",val);
MidiStack[MidiW++]=val; MidiStack[MidiW++]=val;
MidiW&=MIDI_STACK_SIZE_MASK; MidiW&=MIDI_STACK_SIZE_MASK;
MidiInFill++; MidiInFill++;
//Int68kCB(IrqMidi); //Int68kCB(IrqMidi);
// SCSP.data[0x20/2]|=0x8; // SCSP.data[0x20/2]|=0x8;
if (g_Config.multiThreaded)
MIDILock->Unlock();
} }
void SCSP_MidiOutW(BYTE val) void SCSP_MidiOutW(BYTE val)
{ {
/*
* MIDI FIFO critical section
*/
if (g_Config.multiThreaded)
MIDILock->Lock();
//printf("68K: MIDI out\n"); //printf("68K: MIDI out\n");
//DebugLog("Midi Out Buffer push %02X",val); //DebugLog("Midi Out Buffer push %02X",val);
MidiStack[MidiOutW++]=val; MidiStack[MidiOutW++]=val;
MidiOutW&=7; MidiOutW&=7;
++MidiOutFill; ++MidiOutFill;
if (g_Config.multiThreaded)
MIDILock->Unlock();
} }
unsigned char SCSP_MidiOutR() unsigned char SCSP_MidiOutR()
{ {
unsigned char val; unsigned char val;
if(MidiOutR==MidiOutW)
if(MidiOutR==MidiOutW) // I don't think this needs to be a critical section...
return 0xff; return 0xff;
/*
* MIDI FIFO critical section
*/
if (g_Config.multiThreaded)
MIDILock->Lock();
val=MidiStack[MidiOutR++]; val=MidiStack[MidiOutR++];
//DebugLog("Midi Out Buffer pop %02X",val); //DebugLog("Midi Out Buffer pop %02X",val);
MidiOutR&=7; MidiOutR&=7;
--MidiOutFill; --MidiOutFill;
if (g_Config.multiThreaded)
MIDILock->Unlock();
return val; return val;
} }
unsigned char SCSP_MidiOutFill() 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() 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() void SCSP_RTECheck()
@ -2218,4 +2319,8 @@ void SCSP_Deinit(void)
#endif #endif
free(buffertmpl); free(buffertmpl);
free(buffertmpr); free(buffertmpr);
delete MIDILock;
buffertmpl = NULL;
buffertmpr = NULL;
MIDILock = NULL;
} }

View file

@ -44,7 +44,22 @@ UINT8 SCSP_MidiOutFill();
UINT8 SCSP_MidiInFill(); UINT8 SCSP_MidiInFill();
void SCSP_CpuRunScanline(); void SCSP_CpuRunScanline();
UINT8 SCSP_MidiOutR(); 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_SetRAM(int n,UINT8 *r);
void SCSP_RTECheck(); void SCSP_RTECheck();
int SCSP_IRQCB(int); int SCSP_IRQCB(int);