diff --git a/src/burn/drv/sega/sys16_run.cpp b/src/burn/drv/sega/sys16_run.cpp index dbedbb9ef..3e9de3f8c 100644 --- a/src/burn/drv/sega/sys16_run.cpp +++ b/src/burn/drv/sega/sys16_run.cpp @@ -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); } } diff --git a/src/burn/snd/segapcm.cpp b/src/burn/snd/segapcm.cpp index 104887458..3d6dee583 100644 --- a/src/burn/snd/segapcm.cpp +++ b/src/burn/snd/segapcm.cpp @@ -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; } diff --git a/src/burn/snd/segapcm.h b/src/burn/snd/segapcm.h index 6541d6a64..30beb0b3d 100644 --- a/src/burn/snd/segapcm.h +++ b/src/burn/snd/segapcm.h @@ -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);