add soundcore MD2612: eke-eke`s gensplus-gx ym2612 + burn_md2612.cpp/h interface

This commit is contained in:
dinkc64 2017-07-20 11:39:14 +00:00
parent f7c6219860
commit c88d163083
5 changed files with 2553 additions and 2 deletions

View File

@ -94,8 +94,8 @@ depobj = burn.o burn_gun.o burn_led.o burn_shift.o burn_memory.o burn_pal.o bur
mermaid.o namco_c45.o namcoio.o pandora.o resnet.o seibusnd.o sknsspr.o slapstic.o st0020.o t5182.o timekpr.o tms34061.o v3021.o vdc.o tms9928a.o \
watchdog.o \
\
ay8910.o burn_y8950.o burn_ym2151.o burn_ym2203.o burn_ym2413.o burn_ym2608.o burn_ym2610.o burn_ym2612.o \
burn_ym3526.o burn_ym3812.o burn_ymf278b.o c6280.o dac.o es5506.o es8712.o flt_rc.o fm.o fmopl.o gaelco.o ics2115.o iremga20.o \
ay8910.o burn_y8950.o burn_ym2151.o burn_ym2203.o burn_ym2413.o burn_ym2608.o burn_ym2610.o burn_ym2612.o burn_md2612.o \
burn_ym3526.o burn_ym3812.o burn_ymf278b.o c6280.o dac.o es5506.o es8712.o flt_rc.o fm.o fmopl.o ym2612.o gaelco.o ics2115.o iremga20.o \
k005289.o k007232.o k051649.o k053260.o k054539.o msm5205.o msm5232.o msm6295.o namco_snd.o c140.o nes_apu.o tms36xx.o phoenixsound.o \
pleiadssound.o pokey.o rf5c68.o saa1099.o samples.o segapcm.o sn76477.o sn76496.o upd7759.o vlm5030.o wiping.o x1010.o ym2151.o ym2413.o \
ymdeltat.o ymf278b.o ymz280b.o \

View File

@ -0,0 +1,282 @@
// Megadrive ym2612 interface for eke-eke's genplus-gx ym2612, based on MAME's ym2612
#include "burnint.h"
#include "burn_sound.h"
#include "burn_md2612.h"
#define MAX_MD2612 1
void (*BurnMD2612Update)(INT16* pSoundBuf, INT32 nSegmentEnd);
static INT32 (*BurnMD2612StreamCallback)(INT32 nSoundRate);
static INT32 nBurnMD2612SoundRate;
static INT16* pBuffer;
static INT16* pMD2612Buffer[2 * MAX_MD2612];
static INT32 nMD2612Position;
static UINT32 nSampleSize;
static INT32 nFractionalPosition;
static INT32 nNumChips = 0;
static INT32 bMD2612AddSignal;
static double MD2612Volumes[2 * MAX_MD2612];
static INT32 MD2612RouteDirs[2 * MAX_MD2612];
// ----------------------------------------------------------------------------
// Dummy functions
static void MD2612UpdateDummy(INT16*, INT32)
{
return;
}
static INT32 MD2612StreamCallbackDummy(INT32)
{
return 0;
}
// ----------------------------------------------------------------------------
// Execute MD2612 for part of a frame
static void MD2612Render(INT32 nSegmentLength)
{
#if defined FBA_DEBUG
if (!DebugSnd_YM2612Initted) bprintf(PRINT_ERROR, _T("MD2612Render called without init\n"));
#endif
if (nMD2612Position >= nSegmentLength) {
return;
}
nSegmentLength -= nMD2612Position;
pMD2612Buffer[0] = pBuffer + 0 * 4096 + 4 + nMD2612Position;
pMD2612Buffer[1] = pBuffer + 1 * 4096 + 4 + nMD2612Position;
MDYM2612Update(&pMD2612Buffer[0], nSegmentLength);
nMD2612Position += nSegmentLength;
}
// ----------------------------------------------------------------------------
// Update the sound buffer
#define INTERPOLATE_ADD_SOUND_LEFT(route, buffer) \
if ((MD2612RouteDirs[route] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) { \
nLeftSample[0] += (INT32)(pMD2612Buffer[buffer][(nFractionalPosition >> 16) - 3] * MD2612Volumes[route]); \
nLeftSample[1] += (INT32)(pMD2612Buffer[buffer][(nFractionalPosition >> 16) - 2] * MD2612Volumes[route]); \
nLeftSample[2] += (INT32)(pMD2612Buffer[buffer][(nFractionalPosition >> 16) - 1] * MD2612Volumes[route]); \
nLeftSample[3] += (INT32)(pMD2612Buffer[buffer][(nFractionalPosition >> 16) - 0] * MD2612Volumes[route]); \
}
#define INTERPOLATE_ADD_SOUND_RIGHT(route, buffer) \
if ((MD2612RouteDirs[route] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) { \
nRightSample[0] += (INT32)(pMD2612Buffer[buffer][(nFractionalPosition >> 16) - 3] * MD2612Volumes[route]); \
nRightSample[1] += (INT32)(pMD2612Buffer[buffer][(nFractionalPosition >> 16) - 2] * MD2612Volumes[route]); \
nRightSample[2] += (INT32)(pMD2612Buffer[buffer][(nFractionalPosition >> 16) - 1] * MD2612Volumes[route]); \
nRightSample[3] += (INT32)(pMD2612Buffer[buffer][(nFractionalPosition >> 16) - 0] * MD2612Volumes[route]); \
}
static void MD2612UpdateResample(INT16* pSoundBuf, INT32 nSegmentEnd)
{
#if defined FBA_DEBUG
if (!DebugSnd_YM2612Initted) bprintf(PRINT_ERROR, _T("MD2612UpdateResample called without init\n"));
#endif
INT32 nSegmentLength = nSegmentEnd;
INT32 nSamplesNeeded = nSegmentEnd * nBurnMD2612SoundRate / nBurnSoundRate + 1;
if (nSamplesNeeded < nMD2612Position) {
nSamplesNeeded = nMD2612Position;
}
if (nSegmentLength > nBurnSoundLen) {
nSegmentLength = nBurnSoundLen;
}
nSegmentLength <<= 1;
MD2612Render(nSamplesNeeded);
pMD2612Buffer[0] = pBuffer + 0 * 4096 + 4;
pMD2612Buffer[1] = pBuffer + 1 * 4096 + 4;
for (INT32 i = (nFractionalPosition & 0xFFFF0000) >> 15; i < nSegmentLength; i += 2, nFractionalPosition += nSampleSize) {
INT32 nLeftSample[4] = {0, 0, 0, 0};
INT32 nRightSample[4] = {0, 0, 0, 0};
INT32 nTotalLeftSample, nTotalRightSample;
INTERPOLATE_ADD_SOUND_LEFT (BURN_SND_MD2612_MD2612_ROUTE_1, 0)
INTERPOLATE_ADD_SOUND_RIGHT (BURN_SND_MD2612_MD2612_ROUTE_1, 0)
INTERPOLATE_ADD_SOUND_LEFT (BURN_SND_MD2612_MD2612_ROUTE_2, 1)
INTERPOLATE_ADD_SOUND_RIGHT (BURN_SND_MD2612_MD2612_ROUTE_2, 1)
nTotalLeftSample = INTERPOLATE4PS_16BIT((nFractionalPosition >> 4) & 0x0fff, nLeftSample[0], nLeftSample[1], nLeftSample[2], nLeftSample[3]);
nTotalRightSample = INTERPOLATE4PS_16BIT((nFractionalPosition >> 4) & 0x0fff, nRightSample[0], nRightSample[1], nRightSample[2], nRightSample[3]);
nTotalLeftSample = BURN_SND_CLIP(nTotalLeftSample);
nTotalRightSample = BURN_SND_CLIP(nTotalRightSample);
if (bMD2612AddSignal) {
pSoundBuf[i + 0] = BURN_SND_CLIP(pSoundBuf[i + 0] + nTotalLeftSample);
pSoundBuf[i + 1] = BURN_SND_CLIP(pSoundBuf[i + 1] + nTotalRightSample);
} else {
pSoundBuf[i + 0] = nTotalLeftSample;
pSoundBuf[i + 1] = nTotalRightSample;
}
}
if (nSegmentEnd >= nBurnSoundLen) {
INT32 nExtraSamples = nSamplesNeeded - (nFractionalPosition >> 16);
for (INT32 i = -4; i < nExtraSamples; i++) {
pMD2612Buffer[0][i] = pMD2612Buffer[0][(nFractionalPosition >> 16) + i];
pMD2612Buffer[1][i] = pMD2612Buffer[1][(nFractionalPosition >> 16) + i];
}
nFractionalPosition &= 0xFFFF;
nMD2612Position = nExtraSamples;
dTime += 100.0 / nBurnFPS;
}
}
// ----------------------------------------------------------------------------
// Callbacks for YM2612 core
void BurnMD2612UpdateRequest()
{
#if defined FBA_DEBUG
if (!DebugSnd_YM2612Initted) bprintf(PRINT_ERROR, _T("YM2612UpdateRequest called without init\n"));
#endif
MD2612Render(BurnMD2612StreamCallback(nBurnMD2612SoundRate));
}
// ----------------------------------------------------------------------------
// Initialisation, etc.
void BurnMD2612Reset()
{
#if defined FBA_DEBUG
if (!DebugSnd_YM2612Initted) bprintf(PRINT_ERROR, _T("BurnMD2612Reset called without init\n"));
#endif
BurnTimerReset();
MDYM2612Reset();
}
void BurnMD2612Exit()
{
#if defined FBA_DEBUG
if (!DebugSnd_YM2612Initted) bprintf(PRINT_ERROR, _T("BurnMD2612Exit called without init\n"));
#endif
if (!DebugSnd_YM2612Initted) return;
MDYM2612Exit();
BurnTimerExit();
BurnFree(pBuffer);
nNumChips = 0;
bMD2612AddSignal = 0;
DebugSnd_YM2612Initted = 0;
}
INT32 BurnMD2612Init(INT32 num, INT32 bIsPal, INT32 (*StreamCallback)(INT32), double (*GetTimeCallback)(), INT32 bAddSignal)
{
if (num > 1) {
bprintf(0, _T("MD2612 only supports 1 chip!\n"));
return 0;
}
DebugSnd_YM2612Initted = 1;
BurnTimerInit(NULL, GetTimeCallback);
if (nBurnSoundRate <= 0) {
BurnMD2612StreamCallback = MD2612StreamCallbackDummy;
BurnMD2612Update = MD2612UpdateDummy;
MDYM2612Init();
return 0;
}
BurnMD2612StreamCallback = StreamCallback;
if (!StreamCallback) {
bprintf(0, _T("BurnMD2612Init(): StreamCallback is NULL! Crashing in 3..2...1....\n"));
}
// Megadrive's 2612 runs at 53267hz NTSC, 52781hz PAL
nBurnMD2612SoundRate = (bIsPal) ? 52781 : 53267;
BurnMD2612Update = MD2612UpdateResample;
nSampleSize = (UINT32)nBurnMD2612SoundRate * (1 << 16) / nBurnSoundRate;
MDYM2612Init();
pBuffer = (INT16*)BurnMalloc(4096 * 2 * num * sizeof(INT16));
memset(pBuffer, 0, 4096 * 2 * num * sizeof(INT16));
nMD2612Position = 0;
nFractionalPosition = 0;
nNumChips = num;
bMD2612AddSignal = bAddSignal;
// default routes
MD2612Volumes[BURN_SND_MD2612_MD2612_ROUTE_1] = 1.00;
MD2612Volumes[BURN_SND_MD2612_MD2612_ROUTE_2] = 1.00;
MD2612RouteDirs[BURN_SND_MD2612_MD2612_ROUTE_1] = BURN_SND_ROUTE_LEFT;
MD2612RouteDirs[BURN_SND_MD2612_MD2612_ROUTE_2] = BURN_SND_ROUTE_RIGHT;
return 0;
}
void BurnMD2612SetRoute(INT32 nChip, INT32 nIndex, double nVolume, INT32 nRouteDir)
{
#if defined FBA_DEBUG
if (!DebugSnd_YM2612Initted) bprintf(PRINT_ERROR, _T("BurnMD2612SetRoute called without init\n"));
if (nIndex < 0 || nIndex > 1) bprintf(PRINT_ERROR, _T("BurnMD2612SetRoute called with invalid index %i\n"), nIndex);
if (nChip >= nNumChips) bprintf(PRINT_ERROR, _T("BurnMD2612SetRoute called with invalid chip %i\n"), nChip);
#endif
if (nChip == 0) {
MD2612Volumes[nIndex] = nVolume;
MD2612RouteDirs[nIndex] = nRouteDir;
}
if (nChip == 1) {
MD2612Volumes[2 + nIndex] = nVolume;
MD2612RouteDirs[2 + nIndex] = nRouteDir;
}
}
void BurnMD2612Scan(INT32 nAction, INT32* pnMin)
{
#if defined FBA_DEBUG
if (!DebugSnd_YM2612Initted) bprintf(PRINT_ERROR, _T("BurnMD2612Scan called without init\n"));
#endif
if (nAction & ACB_DRIVER_DATA) {
BurnTimerScan(nAction, pnMin);
SCAN_VAR(nMD2612Position);
if (nAction & ACB_WRITE) {
MDYM2612LoadContext();
} else {
MDYM2612SaveContext();
}
}
}
#undef MAX_MD2612

View File

@ -0,0 +1,30 @@
// burn_md2612.h
#include "driver.h"
extern "C" {
#include "ym2612.h"
}
#include "timer.h"
extern "C" void BurnMD2612UpdateRequest();
INT32 BurnMD2612Init(INT32 num, INT32 bIsPal, INT32 (*StreamCallback)(INT32), double (*GetTimeCallback)(), INT32 bAddSignal);
void BurnMD2612SetRoute(INT32 nChip, INT32 nIndex, double nVolume, INT32 nRouteDir);
void BurnMD2612Reset();
void BurnMD2612Exit();
extern void (*BurnMD2612Update)(INT16* pSoundBuf, INT32 nSegmentEnd);
void BurnMD2612Scan(INT32 nAction, INT32* pnMin);
#define BURN_SND_MD2612_MD2612_ROUTE_1 0
#define BURN_SND_MD2612_MD2612_ROUTE_2 1
#define BurnMD2612SetAllRoutes(i, v, d) \
BurnMD2612SetRoute(i, BURN_SND_MD2612_MD2612_ROUTE_1, v, d); \
BurnMD2612SetRoute(i, BURN_SND_MD2612_MD2612_ROUTE_2, v, d);
#define BurnMD2612Read(i, a) MDYM2612Read()
#if defined FBA_DEBUG
#define BurnMD2612Write(i, a, n) if (!DebugSnd_YM2612Initted) bprintf(PRINT_ERROR, _T("BurnMD2612Write called without init\n")); MDYM2612Write(a, n)
#else
#define BurnMD2612Write(i, a, n) MDYM2612Write(a, n)
#endif

2213
src/burn/snd/ym2612.c Normal file

File diff suppressed because it is too large Load Diff

26
src/burn/snd/ym2612.h Normal file
View File

@ -0,0 +1,26 @@
/*
**
** software implementation of Yamaha FM sound generator (YM2612/YM3438)
**
** Original code (MAME fm.c)
**
** Copyright (C) 2001, 2002, 2003 Jarek Burczynski (bujar at mame dot net)
** Copyright (C) 1998 Tatsuyuki Satoh , MultiArcadeMachineEmulator development
**
** Version 1.4 (final beta)
**
** Additional code & fixes by Eke-Eke for Genesis Plus GX
**
*/
extern void MDYM2612Init(void);
extern void MDYM2612Exit(void);
extern void MDYM2612Config(unsigned char dac_bits);
extern void MDYM2612Reset(void);
extern void MDYM2612Update(INT16 **buffer, int length);
extern void MDYM2612Write(unsigned int a, unsigned int v);
extern unsigned int MDYM2612Read(void);
extern int MDYM2612LoadContext();
extern int MDYM2612SaveContext();
void BurnMD2612UpdateRequest();