Skip to content
Permalink
Browse files

fix Linux compile, fix ES5503 sample rate, fix/improve SAA1099 emulation

  • Loading branch information...
ValleyBell committed Jun 7, 2015
1 parent 00abd60 commit bd1b654b1cffb275cb829ea96b8b1a4381331e6f
@@ -118,6 +118,7 @@ EMUOBJS = \
$(EMUOBJ)/pwm.o \
$(EMUOBJ)/qsound.o \
$(EMUOBJ)/rf5c68.o \
$(EMUOBJ)/saa1099.o \
$(EMUOBJ)/segapcm.o \
$(EMUOBJ)/scd_pcm.o \
$(EMUOBJ)/scsp.o \
@@ -32,11 +32,13 @@
#include "stdbool.h"
#include <math.h> // for pow()

#ifdef WIN32
#ifndef NO_WCHAR_FILENAMES
// includes for manual wide-character ZLib open
#include <fcntl.h> // for _O_RDONLY and _O_BINARY
#include <io.h> // for _wopen and _close
#endif

#ifdef WIN32
#include <conio.h> // for _inp()
#include <windows.h>
#else //ifdef UNIX
@@ -1723,6 +1725,7 @@ UINT32 GetVGMFileInfo(const char* FileName, VGM_HEADER* RetVGMHead, GD3_TAG* Ret
return RetVal;
}

#ifndef NO_WCHAR_FILENAMES
UINT32 GetVGMFileInfoW(const wchar_t* FileName, VGM_HEADER* RetVGMHead, GD3_TAG* RetGD3Tag)
{
gzFile hFile;
@@ -1753,6 +1756,7 @@ UINT32 GetVGMFileInfoW(const wchar_t* FileName, VGM_HEADER* RetVGMHead, GD3_TAG*
gzclose(hFile);
return RetVal;
}
#endif

static UINT32 GetVGMFileInfo_Internal(gzFile hFile, UINT32 FileSize,
VGM_HEADER* RetVGMHead, GD3_TAG* RetGD3Tag)
@@ -109,9 +109,9 @@ static const wchar_t* GetTagStrEJ(const wchar_t* EngTag, const wchar_t* JapTag);
static void ShowVGMTag(void);

static void PlayVGM_UI(void);
static INT8 sign(double Value);
static long int Round(double Value);
static double RoundSpecial(double Value, double RoundTo);
INLINE INT8 sign(double Value);
INLINE long int Round(double Value);
INLINE double RoundSpecial(double Value, double RoundTo);
static void PrintMinSec(UINT32 SamplePos, UINT32 SmplRate);


@@ -2627,7 +2627,7 @@ static void PlayVGM_UI(void)
return;
}

static INT8 sign(double Value)
INLINE INT8 sign(double Value)
{
if (Value > 0.0)
return 1;
@@ -2637,13 +2637,13 @@ static INT8 sign(double Value)
return 0;
}

static long int Round(double Value)
INLINE long int Round(double Value)
{
// Alternative: (fabs(Value) + 0.5) * sign(Value);
return (long int)(Value + 0.5 * sign(Value));
}

static double RoundSpecial(double Value, double RoundTo)
INLINE double RoundSpecial(double Value, double RoundTo)
{
return (long int)(Value / RoundTo + 0.5 * sign(Value)) * RoundTo;
}
@@ -2,6 +2,10 @@
//

//#define NO_WCHAR_FILENAMES
#ifndef WIN32
// Linux uses UTF-8 Unicode and has no special wide-character file routines.
#undef NO_WCHAR_FILENAMES
#endif

