mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-22 13:55:38 +00:00
- Added mutex for MIDI FIFO access to SCSP.cpp.
This commit is contained in:
parent
d200dff89e
commit
5bf4a6d52b
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue