mirror of
https://github.com/libretro/fbalpha2012_neogeo.git
synced 2024-11-26 18:20:32 +00:00
Cleanups
This commit is contained in:
parent
05045e103e
commit
7baa965a9e
@ -77,9 +77,9 @@ depobj := $(drvobj) \
|
||||
8255ppi.o 8257dma.o eeprom.o pandora.o seibusnd.o sknsspr.o slapstic.o timekpr.o v3021.o vdc.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 ics2115.o iremga20.o \
|
||||
burn_ym3526.o burn_ym3812.o c6280.o dac.o es5506.o es8712.o flt_rc.o fm.o fmopl.o ics2115.o iremga20.o \
|
||||
k007232.o k051649.o k053260.o k054539.o msm5205.o msm6295.o namco_snd.o rf5c68.o saa1099.o samples.o segapcm.o \
|
||||
sn76496.o upd7759.o x1010.o ym2151.o ym2413.o ymdeltat.o ymf278b.o ymz280b.o \
|
||||
sn76496.o upd7759.o x1010.o ym2151.o ym2413.o ymdeltat.o ymz280b.o \
|
||||
\
|
||||
arm7_intf.o arm_intf.o h6280_intf.o hd6309_intf.o konami_intf.o m6502_intf.o m6800_intf.o m6805_intf.o m6809_intf.o \
|
||||
m68000_intf.o nec_intf.o pic16c5x_intf.o s2650_intf.o z80_intf.o \
|
||||
|
@ -394,8 +394,6 @@ FBA_CPU_DIRS := $(FBA_CPU_DIR) \
|
||||
# Neo Geo Only
|
||||
SOURCES_CXX := $(FBA_BURN_DIR)/devices/eeprom.cpp \
|
||||
$(FBA_BURN_DIR)/snd/burn_ym2610.cpp \
|
||||
$(FBA_BURN_DIR)/snd/burn_ymf278b.cpp \
|
||||
$(FBA_BURN_DIR)/snd/ymz280b.cpp \
|
||||
$(FBA_CPU_DIR)/m68000_intf.cpp \
|
||||
$(FBA_CPU_DIR)/z80_intf.cpp
|
||||
|
||||
@ -405,7 +403,6 @@ endif
|
||||
|
||||
SOURCES_C := $(FBA_BURN_DIR)/snd/ay8910.c \
|
||||
$(FBA_BURN_DIR)/snd/fm.c \
|
||||
$(FBA_BURN_DIR)/snd/ymf278b.c \
|
||||
$(FBA_BURN_DIR)/snd/ymdeltat.c
|
||||
|
||||
ifeq ($(platform), wii)
|
||||
|
@ -28,10 +28,8 @@ UINT8 *BurnMalloc(INT32 size)
|
||||
if (memptr[i] == NULL) {
|
||||
memptr[i] = (UINT8*)malloc(size);
|
||||
|
||||
if (memptr[i] == NULL) {
|
||||
bprintf (0, _T("BurnMalloc failed to allocate %d bytes of memory!\n"), size);
|
||||
if (memptr[i] == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset (memptr[i], 0, size); // set contents to 0
|
||||
|
||||
@ -39,8 +37,6 @@ UINT8 *BurnMalloc(INT32 size)
|
||||
}
|
||||
}
|
||||
|
||||
bprintf (0, _T("BurnMalloc called too many times!\n"));
|
||||
|
||||
return NULL; // Freak out!
|
||||
}
|
||||
|
||||
@ -66,10 +62,8 @@ void BurnExitMemoryManager()
|
||||
{
|
||||
for (INT32 i = 0; i < MAX_MEM_PTR; i++)
|
||||
{
|
||||
if (memptr[i] != NULL) {
|
||||
#if defined FBA_DEBUG
|
||||
bprintf(PRINT_ERROR, _T("BurnExitMemoryManager had to free mem pointer %i\n"), i);
|
||||
#endif
|
||||
if (memptr[i] != NULL)
|
||||
{
|
||||
free (memptr[i]);
|
||||
memptr[i] = NULL;
|
||||
}
|
||||
|
@ -14,16 +14,6 @@
|
||||
#include "state.h"
|
||||
#include "ay8910.h"
|
||||
|
||||
#if defined FBA_DEBUG
|
||||
#ifdef __GNUC__
|
||||
// MSVC doesn't like this - this module only supports debug tracking with GCC only
|
||||
#include <tchar.h>
|
||||
extern UINT8 DebugSnd_AY8910Initted;
|
||||
extern INT32 (__cdecl *bprintf) (INT32 nStatus, TCHAR* szFormat, ...);
|
||||
#define PRINT_ERROR (3)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define MAX_OUTPUT 0x7fff
|
||||
|
||||
#define STEP 0x8000
|
||||
@ -317,13 +307,6 @@ void AY8910Write(INT32 chip, INT32 a, INT32 data)
|
||||
{
|
||||
struct AY8910 *PSG = &AYPSG[chip];
|
||||
|
||||
#if defined FBA_DEBUG
|
||||
#ifdef __GNUC__
|
||||
if (!DebugSnd_AY8910Initted) bprintf(PRINT_ERROR, _T("AY8910Write called without init\n"));
|
||||
if (chip > num) bprintf(PRINT_ERROR, _T("AY8910Write called with invalid chip number %x\n"), chip);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (a & 1)
|
||||
{ /* Data port */
|
||||
AYWriteReg(chip,PSG->register_latch,data);
|
||||
@ -338,13 +321,6 @@ INT32 AY8910Read(INT32 chip)
|
||||
{
|
||||
struct AY8910 *PSG = &AYPSG[chip];
|
||||
|
||||
#if defined FBA_DEBUG
|
||||
#ifdef __GNUC__
|
||||
if (!DebugSnd_AY8910Initted) bprintf(PRINT_ERROR, _T("AY8910Read called without init\n"));
|
||||
if (chip > num) bprintf(PRINT_ERROR, _T("AY8910Read called with invalid chip number %x\n"), chip);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return AYReadReg(chip,PSG->register_latch);
|
||||
}
|
||||
|
||||
@ -354,13 +330,6 @@ void AY8910Update(INT32 chip, INT16 **buffer, INT32 length)
|
||||
INT16 *buf1,*buf2,*buf3;
|
||||
INT32 outn;
|
||||
|
||||
#if defined FBA_DEBUG
|
||||
#ifdef __GNUC__
|
||||
if (!DebugSnd_AY8910Initted) bprintf(PRINT_ERROR, _T("AY8910Update called without init\n"));
|
||||
if (chip > num) bprintf(PRINT_ERROR, _T("AY8910Update called with invalid chip number %x\n"), chip);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
buf1 = buffer[0];
|
||||
buf2 = buffer[1];
|
||||
buf3 = buffer[2];
|
||||
@ -623,13 +592,6 @@ void AY8910_set_clock(INT32 chip, INT32 clock)
|
||||
{
|
||||
struct AY8910 *PSG = &AYPSG[chip];
|
||||
|
||||
#if defined FBA_DEBUG
|
||||
#ifdef __GNUC__
|
||||
if (!DebugSnd_AY8910Initted) bprintf(PRINT_ERROR, _T("AY8910_set_clock called without init\n"));
|
||||
if (chip > num) bprintf(PRINT_ERROR, _T("AY8910_set_clock called with invalid chip number %x\n"), chip);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* the step clock for the tone and noise generators is the chip clock */
|
||||
/* divided by 8; for the envelope generator of the AY-3-8910, it is half */
|
||||
/* that much (clock/16), but the envelope of the YM2149 goes twice as */
|
||||
@ -670,13 +632,6 @@ void AY8910Reset(INT32 chip)
|
||||
INT32 i;
|
||||
struct AY8910 *PSG = &AYPSG[chip];
|
||||
|
||||
#if defined FBA_DEBUG
|
||||
#ifdef __GNUC__
|
||||
if (!DebugSnd_AY8910Initted) bprintf(PRINT_ERROR, _T("AY8910Reset called without init\n"));
|
||||
if (chip > num) bprintf(PRINT_ERROR, _T("AY8910Reset called with invalid chip number %x\n"), chip);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
PSG->register_latch = 0;
|
||||
PSG->RNG = 1;
|
||||
PSG->OutputA = 0;
|
||||
@ -694,22 +649,10 @@ void AY8910Exit(INT32 chip)
|
||||
{
|
||||
(void)chip;
|
||||
|
||||
#if defined FBA_DEBUG
|
||||
#ifdef __GNUC__
|
||||
if (!DebugSnd_AY8910Initted && !chip) bprintf(PRINT_ERROR, _T("AY8910Exit called without init\n"));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
num = 0;
|
||||
ym_num = 0;
|
||||
|
||||
ay8910_index_ym = 0;
|
||||
|
||||
#if defined FBA_DEBUG
|
||||
#ifdef __GNUC__
|
||||
DebugSnd_AY8910Initted = 0;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static void dummy_callback(void)
|
||||
@ -723,12 +666,6 @@ INT32 AY8910Init(INT32 chip, INT32 clock, INT32 sample_rate,
|
||||
{
|
||||
struct AY8910 *PSG = &AYPSG[chip];
|
||||
|
||||
#if defined FBA_DEBUG
|
||||
#ifdef __GNUC__
|
||||
DebugSnd_AY8910Initted = 1;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
AYStreamUpdate = dummy_callback;
|
||||
|
||||
if (chip != num) {
|
||||
@ -784,13 +721,6 @@ INT32 AY8910SetPorts(INT32 chip, read8_handler portAread, read8_handler portBrea
|
||||
write8_handler portAwrite, write8_handler portBwrite)
|
||||
{
|
||||
struct AY8910 *PSG = &AYPSG[chip];
|
||||
|
||||
#if defined FBA_DEBUG
|
||||
#ifdef __GNUC__
|
||||
if (!DebugSnd_AY8910Initted) bprintf(PRINT_ERROR, _T("AY8910SetPorts called without init\n"));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
PSG->PortAread = portAread;
|
||||
PSG->PortBread = portBread;
|
||||
PSG->PortAwrite = portAwrite;
|
||||
@ -804,15 +734,8 @@ INT32 AY8910Scan(INT32 nAction, INT32* pnMin)
|
||||
struct BurnArea ba;
|
||||
INT32 i;
|
||||
|
||||
#if defined FBA_DEBUG
|
||||
#ifdef __GNUC__
|
||||
if (!DebugSnd_AY8910Initted) bprintf(PRINT_ERROR, _T("AY8910Scan called without init\n"));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if ((nAction & ACB_DRIVER_DATA) == 0) {
|
||||
if ((nAction & ACB_DRIVER_DATA) == 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pnMin && *pnMin < 0x029496) { // Return minimum compatible version
|
||||
*pnMin = 0x029496;
|
||||
@ -843,13 +766,6 @@ INT32 AY8910Scan(INT32 nAction, INT32* pnMin)
|
||||
|
||||
void AY8910Render(INT16** buffer, INT16* dest, INT32 length, INT32 bAddSignal)
|
||||
{
|
||||
#if defined FBA_DEBUG
|
||||
#ifdef __GNUC__
|
||||
if (!DebugSnd_AY8910Initted) bprintf(PRINT_ERROR, _T("AY8910Render called without init\n"));
|
||||
if (num >= 7) bprintf(PRINT_ERROR, _T("AY8910Render called with invalid number of chips %i (max is 6)\n"), num);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
INT32 i;
|
||||
INT16 *buf0 = buffer[0];
|
||||
INT16 *buf1 = buffer[1];
|
||||
@ -939,14 +855,6 @@ void AY8910Render(INT16** buffer, INT16* dest, INT32 length, INT32 bAddSignal)
|
||||
|
||||
void AY8910SetRoute(INT32 chip, INT32 nIndex, double nVolume, INT32 nRouteDir)
|
||||
{
|
||||
#if defined FBA_DEBUG
|
||||
#ifdef __GNUC__
|
||||
if (!DebugSnd_AY8910Initted) bprintf(PRINT_ERROR, _T("AY8910SetRoute called without init\n"));
|
||||
if (nIndex < 0 || nIndex > 2) bprintf(PRINT_ERROR, _T("AY8910SetRoute called with invalid index %i\n"), nIndex);
|
||||
if (chip >= num) bprintf(PRINT_ERROR, _T("AY8910SetRoute called with invalid chip %i\n"), chip);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
AY8910Volumes[(chip * 3) + nIndex] = nVolume;
|
||||
AY8910RouteDirs[(chip * 3) + nIndex] = nRouteDir;
|
||||
}
|
||||
|
@ -1,263 +0,0 @@
|
||||
#include "burnint.h"
|
||||
#include "burn_sound.h"
|
||||
#include "burn_ymf278b.h"
|
||||
|
||||
static INT32 (*BurnYMF278BStreamCallback)(INT32 nSoundRate);
|
||||
|
||||
static INT16* pBuffer;
|
||||
static INT16* pYMF278BBuffer[2];
|
||||
|
||||
static INT32 nYMF278BPosition;
|
||||
static INT32 nFractionalPosition;
|
||||
|
||||
static double YMF278BVolumes[2];
|
||||
static INT32 YMF278BRouteDirs[2];
|
||||
// This is not used for NeoGeo right?
|
||||
#if 0
|
||||
// ----------------------------------------------------------------------------
|
||||
// Dummy functions
|
||||
|
||||
static INT32 YMF278BStreamCallbackDummy(INT32 /* nSoundRate */)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Execute YMF278B for part of a frame
|
||||
|
||||
static void YMF278BRender(INT32 nSegmentLength)
|
||||
{
|
||||
#if defined FBA_DEBUG
|
||||
if (!DebugSnd_YMF278BInitted) bprintf(PRINT_ERROR, _T("YMF278BRender called without init\n"));
|
||||
#endif
|
||||
|
||||
if (nYMF278BPosition >= nSegmentLength) {
|
||||
return;
|
||||
}
|
||||
|
||||
// bprintf(PRINT_NORMAL, _T(" YMF278B render %6i -> %6i\n"), nYMF278BPosition, nSegmentLength);
|
||||
|
||||
nSegmentLength -= nYMF278BPosition;
|
||||
|
||||
pYMF278BBuffer[0] = pBuffer + 0 * 4096 + 4 + nYMF278BPosition;
|
||||
pYMF278BBuffer[1] = pBuffer + 1 * 4096 + 4 + nYMF278BPosition;
|
||||
|
||||
ymf278b_pcm_update(0, pYMF278BBuffer, nSegmentLength);
|
||||
|
||||
nYMF278BPosition += nSegmentLength;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Update the sound buffer
|
||||
|
||||
void BurnYMF278BUpdate(INT32 nSegmentEnd)
|
||||
{
|
||||
#if defined FBA_DEBUG
|
||||
if (!DebugSnd_YMF278BInitted) bprintf(PRINT_ERROR, _T("BurnYMF278BUpdate called without init\n"));
|
||||
#endif
|
||||
|
||||
INT16* pSoundBuf = pBurnSoundOut;
|
||||
INT32 nSegmentLength = nSegmentEnd;
|
||||
|
||||
// bprintf(PRINT_NORMAL, _T(" YMF278B render %6i -> %6i\n"), nYMF278BPosition, nSegmentEnd);
|
||||
|
||||
if (nBurnSoundRate == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nSegmentEnd < nYMF278BPosition) {
|
||||
nSegmentEnd = nYMF278BPosition;
|
||||
}
|
||||
|
||||
if (nSegmentLength > nBurnSoundLen) {
|
||||
nSegmentLength = nBurnSoundLen;
|
||||
}
|
||||
|
||||
YMF278BRender(nSegmentEnd);
|
||||
|
||||
pYMF278BBuffer[0] = pBuffer + 0 * 4096 + 4;
|
||||
pYMF278BBuffer[1] = pBuffer + 1 * 4096 + 4;
|
||||
|
||||
for (INT32 n = nFractionalPosition; n < nSegmentLength; n++) {
|
||||
INT32 nLeftSample = 0, nRightSample = 0;
|
||||
|
||||
if ((YMF278BRouteDirs[BURN_SND_YMF278B_YMF278B_ROUTE_1] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
|
||||
nLeftSample += (INT32)(pYMF278BBuffer[0][n] * YMF278BVolumes[BURN_SND_YMF278B_YMF278B_ROUTE_1]);
|
||||
}
|
||||
if ((YMF278BRouteDirs[BURN_SND_YMF278B_YMF278B_ROUTE_1] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
|
||||
nRightSample += (INT32)(pYMF278BBuffer[0][n] * YMF278BVolumes[BURN_SND_YMF278B_YMF278B_ROUTE_1]);
|
||||
}
|
||||
|
||||
if ((YMF278BRouteDirs[BURN_SND_YMF278B_YMF278B_ROUTE_2] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
|
||||
nLeftSample += (INT32)(pYMF278BBuffer[1][n] * YMF278BVolumes[BURN_SND_YMF278B_YMF278B_ROUTE_2]);
|
||||
}
|
||||
if ((YMF278BRouteDirs[BURN_SND_YMF278B_YMF278B_ROUTE_2] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
|
||||
nRightSample += (INT32)(pYMF278BBuffer[1][n] * YMF278BVolumes[BURN_SND_YMF278B_YMF278B_ROUTE_2]);
|
||||
}
|
||||
|
||||
nLeftSample = BURN_SND_CLIP(nLeftSample);
|
||||
nRightSample = BURN_SND_CLIP(nRightSample);
|
||||
|
||||
pSoundBuf[(n << 1) + 0] = nLeftSample;
|
||||
pSoundBuf[(n << 1) + 1] = nRightSample;
|
||||
}
|
||||
|
||||
nFractionalPosition = nSegmentLength;
|
||||
|
||||
if (nSegmentEnd >= nBurnSoundLen) {
|
||||
INT32 nExtraSamples = nSegmentEnd - nBurnSoundLen;
|
||||
|
||||
for (INT32 i = 0; i < nExtraSamples; i++) {
|
||||
pYMF278BBuffer[0][i] = pYMF278BBuffer[0][nBurnSoundLen + i];
|
||||
pYMF278BBuffer[1][i] = pYMF278BBuffer[1][nBurnSoundLen + i];
|
||||
}
|
||||
|
||||
nFractionalPosition = 0;
|
||||
|
||||
nYMF278BPosition = nExtraSamples;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void BurnYMF278BSelectRegister(INT32 nRegister, UINT8 nValue)
|
||||
{
|
||||
#if defined FBA_DEBUG
|
||||
if (!DebugSnd_YMF278BInitted) bprintf(PRINT_ERROR, _T("BurnYMF278BSelectRegister called without init\n"));
|
||||
#endif
|
||||
|
||||
switch (nRegister) {
|
||||
case 0:
|
||||
// bprintf(PRINT_NORMAL, _T(" YMF278B register A -> %i\n"), nValue);
|
||||
YMF278B_control_port_0_A_w(nValue);
|
||||
break;
|
||||
case 1:
|
||||
YMF278B_control_port_0_B_w(nValue);
|
||||
break;
|
||||
case 2:
|
||||
// bprintf(PRINT_NORMAL, _T(" YMF278B register C -> %i\n"), nValue);
|
||||
YMF278B_control_port_0_C_w(nValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
void BurnYMF278BWriteRegister(INT32 nRegister, UINT8 nValue)
|
||||
{
|
||||
#if defined FBA_DEBUG
|
||||
if (!DebugSnd_YMF278BInitted) bprintf(PRINT_ERROR, _T("BurnYMF278BWriteRegister called without init\n"));
|
||||
#endif
|
||||
|
||||
switch (nRegister) {
|
||||
case 0:
|
||||
BurnYMF278BUpdate(BurnYMF278BStreamCallback(nBurnSoundRate));
|
||||
YMF278B_data_port_0_A_w(nValue);
|
||||
break;
|
||||
case 1:
|
||||
YMF278B_data_port_0_B_w(nValue);
|
||||
break;
|
||||
case 2:
|
||||
BurnYMF278BUpdate(BurnYMF278BStreamCallback(nBurnSoundRate));
|
||||
YMF278B_data_port_0_C_w(nValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 BurnYMF278BReadStatus()
|
||||
{
|
||||
#if defined FBA_DEBUG
|
||||
if (!DebugSnd_YMF278BInitted) bprintf(PRINT_ERROR, _T("BurnYMF278BReadStatus called without init\n"));
|
||||
#endif
|
||||
|
||||
BurnYMF278BUpdate(BurnYMF278BStreamCallback(nBurnSoundRate));
|
||||
return YMF278B_status_port_0_r();
|
||||
}
|
||||
|
||||
UINT8 BurnYMF278BReadData()
|
||||
{
|
||||
#if defined FBA_DEBUG
|
||||
if (!DebugSnd_YMF278BInitted) bprintf(PRINT_ERROR, _T("BurnYMF278BReadData called without init\n"));
|
||||
#endif
|
||||
|
||||
return YMF278B_data_port_0_r();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void BurnYMF278BReset()
|
||||
{
|
||||
#if defined FBA_DEBUG
|
||||
if (!DebugSnd_YMF278BInitted) bprintf(PRINT_ERROR, _T("BurnYMF278BReset called without init\n"));
|
||||
#endif
|
||||
|
||||
BurnTimerReset();
|
||||
}
|
||||
|
||||
void BurnYMF278BExit()
|
||||
{
|
||||
#if defined FBA_DEBUG
|
||||
if (!DebugSnd_YMF278BInitted) bprintf(PRINT_ERROR, _T("BurnYMF278BExit called without init\n"));
|
||||
#endif
|
||||
|
||||
YMF278B_sh_stop();
|
||||
|
||||
BurnTimerExit();
|
||||
|
||||
if (pBuffer) {
|
||||
free(pBuffer);
|
||||
pBuffer = NULL;
|
||||
}
|
||||
|
||||
DebugSnd_YMF278BInitted = 0;
|
||||
}
|
||||
|
||||
INT32 BurnYMF278BInit(INT32 /* nClockFrequency */, UINT8* YMF278BROM, void (*IRQCallback)(INT32, INT32), INT32 (*StreamCallback)(INT32))
|
||||
{
|
||||
DebugSnd_YMF278BInitted = 1;
|
||||
BurnYMF278BExit();
|
||||
DebugSnd_YMF278BInitted = 1;
|
||||
|
||||
BurnYMF278BStreamCallback = YMF278BStreamCallbackDummy;
|
||||
if (StreamCallback) {
|
||||
BurnYMF278BStreamCallback = StreamCallback;
|
||||
}
|
||||
|
||||
ymf278b_start(0, YMF278BROM, IRQCallback, BurnYMFTimerCallback, YMF278B_STD_CLOCK, nBurnSoundRate);
|
||||
BurnTimerInit(ymf278b_timer_over, NULL);
|
||||
|
||||
pBuffer = (INT16*)malloc(4096 * 2 * sizeof(INT16));
|
||||
memset(pBuffer, 0, 4096 * 2 * sizeof(INT16));
|
||||
|
||||
nYMF278BPosition = 0;
|
||||
|
||||
nFractionalPosition = 0;
|
||||
|
||||
// default routes
|
||||
YMF278BVolumes[BURN_SND_YMF278B_YMF278B_ROUTE_1] = 1.00;
|
||||
YMF278BVolumes[BURN_SND_YMF278B_YMF278B_ROUTE_2] = 1.00;
|
||||
YMF278BRouteDirs[BURN_SND_YMF278B_YMF278B_ROUTE_1] = BURN_SND_ROUTE_LEFT;
|
||||
YMF278BRouteDirs[BURN_SND_YMF278B_YMF278B_ROUTE_2] = BURN_SND_ROUTE_RIGHT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BurnYMF278BSetRoute(INT32 nIndex, double nVolume, INT32 nRouteDir)
|
||||
{
|
||||
#if defined FBA_DEBUG
|
||||
if (!DebugSnd_YMF278BInitted) bprintf(PRINT_ERROR, _T("BurnYMF278BSetRoute called without init\n"));
|
||||
if (nIndex < 0 || nIndex > 1) bprintf(PRINT_ERROR, _T("BurnYMF278BSetRoute called with invalid index %i\n"), nIndex);
|
||||
#endif
|
||||
|
||||
YMF278BVolumes[nIndex] = nVolume;
|
||||
YMF278BRouteDirs[nIndex] = nRouteDir;
|
||||
}
|
||||
|
||||
void BurnYMF278BScan(INT32 nAction, INT32* pnMin)
|
||||
{
|
||||
#if defined FBA_DEBUG
|
||||
if (!DebugSnd_YMF278BInitted) bprintf(PRINT_ERROR, _T("BurnYMF278BScan called without init\n"));
|
||||
#endif
|
||||
|
||||
BurnTimerScan(nAction, pnMin);
|
||||
}
|
||||
#endif
|
@ -1,25 +0,0 @@
|
||||
#include "driver.h"
|
||||
extern "C" {
|
||||
#include "ymf278b.h"
|
||||
}
|
||||
|
||||
#include "timer.h"
|
||||
|
||||
void BurnYMF278BSelectRegister(INT32 nRegister, UINT8 nValue);
|
||||
void BurnYMF278BWriteRegister(INT32 nRegister, UINT8 nValue);
|
||||
UINT8 BurnYMF278BReadStatus();
|
||||
UINT8 BurnYMF278BReadData();
|
||||
|
||||
INT32 BurnYMF278BInit(INT32 nClockFrequency, UINT8* YMF278BROM, void (*IRQCallback)(INT32, INT32), INT32 (*StreamCallback)(INT32));
|
||||
void BurnYMF278BSetRoute(INT32 nIndex, double nVolume, INT32 nRouteDir);
|
||||
void BurnYMF278BReset();
|
||||
void BurnYMF278BExit();
|
||||
void BurnYMF278BUpdate(INT32 nSegmentEnd);
|
||||
void BurnYMF278BScan(INT32 nAction, INT32* pnMin);
|
||||
|
||||
#define BURN_SND_YMF278B_YMF278B_ROUTE_1 0
|
||||
#define BURN_SND_YMF278B_YMF278B_ROUTE_2 1
|
||||
|
||||
#define BurnYMF278BSetAllRoutes(v, d) \
|
||||
BurnYMF278BSetRoute(BURN_SND_YMF278B_YMF278B_ROUTE_1, v, d); \
|
||||
BurnYMF278BSetRoute(BURN_SND_YMF278B_YMF278B_ROUTE_2, v, d);
|
@ -1,844 +0,0 @@
|
||||
/*
|
||||
Timer and PCM YMF278B. The FM will be shared with the ymf262, eventually.
|
||||
|
||||
This chip roughly splits the difference between the Sega 315-5560 MultiPCM
|
||||
(Multi32, Model 1/2) and YMF 292-F SCSP (later Model 2, STV, Saturn, Model 3).
|
||||
|
||||
By R. Belmont and O. Galibert.
|
||||
|
||||
Copyright (c) 2002-2003 R. Belmont and O. Galibert.
|
||||
|
||||
This software is dual-licensed: it may be used in MAME and properly licensed
|
||||
MAME derivatives under the terms of the MAME license. For use outside of
|
||||
MAME and properly licensed derivatives, it is available under the
|
||||
terms of the GNU Lesser General Public License (LGPL), version 2.1.
|
||||
You may read the LGPL at http://www.gnu.org/licenses/lgpl.html
|
||||
|
||||
Changelog:
|
||||
Sep. 8, 2002 - fixed ymf278b_compute_rate when OCT is negative (RB)
|
||||
Dec. 11, 2002 - added ability to set non-standard clock rates (RB)
|
||||
fixed envelope target for release (fixes missing
|
||||
instruments in hotdebut).
|
||||
Thanks to Team Japump! for MP3s from a real PCB.
|
||||
fixed crash if MAME is run with no sound.
|
||||
June 4, 2003 - Changed to dual-license with LGPL for use in OpenMSX.
|
||||
OpenMSX contributed a bugfix where looped samples were
|
||||
not being addressed properly, causing pitch fluctuation.
|
||||
|
||||
---
|
||||
|
||||
Jan 2005 - All changes needed for FB Alpha are marked as !!! FBA
|
||||
and contained within #if blocks
|
||||
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#include <math.h>
|
||||
#include "driver.h"
|
||||
|
||||
#ifdef FBA /* !!! FBA */
|
||||
#include "ymf278b.h"
|
||||
typedef struct { int sample_rate; } MACHINE;
|
||||
MACHINE machine;
|
||||
MACHINE* Machine = &machine;
|
||||
#else /* !!! FBA */
|
||||
#include "cpuintrf.h"
|
||||
#include "ymf278b.h"
|
||||
#endif /* !!! FBA */
|
||||
|
||||
#undef VERBOSE
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
INT16 wave; /* wavetable number */
|
||||
INT16 FN; /* f-number */
|
||||
INT8 OCT; /* octave */
|
||||
INT8 PRVB; /* pseudo-reverb */
|
||||
INT8 LD; /* level direct */
|
||||
INT8 TL; /* total level */
|
||||
INT8 pan; /* panpot */
|
||||
INT8 lfo; /* LFO */
|
||||
INT8 vib; /* vibrato */
|
||||
INT8 AM; /* AM level */
|
||||
|
||||
INT8 AR;
|
||||
INT8 D1R;
|
||||
INT8 DL;
|
||||
INT8 D2R;
|
||||
INT8 RC; /* rate correction */
|
||||
INT8 RR;
|
||||
|
||||
UINT32 step; /* fixed-point frequency step */
|
||||
UINT32 stepptr; /* fixed-point pointer into the sample */
|
||||
|
||||
INT8 active; /* slot keyed on */
|
||||
INT8 bits; /* width of the samples */
|
||||
UINT32 startaddr;
|
||||
UINT32 loopaddr;
|
||||
UINT32 endaddr;
|
||||
|
||||
int env_step;
|
||||
UINT32 env_vol;
|
||||
UINT32 env_vol_step;
|
||||
UINT32 env_vol_lim;
|
||||
} YMF278BSlot;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
YMF278BSlot slots[24];
|
||||
INT8 lsitest0;
|
||||
INT8 lsitest1;
|
||||
INT8 wavetblhdr;
|
||||
INT8 memmode;
|
||||
INT32 memadr;
|
||||
|
||||
INT32 fm_l, fm_r;
|
||||
INT32 pcm_l, pcm_r;
|
||||
|
||||
UINT8 timer_a_count, timer_b_count, enable, current_irq;
|
||||
#ifndef FBA /* !!! FBA */
|
||||
void *timer_a, *timer_b;
|
||||
#endif /* !!! FBA */
|
||||
int irq_line;
|
||||
|
||||
UINT8 port_A, port_B, port_C;
|
||||
void (*irq_callback)(int, int);
|
||||
#ifdef FBA /* !!! FBA */
|
||||
void (*timer_callback)(int, int, double);
|
||||
#endif /* !!! FBA */
|
||||
|
||||
const UINT8 *rom;
|
||||
float clock_ratio;
|
||||
} YMF278BChip;
|
||||
|
||||
static YMF278BChip YMF278B[MAX_YMF278B];
|
||||
static INT32 volume[256*4]; // precalculated attenuation values with some marging for enveloppe and pan levels
|
||||
static int pan_left[16], pan_right[16]; // pan volume offsets
|
||||
static INT32 mix_level[8];
|
||||
|
||||
static int ymf278b_compute_rate(YMF278BSlot *slot, int val)
|
||||
{
|
||||
int res, oct;
|
||||
|
||||
if(val == 0)
|
||||
return 0;
|
||||
if(val == 15)
|
||||
return 63;
|
||||
if(slot->RC != 15)
|
||||
{
|
||||
oct = slot->OCT;
|
||||
if (oct & 8) oct |= -8;
|
||||
|
||||
res = (oct+slot->RC)*2 + (slot->FN & 0x200 ? 1 : 0) + val*4;
|
||||
}
|
||||
else
|
||||
res = val * 4;
|
||||
if(res < 0)
|
||||
res = 0;
|
||||
else if(res > 63)
|
||||
res = 63;
|
||||
return res;
|
||||
}
|
||||
|
||||
static UINT32 ymf278_compute_decay_rate(int num)
|
||||
{
|
||||
int samples;
|
||||
|
||||
if (num <= 3)
|
||||
samples = 0;
|
||||
else if (num >= 60)
|
||||
samples = 15 << 4;
|
||||
else
|
||||
{
|
||||
samples = (15 << (21 - num / 4)) / (4 + num % 4);
|
||||
if (num % 4 && num / 4 <= 11)
|
||||
samples += 2;
|
||||
else if (num == 51)
|
||||
samples += 2;
|
||||
}
|
||||
|
||||
return ((UINT64)samples * Machine->sample_rate) / 44100;
|
||||
}
|
||||
|
||||
static void ymf278b_envelope_next(YMF278BSlot *slot, float clock_ratio)
|
||||
{
|
||||
if(slot->env_step == 0)
|
||||
{
|
||||
// Attack
|
||||
slot->env_vol = (256U << 23) - 1;
|
||||
slot->env_vol_lim = 256U<<23;
|
||||
#ifdef VERBOSE
|
||||
logerror("YMF278B: Skipping attack (rate = %d)\n", slot->AR);
|
||||
#endif
|
||||
slot->env_step++;
|
||||
}
|
||||
if(slot->env_step == 1)
|
||||
{
|
||||
// Decay 1
|
||||
slot->env_vol = 0;
|
||||
slot->env_step++;
|
||||
if(slot->DL)
|
||||
{
|
||||
int rate = ymf278b_compute_rate(slot, slot->D1R);
|
||||
#ifdef VERBOSE
|
||||
logerror("YMF278B: Decay step 1, dl=%d, val = %d rate = %d, delay = %g\n", slot->DL, slot->D1R, rate, ymf278_compute_decay_rate(rate)*1000.0*clock_ratio/Machine->sample_rate);
|
||||
#endif
|
||||
if(rate<4)
|
||||
slot->env_vol_step = 0;
|
||||
else
|
||||
slot->env_vol_step = ((slot->DL*8)<<23) / (ymf278_compute_decay_rate(rate) * clock_ratio);
|
||||
slot->env_vol_lim = (slot->DL*8)<<23;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(slot->env_step == 2)
|
||||
{
|
||||
// Decay 2
|
||||
int rate = ymf278b_compute_rate(slot, slot->D2R);
|
||||
#ifdef VERBOSE
|
||||
logerror("YMF278B: Decay step 2, val = %d, rate = %d, delay = %g, current vol = %d\n", slot->D2R, rate, ymf278_compute_decay_rate(rate)*1000.0*clock_ratio/Machine->sample_rate, slot->env_vol >> 23);
|
||||
#endif
|
||||
if(rate<4)
|
||||
slot->env_vol_step = 0;
|
||||
else
|
||||
slot->env_vol_step = ((256U-slot->DL*8)<<23) / (ymf278_compute_decay_rate(rate) * clock_ratio);
|
||||
slot->env_vol_lim = 256U<<23;
|
||||
slot->env_step++;
|
||||
return;
|
||||
}
|
||||
if(slot->env_step == 3)
|
||||
{
|
||||
// Decay 2 reached -96dB
|
||||
#ifdef VERBOSE
|
||||
logerror("YMF278B: Voice cleared because of decay 2\n");
|
||||
#endif
|
||||
slot->env_vol = 256U<<23;
|
||||
slot->env_vol_step = 0;
|
||||
slot->env_vol_lim = 0;
|
||||
slot->active = 0;
|
||||
return;
|
||||
}
|
||||
if(slot->env_step == 4)
|
||||
{
|
||||
// Release
|
||||
int rate = ymf278b_compute_rate(slot, slot->RR);
|
||||
#ifdef VERBOSE
|
||||
logerror("YMF278B: Release, val = %d, rate = %d, delay = %g\n", slot->RR, rate, ymf278_compute_decay_rate(rate)*1000.0*clock_ratio/Machine->sample_rate);
|
||||
#endif
|
||||
if(rate<4)
|
||||
slot->env_vol_step = 0;
|
||||
else
|
||||
slot->env_vol_step = ((256U<<23)-slot->env_vol) / (ymf278_compute_decay_rate(rate) * clock_ratio);
|
||||
slot->env_vol_lim = 256U<<23;
|
||||
slot->env_step++;
|
||||
return;
|
||||
}
|
||||
if(slot->env_step == 5)
|
||||
{
|
||||
// Release reached -96dB
|
||||
#ifdef VERBOSE
|
||||
logerror("YMF278B: Release ends\n");
|
||||
#endif
|
||||
slot->env_vol = 256U<<23;
|
||||
slot->env_vol_step = 0;
|
||||
slot->env_vol_lim = 0;
|
||||
slot->active = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ymf278b_pcm_update(int num, INT16 **outputs, int length)
|
||||
{
|
||||
int i, j;
|
||||
YMF278BSlot *slot = NULL;
|
||||
INT16 sample = 0;
|
||||
const UINT8 *rombase;
|
||||
INT32 mix[44100*2];
|
||||
INT32 *mixp;
|
||||
INT32 vl, vr;
|
||||
|
||||
memset(mix, 0, sizeof(mix[0])*length*2);
|
||||
|
||||
rombase = YMF278B[num].rom;
|
||||
|
||||
for (i = 0; i < 24; i++)
|
||||
{
|
||||
slot = &YMF278B[num].slots[i];
|
||||
|
||||
if (slot->active)
|
||||
{
|
||||
mixp = mix;
|
||||
|
||||
for (j = 0; j < length; j++)
|
||||
{
|
||||
switch (slot->bits)
|
||||
{
|
||||
case 8: // 8 bit
|
||||
sample = rombase[slot->startaddr + (slot->stepptr>>16)]<<8;
|
||||
break;
|
||||
|
||||
case 12: // 12 bit
|
||||
if (slot->stepptr & 1)
|
||||
sample = rombase[slot->startaddr + (slot->stepptr>>17)*3 + 2]<<8 | ((rombase[slot->startaddr + (slot->stepptr>>17)*3 + 1] << 4) & 0xf0);
|
||||
else
|
||||
sample = rombase[slot->startaddr + (slot->stepptr>>17)*3]<<8 | (rombase[slot->startaddr + (slot->stepptr>>17)*3 + 1] & 0xf0);
|
||||
break;
|
||||
|
||||
case 16: // 16 bit
|
||||
sample = rombase[slot->startaddr + ((slot->stepptr>>16)*2)]<<8;
|
||||
sample |= rombase[slot->startaddr + ((slot->stepptr>>16)*2) + 1];
|
||||
break;
|
||||
}
|
||||
|
||||
*mixp++ += (sample * volume[slot->TL+pan_left [slot->pan]+(slot->env_vol>>23)])>>17;
|
||||
*mixp++ += (sample * volume[slot->TL+pan_right[slot->pan]+(slot->env_vol>>23)])>>17;
|
||||
|
||||
// update frequency
|
||||
slot->stepptr += slot->step;
|
||||
if(slot->stepptr >= slot->endaddr)
|
||||
{
|
||||
slot->stepptr = slot->stepptr - slot->endaddr + slot->loopaddr;
|
||||
// If the step is bigger than the loop, finish the sample forcibly
|
||||
if(slot->stepptr >= slot->endaddr)
|
||||
{
|
||||
slot->env_vol = 256U<<23;
|
||||
slot->env_vol_step = 0;
|
||||
slot->env_vol_lim = 0;
|
||||
slot->active = 0;
|
||||
slot->stepptr = 0;
|
||||
slot->step = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// update envelope
|
||||
slot->env_vol += slot->env_vol_step;
|
||||
if(((INT32)(slot->env_vol - slot->env_vol_lim)) >= 0)
|
||||
ymf278b_envelope_next(slot, YMF278B[num].clock_ratio);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mixp = mix;
|
||||
vl = mix_level[YMF278B[num].pcm_l];
|
||||
vr = mix_level[YMF278B[num].pcm_r];
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
outputs[0][i] = (*mixp++ * vl) >> 16;
|
||||
outputs[1][i] = (*mixp++ * vr) >> 16;
|
||||
}
|
||||
}
|
||||
|
||||
static void ymf278b_irq_check(int num)
|
||||
{
|
||||
YMF278BChip *chip = &YMF278B[num];
|
||||
int prev_line = chip->irq_line;
|
||||
chip->irq_line = chip->current_irq ? ASSERT_LINE : CLEAR_LINE;
|
||||
if(chip->irq_line != prev_line && chip->irq_callback)
|
||||
chip->irq_callback(num, chip->irq_line);
|
||||
}
|
||||
|
||||
#ifdef FBA /* !!! FBA */
|
||||
int ymf278b_timer_over(int num, int timer)
|
||||
{
|
||||
YMF278BChip *chip = &YMF278B[num];
|
||||
if(!(chip->enable & (0x20 << timer)))
|
||||
{
|
||||
chip->current_irq |= (0x20 << timer);
|
||||
ymf278b_irq_check(num);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else /* !!! FBA */
|
||||
static void ymf278b_timer_a_tick(int num)
|
||||
{
|
||||
YMF278BChip *chip = &YMF278B[num];
|
||||
if(!(chip->enable & 0x40))
|
||||
{
|
||||
chip->current_irq |= 0x40;
|
||||
ymf278b_irq_check(num);
|
||||
}
|
||||
}
|
||||
|
||||
static void ymf278b_timer_b_tick(int num)
|
||||
{
|
||||
YMF278BChip *chip = &YMF278B[num];
|
||||
if(!(chip->enable & 0x20))
|
||||
{
|
||||
chip->current_irq |= 0x20;
|
||||
ymf278b_irq_check(num);
|
||||
}
|
||||
}
|
||||
#endif /* !!! FBA */
|
||||
|
||||
static void ymf278b_timer_a_reset(int num)
|
||||
{
|
||||
YMF278BChip *chip = &YMF278B[num];
|
||||
if(chip->enable & 1)
|
||||
{
|
||||
double period = (256-chip->timer_a_count) * 80.8 * chip->clock_ratio;
|
||||
chip->timer_callback(num, 0, period);
|
||||
}
|
||||
else
|
||||
chip->timer_callback(num, 0, 0);
|
||||
}
|
||||
|
||||
static void ymf278b_timer_b_reset(int num)
|
||||
{
|
||||
YMF278BChip *chip = &YMF278B[num];
|
||||
if(chip->enable & 2)
|
||||
{
|
||||
double period = (256-chip->timer_b_count) * 323.1 * chip->clock_ratio;
|
||||
chip->timer_callback(num, 1, period);
|
||||
}
|
||||
else
|
||||
chip->timer_callback(num, 1, 0);
|
||||
}
|
||||
|
||||
static void ymf278b_A_w(int num, UINT8 reg, UINT8 data)
|
||||
{
|
||||
YMF278BChip *chip = &YMF278B[num];
|
||||
|
||||
if (!Machine->sample_rate) return;
|
||||
|
||||
switch(reg)
|
||||
{
|
||||
case 0x02:
|
||||
chip->timer_a_count = data;
|
||||
ymf278b_timer_a_reset(num);
|
||||
break;
|
||||
case 0x03:
|
||||
chip->timer_b_count = data;
|
||||
ymf278b_timer_b_reset(num);
|
||||
break;
|
||||
case 0x04:
|
||||
if(data & 0x80)
|
||||
chip->current_irq = 0;
|
||||
else
|
||||
{
|
||||
UINT8 old_enable = chip->enable;
|
||||
chip->enable = data;
|
||||
chip->current_irq &= ~data;
|
||||
if((old_enable ^ data) & 1)
|
||||
ymf278b_timer_a_reset(num);
|
||||
if((old_enable ^ data) & 2)
|
||||
ymf278b_timer_b_reset(num);
|
||||
}
|
||||
ymf278b_irq_check(num);
|
||||
break;
|
||||
default:
|
||||
logerror("YMF278B: Port A write %02x, %02x\n", reg, data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ymf278b_B_w(int num, UINT8 reg, UINT8 data)
|
||||
{
|
||||
if (!Machine->sample_rate) return;
|
||||
|
||||
logerror("YMF278B: Port B write %02x, %02x\n", reg, data);
|
||||
}
|
||||
|
||||
static void ymf278b_C_w(int num, UINT8 reg, UINT8 data)
|
||||
{
|
||||
YMF278BChip *chip = &YMF278B[num];
|
||||
|
||||
if (!Machine->sample_rate) return;
|
||||
|
||||
// Handle slot registers specifically
|
||||
if (reg >= 0x08 && reg <= 0xf7)
|
||||
{
|
||||
YMF278BSlot *slot = NULL;
|
||||
int snum;
|
||||
snum = (reg-8) % 24;
|
||||
slot = &YMF278B[num].slots[snum];
|
||||
switch((reg-8) / 24)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
const UINT8 *p;
|
||||
|
||||
slot->wave &= 0x100;
|
||||
slot->wave |= data;
|
||||
|
||||
if(slot->wave < 384 || !chip->wavetblhdr)
|
||||
p = chip->rom + (slot->wave * 12);
|
||||
else
|
||||
p = chip->rom + chip->wavetblhdr*0x80000 + ((slot->wave - 384) * 12);
|
||||
|
||||
switch (p[0]&0xc0)
|
||||
{
|
||||
case 0:
|
||||
slot->bits = 8;
|
||||
break;
|
||||
case 0x40:
|
||||
slot->bits = 12;
|
||||
break;
|
||||
case 0x80:
|
||||
slot->bits = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
slot->lfo = (p[7] >> 2) & 7;
|
||||
slot->vib = p[7] & 7;
|
||||
slot->AR = p[8] >> 4;
|
||||
slot->D1R = p[8] & 0xf;
|
||||
slot->DL = p[9] >> 4;
|
||||
slot->D2R = p[9] & 0xf;
|
||||
slot->RC = p[10] >> 4;
|
||||
slot->RR = p[10] & 0xf;
|
||||
slot->AM = p[11] & 7;
|
||||
|
||||
slot->startaddr = (p[2] | (p[1]<<8) | ((p[0]&0x3f)<<16));
|
||||
slot->loopaddr = (p[4]<<16) | (p[3]<<24);
|
||||
slot->endaddr = (p[6]<<16) | (p[5]<<24);
|
||||
slot->endaddr -= 0x00010000U;
|
||||
slot->endaddr ^= 0xffff0000U;
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
slot->wave &= 0xff;
|
||||
slot->wave |= ((data&0x1)<<8);
|
||||
slot->FN &= 0x380;
|
||||
slot->FN |= (data>>1);
|
||||
break;
|
||||
case 2:
|
||||
slot->FN &= 0x07f;
|
||||
slot->FN |= ((data&0x07)<<7);
|
||||
slot->PRVB = ((data&0x4)>>3);
|
||||
slot->OCT = ((data&0xf0)>>4);
|
||||
break;
|
||||
case 3:
|
||||
slot->TL = (data>>1);
|
||||
slot->LD = data&0x1;
|
||||
break;
|
||||
case 4:
|
||||
slot->pan = data&0xf;
|
||||
if (data & 0x80)
|
||||
{
|
||||
unsigned int step;
|
||||
int oct;
|
||||
|
||||
slot->active = 1;
|
||||
|
||||
oct = slot->OCT;
|
||||
if(oct & 8)
|
||||
oct |= -8;
|
||||
|
||||
slot->env_step = 0;
|
||||
slot->env_vol = 256U<<23;
|
||||
slot->env_vol_step = 0;
|
||||
slot->env_vol_lim = 256U<<23;
|
||||
slot->stepptr = 0;
|
||||
slot->step = 0;
|
||||
|
||||
step = (slot->FN | 1024) << (oct + 7);
|
||||
slot->step = (UINT32) ((((INT64)step)*(44100/4)) / Machine->sample_rate * chip->clock_ratio);
|
||||
|
||||
ymf278b_envelope_next(slot, chip->clock_ratio);
|
||||
|
||||
#ifdef VERBOSE
|
||||
logerror("YMF278B: slot %2d wave %3d lfo=%d vib=%d ar=%d d1r=%d dl=%d d2r=%d rc=%d rr=%d am=%d\n", snum, slot->wave,
|
||||
slot->lfo, slot->vib, slot->AR, slot->D1R, slot->DL, slot->D2R, slot->RC, slot->RR, slot->AM);
|
||||
logerror(" b=%d, start=%x, loop=%x, end=%x, oct=%d, fn=%d, step=%x\n", slot->bits, slot->startaddr, slot->loopaddr>>16, slot->endaddr>>16, oct, slot->FN, slot->step);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef VERBOSE
|
||||
logerror("YMF278B: slot %2d off\n", snum);
|
||||
#endif
|
||||
if(slot->active)
|
||||
{
|
||||
slot->env_step = 4;
|
||||
ymf278b_envelope_next(slot, chip->clock_ratio);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
slot->vib = data&0x7;
|
||||
slot->lfo = (data>>3)&0x7;
|
||||
break;
|
||||
case 6:
|
||||
slot->AR = data>>4;
|
||||
slot->D1R = data&0xf;
|
||||
break;
|
||||
case 7:
|
||||
slot->DL = data>>4;
|
||||
slot->D2R = data&0xf;
|
||||
break;
|
||||
case 8:
|
||||
slot->RC = data>>4;
|
||||
slot->RR = data&0xf;
|
||||
break;
|
||||
case 9:
|
||||
slot->AM = data & 0x7;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// All non-slot registers
|
||||
switch (reg)
|
||||
{
|
||||
case 0x00: // TEST
|
||||
case 0x01:
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
chip->wavetblhdr = (data>>2)&0x7;
|
||||
chip->memmode = data&1;
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
chip->memadr &= 0xffff;
|
||||
chip->memadr |= (data<<16);
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
chip->memadr &= 0xff00ff;
|
||||
chip->memadr |= (data<<8);
|
||||
break;
|
||||
|
||||
case 0x05:
|
||||
chip->memadr &= 0xffff00;
|
||||
chip->memadr |= data;
|
||||
break;
|
||||
|
||||
case 0x06: // memory data (ignored, we don't support RAM)
|
||||
case 0x07: // unused
|
||||
break;
|
||||
|
||||
case 0xf8:
|
||||
chip->fm_l = data & 0x7;
|
||||
chip->fm_r = (data>>3)&0x7;
|
||||
break;
|
||||
|
||||
case 0xf9:
|
||||
chip->pcm_l = data & 0x7;
|
||||
chip->pcm_r = (data>>3)&0x7;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static UINT8 ymf278b_status_port_r(int num)
|
||||
{
|
||||
return YMF278B[num].current_irq | (YMF278B[num].irq_line == ASSERT_LINE ? 0x80 : 0x00);
|
||||
}
|
||||
|
||||
// Not implemented yet
|
||||
static UINT8 ymf278b_data_port_r(int num)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ymf278b_control_port_A_w(int num, UINT8 data)
|
||||
{
|
||||
YMF278B[num].port_A = data;
|
||||
}
|
||||
|
||||
static void ymf278b_data_port_A_w(int num, UINT8 data)
|
||||
{
|
||||
ymf278b_A_w(num, YMF278B[num].port_A, data);
|
||||
}
|
||||
|
||||
static void ymf278b_control_port_B_w(int num, UINT8 data)
|
||||
{
|
||||
YMF278B[num].port_B = data;
|
||||
}
|
||||
|
||||
static void ymf278b_data_port_B_w(int num, UINT8 data)
|
||||
{
|
||||
ymf278b_B_w(num, YMF278B[num].port_B, data);
|
||||
}
|
||||
|
||||
static void ymf278b_control_port_C_w(int num, UINT8 data)
|
||||
{
|
||||
YMF278B[num].port_C = data;
|
||||
}
|
||||
|
||||
static void ymf278b_data_port_C_w(int num, UINT8 data)
|
||||
{
|
||||
ymf278b_C_w(num, YMF278B[num].port_C, data);
|
||||
}
|
||||
|
||||
#ifdef FBA /* !!! FBA */
|
||||
int ymf278b_start(INT8 num, UINT8 *rom, void (*irq_cb)(int, int), void (*timer_cb)(int, int, double), int clock, int rate)
|
||||
{
|
||||
int i;
|
||||
|
||||
memset(&YMF278B[num], 0, sizeof(YMF278BChip));
|
||||
YMF278B[num].rom = rom;
|
||||
YMF278B[num].irq_callback = irq_cb;
|
||||
YMF278B[num].timer_callback = timer_cb;
|
||||
YMF278B[num].irq_line = CLEAR_LINE;
|
||||
YMF278B[num].clock_ratio = (float)clock / (float)YMF278B_STD_CLOCK;
|
||||
|
||||
Machine->sample_rate = rate;
|
||||
|
||||
// Volume table, 1 = -0.375dB, 8 = -3dB, 256 = -96dB
|
||||
for(i = 0; i < 256; i++)
|
||||
volume[i] = 65536*pow(2.0, (-0.375/6)*i);
|
||||
for(i = 256; i < 256*4; i++)
|
||||
volume[i] = 0;
|
||||
|
||||
// Pan values, units are -3dB, i.e. 8.
|
||||
for(i = 0; i < 16; i++)
|
||||
{
|
||||
pan_left[i] = i < 7 ? i*8 : i < 9 ? 256 : 0;
|
||||
pan_right[i] = i < 8 ? 0 : i < 10 ? 256 : (16-i)*8;
|
||||
}
|
||||
|
||||
// Mixing levels, units are -3dB, and add some marging to avoid clipping
|
||||
for(i=0; i<7; i++)
|
||||
mix_level[i] = volume[8*i+8];
|
||||
mix_level[7] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else /* !!! FBA */
|
||||
static void ymf278b_init(INT8 num, UINT8 *rom, void (*cb)(int), int clock)
|
||||
{
|
||||
memset(&YMF278B[num], 0, sizeof(YMF278BChip));
|
||||
YMF278B[num].rom = rom;
|
||||
YMF278B[num].irq_callback = cb;
|
||||
YMF278B[num].timer_a = timer_alloc(ymf278b_timer_a_tick);
|
||||
YMF278B[num].timer_b = timer_alloc(ymf278b_timer_b_tick);
|
||||
YMF278B[num].irq_line = CLEAR_LINE;
|
||||
YMF278B[num].clock_ratio = (float)clock / (float)YMF278B_STD_CLOCK;
|
||||
}
|
||||
|
||||
int YMF278B_sh_start( const struct MachineSound *msound )
|
||||
{
|
||||
char buf[2][40];
|
||||
const char *name[2];
|
||||
int vol[2];
|
||||
struct YMF278B_interface *intf;
|
||||
int i;
|
||||
|
||||
intf = msound->sound_interface;
|
||||
|
||||
for(i=0; i<intf->num; i++)
|
||||
{
|
||||
sprintf(buf[0], "YMF278B %d L", i);
|
||||
sprintf(buf[1], "YMF278B %d R", i);
|
||||
name[0] = buf[0];
|
||||
name[1] = buf[1];
|
||||
vol[0]=intf->mixing_level[i] >> 16;
|
||||
vol[1]=intf->mixing_level[i] & 0xffff;
|
||||
ymf278b_init(i, memory_region(intf->region[0]), intf->irq_callback[i], intf->clock[i]);
|
||||
stream_init_multi(2, name, vol, Machine->sample_rate, i, ymf278b_pcm_update);
|
||||
}
|
||||
|
||||
// Volume table, 1 = -0.375dB, 8 = -3dB, 256 = -96dB
|
||||
for(i = 0; i < 256; i++)
|
||||
volume[i] = 65536*pow(2.0, (-0.375/6)*i);
|
||||
for(i = 256; i < 256*4; i++)
|
||||
volume[i] = 0;
|
||||
|
||||
// Pan values, units are -3dB, i.e. 8.
|
||||
for(i = 0; i < 16; i++)
|
||||
{
|
||||
pan_left[i] = i < 7 ? i*8 : i < 9 ? 256 : 0;
|
||||
pan_right[i] = i < 8 ? 0 : i < 10 ? 256 : (16-i)*8;
|
||||
}
|
||||
|
||||
// Mixing levels, units are -3dB, and add some marging to avoid clipping
|
||||
for(i=0; i<7; i++)
|
||||
mix_level[i] = volume[8*i+8];
|
||||
mix_level[7] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* !!! FBA */
|
||||
|
||||
void YMF278B_sh_stop( void )
|
||||
{
|
||||
}
|
||||
|
||||
READ8_HANDLER( YMF278B_status_port_0_r )
|
||||
{
|
||||
return ymf278b_status_port_r(0);
|
||||
}
|
||||
|
||||
READ8_HANDLER( YMF278B_data_port_0_r )
|
||||
{
|
||||
return ymf278b_data_port_r(0);
|
||||
}
|
||||
|
||||
WRITE8_HANDLER( YMF278B_control_port_0_A_w )
|
||||
{
|
||||
ymf278b_control_port_A_w(0, data);
|
||||
}
|
||||
|
||||
WRITE8_HANDLER( YMF278B_data_port_0_A_w )
|
||||
{
|
||||
ymf278b_data_port_A_w(0, data);
|
||||
}
|
||||
|
||||
WRITE8_HANDLER( YMF278B_control_port_0_B_w )
|
||||
{
|
||||
ymf278b_control_port_B_w(0, data);
|
||||
}
|
||||
|
||||
WRITE8_HANDLER( YMF278B_data_port_0_B_w )
|
||||
{
|
||||
ymf278b_data_port_B_w(0, data);
|
||||
}
|
||||
|
||||
WRITE8_HANDLER( YMF278B_control_port_0_C_w )
|
||||
{
|
||||
ymf278b_control_port_C_w(0, data);
|
||||
}
|
||||
|
||||
WRITE8_HANDLER( YMF278B_data_port_0_C_w )
|
||||
{
|
||||
ymf278b_data_port_C_w(0, data);
|
||||
}
|
||||
|
||||
#ifndef FBA /* !!! FBA */
|
||||
READ8_HANDLER( YMF278B_status_port_1_r )
|
||||
{
|
||||
return ymf278b_status_port_r(1);
|
||||
}
|
||||
|
||||
READ8_HANDLER( YMF278B_data_port_1_r )
|
||||
{
|
||||
return ymf278b_data_port_r(1);
|
||||
}
|
||||
|
||||
WRITE8_HANDLER( YMF278B_control_port_1_A_w )
|
||||
{
|
||||
ymf278b_control_port_A_w(1, data);
|
||||
}
|
||||
|
||||
WRITE8_HANDLER( YMF278B_data_port_1_A_w )
|
||||
{
|
||||
ymf278b_data_port_A_w(1, data);
|
||||
}
|
||||
|
||||
WRITE8_HANDLER( YMF278B_control_port_1_B_w )
|
||||
{
|
||||
ymf278b_control_port_B_w(1, data);
|
||||
}
|
||||
|
||||
WRITE8_HANDLER( YMF278B_data_port_1_B_w )
|
||||
{
|
||||
ymf278b_data_port_B_w(1, data);
|
||||
}
|
||||
|
||||
WRITE8_HANDLER( YMF278B_control_port_1_C_w )
|
||||
{
|
||||
ymf278b_control_port_C_w(1, data);
|
||||
}
|
||||
|
||||
WRITE8_HANDLER( YMF278B_data_port_1_C_w )
|
||||
{
|
||||
ymf278b_data_port_C_w(1, data);
|
||||
}
|
||||
|
||||
|
||||
#endif /* !!! FBA */
|
||||
|
||||
#endif
|
@ -1,49 +0,0 @@
|
||||
#ifndef __YMF278B_H__
|
||||
#define __YMF278B_H__
|
||||
|
||||
#ifdef FBA /* !!! FBA */
|
||||
#define MAX_YMF278B (1)
|
||||
#else /* !!! FBA */
|
||||
#define MAX_YMF278B (2)
|
||||
#endif /* !!! FBA */
|
||||
|
||||
#define YMF278B_STD_CLOCK (33868800) /* standard clock for OPL4 */
|
||||
|
||||
struct YMF278B_interface {
|
||||
int num; /* Number of chips */
|
||||
int clock[MAX_YMF278B]; /* clock input, normally 33.8688 MHz */
|
||||
int region[MAX_YMF278B]; /* memory region of sample ROMs */
|
||||
int mixing_level[MAX_YMF278B]; /* volume */
|
||||
void (*irq_callback[MAX_YMF278B])(int num, int state); /* irq callback */
|
||||
};
|
||||
|
||||
#ifdef FBA /* !!! FBA */
|
||||
void ymf278b_pcm_update(int num, INT16 **outputs, int length);
|
||||
int ymf278b_timer_over(int num, int timer);
|
||||
int ymf278b_start(INT8 num, UINT8 *rom, void (*irq_cb)(int, int), void (*timer_cb)(int, int, double), int clock, int rate);
|
||||
#else /* !!! FBA */
|
||||
int YMF278B_sh_start( const struct MachineSound *msound );
|
||||
#endif /* !!! FBA */
|
||||
void YMF278B_sh_stop(void);
|
||||
|
||||
READ8_HANDLER( YMF278B_status_port_0_r );
|
||||
READ8_HANDLER( YMF278B_data_port_0_r );
|
||||
WRITE8_HANDLER( YMF278B_control_port_0_A_w );
|
||||
WRITE8_HANDLER( YMF278B_data_port_0_A_w );
|
||||
WRITE8_HANDLER( YMF278B_control_port_0_B_w );
|
||||
WRITE8_HANDLER( YMF278B_data_port_0_B_w );
|
||||
WRITE8_HANDLER( YMF278B_control_port_0_C_w );
|
||||
WRITE8_HANDLER( YMF278B_data_port_0_C_w );
|
||||
|
||||
#ifndef FBA /* !!! FBA */
|
||||
READ8_HANDLER( YMF278B_status_port_1_r );
|
||||
READ8_HANDLER( YMF278B_data_port_1_r );
|
||||
WRITE8_HANDLER( YMF278B_control_port_1_A_w );
|
||||
WRITE8_HANDLER( YMF278B_data_port_1_A_w );
|
||||
WRITE8_HANDLER( YMF278B_control_port_1_B_w );
|
||||
WRITE8_HANDLER( YMF278B_data_port_1_B_w );
|
||||
WRITE8_HANDLER( YMF278B_control_port_1_C_w );
|
||||
WRITE8_HANDLER( YMF278B_data_port_1_C_w );
|
||||
#endif /* !!! FBA */
|
||||
|
||||
#endif
|
@ -1,752 +0,0 @@
|
||||
// Yamaha YMZ280B module
|
||||
#if 0
|
||||
#include <math.h>
|
||||
#include "burnint.h"
|
||||
#include "ymz280b.h"
|
||||
#include "burn_sound.h"
|
||||
|
||||
static INT32 nYMZ280BSampleRate;
|
||||
|
||||
UINT8* YMZ280BROM;
|
||||
void (*pYMZ280BRAMWrite)(INT32 offset, INT32 nValue) = NULL;
|
||||
INT32 (*pYMZ280BRAMRead)(INT32 offset) = NULL;
|
||||
|
||||
UINT32 nYMZ280BStatus;
|
||||
UINT32 nYMZ280BRegister;
|
||||
|
||||
static bool bYMZ280BEnable;
|
||||
|
||||
static bool bYMZ280BIRQEnable;
|
||||
static INT32 nYMZ280BIRQMask;
|
||||
static INT32 nYMZ280BIRQStatus;
|
||||
void (*YMZ280BIRQCallback)(INT32 nStatus) = NULL;
|
||||
|
||||
static INT32* pBuffer = NULL;
|
||||
|
||||
static double nYMZ280BFrequency;
|
||||
|
||||
static INT32 YMZ280BDeltaTable[16];
|
||||
|
||||
static INT32 YMZ280BStepShift[8] = {0x0E6, 0x0E6, 0x0E6, 0x0E6, 0x133, 0x199, 0x200, 0x266};
|
||||
|
||||
static double YMZ280BVolumes[2];
|
||||
static INT32 YMZ280BRouteDirs[2];
|
||||
|
||||
struct sYMZ280BChannelInfo {
|
||||
bool bEnabled;
|
||||
bool bPlaying;
|
||||
bool bLoop;
|
||||
INT32 nMode;
|
||||
INT32 nFrequency;
|
||||
INT32 nSample;
|
||||
INT32 nLoopSample;
|
||||
UINT32 nSampleSize;
|
||||
UINT32 nPosition;
|
||||
INT32 nFractionalPosition;
|
||||
INT32 nStep;
|
||||
INT32 nLoopStep;
|
||||
UINT32 nSampleStart;
|
||||
UINT32 nSampleStop;
|
||||
UINT32 nLoopStart;
|
||||
UINT32 nLoopStop;
|
||||
INT32 nVolume;
|
||||
INT32 nVolumeLeft;
|
||||
INT32 nVolumeRight;
|
||||
INT32 nPan;
|
||||
|
||||
INT32 nOutput;
|
||||
INT32 nPreviousOutput;
|
||||
|
||||
INT32 nBufPos;
|
||||
};
|
||||
|
||||
static INT32 nActiveChannel, nDelta, nSample, nCount, nRamReadAddress;
|
||||
static INT32* buf;
|
||||
|
||||
sYMZ280BChannelInfo YMZ280BChannelInfo[8];
|
||||
static sYMZ280BChannelInfo* channelInfo;
|
||||
|
||||
static INT32* YMZ280BChannelData[8];
|
||||
|
||||
void YMZ280BReset()
|
||||
{
|
||||
#if defined FBA_DEBUG
|
||||
if (!DebugSnd_YMZ280BInitted) bprintf(PRINT_ERROR, _T("YMZ280BReset called without init\n"));
|
||||
#endif
|
||||
|
||||
memset(&YMZ280BChannelInfo[0], 0, sizeof(YMZ280BChannelInfo));
|
||||
|
||||
nYMZ280BIRQMask = 0;
|
||||
nYMZ280BIRQStatus = 0;
|
||||
nYMZ280BStatus = 0;
|
||||
bYMZ280BEnable = false;
|
||||
nRamReadAddress = 0;
|
||||
|
||||
for (INT32 j = 0; j < 8; j++) {
|
||||
memset(YMZ280BChannelData[j], 0, 0x1000 * sizeof(INT32));
|
||||
YMZ280BChannelInfo[j].nBufPos = 4;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
inline void YMZ280BSetSampleSize(const INT32 nChannel)
|
||||
{
|
||||
double rate = (double)(YMZ280BChannelInfo[nChannel].nFrequency + 1) * nYMZ280BFrequency * 512;
|
||||
rate /= nYMZ280BSampleRate * 3;
|
||||
|
||||
YMZ280BChannelInfo[nChannel].nSampleSize = (UINT32)rate;
|
||||
}
|
||||
|
||||
INT32 YMZ280BScan()
|
||||
{
|
||||
#if defined FBA_DEBUG
|
||||
if (!DebugSnd_YMZ280BInitted) bprintf(PRINT_ERROR, _T("YMZ280BScan called without init\n"));
|
||||
#endif
|
||||
|
||||
SCAN_VAR(nYMZ280BStatus);
|
||||
SCAN_VAR(nYMZ280BRegister);
|
||||
|
||||
SCAN_VAR(bYMZ280BEnable);
|
||||
|
||||
SCAN_VAR(bYMZ280BIRQEnable);
|
||||
SCAN_VAR(nYMZ280BIRQMask);
|
||||
SCAN_VAR(nYMZ280BIRQStatus);
|
||||
SCAN_VAR(nRamReadAddress);
|
||||
|
||||
for (INT32 j = 0; j < 8; j++) {
|
||||
SCAN_VAR(YMZ280BChannelInfo[j]);
|
||||
YMZ280BSetSampleSize(j);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 YMZ280BInit(INT32 nClock, void (*IRQCallback)(INT32))
|
||||
{
|
||||
DebugSnd_YMZ280BInitted = 1;
|
||||
|
||||
nYMZ280BFrequency = nClock;
|
||||
|
||||
if (nBurnSoundRate > 0) {
|
||||
nYMZ280BSampleRate = nBurnSoundRate;
|
||||
} else {
|
||||
nYMZ280BSampleRate = 11025;
|
||||
}
|
||||
|
||||
// Compute sample deltas
|
||||
for (INT32 n = 0; n < 16; n++) {
|
||||
nDelta = (n & 7) * 2 + 1;
|
||||
if (n & 8) {
|
||||
nDelta = -nDelta;
|
||||
}
|
||||
YMZ280BDeltaTable[n] = nDelta;
|
||||
}
|
||||
|
||||
YMZ280BIRQCallback = IRQCallback;
|
||||
|
||||
if (pBuffer) {
|
||||
free(pBuffer);
|
||||
pBuffer = NULL;
|
||||
}
|
||||
pBuffer = (INT32*)malloc(nYMZ280BSampleRate * 2 * sizeof(INT32));
|
||||
|
||||
for (INT32 j = 0; j < 8; j++) {
|
||||
YMZ280BChannelData[j] = (INT32*)malloc(0x1000 * sizeof(INT32));
|
||||
}
|
||||
|
||||
// default routes
|
||||
YMZ280BVolumes[BURN_SND_YMZ280B_YMZ280B_ROUTE_1] = 1.00;
|
||||
YMZ280BVolumes[BURN_SND_YMZ280B_YMZ280B_ROUTE_2] = 1.00;
|
||||
YMZ280BRouteDirs[BURN_SND_YMZ280B_YMZ280B_ROUTE_1] = BURN_SND_ROUTE_LEFT;
|
||||
YMZ280BRouteDirs[BURN_SND_YMZ280B_YMZ280B_ROUTE_2] = BURN_SND_ROUTE_RIGHT;
|
||||
|
||||
YMZ280BReset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void YMZ280BSetRoute(INT32 nIndex, double nVolume, INT32 nRouteDir)
|
||||
{
|
||||
#if defined FBA_DEBUG
|
||||
if (!DebugSnd_YMZ280BInitted) bprintf(PRINT_ERROR, _T("BurnYMZ280BSetRoute called without init\n"));
|
||||
if (nIndex < 0 || nIndex > 1) bprintf(PRINT_ERROR, _T("BurnYMZ280BSetRoute called with invalid index %i\n"), nIndex);
|
||||
#endif
|
||||
|
||||
YMZ280BVolumes[nIndex] = nVolume;
|
||||
YMZ280BRouteDirs[nIndex] = nRouteDir;
|
||||
}
|
||||
|
||||
void YMZ280BExit()
|
||||
{
|
||||
#if defined FBA_DEBUG
|
||||
if (!DebugSnd_YMZ280BInitted) bprintf(PRINT_ERROR, _T("YMZ280BExit called without init\n"));
|
||||
#endif
|
||||
|
||||
if (pBuffer) {
|
||||
free(pBuffer);
|
||||
pBuffer = NULL;
|
||||
}
|
||||
|
||||
YMZ280BIRQCallback = NULL;
|
||||
pYMZ280BRAMWrite = NULL;
|
||||
pYMZ280BRAMRead = NULL;
|
||||
|
||||
DebugSnd_YMZ280BInitted = 0;
|
||||
}
|
||||
|
||||
inline static void UpdateIRQStatus()
|
||||
{
|
||||
nYMZ280BIRQStatus = 0;
|
||||
if (bYMZ280BIRQEnable && (nYMZ280BStatus & nYMZ280BIRQMask)) {
|
||||
nYMZ280BIRQStatus = 1;
|
||||
}
|
||||
|
||||
if ((YMZ280BIRQCallback != NULL)) {
|
||||
YMZ280BIRQCallback(nYMZ280BIRQStatus);
|
||||
}
|
||||
}
|
||||
|
||||
inline static void ComputeVolume(sYMZ280BChannelInfo* channel)
|
||||
{
|
||||
if (channel->nPan == 8) {
|
||||
channel->nVolumeLeft = channel->nVolume;
|
||||
channel->nVolumeRight = channel->nVolume;
|
||||
} else {
|
||||
if (channel->nPan < 8) {
|
||||
channel->nVolumeLeft = channel->nVolume;
|
||||
channel->nVolumeRight = channel->nVolume * channel->nPan / 8;
|
||||
} else {
|
||||
channel->nVolumeLeft = channel->nVolume * (15 - channel->nPan) / 8;
|
||||
channel->nVolumeRight = channel->nVolume;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline static void RampChannel()
|
||||
{
|
||||
#if 1
|
||||
if (channelInfo->nSample != 0) {
|
||||
if (channelInfo->nSample > 0) {
|
||||
INT32 nRamp = 64 * 32678 / nYMZ280BSampleRate;
|
||||
while (nCount-- && channelInfo->nSample > nRamp) {
|
||||
channelInfo->nSample -= nRamp;
|
||||
*buf++ += channelInfo->nSample * channelInfo->nVolumeLeft;
|
||||
*buf++ += channelInfo->nSample * channelInfo->nVolumeRight;
|
||||
}
|
||||
if (channelInfo->nSample < nRamp) {
|
||||
channelInfo->nSample = 0;
|
||||
}
|
||||
} else {
|
||||
INT32 nRamp = 0 - 64 * 32678 / nYMZ280BSampleRate;
|
||||
while (nCount-- && channelInfo->nSample < nRamp) {
|
||||
channelInfo->nSample -= nRamp;
|
||||
*buf++ += channelInfo->nSample * channelInfo->nVolumeLeft;
|
||||
*buf++ += channelInfo->nSample * channelInfo->nVolumeRight;
|
||||
}
|
||||
if (channelInfo->nSample > nRamp) {
|
||||
channelInfo->nSample = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
inline static void decode_adpcm()
|
||||
{
|
||||
// Get next value & compute delta
|
||||
nDelta = YMZ280BROM[channelInfo->nPosition >> 1];
|
||||
if (channelInfo->nPosition & 1) {
|
||||
nDelta &= 0x0F;
|
||||
} else {
|
||||
nDelta >>= 4;
|
||||
}
|
||||
|
||||
nSample = channelInfo->nSample + channelInfo->nStep * YMZ280BDeltaTable[nDelta] / 8;
|
||||
if (nSample > 32767) {
|
||||
nSample = 32767;
|
||||
} else {
|
||||
if (nSample < -32768) {
|
||||
nSample = -32768;
|
||||
}
|
||||
}
|
||||
channelInfo->nSample = nSample;
|
||||
|
||||
channelInfo->nStep = channelInfo->nStep * YMZ280BStepShift[nDelta & 7] / 256;
|
||||
if (channelInfo->nStep > 0x6000) {
|
||||
channelInfo->nStep = 0x6000;
|
||||
} else {
|
||||
if (channelInfo->nStep < 127) {
|
||||
channelInfo->nStep = 127;
|
||||
}
|
||||
}
|
||||
|
||||
channelInfo->nPosition++;
|
||||
}
|
||||
|
||||
inline static void decode_pcm8()
|
||||
{
|
||||
nDelta = YMZ280BROM[channelInfo->nPosition >> 1];
|
||||
|
||||
channelInfo->nSample = (INT8)nDelta * 256;
|
||||
channelInfo->nPosition+=2;
|
||||
}
|
||||
|
||||
inline static void decode_pcm16()
|
||||
{
|
||||
nDelta = (INT16)((YMZ280BROM[channelInfo->nPosition / 2 + 1] << 8) + YMZ280BROM[channelInfo->nPosition / 2]);
|
||||
|
||||
channelInfo->nSample = nDelta;
|
||||
channelInfo->nPosition+=4;
|
||||
}
|
||||
|
||||
inline static void decode_none()
|
||||
{
|
||||
channelInfo->nSample=0;
|
||||
}
|
||||
|
||||
static void (*decode_table[4])() = { decode_none, decode_adpcm, decode_pcm8, decode_pcm16 };
|
||||
|
||||
inline static void ComputeOutput_Linear()
|
||||
{
|
||||
nSample = channelInfo->nPreviousOutput + (channelInfo->nOutput - channelInfo->nPreviousOutput) * (channelInfo->nFractionalPosition >> 12) / (0x01000000 >> 12);
|
||||
|
||||
*buf++ += nSample * channelInfo->nVolumeLeft;
|
||||
*buf++ += nSample * channelInfo->nVolumeRight;
|
||||
}
|
||||
|
||||
inline static void ComputeOutput_Cubic()
|
||||
{
|
||||
if (channelInfo->nBufPos > 0x0FF0) {
|
||||
YMZ280BChannelData[nActiveChannel][0] = YMZ280BChannelData[nActiveChannel][channelInfo->nBufPos - 4];
|
||||
YMZ280BChannelData[nActiveChannel][1] = YMZ280BChannelData[nActiveChannel][channelInfo->nBufPos - 3];
|
||||
YMZ280BChannelData[nActiveChannel][2] = YMZ280BChannelData[nActiveChannel][channelInfo->nBufPos - 2];
|
||||
YMZ280BChannelData[nActiveChannel][3] = YMZ280BChannelData[nActiveChannel][channelInfo->nBufPos - 1];
|
||||
channelInfo->nBufPos = 4;
|
||||
}
|
||||
|
||||
nSample = INTERPOLATE4PS_16BIT(channelInfo->nFractionalPosition >> 12,
|
||||
YMZ280BChannelData[nActiveChannel][channelInfo->nBufPos - 4],
|
||||
YMZ280BChannelData[nActiveChannel][channelInfo->nBufPos - 3],
|
||||
YMZ280BChannelData[nActiveChannel][channelInfo->nBufPos - 2],
|
||||
YMZ280BChannelData[nActiveChannel][channelInfo->nBufPos - 1]);
|
||||
|
||||
*buf++ += nSample * channelInfo->nVolumeLeft;
|
||||
*buf++ += nSample * channelInfo->nVolumeRight;
|
||||
}
|
||||
|
||||
inline static void RenderADPCM_Linear()
|
||||
{
|
||||
while (nCount--) {
|
||||
if (channelInfo->nFractionalPosition >= 0x01000000) {
|
||||
|
||||
channelInfo->nPreviousOutput = channelInfo->nOutput;
|
||||
|
||||
do {
|
||||
// Check for end of sample
|
||||
if (channelInfo->nPosition >= channelInfo->nSampleStop) {
|
||||
channelInfo->bPlaying = false;
|
||||
|
||||
RampChannel();
|
||||
|
||||
nYMZ280BStatus |= 1 << nActiveChannel;
|
||||
UpdateIRQStatus();
|
||||
|
||||
return;
|
||||
} else {
|
||||
|
||||
decode_table[YMZ280BChannelInfo[nActiveChannel].nMode](); // decode one sample
|
||||
|
||||
// Advance sample position
|
||||
channelInfo->nFractionalPosition -= 0x01000000;
|
||||
}
|
||||
|
||||
} while (channelInfo->nFractionalPosition >= 0x01000000);
|
||||
|
||||
channelInfo->nOutput = channelInfo->nSample;
|
||||
}
|
||||
|
||||
ComputeOutput_Linear();
|
||||
|
||||
channelInfo->nFractionalPosition += channelInfo->nSampleSize;
|
||||
}
|
||||
}
|
||||
|
||||
inline static void RenderADPCMLoop_Linear()
|
||||
{
|
||||
while (nCount--) {
|
||||
if (channelInfo->nFractionalPosition >= 0x01000000) {
|
||||
|
||||
channelInfo->nPreviousOutput = channelInfo->nOutput;
|
||||
|
||||
do {
|
||||
// Check for end of sample
|
||||
if (channelInfo->nPosition == channelInfo->nLoopStop) {
|
||||
channelInfo->nStep = channelInfo->nLoopStep;
|
||||
channelInfo->nSample = channelInfo->nLoopSample;
|
||||
channelInfo->nPosition = channelInfo->nLoopStart;
|
||||
} else {
|
||||
// Store the state of the channel at the point where the loop starts
|
||||
if (channelInfo->nPosition == channelInfo->nLoopStart) {
|
||||
channelInfo->nLoopStep = channelInfo->nStep;
|
||||
channelInfo->nLoopSample = channelInfo->nSample;
|
||||
}
|
||||
}
|
||||
|
||||
decode_table[YMZ280BChannelInfo[nActiveChannel].nMode](); // decode one sample
|
||||
|
||||
// Advance sample position
|
||||
channelInfo->nFractionalPosition -= 0x01000000;
|
||||
|
||||
} while (channelInfo->nFractionalPosition >= 0x01000000);
|
||||
|
||||
channelInfo->nOutput = channelInfo->nSample;
|
||||
}
|
||||
|
||||
ComputeOutput_Linear();
|
||||
|
||||
channelInfo->nFractionalPosition += channelInfo->nSampleSize;
|
||||
}
|
||||
}
|
||||
inline static void RenderADPCM_Cubic()
|
||||
{
|
||||
while (nCount--) {
|
||||
while (channelInfo->nFractionalPosition >= 0x01000000) {
|
||||
|
||||
// Check for end of sample
|
||||
if (channelInfo->nPosition >= channelInfo->nSampleStop) {
|
||||
channelInfo->bPlaying = false;
|
||||
|
||||
RampChannel();
|
||||
|
||||
nYMZ280BStatus |= 1 << nActiveChannel;
|
||||
UpdateIRQStatus();
|
||||
|
||||
return;
|
||||
} else {
|
||||
|
||||
decode_table[YMZ280BChannelInfo[nActiveChannel].nMode](); // decode one sample
|
||||
|
||||
// Advance sample position
|
||||
channelInfo->nFractionalPosition -= 0x01000000;
|
||||
|
||||
YMZ280BChannelData[nActiveChannel][channelInfo->nBufPos++] = channelInfo->nSample;
|
||||
}
|
||||
}
|
||||
|
||||
ComputeOutput_Cubic();
|
||||
|
||||
channelInfo->nFractionalPosition += channelInfo->nSampleSize;
|
||||
}
|
||||
}
|
||||
|
||||
inline static void RenderADPCMLoop_Cubic()
|
||||
{
|
||||
while (nCount--) {
|
||||
|
||||
while (channelInfo->nFractionalPosition >= 0x01000000) {
|
||||
// Check for end of sample
|
||||
if (channelInfo->nPosition >= channelInfo->nLoopStop) {
|
||||
|
||||
channelInfo->nStep = channelInfo->nLoopStep;
|
||||
channelInfo->nSample = channelInfo->nLoopSample;
|
||||
channelInfo->nPosition = channelInfo->nLoopStart;
|
||||
} else {
|
||||
// Store the state of the channel at the point where the loop starts
|
||||
if (channelInfo->nPosition == channelInfo->nLoopStart) {
|
||||
channelInfo->nLoopStep = channelInfo->nStep;
|
||||
channelInfo->nLoopSample = channelInfo->nSample;
|
||||
}
|
||||
}
|
||||
|
||||
decode_table[YMZ280BChannelInfo[nActiveChannel].nMode](); // decode one sample
|
||||
|
||||
// Advance sample position
|
||||
channelInfo->nFractionalPosition -= 0x01000000;
|
||||
|
||||
YMZ280BChannelData[nActiveChannel][channelInfo->nBufPos++] = channelInfo->nSample;
|
||||
}
|
||||
|
||||
ComputeOutput_Cubic();
|
||||
|
||||
channelInfo->nFractionalPosition += channelInfo->nSampleSize;
|
||||
}
|
||||
}
|
||||
|
||||
INT32 YMZ280BRender(INT16* pSoundBuf, INT32 nSegmentLength)
|
||||
{
|
||||
#if defined FBA_DEBUG
|
||||
if (!DebugSnd_YMZ280BInitted) bprintf(PRINT_ERROR, _T("YMZ280BRender called without init\n"));
|
||||
#endif
|
||||
|
||||
memset(pBuffer, 0, nSegmentLength * 2 * sizeof(INT32));
|
||||
|
||||
for (nActiveChannel = 0; nActiveChannel < 8; nActiveChannel++) {
|
||||
nCount = nSegmentLength;
|
||||
buf = pBuffer;
|
||||
channelInfo = &YMZ280BChannelInfo[nActiveChannel];
|
||||
|
||||
if (channelInfo->bPlaying) {
|
||||
if (nInterpolation < 3) {
|
||||
if (channelInfo->bEnabled && channelInfo->bLoop) {
|
||||
RenderADPCMLoop_Linear();
|
||||
} else {
|
||||
RenderADPCM_Linear();
|
||||
}
|
||||
} else {
|
||||
if (channelInfo->bEnabled && channelInfo->bLoop) {
|
||||
RenderADPCMLoop_Cubic();
|
||||
} else {
|
||||
RenderADPCM_Cubic();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
RampChannel();
|
||||
}
|
||||
}
|
||||
|
||||
for (INT32 i = 0; i < nSegmentLength; i++) {
|
||||
INT32 nLeftSample = 0, nRightSample = 0;
|
||||
|
||||
if ((YMZ280BRouteDirs[BURN_SND_YMZ280B_YMZ280B_ROUTE_1] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
|
||||
nLeftSample += (INT32)((pBuffer[(i << 1) + 0] >> 8) * YMZ280BVolumes[BURN_SND_YMZ280B_YMZ280B_ROUTE_1]);
|
||||
}
|
||||
if ((YMZ280BRouteDirs[BURN_SND_YMZ280B_YMZ280B_ROUTE_1] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
|
||||
nRightSample += (INT32)((pBuffer[(i << 1) + 0] >> 8) * YMZ280BVolumes[BURN_SND_YMZ280B_YMZ280B_ROUTE_1]);
|
||||
}
|
||||
|
||||
if ((YMZ280BRouteDirs[BURN_SND_YMZ280B_YMZ280B_ROUTE_2] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
|
||||
nLeftSample += (INT32)((pBuffer[(i << 1) + 1] >> 8) * YMZ280BVolumes[BURN_SND_YMZ280B_YMZ280B_ROUTE_2]);
|
||||
}
|
||||
if ((YMZ280BRouteDirs[BURN_SND_YMZ280B_YMZ280B_ROUTE_2] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
|
||||
nRightSample += (INT32)((pBuffer[(i << 1) + 1] >> 8) * YMZ280BVolumes[BURN_SND_YMZ280B_YMZ280B_ROUTE_2]);
|
||||
}
|
||||
|
||||
pSoundBuf[(i << 1) + 0] = BURN_SND_CLIP(nLeftSample);
|
||||
pSoundBuf[(i << 1) + 1] = BURN_SND_CLIP(nRightSample);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void YMZ280BWriteRegister(UINT8 nValue)
|
||||
{
|
||||
#if defined FBA_DEBUG
|
||||
if (!DebugSnd_YMZ280BInitted) bprintf(PRINT_ERROR, _T("YMZ280BWriteRegister called without init\n"));
|
||||
#endif
|
||||
|
||||
if (nYMZ280BRegister < 0x80) {
|
||||
INT32 nWriteChannel = (nYMZ280BRegister >> 2) & 0x07;
|
||||
|
||||
switch (nYMZ280BRegister & 0x63) {
|
||||
|
||||
// Miscellaneous
|
||||
case 0: // Frequency
|
||||
YMZ280BChannelInfo[nWriteChannel].nFrequency &= 0x0100;
|
||||
YMZ280BChannelInfo[nWriteChannel].nFrequency |= nValue;
|
||||
YMZ280BSetSampleSize(nWriteChannel);
|
||||
break;
|
||||
case 1: { // Start/mode/freq
|
||||
YMZ280BChannelInfo[nWriteChannel].nFrequency &= 0x00FF;
|
||||
YMZ280BChannelInfo[nWriteChannel].nFrequency |= ((nValue & 1) << 8);
|
||||
YMZ280BSetSampleSize(nWriteChannel);
|
||||
|
||||
YMZ280BChannelInfo[nWriteChannel].bLoop = (nValue & 0x10);
|
||||
YMZ280BChannelInfo[nWriteChannel].nMode = ((nValue >> 5) & 0x03);
|
||||
|
||||
if ((nValue & 0x80) == 0) {
|
||||
YMZ280BChannelInfo[nWriteChannel].bEnabled = false;
|
||||
if (!YMZ280BChannelInfo[nWriteChannel].bLoop) {
|
||||
YMZ280BChannelInfo[nWriteChannel].bPlaying = false;
|
||||
}
|
||||
} else {
|
||||
if (!YMZ280BChannelInfo[nWriteChannel].bEnabled) {
|
||||
YMZ280BChannelInfo[nWriteChannel].bEnabled = true;
|
||||
YMZ280BChannelInfo[nWriteChannel].bPlaying = true;
|
||||
YMZ280BChannelInfo[nWriteChannel].nPosition = YMZ280BChannelInfo[nWriteChannel].nSampleStart;
|
||||
YMZ280BChannelInfo[nWriteChannel].nStep = 127;
|
||||
|
||||
if (YMZ280BChannelInfo[nWriteChannel].nMode > 1) {
|
||||
#ifdef DEBUG
|
||||
// bprintf(0,_T("Sample Start: %08X - Stop: %08X.\n"),YMZ280BChannelInfo[nWriteChannel].nSampleStart, YMZ280BChannelInfo[nWriteChannel].nSampleStop);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (nInterpolation < 3) {
|
||||
YMZ280BChannelInfo[nWriteChannel].nFractionalPosition = 0;
|
||||
YMZ280BChannelInfo[nWriteChannel].nPreviousOutput = YMZ280BChannelInfo[nWriteChannel].nSample;
|
||||
YMZ280BChannelInfo[nWriteChannel].nOutput = YMZ280BChannelInfo[nWriteChannel].nSample;
|
||||
} else {
|
||||
YMZ280BChannelInfo[nWriteChannel].nFractionalPosition = 0x03000000;
|
||||
YMZ280BChannelData[nWriteChannel][0] = YMZ280BChannelInfo[nWriteChannel].nSample;
|
||||
YMZ280BChannelInfo[nWriteChannel].nBufPos = 1;
|
||||
}
|
||||
#else
|
||||
YMZ280BChannelInfo[nWriteChannel].nSample = 0;
|
||||
|
||||
if (nInterpolation < 3) {
|
||||
YMZ280BChannelInfo[nWriteChannel].nFractionalPosition = 0;
|
||||
YMZ280BChannelInfo[nWriteChannel].nPreviousOutput = 0;
|
||||
YMZ280BChannelInfo[nWriteChannel].nOutput = 0;
|
||||
} else {
|
||||
YMZ280BChannelInfo[nWriteChannel].nFractionalPosition = 0x03000000;
|
||||
YMZ280BChannelData[nWriteChannel][3] = 0;
|
||||
YMZ280BChannelInfo[nWriteChannel].nBufPos = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 2: // Volume
|
||||
YMZ280BChannelInfo[nWriteChannel].nVolume = nValue;
|
||||
ComputeVolume(&YMZ280BChannelInfo[nWriteChannel]);
|
||||
break;
|
||||
case 3: // Pan
|
||||
YMZ280BChannelInfo[nWriteChannel].nPan = nValue & 0x0F;
|
||||
ComputeVolume(&YMZ280BChannelInfo[nWriteChannel]);
|
||||
break;
|
||||
|
||||
// Hi bits
|
||||
case 0x20:
|
||||
YMZ280BChannelInfo[nWriteChannel].nSampleStart &= 0x0001FFFE;
|
||||
YMZ280BChannelInfo[nWriteChannel].nSampleStart |= (nValue << 17);
|
||||
break;
|
||||
case 0x21:
|
||||
YMZ280BChannelInfo[nWriteChannel].nLoopStart &= 0x0001FFFE;
|
||||
YMZ280BChannelInfo[nWriteChannel].nLoopStart |= (nValue << 17);
|
||||
break;
|
||||
case 0x22:
|
||||
YMZ280BChannelInfo[nWriteChannel].nLoopStop &= 0x0001FFFE;
|
||||
YMZ280BChannelInfo[nWriteChannel].nLoopStop |= (nValue << 17);
|
||||
break;
|
||||
case 0x23:
|
||||
YMZ280BChannelInfo[nWriteChannel].nSampleStop &= 0x0001FFFE;
|
||||
YMZ280BChannelInfo[nWriteChannel].nSampleStop |= (nValue << 17);
|
||||
break;
|
||||
|
||||
// Mid bits
|
||||
case 0x40:
|
||||
YMZ280BChannelInfo[nWriteChannel].nSampleStart &= 0x01FE01FE;
|
||||
YMZ280BChannelInfo[nWriteChannel].nSampleStart |= (nValue << 9);
|
||||
break;
|
||||
case 0x41:
|
||||
YMZ280BChannelInfo[nWriteChannel].nLoopStart &= 0x01FE01FE;
|
||||
YMZ280BChannelInfo[nWriteChannel].nLoopStart |= (nValue << 9);
|
||||
break;
|
||||
case 0x42:
|
||||
YMZ280BChannelInfo[nWriteChannel].nLoopStop &= 0x01FE01FE;
|
||||
YMZ280BChannelInfo[nWriteChannel].nLoopStop |= (nValue << 9);
|
||||
break;
|
||||
case 0x43:
|
||||
YMZ280BChannelInfo[nWriteChannel].nSampleStop &= 0x01FE01FE;
|
||||
YMZ280BChannelInfo[nWriteChannel].nSampleStop |= (nValue << 9);
|
||||
break;
|
||||
|
||||
// Lo bits
|
||||
case 0x60:
|
||||
YMZ280BChannelInfo[nWriteChannel].nSampleStart &= 0x01FFFE00;
|
||||
YMZ280BChannelInfo[nWriteChannel].nSampleStart |= (nValue << 1);
|
||||
break;
|
||||
case 0x61:
|
||||
YMZ280BChannelInfo[nWriteChannel].nLoopStart &= 0x01FFFE00;
|
||||
YMZ280BChannelInfo[nWriteChannel].nLoopStart |= (nValue << 1);
|
||||
break;
|
||||
case 0x62:
|
||||
YMZ280BChannelInfo[nWriteChannel].nLoopStop &= 0x01FFFE00;
|
||||
YMZ280BChannelInfo[nWriteChannel].nLoopStop |= (nValue << 1);
|
||||
break;
|
||||
case 0x63:
|
||||
YMZ280BChannelInfo[nWriteChannel].nSampleStop &= 0x01FFFE00;
|
||||
YMZ280BChannelInfo[nWriteChannel].nSampleStop |= (nValue << 1);
|
||||
break;
|
||||
|
||||
}
|
||||
} else {
|
||||
switch (nYMZ280BRegister)
|
||||
{
|
||||
case 0x84: // ROM readback / RAM write (high)
|
||||
nRamReadAddress &= 0x00ffff;
|
||||
nRamReadAddress |= (nValue << 16);
|
||||
break;
|
||||
|
||||
case 0x85: // ROM readback / RAM write (med)
|
||||
nRamReadAddress &= 0xff00ff;
|
||||
nRamReadAddress |= (nValue << 8);
|
||||
break;
|
||||
|
||||
case 0x86: // ROM readback / RAM write (low)
|
||||
nRamReadAddress &= 0xffff00;
|
||||
nRamReadAddress |= (nValue << 0);
|
||||
break;
|
||||
|
||||
case 0x87: // RAM write
|
||||
if (pYMZ280BRAMWrite) {
|
||||
pYMZ280BRAMWrite(nRamReadAddress, nValue);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xfe: // Set IRQ mask
|
||||
nYMZ280BIRQMask = nValue;
|
||||
UpdateIRQStatus();
|
||||
break;
|
||||
|
||||
case 0xff: // Start/stop playing, enable/disable IRQ
|
||||
{
|
||||
if (nValue & 0x10) {
|
||||
bYMZ280BIRQEnable = true;
|
||||
} else {
|
||||
bYMZ280BIRQEnable = false;
|
||||
}
|
||||
UpdateIRQStatus();
|
||||
|
||||
if (bYMZ280BEnable && !(nValue & 0x80)) {
|
||||
bYMZ280BEnable = false;
|
||||
for (INT32 n = 0; n < 8; n++) {
|
||||
YMZ280BChannelInfo[n].bPlaying = false;
|
||||
}
|
||||
} else {
|
||||
if (!bYMZ280BEnable && (nValue & 0x80)) {
|
||||
bYMZ280BEnable = true;
|
||||
for (INT32 n = 0; n < 8; n++) {
|
||||
if (YMZ280BChannelInfo[n].bEnabled && YMZ280BChannelInfo[n].bLoop) {
|
||||
YMZ280BChannelInfo[n].bPlaying = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UINT32 YMZ280BReadStatus()
|
||||
{
|
||||
#if defined FBA_DEBUG
|
||||
if (!DebugSnd_YMZ280BInitted) bprintf(PRINT_ERROR, _T("YMZ280BReadStatus called without init\n"));
|
||||
#endif
|
||||
|
||||
UINT32 nStatus = nYMZ280BStatus;
|
||||
nYMZ280BStatus = 0;
|
||||
|
||||
UpdateIRQStatus();
|
||||
|
||||
return nStatus;
|
||||
}
|
||||
|
||||
UINT32 YMZ280BReadRAM()
|
||||
{
|
||||
#if defined FBA_DEBUG
|
||||
if (!DebugSnd_YMZ280BInitted) bprintf(PRINT_ERROR, _T("YMZ280BReadRAM called without init\n"));
|
||||
#endif
|
||||
|
||||
if (pYMZ280BRAMRead) {
|
||||
return pYMZ280BRAMRead(nRamReadAddress++ - 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
@ -1,55 +0,0 @@
|
||||
// Yamaha YMZ280B module
|
||||
#if 0
|
||||
INT32 YMZ280BInit(INT32 nClock, void (*IRQCallback)(INT32));
|
||||
void YMZ280BSetRoute(INT32 nIndex, double nVolume, INT32 nRouteDir);
|
||||
void YMZ280BReset();
|
||||
INT32 YMZ280BScan();
|
||||
void YMZ280BExit();
|
||||
INT32 YMZ280BRender(INT16* pSoundBuf, INT32 nSegmenLength);
|
||||
void YMZ280BWriteRegister(UINT8 nValue);
|
||||
UINT32 YMZ280BReadStatus();
|
||||
UINT32 YMZ280BReadRAM();
|
||||
|
||||
extern UINT8* YMZ280BROM;
|
||||
|
||||
// external memory handlers
|
||||
extern void (*pYMZ280BRAMWrite)(INT32 offset, INT32 nValue);
|
||||
extern INT32 (*pYMZ280BRAMRead)(INT32 offset);
|
||||
|
||||
extern UINT32 nYMZ280BStatus;
|
||||
extern UINT32 nYMZ280BRegister;
|
||||
|
||||
inline static void YMZ280BSelectRegister(UINT8 nRegister)
|
||||
{
|
||||
nYMZ280BRegister = nRegister;
|
||||
}
|
||||
|
||||
inline static void YMZ280BWrite(INT32 offset, UINT8 nValue)
|
||||
{
|
||||
if (offset & 1) {
|
||||
YMZ280BWriteRegister(nValue);
|
||||
} else {
|
||||
nYMZ280BRegister = nValue;
|
||||
}
|
||||
}
|
||||
|
||||
inline static UINT32 YMZ280BRead(INT32 offset)
|
||||
{
|
||||
if (offset & 1) {
|
||||
return YMZ280BReadStatus();
|
||||
} else {
|
||||
return YMZ280BReadRAM();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define BURN_SND_YMZ280B_YMZ280B_ROUTE_1 0
|
||||
#define BURN_SND_YMZ280B_YMZ280B_ROUTE_2 1
|
||||
|
||||
#define YMZ280BSetAllRoutes(v, d) \
|
||||
YMZ280BSetRoute(BURN_SND_YMZ280B_YMZ280B_ROUTE_1, v, d); \
|
||||
YMZ280BSetRoute(BURN_SND_YMZ280B_YMZ280B_ROUTE_2, v, d);
|
||||
|
||||
|
||||
#endif
|
@ -43,8 +43,6 @@ INT32 BurnTimerUpdate(INT32 nCycles)
|
||||
|
||||
nTicksTotal = MAKE_TIMER_TICKS(nCycles, nCPUClockspeed);
|
||||
|
||||
// bprintf(PRINT_NORMAL, _T(" -- Ticks: %08X, cycles %i\n"), nTicksTotal, nCycles);
|
||||
|
||||
while (nTicksDone < nTicksTotal) {
|
||||
INT32 nTimer, nCyclesSegment, nTicksSegment;
|
||||
|
||||
@ -59,21 +57,18 @@ INT32 BurnTimerUpdate(INT32 nCycles)
|
||||
}
|
||||
|
||||
nCyclesSegment = MAKE_CPU_CYLES(nTicksSegment + nTicksExtra, nCPUClockspeed);
|
||||
// bprintf(PRINT_NORMAL, _T(" - Timer: %08X, %08X, %08X, cycles %i, %i\n"), nTicksDone, nTicksSegment, nTicksTotal, nCyclesSegment, pCPUTotalCycles());
|
||||
|
||||
pCPURun(nCyclesSegment - pCPUTotalCycles());
|
||||
|
||||
nTicksDone = MAKE_TIMER_TICKS(pCPUTotalCycles() + 1, nCPUClockspeed) - 1;
|
||||
// bprintf(PRINT_NORMAL, _T(" - ticks done -> %08X cycles -> %i\n"), nTicksDone, pCPUTotalCycles());
|
||||
|
||||
nTimer = 0;
|
||||
if (nTicksDone >= nTimerCount[0]) {
|
||||
if (nTimerStart[0] == MAX_TIMER_VALUE) {
|
||||
if (nTicksDone >= nTimerCount[0])
|
||||
{
|
||||
if (nTimerStart[0] == MAX_TIMER_VALUE)
|
||||
nTimerCount[0] = MAX_TIMER_VALUE;
|
||||
} else {
|
||||
else
|
||||
nTimerCount[0] += nTimerStart[0];
|
||||
}
|
||||
// bprintf(PRINT_NORMAL, _T(" - timer 0 fired\n"));
|
||||
nTimer |= 1;
|
||||
}
|
||||
if (nTicksDone >= nTimerCount[1]) {
|
||||
@ -82,7 +77,6 @@ INT32 BurnTimerUpdate(INT32 nCycles)
|
||||
} else {
|
||||
nTimerCount[1] += nTimerStart[1];
|
||||
}
|
||||
// bprintf(PRINT_NORMAL, _T(" - timer 1 fired\n"));
|
||||
nTimer |= 2;
|
||||
}
|
||||
if (nTimer & 1) {
|
||||
@ -110,16 +104,12 @@ void BurnTimerEndFrame(INT32 nCycles)
|
||||
}
|
||||
|
||||
nTicksDone -= nTicks;
|
||||
if (nTicksDone < 0) {
|
||||
// bprintf(PRINT_ERROR, _T(" -- ticks done -> %08X\n"), nTicksDone);
|
||||
if (nTicksDone < 0)
|
||||
nTicksDone = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void BurnTimerUpdateEnd()
|
||||
void BurnTimerUpdateEnd(void)
|
||||
{
|
||||
// bprintf(PRINT_NORMAL, _T(" - end %i\n"), pCPUTotalCycles());
|
||||
|
||||
pCPURunEnd();
|
||||
|
||||
nTicksTotal = 0;
|
||||
@ -138,16 +128,14 @@ void BurnOPLTimerCallback(INT32 c, double period)
|
||||
{
|
||||
pCPURunEnd();
|
||||
|
||||
if (period == 0.0) {
|
||||
if (period == 0.0)
|
||||
{
|
||||
nTimerCount[c] = MAX_TIMER_VALUE;
|
||||
// bprintf(PRINT_NORMAL, _T(" - timer %i stopped\n"), c);
|
||||
return;
|
||||
}
|
||||
|
||||
nTimerCount[c] = (INT32)(period * (double)TIMER_TICKS_PER_SECOND);
|
||||
nTimerCount[c] += MAKE_TIMER_TICKS(pCPUTotalCycles(), nCPUClockspeed);
|
||||
|
||||
// bprintf(PRINT_NORMAL, _T(" - timer %i started, %08X ticks (fires in %lf seconds)\n"), c, nTimerCount[c], period);
|
||||
}
|
||||
|
||||
void BurnOPMTimerCallback(INT32 c, double period)
|
||||
@ -167,71 +155,56 @@ void BurnOPNTimerCallback(INT32 /*n */, INT32 c, INT32 cnt, double stepTime)
|
||||
{
|
||||
pCPURunEnd();
|
||||
|
||||
if (cnt == 0) {
|
||||
if (cnt == 0)
|
||||
{
|
||||
nTimerCount[c] = MAX_TIMER_VALUE;
|
||||
|
||||
// bprintf(PRINT_NORMAL, _T(" - timer %i stopped\n"), c);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
nTimerCount[c] = (INT32)(stepTime * cnt * (double)TIMER_TICKS_PER_SECOND);
|
||||
nTimerCount[c] += MAKE_TIMER_TICKS(pCPUTotalCycles(), nCPUClockspeed);
|
||||
// bprintf(PRINT_NORMAL, _T(" - timer %i started, %08X ticks (fires in %lf seconds)\n"), c, nTimerCount[c], stepTime * cnt);
|
||||
}
|
||||
|
||||
void BurnYMFTimerCallback(INT32 /* n */, INT32 c, double period)
|
||||
{
|
||||
pCPURunEnd();
|
||||
|
||||
if (period == 0.0) {
|
||||
if (period == 0.0)
|
||||
{
|
||||
nTimerStart[c] = nTimerCount[c] = MAX_TIMER_VALUE;
|
||||
|
||||
// bprintf(PRINT_NORMAL, _T(" - timer %i stopped\n"), c);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
nTimerStart[c] = nTimerCount[c] = (INT32)(period * (double)(TIMER_TICKS_PER_SECOND / 1000000));
|
||||
nTimerCount[c] += MAKE_TIMER_TICKS(pCPUTotalCycles(), nCPUClockspeed);
|
||||
|
||||
// bprintf(PRINT_NORMAL, _T(" - timer %i started, %08X ticks (fires in %lf seconds)\n"), c, nTimerCount[c], period);
|
||||
}
|
||||
|
||||
void BurnTimerSetRetrig(INT32 c, double period)
|
||||
{
|
||||
pCPURunEnd();
|
||||
|
||||
if (period == 0.0) {
|
||||
if (period == 0.0)
|
||||
{
|
||||
nTimerStart[c] = nTimerCount[c] = MAX_TIMER_VALUE;
|
||||
|
||||
// bprintf(PRINT_NORMAL, _T(" - timer %i stopped\n"), c);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
nTimerStart[c] = nTimerCount[c] = (INT32)(period * (double)(TIMER_TICKS_PER_SECOND));
|
||||
nTimerCount[c] += MAKE_TIMER_TICKS(pCPUTotalCycles(), nCPUClockspeed);
|
||||
|
||||
// bprintf(PRINT_NORMAL, _T(" - timer %i started, %08X ticks (fires in %lf seconds)\n"), c, nTimerCount[c], period);
|
||||
}
|
||||
|
||||
void BurnTimerSetOneshot(INT32 c, double period)
|
||||
{
|
||||
pCPURunEnd();
|
||||
|
||||
if (period == 0.0) {
|
||||
if (period == 0.0)
|
||||
{
|
||||
nTimerStart[c] = nTimerCount[c] = MAX_TIMER_VALUE;
|
||||
|
||||
// bprintf(PRINT_NORMAL, _T(" - timer %i stopped\n"), c);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
nTimerCount[c] = (INT32)(period * (double)(TIMER_TICKS_PER_SECOND));
|
||||
nTimerCount[c] += MAKE_TIMER_TICKS(pCPUTotalCycles(), nCPUClockspeed);
|
||||
|
||||
// bprintf(PRINT_NORMAL, _T(" - timer %i started, %08X ticks (fires in %lf seconds)\n"), c, nTimerCount[c], period / 1000000.0);
|
||||
}
|
||||
|
||||
// ------------------------------------ ---------------------------------------
|
||||
@ -293,8 +266,6 @@ INT32 BurnTimerAttachSek(INT32 nClockspeed)
|
||||
|
||||
nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1;
|
||||
|
||||
// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -307,7 +278,5 @@ INT32 BurnTimerAttachZet(INT32 nClockspeed)
|
||||
|
||||
nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1;
|
||||
|
||||
// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user