[Core/Sound] rewrote PSG core from scratch & replaced deprecated "PSG boot noise" option with optional Hiqh Quality PSG resampling

This commit is contained in:
EkeEke 2016-12-18 23:36:59 +01:00
parent 41285e1131
commit 9bb64c47f9
38 changed files with 759 additions and 561 deletions

View File

@ -113,6 +113,11 @@ Genesis Plus GX 1.7.5 (xx/xx/xxxx) (Eke-Eke)
* fixed 68k cycles delay on invalid VRAM writes (fixes "Microcosm" intro loop) * fixed 68k cycles delay on invalid VRAM writes (fixes "Microcosm" intro loop)
* optimized tile caching * optimized tile caching
[Core/Sound]
---------------
* rewrote optimized & more accurate PSG core from scratch
* removed PSG boost noise feature & added optional high-quality PSG resampling
[Gamecube/Wii] [Gamecube/Wii]
--------------- ---------------
* added configurable BIOS & Lock-on ROM files * added configurable BIOS & Lock-on ROM files

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 MiB

After

Width:  |  Height:  |  Size: 3.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 MiB

After

Width:  |  Height:  |  Size: 3.3 MiB

View File

@ -570,7 +570,7 @@ void io_gg_write(unsigned int offset, unsigned int data)
case 6: /* PSG Stereo output control */ case 6: /* PSG Stereo output control */
io_reg[6] = data; io_reg[6] = data;
SN76489_Config(Z80.cycles, config.psg_preamp, config.psgBoostNoise, data); psg_config(Z80.cycles, config.psg_preamp, data);
return; return;
default: /* Read-only */ default: /* Read-only */

View File