typedef struct waveform_16bit_stereo
{
@@ -118,3 +118,10 @@ Updates since 0.4.0u5 (13.04.2014)
- [VGMPlay] fixed YM2612 DAC not being muteable via MuteMask
- added ES5503, ES5506, Seta X1-010, Namco C352, Irem GA20 support
- [VGMPlay] fixed Loop Length (is now adjusted for changed playback rates)

Updates since 0.4.0u6 (30.05.2015)
- fixed SAA1099 muting (muting channel 1 or 4 prevented the envelope generator from running, thus muting 0-2 or 3-5 respectively)
- made SAA1099 output bipolar
- [VGMPlay] fix compiling under Linux (broken since Wide-Charcter file name support)
- fixed ES5503 sample rate (divider was off by one)
- applied fix from VOGONS that makes the SAA1099 core actually use the chip clock
@@ -120,6 +120,7 @@ static void es5503_halt_osc(ES5503Chip *chip, int onum, int type, UINT32 *accumu
ES5503Osc *pOsc = &chip->oscillators[onum];
ES5503Osc *pPartner = &chip->oscillators[onum^1];
int mode = (pOsc->control>>1) & 3;
int omode = (pPartner->control>>1) & 3;

// if 0 found in sample data or mode is not free-run, halt this oscillator
if ((mode != MODE_FREE) || (type != 0))
@@ -144,7 +145,7 @@ static void es5503_halt_osc(ES5503Chip *chip, int onum, int type, UINT32 *accumu
}

// if swap mode, start the partner
if (mode == MODE_SWAP)
if ((mode == MODE_SWAP) || (omode == MODE_SWAP))
{
pPartner->control &= ~1; // clear the halt bit
pPartner->accumulator = 0; // and make sure it starts from the top (does this also need phase preservation?)
@@ -170,7 +171,6 @@ void es5503_pcm_update(UINT8 ChipID, stream_sample_t **outputs, int samples)
// as 'static' and thus re-allocated for every single call.
//INT32 mix[48000*2];
//INT32 *mixp;
int oscCnt;
int osc, snum;
UINT32 ramptr;
//ES5503Chip *chip = (ES5503Chip *)param;
@@ -182,8 +182,7 @@ void es5503_pcm_update(UINT8 ChipID, stream_sample_t **outputs, int samples)
//memset(mix, 0, sizeof(mix));

chnsStereo = chip->output_channels & ~1;
oscCnt = chip->oscsenabled + 1;
for (osc = 0; osc < oscCnt; osc++)
for (osc = 0; osc < chip->oscsenabled; osc++)
{
ES5503Osc *pOsc = &chip->oscillators[osc];

@@ -359,7 +358,7 @@ void device_reset_es5503(UINT8 ChipID)
chip->channel_strobe = 0;
memset(chip->docram, 0x00, chip->dramsize);

chip->output_rate = (chip->clock/8)/34; // (input clock / 8) / # of oscs. enabled + 2
chip->output_rate = (chip->clock/8)/(2+chip->oscsenabled); // (input clock / 8) / # of oscs. enabled + 2
if (chip->SmpRateFunc != NULL)
chip->SmpRateFunc(chip->SmpRateData, chip->output_rate);

@@ -423,7 +422,7 @@ UINT8 es5503_r(UINT8 ChipID, offs_t offset)
//m_irq_func(0);

// scan all oscillators
for (i = 0; i < chip->oscsenabled+1; i++)
for (i = 0; i < chip->oscsenabled; i++)
{
if (chip->oscillators[i].irqpend)
{
@@ -444,7 +443,7 @@ UINT8 es5503_r(UINT8 ChipID, offs_t offset)
}

// if any oscillators still need to be serviced, assert IRQ again immediately
/*for (i = 0; i < chip->oscsenabled+1; i++)
/*for (i = 0; i < chip->oscsenabled; i++)
{
if (chip->oscillators[i].irqpend)
{
@@ -459,7 +458,7 @@ UINT8 es5503_r(UINT8 ChipID, offs_t offset)
return retval;

case 0xe1: // oscillator enable
return chip->oscsenabled<<1;
return (chip->oscsenabled-1)<<1;

case 0xe2: // A/D converter
/*if (chip->adc_read)
@@ -542,7 +541,7 @@ void es5503_w(UINT8 ChipID, offs_t offset, UINT8 data)
break;

case 0xe1: // oscillator enable
chip->oscsenabled = (data>>1);
chip->oscsenabled = 1 + ((data>>1) & 0x1f);

chip->output_rate = (chip->clock/8)/(2+chip->oscsenabled);
//stream_set_sample_rate(chip->stream, chip->output_rate);
@@ -2234,9 +2234,9 @@ static UINT8 es5505_r(es5506_state *chip, offs_t offset)

/* return the high byte */
if (offset & 0x01)
return (result & 0x00FF);
return (result & 0x00FF) >> 0;
else
return (result & 0xFF00);
return (result & 0xFF00) >> 8;
}

UINT8 es550x_r(UINT8 ChipID, offs_t offset)
@@ -38,14 +38,14 @@ It's not currently known whether this chip is stereo.
struct IremGA20_channel_def
{
UINT32 rate;
UINT32 size;
//UINT32 size;
UINT32 start;
UINT32 pos;
UINT32 frac;
UINT32 end;
UINT32 volume;
UINT32 pan;
UINT32 effect;
//UINT32 effect;
UINT32 play;
UINT8 Muted;
};
@@ -229,14 +229,14 @@ static void iremga20_reset(ga20_state *chip)

for( i = 0; i < 4; i++ ) {
chip->channel[i].rate = 0;
chip->channel[i].size = 0;
//chip->channel[i].size = 0;
chip->channel[i].start = 0;
chip->channel[i].pos = 0;
chip->channel[i].frac = 0;
chip->channel[i].end = 0;
chip->channel[i].volume = 0;
chip->channel[i].pan = 0;
chip->channel[i].effect = 0;
//chip->channel[i].effect = 0;
chip->channel[i].play = 0;
}
}
@@ -117,6 +117,7 @@ struct _saa1099_state
struct saa1099_channel channels[6]; /* channels */
struct saa1099_noise noise[2]; /* noise generators */
double sample_rate;
int master_clock;
};

static const int amplitude_lookup[16] = {
@@ -230,6 +231,7 @@ void saa1099_update(UINT8 ChipID, stream_sample_t **outputs, int samples)
//saa1099_state *saa = (saa1099_state *)param;
saa1099_state *saa = &SAA1099Data[ChipID];
int j, ch;
int clkdiv512;

/* if the channels are disabled we're done */
if (!saa->all_ch_enable)
@@ -244,13 +246,16 @@ void saa1099_update(UINT8 ChipID, stream_sample_t **outputs, int samples)
{
switch (saa->noise_params[ch])
{
case 0: saa->noise[ch].freq = 31250.0 * 2; break;
case 1: saa->noise[ch].freq = 15625.0 * 2; break;
case 2: saa->noise[ch].freq = 7812.5 * 2; break;
case 3: saa->noise[ch].freq = saa->channels[ch * 3].freq; break;
case 0: saa->noise[ch].freq = saa->master_clock/ 256.0 * 2; break;
case 1: saa->noise[ch].freq = saa->master_clock/ 512.0 * 2; break;
case 2: saa->noise[ch].freq = saa->master_clock/1024.0 * 2; break;
case 3: saa->noise[ch].freq = saa->channels[ch * 3].freq; break;
}
}

// clock fix thanks to http://www.vogons.org/viewtopic.php?p=344227#p344227
clkdiv512 = saa->master_clock / 512;

/* fill all data needed */
for( j = 0; j < samples; j++ )
{
@@ -259,19 +264,16 @@ void saa1099_update(UINT8 ChipID, stream_sample_t **outputs, int samples)
/* for each channel */
for (ch = 0; ch < 6; ch++)
{
if (saa->channels[ch].Muted)
continue;

if (saa->channels[ch].freq == 0.0)
saa->channels[ch].freq = (double)((2 * 15625) << saa->channels[ch].octave) /
saa->channels[ch].freq = (double)((2 * clkdiv512) << saa->channels[ch].octave) /
(511.0 - (double)saa->channels[ch].frequency);

/* check the actual position in the square wave */
saa->channels[ch].counter -= saa->channels[ch].freq;
while (saa->channels[ch].counter < 0)
{
/* calculate new frequency now after the half wave is updated */
saa->channels[ch].freq = (double)((2 * 15625) << saa->channels[ch].octave) /
saa->channels[ch].freq = (double)((2 * clkdiv512) << saa->channels[ch].octave) /
(511.0 - (double)saa->channels[ch].frequency);

saa->channels[ch].counter += saa->sample_rate;
@@ -284,28 +286,62 @@ void saa1099_update(UINT8 ChipID, stream_sample_t **outputs, int samples)
saa1099_envelope(saa, 1);
}

/* if the noise is enabled */
if (saa->channels[ch].Muted)
continue; // placed here to ensure that envelopes are updated

#if 0
// if the noise is enabled
if (saa->channels[ch].noise_enable)
{
/* if the noise level is high (noise 0: chan 0-2, noise 1: chan 3-5) */
// if the noise level is high (noise 0: chan 0-2, noise 1: chan 3-5)
if (saa->noise[ch/3].level & 1)
{
/* subtract to avoid overflows, also use only half amplitude */
// subtract to avoid overflows, also use only half amplitude
output_l -= saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 16 / 2;
output_r -= saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 16 / 2;
}
}

/* if the square wave is enabled */
// if the square wave is enabled
if (saa->channels[ch].freq_enable)
{
/* if the channel level is high */
// if the channel level is high
if (saa->channels[ch].level & 1)
{
output_l += saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 16;
output_r += saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 16;
}
}
#else
// Now with bipolar output. -Valley Bell
if (saa->channels[ch].noise_enable)
{
if (saa->noise[ch/3].level & 1)
{
output_l += saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 32 / 2;
output_r += saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 32 / 2;
}
else
{
output_l -= saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 32 / 2;
output_r -= saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 32 / 2;
}
}

if (saa->channels[ch].freq_enable)
{
if (saa->channels[ch].level & 1)
{
output_l += saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 32;
output_r += saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 32;
}
else
{
output_l -= saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 32;
output_r -= saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 32;
}
}
#endif
}

for (ch = 0; ch < 2; ch++)
@@ -344,6 +380,7 @@ int device_start_saa1099(UINT8 ChipID, int clock)
/* copy global parameters */
//saa->device = device;
//saa->sample_rate = device->clock() / 256;
saa->master_clock = clock;
saa->sample_rate = clock / 256.0;

/* for each chip allocate one stream */
@@ -1,8 +1,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>

#include "chips/mamedef.h"
#include "stdbool.h"
#include "utils.h"
#include "VGMPlay.h"
#include "VGMPlay_Intf.h"

0 comments on commit bd1b654

Please sign in to comment.
You can’t perform that action at this time.