Add support to segapcm.cpp for multiple chips, convert to use BurnMalloc

This commit is contained in:
Barry Harris 2012-07-23 10:16:27 +00:00
parent 938c78b495
commit 6ecdd6e5a8
3 changed files with 121 additions and 92 deletions

View File

@ -535,7 +535,7 @@ void __fastcall System16Z80Write(UINT16 a, UINT8 d)
UINT8 __fastcall System16Z80PCMRead(UINT16 a)
{
if (a >= 0xf000 && a <= 0xf0ff) {
return SegaPCMRead(a - 0xf000);
return SegaPCMRead(0, a - 0xf000);
}
#if 0 && defined FBA_DEBUG
@ -548,7 +548,7 @@ UINT8 __fastcall System16Z80PCMRead(UINT16 a)
void __fastcall System16Z80PCMWrite(UINT16 a, UINT8 d)
{
if (a >= 0xf000 && a <= 0xf0ff) {
SegaPCMWrite(a - 0xf000, d);
SegaPCMWrite(0, a - 0xf000, d);
return;
}
@ -578,7 +578,7 @@ UINT8 __fastcall System16Z802203PortRead(UINT16 a)
UINT8 __fastcall System16Z802203Read(UINT16 a)
{
if (a >= 0xe000 && a <= 0xe0ff) {
return SegaPCMRead(a - 0xe000);
return SegaPCMRead(0, a - 0xe000);
}
switch (a) {
@ -597,7 +597,7 @@ UINT8 __fastcall System16Z802203Read(UINT16 a)
void __fastcall System16Z802203Write(UINT16 a, UINT8 d)
{
if (a >= 0xe000 && a <= 0xe0ff) {
SegaPCMWrite(a - 0xe000, d);
SegaPCMWrite(0, a - 0xe000, d);
return;
}
@ -2096,12 +2096,12 @@ INT32 System16Init()
if (System16PCMDataSize) {
if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_YM2203) {
SegaPCMInit(8000000, BANK_512, System16PCMData, System16PCMDataSize);
SegaPCMInit(0, 8000000, BANK_512, System16PCMData, System16PCMDataSize);
} else {
SegaPCMInit(4000000, BANK_512, System16PCMData, System16PCMDataSize);
SegaPCMInit(0, 4000000, BANK_512, System16PCMData, System16PCMDataSize);
}
SegaPCMSetRoute(BURN_SND_SEGAPCM_ROUTE_1, 1.0, BURN_SND_ROUTE_LEFT);
SegaPCMSetRoute(BURN_SND_SEGAPCM_ROUTE_2, 1.0, BURN_SND_ROUTE_RIGHT);
SegaPCMSetRoute(0, BURN_SND_SEGAPCM_ROUTE_1, 1.0, BURN_SND_ROUTE_LEFT);
SegaPCMSetRoute(0, BURN_SND_SEGAPCM_ROUTE_2, 1.0, BURN_SND_ROUTE_RIGHT);
}
System16TileBankSize = 0x1000;
@ -2170,11 +2170,11 @@ INT32 System16Init()
BurnYM2151SetRoute(BURN_SND_YM2151_YM2151_ROUTE_2, 0.43, BURN_SND_ROUTE_RIGHT);
if (System16PCMDataSize) {
SegaPCMInit(4000000, BANK_512, System16PCMData, System16PCMDataSize);
SegaPCMSetRoute(BURN_SND_SEGAPCM_ROUTE_1, 1.0, BURN_SND_ROUTE_LEFT);
SegaPCMSetRoute(BURN_SND_SEGAPCM_ROUTE_2, 1.0, BURN_SND_ROUTE_RIGHT);
SegaPCMInit(0, 4000000, BANK_512, System16PCMData, System16PCMDataSize);
SegaPCMSetRoute(0, BURN_SND_SEGAPCM_ROUTE_1, 1.0, BURN_SND_ROUTE_LEFT);
SegaPCMSetRoute(0, BURN_SND_SEGAPCM_ROUTE_2, 1.0, BURN_SND_ROUTE_RIGHT);
}
System16RoadColorOffset1 = 0x400;
System16RoadColorOffset2 = 0x420;
System16RoadColorOffset3 = 0x780;
@ -2264,9 +2264,9 @@ INT32 System16Init()
BurnYM2151SetRoute(BURN_SND_YM2151_YM2151_ROUTE_2, 0.43, BURN_SND_ROUTE_RIGHT);
if (System16PCMDataSize) {
SegaPCMInit(4000000, BANK_512, System16PCMData, System16PCMDataSize);
SegaPCMSetRoute(BURN_SND_SEGAPCM_ROUTE_1, 1.0, BURN_SND_ROUTE_LEFT);
SegaPCMSetRoute(BURN_SND_SEGAPCM_ROUTE_2, 1.0, BURN_SND_ROUTE_RIGHT);
SegaPCMInit(0, 4000000, BANK_512, System16PCMData, System16PCMDataSize);
SegaPCMSetRoute(0, BURN_SND_SEGAPCM_ROUTE_1, 1.0, BURN_SND_ROUTE_LEFT);
SegaPCMSetRoute(0, BURN_SND_SEGAPCM_ROUTE_2, 1.0, BURN_SND_ROUTE_RIGHT);
}
System16RoadColorOffset1 = 0x1700;
@ -2347,9 +2347,9 @@ INT32 System16Init()
BurnYM2151SetRoute(BURN_SND_YM2151_YM2151_ROUTE_2, 0.43, BURN_SND_ROUTE_RIGHT);
if (System16PCMDataSize) {
SegaPCMInit(32215900 / 8, BANK_12M | BANK_MASKF8, System16PCMData, System16PCMDataSize);
SegaPCMSetRoute(BURN_SND_SEGAPCM_ROUTE_1, 1.0, BURN_SND_ROUTE_LEFT);
SegaPCMSetRoute(BURN_SND_SEGAPCM_ROUTE_2, 1.0, BURN_SND_ROUTE_RIGHT);
SegaPCMInit(0, 32215900 / 8, BANK_12M | BANK_MASKF8, System16PCMData, System16PCMDataSize);
SegaPCMSetRoute(0, BURN_SND_SEGAPCM_ROUTE_1, 1.0, BURN_SND_ROUTE_LEFT);
SegaPCMSetRoute(0, BURN_SND_SEGAPCM_ROUTE_2, 1.0, BURN_SND_ROUTE_RIGHT);
}
}

View File

@ -2,9 +2,11 @@
#include "burn_sound.h"
#include "segapcm.h"
#define MAX_CHIPS 2
struct segapcm
{
UINT8 *ram;
UINT8 ram[0x800];
UINT8 low[16];
const UINT8 *rom;
INT32 bankshift;
@ -14,26 +16,24 @@ struct segapcm
INT32 OutputDir[2];
};
static struct segapcm *Chip = NULL;
static INT32 *Left = NULL;
static INT32 *Right = NULL;
static struct segapcm *Chip[MAX_CHIPS] = { NULL, };
static INT32 *Left[MAX_CHIPS] = { NULL, };
static INT32 *Right[MAX_CHIPS] = { NULL, };
void SegaPCMUpdate(INT16* pSoundBuf, INT32 nLength)
static INT32 nNumChips = 0;
static void SegaPCMUpdateOne(INT32 nChip, INT32 nLength)
{
#if defined FBA_DEBUG
if (!DebugSnd_SegaPCMInitted) bprintf(PRINT_ERROR, _T("SegaPCMUpdate called without init\n"));
#endif
INT32 Channel;
memset(Left, 0, nLength * sizeof(INT32));
memset(Right, 0, nLength * sizeof(INT32));
memset(Left[nChip], 0, nLength * sizeof(INT32));
memset(Right[nChip], 0, nLength * sizeof(INT32));
for (Channel = 0; Channel < 16; Channel++) {
UINT8 *Regs = Chip->ram + 8 * Channel;
UINT8 *Regs = Chip[nChip]->ram + 8 * Channel;
if (!(Regs[0x86] & 1)) {
const UINT8 *Rom = Chip->rom + ((Regs[0x86] & Chip->bankmask) << Chip->bankshift);
UINT32 Addr = (Regs[0x85] << 16) | (Regs[0x84] << 8) | Chip->low[Channel];
const UINT8 *Rom = Chip[nChip]->rom + ((Regs[0x86] & Chip[nChip]->bankmask) << Chip[nChip]->bankshift);
UINT32 Addr = (Regs[0x85] << 16) | (Regs[0x84] << 8) | Chip[nChip]->low[Channel];
UINT32 Loop = (Regs[0x05] << 16) | (Regs[0x04] << 8);
UINT8 End = Regs[6] + 1;
INT32 i;
@ -52,60 +52,89 @@ void SegaPCMUpdate(INT16* pSoundBuf, INT32 nLength)
v = Rom[Addr >> 8] - 0x80;
Left[i] += v * Regs[2];
Right[i] += v * Regs[3];
Addr = (Addr + ((Regs[7] * Chip->UpdateStep) >> 16)) & 0xffffff;
Left[nChip][i] += v * Regs[2];
Right[nChip][i] += v * Regs[3];
Addr = (Addr + ((Regs[7] * Chip[nChip]->UpdateStep) >> 16)) & 0xffffff;
}
Regs[0x84] = Addr >> 8;
Regs[0x85] = Addr >> 16;
Chip->low[Channel] = Regs[0x86] & 1 ? 0 : Addr;
Chip[nChip]->low[Channel] = Regs[0x86] & 1 ? 0 : Addr;
}
}
}
void SegaPCMUpdate(INT16* pSoundBuf, INT32 nLength)
{
#if defined FBA_DEBUG
if (!DebugSnd_SegaPCMInitted) bprintf(PRINT_ERROR, _T("SegaPCMUpdate called without init\n"));
#endif
for (INT32 i = 0; i < nNumChips + 1; i++) {
SegaPCMUpdateOne(i, nLength);
}
for (INT32 i = 0; i < nLength; i++) {
INT32 nLeftSample = 0;
INT32 nRightSample = 0;
if ((Chip->OutputDir[BURN_SND_SEGAPCM_ROUTE_1] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
nLeftSample += (INT32)(Left[i] * Chip->Volume[BURN_SND_SEGAPCM_ROUTE_1]);
if ((Chip[0]->OutputDir[BURN_SND_SEGAPCM_ROUTE_1] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
nLeftSample += (INT32)(Left[0][i] * Chip[0]->Volume[BURN_SND_SEGAPCM_ROUTE_1]);
}
if ((Chip->OutputDir[BURN_SND_SEGAPCM_ROUTE_1] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
nRightSample += (INT32)(Left[i] * Chip->Volume[BURN_SND_SEGAPCM_ROUTE_1]);
if ((Chip[0]->OutputDir[BURN_SND_SEGAPCM_ROUTE_1] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
nRightSample += (INT32)(Left[0][i] * Chip[0]->Volume[BURN_SND_SEGAPCM_ROUTE_1]);
}
if ((Chip->OutputDir[BURN_SND_SEGAPCM_ROUTE_2] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
nLeftSample += (INT32)(Right[i] * Chip->Volume[BURN_SND_SEGAPCM_ROUTE_2]);
if ((Chip[0]->OutputDir[BURN_SND_SEGAPCM_ROUTE_2] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
nLeftSample += (INT32)(Right[0][i] * Chip[0]->Volume[BURN_SND_SEGAPCM_ROUTE_2]);
}
if ((Chip->OutputDir[BURN_SND_SEGAPCM_ROUTE_2] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
nRightSample += (INT32)(Right[i] * Chip->Volume[BURN_SND_SEGAPCM_ROUTE_2]);
if ((Chip[0]->OutputDir[BURN_SND_SEGAPCM_ROUTE_2] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
nRightSample += (INT32)(Right[0][i] * Chip[0]->Volume[BURN_SND_SEGAPCM_ROUTE_2]);
}
nLeftSample = BURN_SND_CLIP(nLeftSample);
nRightSample = BURN_SND_CLIP(nRightSample);
if (nNumChips >= 1) {
if ((Chip[1]->OutputDir[BURN_SND_SEGAPCM_ROUTE_1] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
nLeftSample += (INT32)(Left[1][i] * Chip[1]->Volume[BURN_SND_SEGAPCM_ROUTE_1]);
}
if ((Chip[1]->OutputDir[BURN_SND_SEGAPCM_ROUTE_1] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
nRightSample += (INT32)(Left[1][i] * Chip[1]->Volume[BURN_SND_SEGAPCM_ROUTE_1]);
}
if ((Chip[1]->OutputDir[BURN_SND_SEGAPCM_ROUTE_2] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
nLeftSample += (INT32)(Right[1][i] * Chip[1]->Volume[BURN_SND_SEGAPCM_ROUTE_2]);
}
if ((Chip[1]->OutputDir[BURN_SND_SEGAPCM_ROUTE_2] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
nRightSample += (INT32)(Right[1][i] * Chip[1]->Volume[BURN_SND_SEGAPCM_ROUTE_2]);
}
nLeftSample = BURN_SND_CLIP(nLeftSample);
nRightSample = BURN_SND_CLIP(nRightSample);
}
pSoundBuf[0] += nLeftSample;
pSoundBuf[1] += nRightSample;
pSoundBuf += 2;
}
}
void SegaPCMInit(INT32 clock, INT32 bank, UINT8 *pPCMData, INT32 PCMDataSize)
void SegaPCMInit(INT32 nChip, INT32 clock, INT32 bank, UINT8 *pPCMData, INT32 PCMDataSize)
{
INT32 Mask, RomMask;
Chip = (struct segapcm*)malloc(sizeof(*Chip));
memset(Chip, 0, sizeof(*Chip));
Chip[nChip] = (struct segapcm*)BurnMalloc(sizeof(*Chip[nChip]));
memset(Chip[nChip], 0, sizeof(*Chip[nChip]));
Chip->rom = pPCMData;
Chip[nChip]->rom = pPCMData;
Chip->ram = (UINT8*)malloc(0x800);
memset(Chip->ram, 0xff, 0x800);
memset(Chip[nChip]->ram, 0xff, 0x800);
Left = (INT32*)malloc(nBurnSoundLen * sizeof(INT32));
Right = (INT32*)malloc(nBurnSoundLen * sizeof(INT32));
Left[nChip] = (INT32*)BurnMalloc(nBurnSoundLen * sizeof(INT32));
Right[nChip] = (INT32*)BurnMalloc(nBurnSoundLen * sizeof(INT32));
Chip->bankshift = bank;
Chip[nChip]->bankshift = bank;
Mask = bank >> 16;
if(!Mask)
Mask = BANK_MASK7 >> 16;
@ -113,28 +142,31 @@ void SegaPCMInit(INT32 clock, INT32 bank, UINT8 *pPCMData, INT32 PCMDataSize)
for (RomMask = 1; RomMask < PCMDataSize; RomMask *= 2) {}
RomMask--;
Chip->bankmask = Mask & (RomMask >> Chip->bankshift);
Chip[nChip]->bankmask = Mask & (RomMask >> Chip[nChip]->bankshift);
double Rate = (double)clock / 128 / nBurnSoundRate;
Chip->UpdateStep = (INT32)(Rate * 0x10000);
Chip[nChip]->UpdateStep = (INT32)(Rate * 0x10000);
Chip->Volume[BURN_SND_SEGAPCM_ROUTE_1] = 1.00;
Chip->Volume[BURN_SND_SEGAPCM_ROUTE_2] = 1.00;
Chip->OutputDir[BURN_SND_SEGAPCM_ROUTE_1] = BURN_SND_ROUTE_LEFT;
Chip->OutputDir[BURN_SND_SEGAPCM_ROUTE_2] = BURN_SND_ROUTE_RIGHT;
Chip[nChip]->Volume[BURN_SND_SEGAPCM_ROUTE_1] = 1.00;
Chip[nChip]->Volume[BURN_SND_SEGAPCM_ROUTE_2] = 1.00;
Chip[nChip]->OutputDir[BURN_SND_SEGAPCM_ROUTE_1] = BURN_SND_ROUTE_LEFT;
Chip[nChip]->OutputDir[BURN_SND_SEGAPCM_ROUTE_2] = BURN_SND_ROUTE_RIGHT;
nNumChips = nChip;
DebugSnd_SegaPCMInitted = 1;
}
void SegaPCMSetRoute(INT32 nIndex, double nVolume, INT32 nRouteDir)
void SegaPCMSetRoute(INT32 nChip, INT32 nIndex, double nVolume, INT32 nRouteDir)
{
#if defined FBA_DEBUG
if (!DebugSnd_SegaPCMInitted) bprintf(PRINT_ERROR, _T("SegaPCMSetRoute called without init\n"));
if (nIndex < 0 || nIndex > 1) bprintf(PRINT_ERROR, _T("SegaPCMSetRoute called with invalid index %i\n"), nIndex);
if (nChip > nNumChips) bprintf(PRINT_ERROR, _T("SegaPCMSetRoute called with invalid chip %i\n"), nChip);
#endif
Chip->Volume[nIndex] = nVolume;
Chip->OutputDir[nIndex] = nRouteDir;
Chip[nChip]->Volume[nIndex] = nVolume;
Chip[nChip]->OutputDir[nIndex] = nRouteDir;
}
void SegaPCMExit()
@ -143,20 +175,13 @@ void SegaPCMExit()
if (!DebugSnd_SegaPCMInitted) bprintf(PRINT_ERROR, _T("SegaPCMExit called without init\n"));
#endif
if (Chip) {
free(Chip);
Chip = NULL;
for (INT32 i = 0; i < nNumChips + 1; i++) {
BurnFree(Chip[i]);
BurnFree(Left[i]);
BurnFree(Right[i]);
}
if (Left) {
free(Left);
Left = NULL;
}
if (Right) {
free(Right);
Right = NULL;
}
nNumChips = 0;
DebugSnd_SegaPCMInitted = 0;
}
@ -173,33 +198,37 @@ INT32 SegaPCMScan(INT32 nAction,INT32 *pnMin)
*pnMin = 0x029719;
}
if (nAction & ACB_DRIVER_DATA) {
ScanVar(Chip->low, 16 * sizeof(UINT8), "SegaPCMlow");
for (INT32 i = 0; i < nNumChips + 1; i++) {
if (nAction & ACB_DRIVER_DATA) {
ScanVar(Chip[i]->low, 16 * sizeof(UINT8), "SegaPCMlow");
memset(&ba, 0, sizeof(ba));
ba.Data = Chip->ram;
ba.nLen = 0x800;
ba.szName = "SegaPCMRAM";
BurnAcb(&ba);
memset(&ba, 0, sizeof(ba));
ba.Data = Chip[i]->ram;
ba.nLen = 0x800;
ba.szName = "SegaPCMRAM";
BurnAcb(&ba);
}
}
return 0;
}
UINT8 SegaPCMRead(UINT32 Offset)
UINT8 SegaPCMRead(INT32 nChip, UINT32 Offset)
{
#if defined FBA_DEBUG
if (!DebugSnd_SegaPCMInitted) bprintf(PRINT_ERROR, _T("SegaPCMRead called without init\n"));
if (nChip > nNumChips) bprintf(PRINT_ERROR, _T("SegaPCMRead called with invalid chip %i\n"), nChip);
#endif
return Chip->ram[Offset & 0x07ff];
return Chip[nChip]->ram[Offset & 0x07ff];
}
void SegaPCMWrite(UINT32 Offset, UINT8 Data)
void SegaPCMWrite(INT32 nChip, UINT32 Offset, UINT8 Data)
{
#if defined FBA_DEBUG
if (!DebugSnd_SegaPCMInitted) bprintf(PRINT_ERROR, _T("SegaPCMWrite called without init\n"));
if (nChip > nNumChips) bprintf(PRINT_ERROR, _T("SegaPCMWrite called with invalid chip %i\n"), nChip);
#endif
Chip->ram[Offset & 0x07ff] = Data;
Chip[nChip]->ram[Offset & 0x07ff] = Data;
}

View File

@ -6,16 +6,16 @@
#define BANK_MASKF8 (0xf8<<16)
void SegaPCMUpdate(INT16* pSoundBuf, INT32 nLength);
void SegaPCMInit(INT32 clock, INT32 bank, UINT8 *pPCMData, INT32 PCMDataSize);
void SegaPCMSetRoute(INT32 nIndex, double nVolume, INT32 nRouteDir);
void SegaPCMInit(INT32 nChip, INT32 clock, INT32 bank, UINT8 *pPCMData, INT32 PCMDataSize);
void SegaPCMSetRoute(INT32 nChip, INT32 nIndex, double nVolume, INT32 nRouteDir);
void SegaPCMExit();
INT32 SegaPCMScan(INT32 nAction,INT32 *pnMin);
UINT8 SegaPCMRead(UINT32 Offset);
void SegaPCMWrite(UINT32 Offset, UINT8 Data);
UINT8 SegaPCMRead(INT32 nChip, UINT32 Offset);
void SegaPCMWrite(INT32 nChip, UINT32 Offset, UINT8 Data);
#define BURN_SND_SEGAPCM_ROUTE_1 0
#define BURN_SND_SEGAPCM_ROUTE_2 1
#define SegaPCMSetAllRoutes(v, d) \
SegaPCMSetRoute(BURN_SND_SEGAPCM_ROUTE_1, v, d); \
SegaPCMSetRoute(BURN_SND_SEGAPCM_ROUTE_2, v, d);
#define SegaPCMSetAllRoutes(n, v, d) \
SegaPCMSetRoute(n, BURN_SND_SEGAPCM_ROUTE_1, v, d); \
SegaPCMSetRoute(n, BURN_SND_SEGAPCM_ROUTE_2, v, d);