@ -1218,7 +1218,7 @@ void vdp_write_byte(unsigned int address, unsigned int data)
{ {
if (address & 1) if (address & 1)
{ {
SN76489_Write(m68k.cycles, data); psg_write(m68k.cycles, data);
return; return;
} }
m68k_unused_8_w(address, data); m68k_unused_8_w(address, data);
@ -1264,7 +1264,7 @@ void vdp_write_word(unsigned int address, unsigned int data)
case 0x10: /* PSG */ case 0x10: /* PSG */
case 0x14: case 0x14:
{ {
SN76489_Write(m68k.cycles, data & 0xFF); psg_write(m68k.cycles, data & 0xFF);
return; return;
} }

View File

@ -2,8 +2,8 @@
* Genesis Plus * Genesis Plus
* Z80 bank access to 68k bus * Z80 bank access to 68k bus
* *
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code) * Copyright (C) 1998-2003 Charles Mac Donald (original code)
* Copyright (C) 2007-2011 Eke-Eke (Genesis Plus GX) * Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
* *
* Redistribution and use of this code or any derivative works are permitted * Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met: * provided that the following conditions are met:
@ -294,7 +294,7 @@ void zbank_write_vdp(unsigned int address, unsigned int data)
{ {
if (address & 1) if (address & 1)
{ {
SN76489_Write(Z80.cycles, data); psg_write(Z80.cycles, data);
return; return;
} }
zbank_unused_w(address, data); zbank_unused_w(address, data);

View File

@ -2,8 +2,8 @@
* Genesis Plus * Genesis Plus
* Z80 bank access to 68k bus * Z80 bank access to 68k bus
* *
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code) * Copyright (C) 1998-2003 Charles Mac Donald (original code)
* Copyright (C) 2007-2012 Eke-Eke (Genesis Plus GX) * Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
* *
* Redistribution and use of this code or any derivative works are permitted * Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met: * provided that the following conditions are met:

View File

@ -231,7 +231,7 @@ void z80_md_port_w(unsigned int port, unsigned char data)
case 0x40: case 0x40:
case 0x41: case 0x41:
{ {
SN76489_Write(Z80.cycles, data); psg_write(Z80.cycles, data);
return; return;
} }
@ -345,7 +345,7 @@ void z80_gg_port_w(unsigned int port, unsigned char data)
case 0x40: case 0x40:
case 0x41: case 0x41:
{ {
SN76489_Write(Z80.cycles, data); psg_write(Z80.cycles, data);
return; return;
} }
@ -450,7 +450,7 @@ void z80_ms_port_w(unsigned int port, unsigned char data)
case 0x40: case 0x40:
case 0x41: case 0x41:
{ {
SN76489_Write(Z80.cycles, data); psg_write(Z80.cycles, data);
return; return;
} }
@ -493,7 +493,7 @@ void z80_ms_port_w(unsigned int port, unsigned char data)
1 0 : disable both PSG & FM output 1 0 : disable both PSG & FM output
1 1 : enable both PSG and FM output 1 1 : enable both PSG and FM output
*/ */
SN76489_Config(Z80.cycles, config.psg_preamp, config.psgBoostNoise, ((data + 1) & 0x02) ? 0x00 : 0xFF); psg_config(Z80.cycles, config.psg_preamp, ((data + 1) & 0x02) ? 0x00 : 0xFF);
fm_write(Z80.cycles, 0x02, data); fm_write(Z80.cycles, 0x02, data);
io_reg[6] = data; io_reg[6] = data;
return; return;
@ -611,7 +611,7 @@ void z80_m3_port_w(unsigned int port, unsigned char data)
case 0x40: case 0x40:
case 0x41: case 0x41:
{ {
SN76489_Write(Z80.cycles, data); psg_write(Z80.cycles, data);
return; return;
} }
@ -699,7 +699,7 @@ void z80_sg_port_w(unsigned int port, unsigned char data)
case 0x40: case 0x40:
case 0x41: case 0x41:
{ {
SN76489_Write(Z80.cycles, data); psg_write(Z80.cycles, data);
/* Z80 !WAIT input is tied to SN76489AN chip READY pin (held low for 32 clocks after each write access) */ /* Z80 !WAIT input is tied to SN76489AN chip READY pin (held low for 32 clocks after each write access) */
Z80.cycles += (32 * 15); Z80.cycles += (32 * 15);

View File

@ -22,7 +22,7 @@
#include "io_ctrl.h" #include "io_ctrl.h"
#include "input.h" #include "input.h"
#include "sound.h" #include "sound.h"
#include "sn76489.h" #include "psg.h"
#include "ym2413.h" #include "ym2413.h"
#include "ym2612.h" #include "ym2612.h"
#include "sram.h" #include "sram.h"

591
core/sound/psg.c Normal file
View File

@ -0,0 +1,591 @@
/***************************************************************************************
* Genesis Plus
* PSG sound chip (SN76489A compatible)
*
* Support for discrete chip & integrated (ASIC) clones
*
* Noise implementation based on http://www.smspower.org/Development/SN76489#NoiseChannel
*
* Copyright (C) 2016 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
*
* - Redistributions may not be sold, nor may they be used in a commercial
* product or activity.
*
* - Redistributions that are modified from the original source must include the
* complete source code, including the source code for all components used by a
* binary built from the modified sources. However, as a special exception, the
* source code distributed need not include anything that is normally distributed
* (in either source or binary form) with the major components (compiler, kernel,
* and so on) of the operating system on which the executable runs, unless that
* component itself accompanies the executable.
*
* - Redistributions must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************************/
#include "shared.h"
#include "blip_buf.h"
/* internal clock = input clock : 16 = (master clock : 15) : 16 */
#define PSG_MCYCLES_RATIO (15*16)
/* maximal channel output (roughly adjusted to match VA4 MD1 PSG/FM balance with 1.5x amplification of PSG output) */
#define PSG_MAX_VOLUME 2800
static const uint8 noiseShiftWidth[2] = {14,15};
static const uint8 noiseBitMask[2] = {0x6,0x9};
static const uint8 noiseFeedback[10] = {0,1,1,0,1,0,0,1,1,0};
static const uint16 chanVolume[16] = {
PSG_MAX_VOLUME, /* MAX */
PSG_MAX_VOLUME * 0.794328234, /* -2dB */
PSG_MAX_VOLUME * 0.630957344, /* -4dB */
PSG_MAX_VOLUME * 0.501187233, /* -6dB */
PSG_MAX_VOLUME * 0.398107170, /* -8dB */
PSG_MAX_VOLUME * 0.316227766, /* -10dB */
PSG_MAX_VOLUME * 0.251188643, /* -12dB */
PSG_MAX_VOLUME * 0.199526231, /* -14dB */
PSG_MAX_VOLUME * 0.158489319, /* -16dB */
PSG_MAX_VOLUME * 0.125892541, /* -18dB */
PSG_MAX_VOLUME * 0.1, /* -20dB */
PSG_MAX_VOLUME * 0.079432823, /* -22dB */
PSG_MAX_VOLUME * 0.063095734, /* -24dB */
PSG_MAX_VOLUME * 0.050118723, /* -26dB */
PSG_MAX_VOLUME * 0.039810717, /* -28dB */
0 /* OFF */
};
static struct
{
int clocks;
int latch;
int noiseShiftValue;
int noiseShiftWidth;
int noiseBitMask;
int regs[8];
int freqInc[4];
int freqCounter[4];
int polarity[4];
int chanDelta[4][2];
int chanOut[4][2];
int chanAmp[4][2];
} psg;
static void psg_update(unsigned int clocks);
void psg_init(PSG_TYPE type)
{
int i;
/* Initialize stereo amplification (default) */
for (i=0; i<4; i++)
{
psg.chanAmp[i][0] = 100;
psg.chanAmp[i][1] = 100;
}
/* Initialize Noise LSFR type */
psg.noiseShiftWidth = noiseShiftWidth[type];
psg.noiseBitMask = noiseBitMask[type];
}
void psg_reset()
{
int i;
/* power-on state (verified on 315-5313A & 315-5660 integrated version only) */
for (i=0; i<4; i++)
{
psg.regs[i*2] = 0;
psg.regs[i*2+1] = 0;
psg.freqInc[i] = (i < 3) ? (1 * PSG_MCYCLES_RATIO) : (16 * PSG_MCYCLES_RATIO);
psg.freqCounter[i] = 0;
psg.polarity[i] = -1;
psg.chanDelta[i][0] = 0;
psg.chanDelta[i][1] = 0;
psg.chanOut[i][0] = 0;
psg.chanOut[i][1] = 0;
}
/* noise attenuation register is latched on power-on (verified on 315-5313A & 315-5660 integrated version only) */
psg.latch = 7;
/* reset noise shift register */
psg.noiseShiftValue = 1 << psg.noiseShiftWidth;
/* reset internal M-cycles clock counter */
psg.clocks = 0;
}
int psg_context_save(uint8 *state)
{
int bufferptr = 0;
save_param(&psg.clocks,sizeof(psg.clocks));
save_param(&psg.latch,sizeof(psg.latch));
save_param(&psg.noiseShiftValue,sizeof(psg.noiseShiftValue));
save_param(psg.regs,sizeof(psg.regs));
save_param(psg.freqInc,sizeof(psg.freqInc));
save_param(psg.freqCounter,sizeof(psg.freqCounter));
save_param(psg.polarity,sizeof(psg.polarity));
save_param(psg.chanDelta,sizeof(psg.chanDelta));
save_param(psg.chanOut,sizeof(psg.chanOut));
return bufferptr;
}
int psg_context_load(uint8 *state)
{
int chanOut[4][2], delta[2];
int i, bufferptr = 0;
/* get current tone channels output */
for (i=0; i<3; i++)
{
if (psg.polarity[i] > 0)
{
chanOut[i][0] = psg.chanOut[i][0];
chanOut[i][1] = psg.chanOut[i][1];
}
else
{
chanOut[i][0] = 0;
chanOut[i][1] = 0;
}
}
/* get current noise channel output */
if (psg.noiseShiftValue & 1)
{
chanOut[3][0] = psg.chanOut[3][0];
chanOut[3][1] = psg.chanOut[3][1];
}
else
{
chanOut[3][0] = 0;
chanOut[3][1] = 0;
}
load_param(&psg.clocks,sizeof(psg.clocks));
load_param(&psg.latch,sizeof(psg.latch));
load_param(&psg.noiseShiftValue,sizeof(psg.noiseShiftValue));
load_param(psg.regs,sizeof(psg.regs));
load_param(psg.freqInc,sizeof(psg.freqInc));
load_param(psg.freqCounter,sizeof(psg.freqCounter));
load_param(psg.polarity,sizeof(psg.polarity));
load_param(psg.chanDelta,sizeof(psg.chanDelta));
load_param(psg.chanOut,sizeof(psg.chanOut));
/* apply any pending channel volume variation */
for (i=0; i<4; i++)
{
psg.chanOut[i][0] += psg.chanDelta[i][0];
psg.chanOut[i][1] += psg.chanDelta[i][1];
psg.chanDelta[i][0] = 0;
psg.chanDelta[i][1] = 0;
}
/* calculate noise channel output variations */
if (psg.noiseShiftValue & 1)
{
/* channel output is high */
delta[0] = psg.chanOut[3][0] - chanOut[3][0];
delta[1] = psg.chanOut[3][0] - chanOut[3][1];
}
else
{
/* channel output is low */
delta[0] = -chanOut[3][0];
delta[1] = -chanOut[3][1];
}
/* add tone channels output variations */
for (i=0; i<3; i++)
{
if (psg.polarity[i] > 0)
{
/* channel output is high */
delta[0] += (psg.chanOut[i][0] - chanOut[i][0]);
delta[1] += (psg.chanOut[i][0] - chanOut[i][1]);
}
else
{
/* channel output is low */
delta[0] -= chanOut[i][0];
delta[1] -= chanOut[i][1];
}
}
/* update mixed channels output */
if (config.hq_psg)
{
blip_add_delta(snd.blips[0], psg.clocks, delta[0], delta[1]);
}
else
{
blip_add_delta_fast(snd.blips[0], psg.clocks, delta[0], delta[1]);
}
return bufferptr;
}
void psg_write(unsigned int clocks, unsigned int data)
{
int index;
/* PSG chip synchronization */
if (clocks > psg.clocks)
{
/* run PSG chip until current timestamp */
psg_update(clocks);
/* update internal M-cycles clock counter */
psg.clocks += ((clocks - psg.clocks + PSG_MCYCLES_RATIO - 1) / PSG_MCYCLES_RATIO) * PSG_MCYCLES_RATIO;
}
if (data & 0x80)
{
/* latch register index (1xxx----) */
psg.latch = index = (data >> 4) & 0x07;
}
else
{
/* restore latched register index */
index= psg.latch;
}
switch (index)
{
case 0:
case 2:
case 4: /* Tone channels frequency */
{
/* recalculate frequency register value */
if (data & 0x80)
{
/* update 10-bit register LSB (1---xxxx) */
data = (psg.regs[index] & 0x3f0) | (data & 0x0f);
}
else
{
/* update 10-bit register MSB (0-xxxxxx) */
data = (psg.regs[index] & 0x00f) | ((data & 0x3f) << 4);
}
/* update channel M-cycle counter increment */
if (data)
{
psg.freqInc[index>>1] = data * PSG_MCYCLES_RATIO;
}
else
{
/* zero value behaves the same as a value of 1 (verified on integrated version only) */
psg.freqInc[index>>1] = PSG_MCYCLES_RATIO;
}
/* update noise channel counter increment if required */
if ((index == 4) && ((psg.regs[6] & 0x03) == 0x03))
{
psg.freqInc[3] = psg.freqInc[2];
}
break;
}
case 6: /* Noise control */
{
/* noise signal generator frequency (----?xxx) */
int noiseFreq = (data & 0x03);
if (noiseFreq == 0x03)
{
/* noise generator is controlled by tone channel #3 generator */
psg.freqInc[3] = psg.freqInc[2];
psg.freqCounter[3] = psg.freqCounter[2];
}
else
{
/* noise generator is running at separate frequency */
psg.freqInc[3] = (0x10 << noiseFreq) * PSG_MCYCLES_RATIO;
}
/* reset shift register value */
psg.noiseShiftValue = 1 << psg.noiseShiftWidth;;
break;
}
case 7: /* Noise channel attenuation */
{
/* convert 4-bit attenuation value (----xxxx) to 16-bit volume value */
data = chanVolume[data & 0x0f];
/* check noise shift register output */
if (psg.noiseShiftValue & 1)
{
/* channel output is high, volume variation will be applied at next internal cycle update */
psg.chanDelta[3][0] = ((data * psg.chanAmp[3][0]) / 100) - psg.chanOut[3][0];
psg.chanDelta[3][1] = ((data * psg.chanAmp[3][1]) / 100) - psg.chanOut[3][1];
}
else
{
/* channel output is low, volume variation will be applied at next transition */
psg.chanOut[3][0] = (data * psg.chanAmp[3][0]) / 100;
psg.chanOut[3][1] = (data * psg.chanAmp[3][1]) / 100;
}
break;
}
default: /* Tone channels attenuation */
{
/* channel number (0-2) */
int i = index >> 1;
/* convert 4-bit attenuation value (----xxxx) to 16-bit volume value */
data = chanVolume[data & 0x0f];
/* check tone generator polarity */
if (psg.polarity[i] > 0)
{
/* channel output is high, volume variation will be applied at next internal cycle update */
psg.chanDelta[i][0] = ((data * psg.chanAmp[i][0]) / 100) - psg.chanOut[i][0];
psg.chanDelta[i][1] = ((data * psg.chanAmp[i][1]) / 100) - psg.chanOut[i][1];
}
else
{
/* channel output is low, volume variation will be applied at next transition */
psg.chanOut[i][0] = (data * psg.chanAmp[i][0]) / 100;
psg.chanOut[i][1] = (data * psg.chanAmp[i][1]) / 100;
}
break;
}
}
/* save register value */
psg.regs[index] = data;
}
void psg_config(unsigned int clocks, unsigned int preamp, unsigned int panning)
{
int i;
/* PSG chip synchronization */
if (clocks > psg.clocks)
{
/* run PSG chip until current timestamp */
psg_update(clocks);
/* update internal M-cycles clock counter */
psg.clocks += ((clocks - psg.clocks + PSG_MCYCLES_RATIO - 1) / PSG_MCYCLES_RATIO) * PSG_MCYCLES_RATIO;
}
for (i=0; i<4; i++)
{
/* channel internal volume */
int volume = psg.regs[i*2+1];
/* update channel stereo amplification */
psg.chanAmp[i][0] = preamp * ((panning >> (i + 4)) & 1);
psg.chanAmp[i][1] = preamp * ((panning >> (i + 0)) & 1);
/* tone channels */
if (i < 3)
{
/* check tone generator polarity */
if (psg.polarity[i] > 0)
{
/* channel output is high, volume variation will be applied at next internal cycle update */
psg.chanDelta[i][0] = ((volume * psg.chanAmp[i][0]) / 100) - psg.chanOut[i][0];
psg.chanDelta[i][1] = ((volume * psg.chanAmp[i][1]) / 100) - psg.chanOut[i][1];
}
else
{
/* channel output is low, volume variation will be applied at next transition*/
psg.chanOut[i][0] = (volume * psg.chanAmp[i][0]) / 100;
psg.chanOut[i][1] = (volume * psg.chanAmp[i][1]) / 100;
}
}
/* noise channel */
else
{
/* check noise shift register output */
if (psg.noiseShiftValue & 1)
{
/* channel output is high, volume variation will be applied at next internal cycle update */
psg.chanDelta[3][0] = ((volume * psg.chanAmp[3][0]) / 100) - psg.chanOut[3][0];
psg.chanDelta[3][1] = ((volume * psg.chanAmp[3][1]) / 100) - psg.chanOut[3][1];
}
else
{
/* channel output is low, volume variation will be applied at next transition */
psg.chanOut[3][0] = (volume * psg.chanAmp[3][0]) / 100;
psg.chanOut[3][1] = (volume * psg.chanAmp[3][1]) / 100;
}
}
}
}
void psg_end_frame(unsigned int clocks)
{
int i;
if (clocks > psg.clocks)
{
/* run PSG chip until current timestamp */
psg_update(clocks);
/* update internal M-cycles clock counter */
psg.clocks += ((clocks - psg.clocks + PSG_MCYCLES_RATIO - 1) / PSG_MCYCLES_RATIO) * PSG_MCYCLES_RATIO;
}
/* adjust internal M-cycles clock counter for next frame */
psg.clocks -= clocks;
/* adjust channels time counters for next frame */
for (i=0; i<4; ++i)
{
psg.freqCounter[i] -= clocks;
}
}
static void psg_update(unsigned int clocks)
{
int i, timestamp, polarity;
for (i=0; i<4; i++)
{
/* apply any pending channel volume variations */
if (psg.chanDelta[i][0] | psg.chanDelta[i][1])
{
/* update channel output */
if (config.hq_psg)
{
blip_add_delta(snd.blips[0], psg.clocks, psg.chanDelta[i][0], psg.chanDelta[i][1]);
}
else
{
blip_add_delta_fast(snd.blips[0], psg.clocks, psg.chanDelta[i][0], psg.chanDelta[i][1]);
}
/* update channel volume */
psg.chanOut[i][0] += psg.chanDelta[i][0];
psg.chanOut[i][1] += psg.chanDelta[i][1];
/* clear pending channel volume variations */
psg.chanDelta[i][0] = 0;
psg.chanDelta[i][1] = 0;
}
/* timestamp of next transition */
timestamp = psg.freqCounter[i];
/* current channel generator polarity */
polarity = psg.polarity[i];
/* Tone channels */
if (i < 3)
{
/* process all transitions occurring until current clock timestamp */
while (timestamp < clocks)
{
/* invert tone generator polarity */
polarity = -polarity;
/* update channel output */
if (config.hq_psg)
{
blip_add_delta(snd.blips[0], timestamp, polarity*psg.chanOut[i][0], polarity*psg.chanOut[i][1]);
}
else
{
blip_add_delta_fast(snd.blips[0], timestamp, polarity*psg.chanOut[i][0], polarity*psg.chanOut[i][1]);
}
/* timestamp of next transition */
timestamp += psg.freqInc[i];
}
}
/* Noise channel */
else
{
/* current noise shift register value */
int shiftValue = psg.noiseShiftValue;
/* process all transitions occurring until current clock timestamp */
while (timestamp < clocks)
{
/* invert noise generator polarity */
polarity = -polarity;
/* noise register is shifted on positive edge only */
if (polarity > 0)
{
/* current shift register output */
int shiftOutput = shiftValue & 0x01;
/* White noise (----1xxx) */
if (psg.regs[6] & 0x04)
{
/* shift and apply XOR feedback network */
shiftValue = (shiftValue >> 1) | (noiseFeedback[shiftValue & psg.noiseBitMask] << psg.noiseShiftWidth);
}
/* Periodic noise (----0xxx) */
else
{
/* shift and feedback current output */
shiftValue = (shiftValue >> 1) | (shiftOutput << psg.noiseShiftWidth);
}
/* shift register output variation */
shiftOutput = (shiftValue & 0x1) - shiftOutput;
/* update noise channel output */
if (config.hq_psg)
{
blip_add_delta(snd.blips[0], timestamp, shiftOutput*psg.chanOut[3][0], shiftOutput*psg.chanOut[3][1]);
}
else
{
blip_add_delta_fast(snd.blips[0], timestamp, shiftOutput*psg.chanOut[3][0], shiftOutput*psg.chanOut[3][1]);
}
}
/* timestamp of next transition */
timestamp += psg.freqInc[3];
}
/* save shift register value */
psg.noiseShiftValue = shiftValue;
}
/* save timestamp of next transition */
psg.freqCounter[i] = timestamp;
/* save channel generator polarity */
psg.polarity[i] = polarity;
}
}

60
core/sound/psg.h Normal file
View File

@ -0,0 +1,60 @@
/***************************************************************************************
* Genesis Plus
* PSG sound chip (SN76489A compatible)
*
* Support for discrete chip & integrated (ASIC) clones
*
* Noise implementation based on http://www.smspower.org/Development/SN76489#NoiseChannel
*
* Copyright (C) 2016 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
*
* - Redistributions may not be sold, nor may they be used in a commercial
* product or activity.
*
* - Redistributions that are modified from the original source must include the
* complete source code, including the source code for all components used by a
* binary built from the modified sources. However, as a special exception, the
* source code distributed need not include anything that is normally distributed
* (in either source or binary form) with the major components (compiler, kernel,
* and so on) of the operating system on which the executable runs, unless that
* component itself accompanies the executable.
*
* - Redistributions must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************************/
#ifndef _PSG_H_
#define _PSG_H_
typedef enum {
PSG_DISCRETE,
PSG_INTEGRATED
} PSG_TYPE;
/* Function prototypes */
extern void psg_init(PSG_TYPE type);
extern void psg_reset(void);
extern int psg_context_save(uint8 *state);
extern int psg_context_load(uint8 *state);
extern void psg_write(unsigned int clocks, unsigned int data);
extern void psg_config(unsigned int clocks, unsigned int preamp, unsigned int panning);
extern void psg_end_frame(unsigned int clocks);
#endif /* _PSG_H_ */

View File

@ -1,418 +0,0 @@
/*
SN76489 emulation
by Maxim in 2001 and 2002
converted from my original Delphi implementation
I'm a C newbie so I'm sure there are loads of stupid things
in here which I'll come back to some day and redo
Includes:
- Super-high quality tone channel "oversampling" by calculating fractional positions on transitions
- Noise output pattern reverse engineered from actual SMS output
- Volume levels taken from actual SMS output
07/08/04 Charles MacDonald
Modified for use with SMS Plus:
- Added support for multiple PSG chips.
- Added reset/config/update routines.
- Added context management routines.
- Removed SN76489_GetValues().
- Removed some unused variables.
25/04/07 Eke-Eke (Genesis Plus GX)
- Removed stereo GG support (unused)
- Made SN76489_Update outputs 16bits mono samples
- Replaced volume table with VGM plugin's one
05/01/09 Eke-Eke (Genesis Plus GX)
- Modified Cut-Off frequency (according to Steve Snake: http://www.smspower.org/forums/viewtopic.php?t=1746)
24/08/10 Eke-Eke (Genesis Plus GX)
- Removed multichip support (unused)
- Removed alternate volume table, panning & mute support (unused)
- Removed configurable Feedback and Shift Register Width (always use Sega ones)
- Added linear resampling using Blip Buffer (based on Blargg's implementation: http://www.smspower.org/forums/viewtopic.php?t=11376)
01/09/12 Eke-Eke (Genesis Plus GX)
- Added generic Blip-Buffer support internally, using common Master Clock as timebase
- Re-added stereo GG support
- Re-added configurable Feedback and Shift Register Width
- Rewrote core with various optimizations
04/11/16 Eke-Eke (Genesis Plus GX)
- improved resampling quality (removes aliasing noise when using high frequency tones)
- removed cut-off value (improves emulation accuracy of highest frequency tones)
- modified channels output to 0/1 like real chip instead of -1/+1 (fixes PCM voices when cut-off value is removed)
*/
#include "shared.h"
#define PSG_MCYCLES_RATIO (16 * 15)
/* Initial state of shift register */
#define NoiseInitialState 0x8000
/* original Texas Instruments TMS SN76489AN (rev. A) used in SG-1000, SC-3000H & SF-7000 computers */
#define FB_DISCRETE 0x0006
#define SRW_DISCRETE 15
/* SN76489AN clone integrated in Sega's VDP chips (315-5124, 315-5246, 315-5313, Game Gear) */
#define FB_SEGAVDP 0x0009
#define SRW_SEGAVDP 16
typedef struct
{
/* Configuration */
int PreAmp[4][2]; /* stereo channels pre-amplification ratio (%) */
int NoiseFeedback;
int SRWidth;
/* PSG registers: */
int Registers[8]; /* Tone, vol x4 */
int LatchedRegister;
int NoiseShiftRegister;
int NoiseFreq; /* Noise channel signal generator frequency */
/* Output calculation variables */
int ToneFreqVals[4]; /* Frequency register values (counters) */
int ToneFreqPos[4]; /* Frequency channel flip-flops */
int Channel[4][2]; /* current amplitude of each (stereo) channel */
int ChanOut[4][2]; /* current output value of each (stereo) channel */
/* Internal M-clock counter */
unsigned long clocks;
} SN76489_Context;
static const uint16 PSGVolumeValues[16] =
{
/* These values are taken from a real SMS2's output */
/*{892,892,892,760,623,497,404,323,257,198,159,123,96,75,60,0}, */
/* I can't remember why 892... :P some scaling I did at some point */
/* these values are true volumes for 2dB drops at each step (multiply previous by 10^-0.1) */
1516,1205,957,760,603,479,381,303,240,191,152,120,96,76,60,0
};
static SN76489_Context SN76489;
void SN76489_Init(int type)
{
int i;
for (i=0; i<4; i++)
{
SN76489.PreAmp[i][0] = 100;
SN76489.PreAmp[i][1] = 100;
}
if (type == SN_DISCRETE)
{
SN76489.NoiseFeedback = FB_DISCRETE;
SN76489.SRWidth = SRW_DISCRETE;
}
else
{
SN76489.NoiseFeedback = FB_SEGAVDP;
SN76489.SRWidth = SRW_SEGAVDP;
}
}
void SN76489_Reset()
{
int i;
for(i = 0; i <= 3; i++)
{
/* Initialise PSG state */
SN76489.Registers[2*i] = 1; /* tone freq=1 */
SN76489.Registers[2*i+1] = 0xf; /* vol=off */
/* Set counters to 0 */
SN76489.ToneFreqVals[i] = 0;
/* Set flip-flops to 1 */
SN76489.ToneFreqPos[i] = 1;
/* Clear stereo channels amplitude */
SN76489.Channel[i][0] = 0;
SN76489.Channel[i][1] = 0;
/* Clear stereo channel outputs in delta buffer */
SN76489.ChanOut[i][0] = 0;
SN76489.ChanOut[i][1] = 0;
}
/* Initialise latched register index */
SN76489.LatchedRegister = 0;
/* Initialise noise generator */
SN76489.NoiseShiftRegister=NoiseInitialState;
SN76489.NoiseFreq = 0x10;
/* Reset internal M-cycle counter */
SN76489.clocks = 0;
}
void *SN76489_GetContextPtr(void)
{
return (uint8 *)&SN76489;
}
int SN76489_GetContextSize(void)
{
return sizeof(SN76489_Context);
}
/* Updates tone amplitude in delta buffer. Call whenever amplitude might have changed. */
INLINE void UpdateToneAmplitude(int i, int time)
{
/* left & right output */
int delta_l = (SN76489.Channel[i][0] * SN76489.ToneFreqPos[i]) - SN76489.ChanOut[i][0];
int delta_r = (SN76489.Channel[i][1] * SN76489.ToneFreqPos[i]) - SN76489.ChanOut[i][1];
blip_add_delta(snd.blips[0], time, delta_l, delta_r);
SN76489.ChanOut[i][0] += delta_l;
SN76489.ChanOut[i][1] += delta_r;
}
/* Updates noise amplitude in delta buffer. Call whenever amplitude might have changed. */
INLINE void UpdateNoiseAmplitude(int time)
{
/* left & right output */
int delta_l = (SN76489.Channel[3][0] * ( SN76489.NoiseShiftRegister & 0x1 )) - SN76489.ChanOut[3][0];
int delta_r = (SN76489.Channel[3][1] * ( SN76489.NoiseShiftRegister & 0x1 )) - SN76489.ChanOut[3][1];
blip_add_delta(snd.blips[0], time, delta_l, delta_r);
SN76489.ChanOut[3][0] += delta_l;
SN76489.ChanOut[3][1] += delta_r;
}
/* Runs tone channel for clock_length clocks */
static void RunTone(int i, int clocks)
{
int time;
/* Update in case a register changed etc. */
UpdateToneAmplitude(i, SN76489.clocks);
/* Time of next transition */
time = SN76489.ToneFreqVals[i];
/* Process any transitions that occur within clocks we're running */
while (time < clocks)
{
/* Flip the flip-flop */
SN76489.ToneFreqPos[i] ^= 1;
UpdateToneAmplitude(i, time);
/* Advance to time of next transition */
time += SN76489.Registers[i*2] * PSG_MCYCLES_RATIO;
}
/* Update channel tone counter */
SN76489.ToneFreqVals[i] = time;
}
/* Runs noise channel for clock_length clocks */
static void RunNoise(int clocks)
{
int time;
/* Noise channel: match to tone2 if in slave mode */
int NoiseFreq = SN76489.NoiseFreq;
if (NoiseFreq == 0x80)
{
NoiseFreq = SN76489.Registers[2*2];
SN76489.ToneFreqVals[3] = SN76489.ToneFreqVals[2];
}
/* Update in case a register changed etc. */
UpdateNoiseAmplitude(SN76489.clocks);
/* Time of next transition */
time = SN76489.ToneFreqVals[3];
/* Process any transitions that occur within clocks we're running */
while (time < clocks)
{
/* Flip the flip-flop */
SN76489.ToneFreqPos[3] ^= 1;
if (SN76489.ToneFreqPos[3])
{
/* On the positive edge of the square wave (only once per cycle) */
int Feedback = SN76489.NoiseShiftRegister;
if ( SN76489.Registers[6] & 0x4 )
{
/* White noise */
/* Calculate parity of fed-back bits for feedback */
/* Do some optimised calculations for common (known) feedback values */
/* If two bits fed back, I can do Feedback=(nsr & fb) && (nsr & fb ^ fb) */
/* since that's (one or more bits set) && (not all bits set) */
Feedback = ((Feedback & SN76489.NoiseFeedback) && ((Feedback & SN76489.NoiseFeedback) ^ SN76489.NoiseFeedback));
}
else /* Periodic noise */
Feedback = Feedback & 1;
SN76489.NoiseShiftRegister = (SN76489.NoiseShiftRegister >> 1) | (Feedback << (SN76489.SRWidth - 1));
UpdateNoiseAmplitude(time);
}
/* Advance to time of next transition */
time += NoiseFreq * PSG_MCYCLES_RATIO;
}
/* Update channel tone counter */
SN76489.ToneFreqVals[3] = time;
}
static void SN76489_RunUntil(unsigned int clocks)
{
int i;
/* Run noise first, since it might use current value of third tone frequency counter */
RunNoise(clocks);
/* Run tone channels */
for (i=0; i<3; ++i)
{
RunTone(i, clocks);
}
}
void SN76489_Config(unsigned int clocks, int preAmp, int boostNoise, int stereo)
{
int i;
/* cycle-accurate Game Gear stereo */
if (clocks > SN76489.clocks)
{
/* Run chip until current timestamp */
SN76489_RunUntil(clocks);
/* Update internal M-cycle counter */
SN76489.clocks += ((clocks - SN76489.clocks + PSG_MCYCLES_RATIO - 1) / PSG_MCYCLES_RATIO) * PSG_MCYCLES_RATIO;
}
for (i=0; i<4; i++)
{
/* stereo channel pre-amplification */
SN76489.PreAmp[i][0] = preAmp * ((stereo >> (i + 4)) & 1);
SN76489.PreAmp[i][1] = preAmp * ((stereo >> (i + 0)) & 1);
/* noise channel boost (applied to all channels) */
SN76489.PreAmp[i][0] = SN76489.PreAmp[i][0] << boostNoise;
SN76489.PreAmp[i][1] = SN76489.PreAmp[i][1] << boostNoise;
/* update stereo channel amplitude */
SN76489.Channel[i][0]= (PSGVolumeValues[SN76489.Registers[i*2 + 1]] * SN76489.PreAmp[i][0]) / 100;
SN76489.Channel[i][1]= (PSGVolumeValues[SN76489.Registers[i*2 + 1]] * SN76489.PreAmp[i][1]) / 100;
}
}
void SN76489_Update(unsigned int clocks)
{
int i;
if (clocks > SN76489.clocks)
{
/* Run chip until current timestamp */
SN76489_RunUntil(clocks);
/* Update internal M-cycle counter */
SN76489.clocks += ((clocks - SN76489.clocks + PSG_MCYCLES_RATIO - 1) / PSG_MCYCLES_RATIO) * PSG_MCYCLES_RATIO;
}
/* Adjust internal M-cycle counter for next frame */
SN76489.clocks -= clocks;
/* Adjust channel time counters for new frame */
for (i=0; i<4; ++i)
{
SN76489.ToneFreqVals[i] -= clocks;
}
}
void SN76489_Write(unsigned int clocks, unsigned int data)
{
unsigned int index;
if (clocks > SN76489.clocks)
{
/* run chip until current timestamp */
SN76489_RunUntil(clocks);
/* update internal M-cycle counter */
SN76489.clocks += ((clocks - SN76489.clocks + PSG_MCYCLES_RATIO - 1) / PSG_MCYCLES_RATIO) * PSG_MCYCLES_RATIO;
}
if (data & 0x80)
{
/* latch byte %1 cc t dddd */
SN76489.LatchedRegister = index = (data >> 4) & 0x07;
}
else
{
/* restore latched register index */
index = SN76489.LatchedRegister;
}
switch (index)
{
case 0:
case 2:
case 4: /* Tone Channels frequency */
{
if (data & 0x80)
{
/* Data byte %1 cc t dddd */
SN76489.Registers[index] = (SN76489.Registers[index] & 0x3f0) | (data & 0xf);
}
else
{
/* Data byte %0 - dddddd */
SN76489.Registers[index] = (SN76489.Registers[index] & 0x00f) | ((data & 0x3f) << 4);
}
/* zero frequency behaves the same as a value of 1 */
if (SN76489.Registers[index] == 0)
{
SN76489.Registers[index] = 1;
}
break;
}
case 1:
case 3:
case 5: /* Tone Channels attenuation */
{
data &= 0x0f;
SN76489.Registers[index] = data;
data = PSGVolumeValues[data];
index >>= 1;
SN76489.Channel[index][0] = (data * SN76489.PreAmp[index][0]) / 100;
SN76489.Channel[index][1] = (data * SN76489.PreAmp[index][1]) / 100;
break;
}
case 6: /* Noise control */
{
SN76489.Registers[6] = data & 0x0f;
/* reset shift register */
SN76489.NoiseShiftRegister = NoiseInitialState;
/* set noise signal generator frequency */
SN76489.NoiseFreq = 0x10 << (data&0x3);
break;
}
case 7: /* Noise attenuation */
{
data &= 0x0f;
SN76489.Registers[7] = data;
data = PSGVolumeValues[data];
SN76489.Channel[3][0] = (data * SN76489.PreAmp[3][0]) / 100;
SN76489.Channel[3][1] = (data * SN76489.PreAmp[3][1]) / 100;
break;
}
}
}

View File

@ -1,23 +0,0 @@
/*
SN76489 emulation
by Maxim in 2001 and 2002
*/
#ifndef _SN76489_H_
#define _SN76489_H_
#include "blip_buf.h"
#define SN_DISCRETE 0
#define SN_INTEGRATED 1
/* Function prototypes */
extern void SN76489_Init(int type);
extern void SN76489_Reset(void);
extern void SN76489_Config(unsigned int clocks, int preAmp, int boostNoise, int stereo);
extern void SN76489_Write(unsigned int clocks, unsigned int data);
extern void SN76489_Update(unsigned int cycles);
extern void *SN76489_GetContextPtr(void);
extern int SN76489_GetContextSize(void);
#endif /* _SN76489_H_ */

View File

@ -86,7 +86,7 @@ void sound_init( void )
YM_Update = YM2612Update; YM_Update = YM2612Update;
YM_Write = YM2612Write; YM_Write = YM2612Write;
/* chip is running a VCLK / 144 = MCLK / 7 / 144 */ /* chip is running at VCLK / 144 = MCLK / 7 / 144 */
fm_cycles_ratio = 144 * 7; fm_cycles_ratio = 144 * 7;
} }
else else
@ -97,21 +97,20 @@ void sound_init( void )
YM_Update = YM2413Update; YM_Update = YM2413Update;
YM_Write = YM2413Write; YM_Write = YM2413Write;
/* chip is running a ZCLK / 72 = MCLK / 15 / 72 */ /* chip is running at ZCLK / 72 = MCLK / 15 / 72 */
fm_cycles_ratio = 72 * 15; fm_cycles_ratio = 72 * 15;
} }
/* Initialize PSG chip */ /* Initialize PSG chip */
SN76489_Init((system_hw == SYSTEM_SG) ? SN_DISCRETE : SN_INTEGRATED); psg_init((system_hw == SYSTEM_SG) ? PSG_DISCRETE : PSG_INTEGRATED);
SN76489_Config(0, config.psg_preamp, config.psgBoostNoise, 0xff);
} }
void sound_reset(void) void sound_reset(void)
{ {
/* reset sound chips */ /* reset sound chips */
YM_Reset(); YM_Reset();
SN76489_Reset(); psg_reset();
SN76489_Config(0, config.psg_preamp, config.psgBoostNoise, 0xff); psg_config(0, config.psg_preamp, 0xff);
/* reset FM buffer ouput */ /* reset FM buffer ouput */
fm_last[0] = fm_last[1] = 0; fm_last[0] = fm_last[1] = 0;
@ -127,8 +126,10 @@ int sound_update(unsigned int cycles)
{ {
int prev_l, prev_r, preamp, time, l, r, *ptr; int prev_l, prev_r, preamp, time, l, r, *ptr;
/* Run PSG & FM chips until end of frame */ /* Run PSG chip until end of frame */
SN76489_Update(cycles); psg_end_frame(cycles);
/* Run FM chip until end of frame */
fm_update(cycles); fm_update(cycles);
/* FM output pre-amplification */ /* FM output pre-amplification */
@ -210,7 +211,7 @@ int sound_context_save(uint8 *state)
save_param(YM2413GetContextPtr(),YM2413GetContextSize()); save_param(YM2413GetContextPtr(),YM2413GetContextSize());
} }
save_param(SN76489_GetContextPtr(),SN76489_GetContextSize()); bufferptr += psg_context_save(&state[bufferptr]);
save_param(&fm_cycles_start,sizeof(fm_cycles_start)); save_param(&fm_cycles_start,sizeof(fm_cycles_start));
@ -231,7 +232,7 @@ int sound_context_load(uint8 *state)
load_param(YM2413GetContextPtr(),YM2413GetContextSize()); load_param(YM2413GetContextPtr(),YM2413GetContextSize());
} }
load_param(SN76489_GetContextPtr(),SN76489_GetContextSize()); bufferptr += psg_context_load(&state[bufferptr]);
load_param(&fm_cycles_start,sizeof(fm_cycles_start)); load_param(&fm_cycles_start,sizeof(fm_cycles_start));
fm_cycles_count = fm_cycles_start; fm_cycles_count = fm_cycles_start;

