mirror of
https://github.com/libretro/FBNeo.git
synced 2025-02-01 06:32:17 +00:00
add soundcore MD2612: eke-eke`s gensplus-gx ym2612 + burn_md2612.cpp/h interface
This commit is contained in:
parent
f7c6219860
commit
c88d163083
@ -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 \
|
||||
|
282
src/burn/snd/burn_md2612.cpp
Normal file
282
src/burn/snd/burn_md2612.cpp
Normal 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
|
30
src/burn/snd/burn_md2612.h
Normal file
30
src/burn/snd/burn_md2612.h
Normal 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
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
26
src/burn/snd/ym2612.h
Normal 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();
|
Loading…
x
Reference in New Issue
Block a user