This commit is contained in:
twinaphex 2020-11-12 03:02:53 +01:00
parent 05045e103e
commit 7baa965a9e
11 changed files with 22 additions and 2142 deletions

View File

@ -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 \

View File

@ -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)

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}