View File

@ -2,7 +2,7 @@
* Genesis Plus * Genesis Plus
* Savestate support * Savestate support
* *
* Copyright (C) 2007-2014 Eke-Eke (Genesis Plus GX) * Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
* *
* Redistribution and use of this code or any derivative works are permitted * Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met: * provided that the following conditions are met:
@ -116,11 +116,11 @@ int state_load(unsigned char *state)
bufferptr += sound_context_load(&state[bufferptr]); bufferptr += sound_context_load(&state[bufferptr]);
if ((system_hw & SYSTEM_PBC) == SYSTEM_MD) if ((system_hw & SYSTEM_PBC) == SYSTEM_MD)
{ {
SN76489_Config(0, config.psg_preamp, config.psgBoostNoise, 0xff); psg_config(0, config.psg_preamp, 0xff);
} }
else else
{ {
SN76489_Config(0, config.psg_preamp, config.psgBoostNoise, io_reg[6]); psg_config(0, config.psg_preamp, io_reg[6]);
} }
/* 68000 */ /* 68000 */

View File

@ -2,7 +2,7 @@
* Genesis Plus * Genesis Plus
* Savestate support * Savestate support
* *
* Copyright (C) 2007-2014 Eke-Eke (Genesis Plus GX) * Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
* *
* Redistribution and use of this code or any derivative works are permitted * Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met: * provided that the following conditions are met:

View File

@ -71,7 +71,7 @@ OBJECTS += $(OBJDIR)/input.o \
$(OBJDIR)/graphic_board.o $(OBJDIR)/graphic_board.o
OBJECTS += $(OBJDIR)/sound.o \ OBJECTS += $(OBJDIR)/sound.o \
$(OBJDIR)/sn76489.o \ $(OBJDIR)/psg.o \
$(OBJDIR)/ym2413.o \ $(OBJDIR)/ym2413.o \
$(OBJDIR)/ym2612.o $(OBJDIR)/ym2612.o

View File

@ -42,7 +42,7 @@ void set_config_defaults(void)
config.psg_preamp = 150; config.psg_preamp = 150;
config.fm_preamp = 100; config.fm_preamp = 100;
config.hq_fm = 1; config.hq_fm = 1;
config.psgBoostNoise = 1; config.hq_psg = 1;
config.filter = 1; config.filter = 1;
config.low_freq = 200; config.low_freq = 200;
config.high_freq = 8000; config.high_freq = 8000;

View File

@ -20,7 +20,7 @@ typedef struct
{ {
uint8 hq_fm; uint8 hq_fm;
uint8 filter; uint8 filter;
uint8 psgBoostNoise; uint8 hq_psg;
uint8 dac_bits; uint8 dac_bits;
uint8 ym2413; uint8 ym2413;
int16 psg_preamp; int16 psg_preamp;

View File

@ -3,7 +3,7 @@
* *
* Genesis Plus GX configuration file support * Genesis Plus GX configuration file support
* *
* Copyright Eke-Eke (2007-2015) * Copyright Eke-Eke (2007-2016)
* *
* Redistribution and use of this code or any derivative works are permitted * Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met: * provided that the following conditions are met:
@ -101,7 +101,7 @@ void config_default(void)
config.psg_preamp = 150; config.psg_preamp = 150;
config.fm_preamp = 100; config.fm_preamp = 100;
config.hq_fm = 1; config.hq_fm = 1;
config.psgBoostNoise = 1; config.hq_psg = 1;
config.filter = 1; config.filter = 1;
config.lp_range = 0x9999; /* 0.6 in 16.16 fixed point */ config.lp_range = 0x9999; /* 0.6 in 16.16 fixed point */
config.low_freq = 880; config.low_freq = 880;

View File

@ -3,7 +3,7 @@
* *
* Genesis Plus GX configuration file support * Genesis Plus GX configuration file support
* *
* Copyright Eke-Eke (2007-2015) * Copyright Eke-Eke (2007-2016)
* *
* Redistribution and use of this code or any derivative works are permitted * Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met: * provided that the following conditions are met:
@ -51,7 +51,7 @@ typedef struct
char version[16]; char version[16];
uint8 hq_fm; uint8 hq_fm;
uint8 filter; uint8 filter;
uint8 psgBoostNoise; uint8 hq_psg;
uint8 dac_bits; uint8 dac_bits;
uint8 ym2413; uint8 ym2413;
uint8 mono; uint8 mono;

View File

@ -341,19 +341,19 @@ static gui_item items_options[] =
/* Audio options */ /* Audio options */
static gui_item items_audio[] = static gui_item items_audio[] =
{ {
{NULL,NULL,"Master System FM: AUTO", "Enable/disable YM2413 chip", 56,132,276,48}, {NULL,NULL,"Master System FM: AUTO", "Enable/Disable YM2413 chip", 56,132,276,48},
{NULL,NULL,"High-Quality FM: ON", "Adjust YM2612/YM2413 resampling quality", 56,132,276,48}, {NULL,NULL,"High-Quality FM: ON", "Enable/Disable YM2612/YM2413 high-quality resampling", 56,132,276,48},
{NULL,NULL,"FM Resolution: MAX", "Adjust YM2612 DAC precision", 56,132,276,48}, {NULL,NULL,"FM Resolution: MAX", "Adjust YM2612 DAC precision", 56,132,276,48},
{NULL,NULL,"FM Volume: 1.00", "Adjust YM2612/YM2413 output level", 56,132,276,48}, {NULL,NULL,"FM Volume: 1.00", "Adjust YM2612/YM2413 audio balance", 56,132,276,48},
{NULL,NULL,"PSG Volume: 2.50", "Adjust SN76489 output level", 56,132,276,48}, {NULL,NULL,"PSG Volume: 2.50", "Adjust SN76489 audio balance", 56,132,276,48},
{NULL,NULL,"PSG Noise Boost: OFF", "Boost SN76489 Noise Channel", 56,132,276,48}, {NULL,NULL,"High-Quality PSG: ON", "Enable/Disable SN76489 high-quality resampling", 56,132,276,48},
{NULL,NULL,"Audio Out: STEREO", "Select audio mixing output type", 56,132,276,48}, {NULL,NULL,"Audio Output: STEREO", "Select audio mixing output type", 56,132,276,48},
{NULL,NULL,"Filtering: 3-BAND EQ", "Setup Audio filtering", 56,132,276,48}, {NULL,NULL,"Filtering: 3-BAND EQ", "Select audio filtering type", 56,132,276,48},
{NULL,NULL,"Low Gain: 1.00", "Adjust EQ Low Band Gain", 56,132,276,48}, {NULL,NULL,"Low Gain: 1.00", "Adjust EQ Low Band Gain", 56,132,276,48},
{NULL,NULL,"Mid Gain: 1.00", "Adjust EQ Mid Band Gain", 56,132,276,48}, {NULL,NULL,"Mid Gain: 1.00", "Adjust EQ Mid Band Gain", 56,132,276,48},
{NULL,NULL,"High Gain: 1.00", "Adjust EQ High Band Gain", 56,132,276,48}, {NULL,NULL,"High Gain: 1.00", "Adjust EQ High Band Gain", 56,132,276,48},
{NULL,NULL,"Low Freq: 200 Hz", "Adjust EQ Lowest Frequency", 56,132,276,48}, {NULL,NULL,"Low Freq: 200 Hz", "Adjust EQ Lowest Frequency", 56,132,276,48},
{NULL,NULL,"High Freq: 20000 Hz", "Adjust EQ Highest Frequency", 56,132,276,48} {NULL,NULL,"High Freq: 20000 Hz", "Adjust EQ Highest Frequency", 56,132,276,48}
}; };
/* System ROM paths */ /* System ROM paths */
@ -381,10 +381,10 @@ static gui_item items_system[] =
{NULL,NULL,"VDP Mode: AUTO", "Select VDP mode", 56,132,276,48}, {NULL,NULL,"VDP Mode: AUTO", "Select VDP mode", 56,132,276,48},
{NULL,NULL,"System Clock: AUTO", "Select system clock frequency", 56,132,276,48}, {NULL,NULL,"System Clock: AUTO", "Select system clock frequency", 56,132,276,48},
{NULL,NULL,"System Boot: BIOS&CART", "Select system booting method", 56,132,276,48}, {NULL,NULL,"System Boot: BIOS&CART", "Select system booting method", 56,132,276,48},
{NULL,NULL,"System Lockups: ON", "Enable/disable original system lock-ups", 56,132,276,48}, {NULL,NULL,"System Lockups: ON", "Enable/Disable original system lock-ups", 56,132,276,48},
{NULL,NULL,"68k Address Error: ON", "Enable/disable 68k address error exceptions", 56,132,276,48}, {NULL,NULL,"68k Address Error: ON", "Enable/Disable 68k address error exceptions", 56,132,276,48},
{NULL,NULL,"Lock-on: OFF", "Select Lock-On cartridge type", 56,132,276,48}, {NULL,NULL,"Lock-on: OFF", "Select Lock-On cartridge type", 56,132,276,48},
{NULL,NULL,"Cartridge Swap: OFF", "Enable/disable cartridge hot swap", 56,132,276,48}, {NULL,NULL,"Cartridge Swap: OFF", "Enable/Disable cartridge hot swap", 56,132,276,48},
{NULL,NULL,"BIOS & Lock-On ROM paths","Configure BIOS & Lock-On ROM paths", 56,132,276,48}, {NULL,NULL,"BIOS & Lock-On ROM paths","Configure BIOS & Lock-On ROM paths", 56,132,276,48},
{NULL,NULL,"SVP Cycles: 1500", "Adjust SVP chip emulation speed", 56,132,276,48} {NULL,NULL,"SVP Cycles: 1500", "Adjust SVP chip emulation speed", 56,132,276,48}
}; };
@ -394,22 +394,22 @@ static gui_item items_video[] =
{ {
{NULL,NULL,"Display: PROGRESSIVE", "Select video mode", 56,132,276,48}, {NULL,NULL,"Display: PROGRESSIVE", "Select video mode", 56,132,276,48},
{NULL,NULL,"TV mode: 50/60HZ", "Select video refresh rate", 56,132,276,48}, {NULL,NULL,"TV mode: 50/60HZ", "Select video refresh rate", 56,132,276,48},
{NULL,NULL,"VSYNC: AUTO", "Enable/disable sync with video hardware", 56,132,276,48}, {NULL,NULL,"VSYNC: AUTO", "Enable/Disable sync with video hardware", 56,132,276,48},
{NULL,NULL,"Bilinear Filter: OFF", "Enable/disable GX hardware texture filtering", 56,132,276,48}, {NULL,NULL,"Bilinear Filter: OFF", "Enable/Disable GX hardware texture filtering", 56,132,276,48},
{NULL,NULL,"Deflickering Filter: AUTO", "Enable/disable GX hardware framebuffer filtering", 56,132,276,48}, {NULL,NULL,"Deflickering Filter: AUTO", "Enable/Disable GX hardware framebuffer filtering", 56,132,276,48},
#ifdef HW_RVL #ifdef HW_RVL
{NULL,NULL,"Trap Filter: ON", "Enable/disable VI hardware composite out filtering",56,132,276,48}, {NULL,NULL,"Trap Filter: ON", "Enable/Disable VI hardware composite out filtering",56,132,276,48},
{NULL,NULL,"Gamma Correction: 1.0", "Adjust VI hardware gamma correction", 56,132,276,48}, {NULL,NULL,"Gamma Correction: 1.0", "Adjust VI hardware gamma correction", 56,132,276,48},
#endif #endif
{NULL,NULL,"LCD Ghosting Filter: OFF", "Enable/disable software LCD image persistence", 56,132,276,48}, {NULL,NULL,"LCD Ghosting Filter: OFF", "Enable/Disable software LCD image persistence", 56,132,276,48},
{NULL,NULL,"NTSC Filter: COMPOSITE", "Enable/disable software NTSC filtering", 56,132,276,48}, {NULL,NULL,"NTSC Filter: COMPOSITE", "Enable/Disable software NTSC filtering", 56,132,276,48},
{NULL,NULL,"NTSC Sharpness: 0.0", "Adjust edge contrast enhancement/blurring", 56,132,276,48}, {NULL,NULL,"NTSC Sharpness: 0.0", "Adjust edge contrast enhancement/blurring", 56,132,276,48},
{NULL,NULL,"NTSC Resolution: 0.0", "Adjust image resolution", 56,132,276,48}, {NULL,NULL,"NTSC Resolution: 0.0", "Adjust image resolution", 56,132,276,48},
{NULL,NULL,"NTSC Artifacts: 0.0", "Adjust artifacts caused by color changes", 56,132,276,48}, {NULL,NULL,"NTSC Artifacts: 0.0", "Adjust artifacts caused by color changes", 56,132,276,48},
{NULL,NULL,"NTSC Color Bleed: 0.0", "Adjust color resolution reduction", 56,132,276,48}, {NULL,NULL,"NTSC Color Bleed: 0.0", "Adjust color resolution reduction", 56,132,276,48},
{NULL,NULL,"NTSC Color Fringing: 0.0", "Adjust artifacts caused by brightness changes", 56,132,276,48}, {NULL,NULL,"NTSC Color Fringing: 0.0", "Adjust artifacts caused by brightness changes", 56,132,276,48},
{NULL,NULL,"Borders: OFF", "Enable/disable overscan emulation", 56,132,276,48}, {NULL,NULL,"Borders: OFF", "Enable/Disable overscan emulation", 56,132,276,48},
{NULL,NULL,"GG screen: ORIGINAL", "Enable/disable Game Gear extended screen", 56,132,276,48}, {NULL,NULL,"GG screen: ORIGINAL", "Enable/Disable Game Gear extended screen", 56,132,276,48},
{NULL,NULL,"Aspect: ORIGINAL (4:3)", "Select display aspect ratio", 56,132,276,48}, {NULL,NULL,"Aspect: ORIGINAL (4:3)", "Select display aspect ratio", 56,132,276,48},
{NULL,NULL,"Screen Position (+0,+0)", "Adjust display position", 56,132,276,48}, {NULL,NULL,"Screen Position (+0,+0)", "Adjust display position", 56,132,276,48},
{NULL,NULL,"Screen Scaling (+0,+0)", "Adjust display scaling", 56,132,276,48} {NULL,NULL,"Screen Scaling (+0,+0)", "Adjust display scaling", 56,132,276,48}
@ -418,19 +418,19 @@ static gui_item items_video[] =
/* Menu options */ /* Menu options */
static gui_item items_prefs[] = static gui_item items_prefs[] =
{ {
{NULL,NULL,"Auto ROM Load: OFF", "Enable/disable automatic ROM loading on startup", 56,132,276,48}, {NULL,NULL,"Auto ROM Load: OFF", "Enable/Disable automatic ROM loading on startup", 56,132,276,48},
{NULL,NULL,"Auto Cheats: OFF", "Enable/disable automatic cheats activation", 56,132,276,48}, {NULL,NULL,"Auto Cheats: OFF", "Enable/Disable automatic cheats activation", 56,132,276,48},
{NULL,NULL,"Auto Saves: OFF", "Enable/disable automatic saves", 56,132,276,48}, {NULL,NULL,"Auto Saves: OFF", "Enable/Disable automatic saves", 56,132,276,48},
{NULL,NULL,"ROM Load Device: SD", "Configure default device for ROM files", 56,132,276,48}, {NULL,NULL,"ROM Load Device: SD", "Configure default device for ROM files", 56,132,276,48},
{NULL,NULL,"Saves Device: FAT", "Configure default device for Save files", 56,132,276,48}, {NULL,NULL,"Saves Device: FAT", "Configure default device for Save files", 56,132,276,48},
{NULL,NULL,"SFX Volume: 100", "Adjust sound effects volume", 56,132,276,48}, {NULL,NULL,"SFX Volume: 100", "Adjust sound effects volume", 56,132,276,48},
{NULL,NULL,"BGM Volume: 100", "Adjust background music volume", 56,132,276,48}, {NULL,NULL,"BGM Volume: 100", "Adjust background music volume", 56,132,276,48},
{NULL,NULL,"BG Overlay: ON", "Enable/disable background overlay", 56,132,276,48}, {NULL,NULL,"BG Overlay: ON", "Enable/Disable background overlay", 56,132,276,48},
{NULL,NULL,"Screen Width: 658", "Adjust menu screen width in pixels", 56,132,276,48}, {NULL,NULL,"Screen Width: 658", "Adjust menu screen width in pixels", 56,132,276,48},
{NULL,NULL,"Show CD Leds: OFF", "Enable/disable CD leds display", 56,132,276,48}, {NULL,NULL,"Show CD Leds: OFF", "Enable/Disable CD leds display", 56,132,276,48},
{NULL,NULL,"Show FPS: OFF", "Enable/disable FPS counter", 56,132,276,48}, {NULL,NULL,"Show FPS: OFF", "Enable/Disable FPS counter", 56,132,276,48},
#ifdef HW_RVL #ifdef HW_RVL
{NULL,NULL,"Wiimote Timeout: OFF","Enable/disable Wii remote automatic shutodwn", 56,132,276,48}, {NULL,NULL,"Wiimote Timeout: OFF","Enable/Disable Wii remote automatic shutodwn", 56,132,276,48},
{NULL,NULL,"Wiimote Calibration: AUTO","Calibrate Wii remote pointer", 56,132,276,48}, {NULL,NULL,"Wiimote Calibration: AUTO","Calibrate Wii remote pointer", 56,132,276,48},
#endif #endif
}; };
@ -899,16 +899,15 @@ static void soundmenu ()
else if (config.ym2413 == 1) sprintf (items[0].text, "Master System FM: ON"); else if (config.ym2413 == 1) sprintf (items[0].text, "Master System FM: ON");
else sprintf (items[0].text, "Master System FM: AUTO"); else sprintf (items[0].text, "Master System FM: AUTO");
if (config.hq_fm) sprintf (items[1].text, "High-Quality FM: ON"); sprintf (items[1].text, "High-Quality FM: %s", config.hq_fm ? "ON":"OFF");
else sprintf (items[1].text, "High-Quality FM: OFF");
if (config.dac_bits < 14) sprintf (items[2].text, "FM Resolution: %d bits", config.dac_bits); if (config.dac_bits < 14) sprintf (items[2].text, "FM Resolution: %d bits", config.dac_bits);
else sprintf (items[2].text, "FM Resolution: MAX"); else sprintf (items[2].text, "FM Resolution: MAX");
sprintf (items[3].text, "FM Volume: %1.2f", fm_volume); sprintf (items[3].text, "FM Volume: %1.2f", fm_volume);
sprintf (items[4].text, "PSG Volume: %1.2f", psg_volume); sprintf (items[4].text, "PSG Volume: %1.2f", psg_volume);
sprintf (items[5].text, "PSG Noise Boost: %s", config.psgBoostNoise ? "ON":"OFF"); sprintf (items[5].text, "High-Quality PSG: %s", config.hq_psg? "ON":"OFF");
sprintf (items[6].text, "Audio Out: %s", config.mono ? "MONO":"STEREO"); sprintf (items[6].text, "Audio Output: %s", config.mono ? "MONO":"STEREO");
if (config.filter == 2) if (config.filter == 2)
{ {
@ -971,8 +970,7 @@ static void soundmenu ()
case 1: case 1:
{ {
config.hq_fm ^= 1; config.hq_fm ^= 1;
if (config.hq_fm) sprintf (items[1].text, "High-Quality FM: ON"); sprintf (items[1].text, "High-Quality FM: %s", config.hq_fm ? "ON":"OFF");
else sprintf (items[1].text, "High-Quality FM: OFF");
break; break;
} }
@ -1001,27 +999,19 @@ static void soundmenu ()
config.psg_preamp = (int)(psg_volume * 100.0 + 0.5); config.psg_preamp = (int)(psg_volume * 100.0 + 0.5);
if ((system_hw & SYSTEM_PBC) == SYSTEM_MD) if ((system_hw & SYSTEM_PBC) == SYSTEM_MD)
{ {
SN76489_Config(0, config.psg_preamp, config.psgBoostNoise, 0xff); psg_config(0, config.psg_preamp, 0xff);
} }
else else
{ {
SN76489_Config(0, config.psg_preamp, config.psgBoostNoise, io_reg[6]); psg_config(0, config.psg_preamp, io_reg[6]);
} }
break; break;
} }
case 5: case 5:
{ {
config.psgBoostNoise ^= 1; config.hq_psg ^= 1;
sprintf (items[5].text, "PSG Noise Boost: %s", config.psgBoostNoise ? "ON":"OFF"); sprintf (items[5].text, "High-Quality PSG: %s", config.hq_psg ? "ON":"OFF");
if ((system_hw & SYSTEM_PBC) == SYSTEM_MD)
{
SN76489_Config(0, config.psg_preamp, config.psgBoostNoise, 0xff);
}
else
{
SN76489_Config(0, config.psg_preamp, config.psgBoostNoise, io_reg[6]);
}
break; break;
} }
@ -1745,8 +1735,8 @@ static void videomenu ()
else else
sprintf (items[VI_OFFSET+1].text, "NTSC Filter: OFF"); sprintf (items[VI_OFFSET+1].text, "NTSC Filter: OFF");
strcpy(items[VI_OFFSET+2+ntsc_offset].comment, "Enable/disable overscan emulation"); strcpy(items[VI_OFFSET+2+ntsc_offset].comment, "Enable/Disable overscan emulation");
strcpy(items[VI_OFFSET+3+ntsc_offset].comment, "Enable/disable Game Gear extended screen"); strcpy(items[VI_OFFSET+3+ntsc_offset].comment, "Enable/Disable Game Gear extended screen");
strcpy(items[VI_OFFSET+4+ntsc_offset].comment, "Select display aspect ratio"); strcpy(items[VI_OFFSET+4+ntsc_offset].comment, "Select display aspect ratio");
strcpy(items[VI_OFFSET+5+ntsc_offset].comment, "Adjust display position"); strcpy(items[VI_OFFSET+5+ntsc_offset].comment, "Adjust display position");
strcpy(items[VI_OFFSET+6+ntsc_offset].comment, "Adjust display scaling"); strcpy(items[VI_OFFSET+6+ntsc_offset].comment, "Adjust display scaling");
@ -3645,15 +3635,15 @@ static void showcredits(void)
gxDrawTexture(texture, (640-texture->width)/2, (480-texture->height)/2, texture->width, texture->height,255); gxDrawTexture(texture, (640-texture->width)/2, (480-texture->height)/2, texture->width, texture->height,255);
FONT_writeCenter("Genesis Plus Core", 24, 0, 640, 480 - offset, (GXColor)LIGHT_BLUE); FONT_writeCenter("Genesis Plus Core", 24, 0, 640, 480 - offset, (GXColor)LIGHT_BLUE);
FONT_writeCenter("improved emulation code, fixes & extra features by Eke-Eke", 18, 0, 640, 516 - offset, (GXColor)WHITE); FONT_writeCenter("improved emulation code & extra features by Eke-Eke", 18, 0, 640, 516 - offset, (GXColor)WHITE);
FONT_writeCenter("original 1.3 version by Charles MacDonald", 18, 0, 640, 534 - offset, (GXColor)WHITE); FONT_writeCenter("original 1.3 version by Charles MacDonald", 18, 0, 640, 534 - offset, (GXColor)WHITE);
FONT_writeCenter("original Z80 core by Juergen Buchmueller", 18, 0, 640, 552 - offset, (GXColor)WHITE); FONT_writeCenter("original Z80 core by Juergen Buchmueller", 18, 0, 640, 552 - offset, (GXColor)WHITE);
FONT_writeCenter("original 68k core (Musashi) by Karl Stenerud", 18, 0, 640, 570 - offset, (GXColor)WHITE); FONT_writeCenter("original 68k core (Musashi) by Karl Stenerud", 18, 0, 640, 570 - offset, (GXColor)WHITE);
FONT_writeCenter("original YM2612/2413 cores by Jarek Burczynski, Tatsuyuki Satoh", 18, 0, 640, 588 - offset, (GXColor)WHITE); FONT_writeCenter("original YM2612/2413 cores by Jarek Burczynski, Tatsuyuki Satoh", 18, 0, 640, 588 - offset, (GXColor)WHITE);
FONT_writeCenter("original SN76489 core by Maxim", 18, 0, 640, 606 - offset, (GXColor)WHITE); FONT_writeCenter("SVP core by Gravydas Ignotas (Notaz)", 18, 0, 640, 606 - offset, (GXColor)WHITE);
FONT_writeCenter("SVP core by Gravydas Ignotas (Notaz)", 18, 0, 640, 624 - offset, (GXColor)WHITE); FONT_writeCenter("Blip Buffer Library & NTSC Video Filter by Shay Green (Blargg)", 18, 0, 640, 624 - offset, (GXColor)WHITE);
FONT_writeCenter("Blip Buffer Library & NTSC Video Filter by Shay Green (Blargg)", 18, 0, 640, 642 - offset, (GXColor)WHITE); FONT_writeCenter("3-Band EQ implementation by Neil C", 18, 0, 640, 642 - offset, (GXColor)WHITE);
FONT_writeCenter("3-Band EQ implementation by Neil C", 18, 0, 640, 660 - offset, (GXColor)WHITE); FONT_writeCenter("Ogg Vorbis 'Tremor' Library by Xiph.org Foundation", 18, 0, 640, 660 - offset, (GXColor)WHITE);
FONT_writeCenter("Special thanks to ...", 20, 0, 640, 700 - offset, (GXColor)LIGHT_GREEN); FONT_writeCenter("Special thanks to ...", 20, 0, 640, 700 - offset, (GXColor)LIGHT_GREEN);
FONT_writeCenter("Nemesis, Tasco Deluxe, Bart Trzynadlowski, Jorge Cwik, Haze,", 18, 0, 640, 736 - offset, (GXColor)WHITE); FONT_writeCenter("Nemesis, Tasco Deluxe, Bart Trzynadlowski, Jorge Cwik, Haze,", 18, 0, 640, 736 - offset, (GXColor)WHITE);
@ -3670,7 +3660,7 @@ static void showcredits(void)
FONT_writeCenter("libfat by Chism", 18, 0, 640, 978 - offset, (GXColor)WHITE); FONT_writeCenter("libfat by Chism", 18, 0, 640, 978 - offset, (GXColor)WHITE);
FONT_writeCenter("wiiuse by Michael Laforest (Para)", 18, 0, 640, 996 - offset, (GXColor)WHITE); FONT_writeCenter("wiiuse by Michael Laforest (Para)", 18, 0, 640, 996 - offset, (GXColor)WHITE);
FONT_writeCenter("asndlib & OGG player by Francisco Muñoz (Hermes)", 18, 0, 640, 1014 - offset, (GXColor)WHITE); FONT_writeCenter("asndlib & OGG player by Francisco Muñoz (Hermes)", 18, 0, 640, 1014 - offset, (GXColor)WHITE);
FONT_writeCenter("zlib, libpng & libtremor by their respective authors", 18, 0, 640, 1032 - offset, (GXColor)WHITE); FONT_writeCenter("zlib & libpng by their respective authors", 18, 0, 640, 1032 - offset, (GXColor)WHITE);
FONT_writeCenter("devkitPPC by Wintermute", 18, 0, 640, 1050 - offset, (GXColor)WHITE); FONT_writeCenter("devkitPPC by Wintermute", 18, 0, 640, 1050 - offset, (GXColor)WHITE);
FONT_writeCenter("Special thanks to ...", 20, 0, 640, 1090 - offset, (GXColor)LIGHT_GREEN); FONT_writeCenter("Special thanks to ...", 20, 0, 640, 1090 - offset, (GXColor)LIGHT_GREEN);

View File

@ -13,7 +13,7 @@ Upstream Authors:
Files: * Files: *
Copyright: 1998, 1999, 2000, 2001, 2002, 2003 Charles MacDonald Copyright: 1998, 1999, 2000, 2001, 2002, 2003 Charles MacDonald
Some portions copyright Nicola Salmoria and the MAME team. All rights reserved. Some portions copyright Nicola Salmoria and the MAME team. All rights reserved.
2007-2015 Eke-Eke. All rights reserved. 2007-2016 Eke-Eke. All rights reserved.
License: License:
Unless otherwise explicitly stated, all code in Genesis Plus GX is released Unless otherwise explicitly stated, all code in Genesis Plus GX is released
under the following license: under the following license:
@ -77,7 +77,6 @@ License: LGPLv2.1
Files: core/sound/blip_buf.c Files: core/sound/blip_buf.c
core/sound/blip_buf.h core/sound/blip_buf.h
Copyright: 2003-2009 Shay Green Copyright: 2003-2009 Shay Green
2012-2013 EkeEke
License: LGPLv2.1 License: LGPLv2.1
Files: core/sound/eq.c Files: core/sound/eq.c
@ -90,13 +89,6 @@ License: Public domain
The author assumes NO RESPONSIBILITY for any problems caused by the use of The author assumes NO RESPONSIBILITY for any problems caused by the use of
this software. this software.
Files: core/sound/sn76489.c
core/sound/sn76489.h
Copyright: 2001, 2002 Maxim
2004 Charles MacDonald
2007, 2009, 2010, 2012 Eke-Eke
License: Genesis Plus GX license
Files: core/sound/ym2413.c Files: core/sound/ym2413.c
core/sound/ym2413.h core/sound/ym2413.h
Copyright: 2002 Jarek Burczynski Copyright: 2002 Jarek Burczynski

View File

@ -3,7 +3,7 @@
* *
* Genesis Plus GX libretro port * Genesis Plus GX libretro port
* *
* Copyright Eke-Eke (2007-2015) * Copyright Eke-Eke (2007-2016)
* *
* Copyright Daniel De Matteis (2012-2016) * Copyright Daniel De Matteis (2012-2016)
* *
@ -495,8 +495,8 @@ static void config_default(void)
/* sound options */ /* sound options */
config.psg_preamp = 150; config.psg_preamp = 150;
config.fm_preamp = 100; config.fm_preamp = 100;
config.hq_fm = 1; /* high-quality resampling */ config.hq_fm = 1; /* high-quality FM resampling (slower) */
config.psgBoostNoise = 1; config.hq_psg = 1; /* high-quality PSG resampling (slower) */
config.filter = 0; /* no filter */ config.filter = 0; /* no filter */
config.lp_range = 0x9999; /* 0.6 in 16.16 fixed point */ config.lp_range = 0x9999; /* 0.6 in 16.16 fixed point */
config.low_freq = 880; config.low_freq = 880;
@ -504,7 +504,7 @@ static void config_default(void)
config.lg = 1.0; config.lg = 1.0;
config.mg = 1.0; config.mg = 1.0;
config.hg = 1.0; config.hg = 1.0;
config.dac_bits = 14; /* MAX DEPTH */ config.dac_bits = 14; /* MAX DEPTH */
config.ym2413 = 2; /* AUTO */ config.ym2413 = 2; /* AUTO */
config.mono = 0; /* STEREO output */ config.mono = 0; /* STEREO output */

View File

@ -394,7 +394,7 @@
RelativePath="..\..\..\core\sound\eq.c"> RelativePath="..\..\..\core\sound\eq.c">
</File> </File>
<File <File
RelativePath="..\..\..\core\sound\sn76489.c"> RelativePath="..\..\..\core\sound\psg.c">
</File> </File>
<File <File
RelativePath="..\..\..\core\sound\sound.c"> RelativePath="..\..\..\core\sound\sound.c">

View File

@ -143,7 +143,7 @@
<CompileAs Condition="'$(Configuration)|$(Platform)'=='Release_LTCG|Xbox 360'">CompileAsC</CompileAs> <CompileAs Condition="'$(Configuration)|$(Platform)'=='Release_LTCG|Xbox 360'">CompileAsC</CompileAs>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\..\core\sound\eq.c" /> <ClCompile Include="..\..\..\core\sound\eq.c" />
<ClCompile Include="..\..\..\core\sound\sn76489.c" /> <ClCompile Include="..\..\..\core\sound\psg.c" />
<ClCompile Include="..\..\..\core\sound\sound.c" /> <ClCompile Include="..\..\..\core\sound\sound.c" />
<ClCompile Include="..\..\..\core\sound\ym2413.c" /> <ClCompile Include="..\..\..\core\sound\ym2413.c" />
<ClCompile Include="..\..\..\core\sound\ym2612.c" /> <ClCompile Include="..\..\..\core\sound\ym2612.c" />

View File

@ -80,7 +80,7 @@
<ClCompile Include="..\..\..\core\sound\eq.c"> <ClCompile Include="..\..\..\core\sound\eq.c">
<Filter>Source Files\sound</Filter> <Filter>Source Files\sound</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\..\core\sound\sn76489.c"> <ClCompile Include="..\..\..\core\sound\psg.c">
<Filter>Source Files\sound</Filter> <Filter>Source Files\sound</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\..\core\sound\sound.c"> <ClCompile Include="..\..\..\core\sound\sound.c">

View File

@ -49,7 +49,7 @@
<ClCompile Include="..\..\..\core\ntsc\sms_ntsc.c" /> <ClCompile Include="..\..\..\core\ntsc\sms_ntsc.c" />
<ClCompile Include="..\..\..\core\sound\blip_buf.c" /> <ClCompile Include="..\..\..\core\sound\blip_buf.c" />
<ClCompile Include="..\..\..\core\sound\eq.c" /> <ClCompile Include="..\..\..\core\sound\eq.c" />
<ClCompile Include="..\..\..\core\sound\sn76489.c" /> <ClCompile Include="..\..\..\core\sound\psg.c" />
<ClCompile Include="..\..\..\core\sound\sound.c" /> <ClCompile Include="..\..\..\core\sound\sound.c" />
<ClCompile Include="..\..\..\core\sound\ym2413.c" /> <ClCompile Include="..\..\..\core\sound\ym2413.c" />
<ClCompile Include="..\..\..\core\sound\ym2612.c" /> <ClCompile Include="..\..\..\core\sound\ym2612.c" />

View File

@ -117,7 +117,7 @@
<ClCompile Include="..\..\..\core\sound\eq.c"> <ClCompile Include="..\..\..\core\sound\eq.c">
<Filter>Source Files\sound</Filter> <Filter>Source Files\sound</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\..\core\sound\sn76489.c"> <ClCompile Include="..\..\..\core\sound\psg.c">
<Filter>Source Files\sound</Filter> <Filter>Source Files\sound</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\..\core\sound\sound.c"> <ClCompile Include="..\..\..\core\sound\sound.c">

View File

@ -3,7 +3,7 @@
* *
* Genesis Plus GX libretro port * Genesis Plus GX libretro port
* *
* Copyright Eke-Eke (2007-2015) * Copyright Eke-Eke (2007-2016)
* *
* Copyright Daniel De Matteis (2012-2016) * Copyright Daniel De Matteis (2012-2016)
* *
@ -84,7 +84,7 @@ struct
char version[16]; char version[16];
uint8 hq_fm; uint8 hq_fm;
uint8 filter; uint8 filter;
uint8 psgBoostNoise; uint8 hq_psg;
uint8 dac_bits; uint8 dac_bits;
uint8 ym2413; uint8 ym2413;
uint8 mono; uint8 mono;

View File

@ -69,7 +69,7 @@ OBJECTS += $(OBJDIR)/input.o \
$(OBJDIR)/graphic_board.o $(OBJDIR)/graphic_board.o
OBJECTS += $(OBJDIR)/sound.o \ OBJECTS += $(OBJDIR)/sound.o \
$(OBJDIR)/sn76489.o \ $(OBJDIR)/psg.o \
$(OBJDIR)/ym2413.o \ $(OBJDIR)/ym2413.o \
$(OBJDIR)/ym2612.o $(OBJDIR)/ym2612.o

View File

@ -11,7 +11,7 @@ void set_config_defaults(void)
config.psg_preamp = 150; config.psg_preamp = 150;
config.fm_preamp = 100; config.fm_preamp = 100;
config.hq_fm = 0; config.hq_fm = 0;
config.psgBoostNoise = 1; config.hq_psg = 0;
config.filter = 1; config.filter = 1;
config.low_freq = 200; config.low_freq = 200;
config.high_freq = 8000; config.high_freq = 8000;

View File

@ -19,7 +19,7 @@ typedef struct
{ {
uint8 hq_fm; uint8 hq_fm;
uint8 filter; uint8 filter;
uint8 psgBoostNoise; uint8 hq_psg;
uint8 dac_bits; uint8 dac_bits;
uint8 ym2413; uint8 ym2413;
int16 psg_preamp; int16 psg_preamp;

View File

@ -67,7 +67,7 @@ OBJECTS += $(OBJDIR)/input.o \
$(OBJDIR)/graphic_board.o $(OBJDIR)/graphic_board.o
OBJECTS += $(OBJDIR)/sound.o \ OBJECTS += $(OBJDIR)/sound.o \
$(OBJDIR)/sn76489.o \ $(OBJDIR)/psg.o \
$(OBJDIR)/ym2413.o \ $(OBJDIR)/ym2413.o \
$(OBJDIR)/ym2612.o $(OBJDIR)/ym2612.o

View File

@ -67,7 +67,7 @@ OBJECTS += $(OBJDIR)/input.o \
$(OBJDIR)/graphic_board.o $(OBJDIR)/graphic_board.o
OBJECTS += $(OBJDIR)/sound.o \ OBJECTS += $(OBJDIR)/sound.o \
$(OBJDIR)/sn76489.o \ $(OBJDIR)/psg.o \
$(OBJDIR)/ym2413.o \ $(OBJDIR)/ym2413.o \
$(OBJDIR)/ym2612.o $(OBJDIR)/ym2612.o

View File

@ -12,7 +12,7 @@ void set_config_defaults(void)
config.psg_preamp = 150; config.psg_preamp = 150;
config.fm_preamp = 100; config.fm_preamp = 100;
config.hq_fm = 1; config.hq_fm = 1;
config.psgBoostNoise = 1; config.hq_psg = 1;
config.filter = 1; config.filter = 1;
config.low_freq = 200; config.low_freq = 200;
config.high_freq = 8000; config.high_freq = 8000;

View File

@ -15,7 +15,7 @@ typedef struct
{ {
uint8 hq_fm; uint8 hq_fm;
uint8 filter; uint8 filter;
uint8 psgBoostNoise; uint8 hq_psg;
uint8 dac_bits; uint8 dac_bits;
uint8 ym2413; uint8 ym2413;
int16 psg_preamp; int16 psg_preamp;