mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-12-27 03:31:49 +01:00
added YM2413 emulation in Master System compatibility mode
This commit is contained in:
parent
b6bc325353
commit
d0eab7d8d9
@ -85,6 +85,7 @@ void config_default(void)
|
||||
config.hg = 1.0;
|
||||
config.rolloff = 0.995;
|
||||
config.dac_bits = 14;
|
||||
config.ym2413_enabled = 1;
|
||||
|
||||
/* system options */
|
||||
config.region_detect = 0;
|
||||
|
@ -24,7 +24,7 @@
|
||||
#ifndef _CONFIG_H_
|
||||
#define _CONFIG_H_
|
||||
|
||||
#define CONFIG_VERSION "GENPLUS-GX 1.4.1"
|
||||
#define CONFIG_VERSION "GENPLUS-GX 1.5.1"
|
||||
|
||||
/****************************************************************************
|
||||
* Config Option
|
||||
@ -37,6 +37,7 @@ typedef struct
|
||||
uint8 filter;
|
||||
uint8 psgBoostNoise;
|
||||
uint8 dac_bits;
|
||||
uint8 ym2413_enabled;
|
||||
int16 psg_preamp;
|
||||
int16 fm_preamp;
|
||||
int16 lp_range;
|
||||
|
@ -321,20 +321,21 @@ static gui_item items_options[5] =
|
||||
};
|
||||
|
||||
/* Audio options */
|
||||
static gui_item items_audio[12] =
|
||||
static gui_item items_audio[13] =
|
||||
{
|
||||
{NULL,NULL,"High-Quality FM: ON", "Enable/disable YM2612 resampling", 56,132,276,48},
|
||||
{NULL,NULL,"FM Roll-off: 0.999", "Adjust FIR low-pass filtering", 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 output level", 56,132,276,48},
|
||||
{NULL,NULL,"PSG Volume: 2.50", "Adjust SN76489 output level", 56,132,276,48},
|
||||
{NULL,NULL,"PSG Noise Boost: OFF", "Boost SN76489 Noise Channel", 56,132,276,48},
|
||||
{NULL,NULL,"Filtering: 3-BAND EQ", "Setup Audio filtering", 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,"High Gain: 1.00", "Adjust EQ High BandGain", 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,"Master System FM: ON", "Enable/disable YM2413 chip", 56,132,276,48},
|
||||
{NULL,NULL,"High-Quality FM: ON", "Enable/disable YM2612/YM2413 resampling", 56,132,276,48},
|
||||
{NULL,NULL,"FM Roll-off: 0.999", "Adjust FIR low-pass filtering", 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,"PSG Volume: 2.50", "Adjust SN76489 output level", 56,132,276,48},
|
||||
{NULL,NULL,"PSG Noise Boost: OFF", "Boost SN76489 Noise Channel", 56,132,276,48},
|
||||
{NULL,NULL,"Filtering: 3-BAND EQ", "Setup Audio filtering", 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,"High Gain: 1.00", "Adjust EQ High BandGain", 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}
|
||||
};
|
||||
|
||||
/* System options */
|
||||
@ -584,7 +585,7 @@ static gui_menu menu_audio =
|
||||
{
|
||||
"Audio Settings",
|
||||
0,0,
|
||||
8,4,6,0,
|
||||
9,4,6,0,
|
||||
items_audio,
|
||||
buttons_list,
|
||||
bg_list,
|
||||
@ -755,19 +756,19 @@ static int update_snd_items(void)
|
||||
|
||||
if (config.hq_fm)
|
||||
{
|
||||
sprintf (items[0].text, "High-Quality FM: ON");
|
||||
sprintf (items[1].text, "FM Roll-off: %1.2f %%",rolloff);
|
||||
strcpy (items[1].comment, "Adjust FIR low-pass filtering");
|
||||
offset = 2;
|
||||
sprintf (items[1].text, "High-Quality FM: ON");
|
||||
sprintf (items[2].text, "FM Roll-off: %1.2f %%",rolloff);
|
||||
strcpy (items[2].comment, "Adjust FIR low-pass filtering");
|
||||
offset = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf (items[0].text, "High-Quality FM: OFF");
|
||||
offset = 1;
|
||||
sprintf (items[1].text, "High-Quality FM: OFF");
|
||||
offset = 2;
|
||||
}
|
||||
|
||||
strcpy(items[offset].comment, "Adjust YM2612 DAC precision");
|
||||
strcpy(items[offset+1].comment, "Adjust YM2612 output level");
|
||||
strcpy(items[offset+1].comment, "Adjust YM2612/YM2413 output level");
|
||||
strcpy(items[offset+2].comment, "Adjust SN76489 output level");
|
||||
strcpy(items[offset+3].comment, "Boost SN76489 Noise Channel");
|
||||
strcpy(items[offset+4].comment, "Configure Audio filtering");
|
||||
@ -836,10 +837,10 @@ static void soundmenu ()
|
||||
/* special case */
|
||||
if (config.hq_fm)
|
||||
{
|
||||
if (ret == 1)
|
||||
if (ret == 2)
|
||||
{
|
||||
GUI_OptionBox(m,0,"FM Roll-off",(void *)&rolloff,0.1,95.0,99.9,0);
|
||||
sprintf (items[1].text, "FM Roll-off: %1.2f %%",rolloff);
|
||||
sprintf (items[2].text, "FM Roll-off: %1.2f %%",rolloff);
|
||||
config.rolloff = rolloff / 100.0;
|
||||
ret = 255;
|
||||
if (cart.romsize)
|
||||
@ -860,7 +861,7 @@ static void soundmenu ()
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ret > 1)
|
||||
else if (ret > 2)
|
||||
{
|
||||
ret--;
|
||||
}
|
||||
@ -869,6 +870,11 @@ static void soundmenu ()
|
||||
switch (ret)
|
||||
{
|
||||
case 0:
|
||||
config.ym2413_enabled ^= 1;
|
||||
sprintf (items[0].text, "Master System FM: %s", config.ym2413_enabled ? "ON":"OFF");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
config.hq_fm ^= 1;
|
||||
offset = update_snd_items();
|
||||
|
||||
@ -891,7 +897,7 @@ static void soundmenu ()
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 2:
|
||||
config.dac_bits++;
|
||||
if (config.dac_bits > 14)
|
||||
config.dac_bits = 7;
|
||||
@ -919,25 +925,25 @@ static void soundmenu ()
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
GUI_OptionBox(m,0,"FM Volume",(void *)&fm_volume,0.01,0.0,5.0,0);
|
||||
sprintf (items[offset+1].text, "FM Volume: %1.2f", fm_volume);
|
||||
config.fm_preamp = (int)(fm_volume * 100.0 + 0.5);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
case 4:
|
||||
GUI_OptionBox(m,0,"PSG Volume",(void *)&psg_volume,0.01,0.0,5.0,0);
|
||||
sprintf (items[offset+2].text, "PSG Volume: %1.2f", psg_volume);
|
||||
config.psg_preamp = (int)(psg_volume * 100.0 + 0.5);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
case 5:
|
||||
config.psgBoostNoise ^= 1;
|
||||
sprintf (items[offset+3].text, "PSG Noise Boost: %s", config.psgBoostNoise ? "ON":"OFF");
|
||||
SN76489_BoostNoise(config.psgBoostNoise);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
case 6:
|
||||
config.filter = (config.filter + 1) % 3;
|
||||
if (config.filter == 2)
|
||||
{
|
||||
@ -967,7 +973,7 @@ static void soundmenu ()
|
||||
}
|
||||
break;
|
||||
|
||||
case 6:
|
||||
case 7:
|
||||
if (config.filter == 1)
|
||||
{
|
||||
GUI_OptionBox(m,0,"Low-Pass Rate",(void *)&config.lp_range,1,0,100,1);
|
||||
@ -982,27 +988,27 @@ static void soundmenu ()
|
||||
}
|
||||
break;
|
||||
|
||||
case 7:
|
||||
case 8:
|
||||
GUI_OptionBox(m,0,"Middle Gain",(void *)&mg,0.01,0.0,2.0,0);
|
||||
sprintf (items[offset+6].text, "Middle Gain: %1.2f", mg);
|
||||
config.mg = (int)(mg * 100.0);
|
||||
audio_set_equalizer();
|
||||
break;
|
||||
|
||||
case 8:
|
||||
case 9:
|
||||
GUI_OptionBox(m,0,"High Gain",(void *)&hg,0.01,0.0,2.0,0);
|
||||
sprintf (items[offset+7].text, "High Gain: %1.2f", hg);
|
||||
config.hg = (int)(hg * 100.0);
|
||||
audio_set_equalizer();
|
||||
break;
|
||||
|
||||
case 9:
|
||||
case 10:
|
||||
GUI_OptionBox(m,0,"Low Frequency",(void *)&config.low_freq,10,0,config.high_freq,1);
|
||||
sprintf (items[offset+8].text, "Low Freq: %d", config.low_freq);
|
||||
audio_set_equalizer();
|
||||
break;
|
||||
|
||||
case 10:
|
||||
case 11:
|
||||
GUI_OptionBox(m,0,"High Frequency",(void *)&config.high_freq,100,config.low_freq,30000,1);
|
||||
sprintf (items[offset+9].text, "High Freq: %d", config.high_freq);
|
||||
audio_set_equalizer();
|
||||
|
@ -252,6 +252,13 @@ void z80_sms_port_w(unsigned int port, unsigned char data)
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ((port >= 0xF0) && (config.ym2413_enabled))
|
||||
{
|
||||
fm_write(mcycles_z80, port&3, data);
|
||||
return;
|
||||
}
|
||||
|
||||
z80_unused_port_w(port, data);
|
||||
return;
|
||||
}
|
||||
@ -285,11 +292,17 @@ unsigned char z80_sms_port_r(unsigned int port)
|
||||
default:
|
||||
{
|
||||
port &= 0xFF;
|
||||
|
||||
if ((port == 0xC0) || (port == 0xC1) || (port == 0xDC) || (port == 0xDD) || (port == 0xDE) || (port == 0xDF))
|
||||
{
|
||||
return io_z80_read(port & 1);
|
||||
}
|
||||
|
||||
if ((port >= 0xF0) && (config.ym2413_enabled))
|
||||
{
|
||||
return YM2413Read(port & 3);
|
||||
}
|
||||
|
||||
return z80_unused_port_r(port);
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "state.h"
|
||||
#include "sound.h"
|
||||
#include "sn76489.h"
|
||||
#include "ym2413.h"
|
||||
#include "ym2612.h"
|
||||
#include "loadrom.h"
|
||||
#include "sms_cart.h"
|
||||
|
@ -30,6 +30,11 @@ static unsigned int psg_cycles_count;
|
||||
static unsigned int fm_cycles_ratio;
|
||||
static unsigned int fm_cycles_count;
|
||||
|
||||
/* YM chip function pointers */
|
||||
static void (*YM_Reset)(void);
|
||||
static void (*YM_Update)(long int *buffer, int length);
|
||||
static void (*YM_Write)(unsigned int a, unsigned int v);
|
||||
|
||||
/* Run FM chip for required M-cycles */
|
||||
static inline void fm_update(unsigned int cycles)
|
||||
{
|
||||
@ -66,7 +71,7 @@ static inline void fm_update(unsigned int cycles)
|
||||
}
|
||||
|
||||
/* run FM chip & get samples */
|
||||
YM2612Update(buffer, cnt);
|
||||
YM_Update(buffer, cnt);
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,14 +137,38 @@ void sound_init(void)
|
||||
/* Initialize core emulation (input clock based on input frequency for 100% accuracy) */
|
||||
/* By default, both chips are running at the output frequency. */
|
||||
SN76489_Init(mclk/15.0,snd.sample_rate);
|
||||
YM2612Init(mclk/7.0,snd.sample_rate);
|
||||
|
||||
/* In HQ mode, YM2612 is running at its original rate (one sample each 144*7 M-cycles) */
|
||||
/* FM stream is resampled to the output frequency at the end of a frame. */
|
||||
if (config.hq_fm)
|
||||
if (system_hw != SYSTEM_PBC)
|
||||
{
|
||||
fm_cycles_ratio = 144 * 7 * (1 << 11);
|
||||
Fir_Resampler_time_ratio(mclk / (double)snd.sample_rate / (144.0 * 7.0), config.rolloff);
|
||||
/* YM2612 */
|
||||
YM2612Init(mclk/7.0,snd.sample_rate);
|
||||
YM_Reset = YM2612ResetChip;
|
||||
YM_Update = YM2612Update;
|
||||
YM_Write = YM2612Write;
|
||||
|
||||
/* In HQ mode, YM2612 is running at its original rate (one sample each 144*7 M-cycles) */
|
||||
/* FM stream is resampled to the output frequency at the end of a frame. */
|
||||
if (config.hq_fm)
|
||||
{
|
||||
fm_cycles_ratio = 144 * 7 * (1 << 11);
|
||||
Fir_Resampler_time_ratio(mclk / (double)snd.sample_rate / (144.0 * 7.0), config.rolloff);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* YM2413 */
|
||||
YM2413Init(mclk/15.0,snd.sample_rate);
|
||||
YM_Reset = YM2413ResetChip;
|
||||
YM_Update = YM2413Update;
|
||||
YM_Write = YM2413Write;
|
||||
|
||||
/* In HQ mode, YM2413 is running at its original rate (one sample each 72*15 M-cycles) */
|
||||
/* FM stream is resampled to the output frequency at the end of a frame. */
|
||||
if (config.hq_fm)
|
||||
{
|
||||
fm_cycles_ratio = 72 * 15 * (1 << 11);
|
||||
Fir_Resampler_time_ratio(mclk / (double)snd.sample_rate / (72.0 * 15.0), config.rolloff);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LOGSOUND
|
||||
@ -151,7 +180,7 @@ void sound_init(void)
|
||||
/* Reset sound chips emulation */
|
||||
void sound_reset(void)
|
||||
{
|
||||
YM2612ResetChip();
|
||||
YM_Reset();
|
||||
SN76489_Reset();
|
||||
fm_cycles_count = 0;
|
||||
psg_cycles_count = 0;
|
||||
@ -209,7 +238,7 @@ int sound_update(unsigned int cycles)
|
||||
/* FM chip is late for one (or two) samples */
|
||||
do
|
||||
{
|
||||
YM2612Update(Fir_Resampler_buffer(), 1);
|
||||
YM_Update(Fir_Resampler_buffer(), 1);
|
||||
Fir_Resampler_write(2);
|
||||
avail = Fir_Resampler_avail();
|
||||
}
|
||||
@ -250,17 +279,17 @@ int sound_update(unsigned int cycles)
|
||||
void fm_reset(unsigned int cycles)
|
||||
{
|
||||
fm_update(cycles << 11);
|
||||
YM2612ResetChip();
|
||||
YM_Reset();
|
||||
}
|
||||
|
||||
/* Write FM chip */
|
||||
void fm_write(unsigned int cycles, unsigned int address, unsigned int data)
|
||||
{
|
||||
if (address & 1) fm_update(cycles << 11);
|
||||
YM2612Write(address, data);
|
||||
YM_Write(address, data);
|
||||
}
|
||||
|
||||
/* Read FM status */
|
||||
/* Read FM status (YM2612 only) */
|
||||
unsigned int fm_read(unsigned int cycles, unsigned int address)
|
||||
{
|
||||
fm_update(cycles << 11);
|
||||
|
1735
source/sound/ym2413.c
Normal file
1735
source/sound/ym2413.c
Normal file
File diff suppressed because it is too large
Load Diff
22
source/sound/ym2413.h
Normal file
22
source/sound/ym2413.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
**
|
||||
** File: ym2413.c - software implementation of YM2413
|
||||
** FM sound generator type OPLL
|
||||
**
|
||||
** Copyright (C) 2002 Jarek Burczynski
|
||||
**
|
||||
** Version 1.0
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef _H_YM2413_
|
||||
#define _H_YM2413_
|
||||
|
||||
extern void YM2413Init(double clock, int rate);
|
||||
extern void YM2413ResetChip(void);
|
||||
extern void YM2413Update(long int *buffer, int length);
|
||||
extern void YM2413Write(unsigned int a, unsigned int v);
|
||||
extern unsigned int YM2413Read(unsigned int a);
|
||||
|
||||
|
||||
#endif /*_H_YM2413_*/
|
@ -133,6 +133,11 @@
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
/* compiler dependence */
|
||||
#ifndef INLINE
|
||||
#define INLINE static __inline__
|
||||
#endif
|
||||
|
||||
/* globals */
|
||||
#define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */
|
||||
#define EG_SH 16 /* 16.16 fixed point (envelope generator timing) */
|
||||
@ -1933,18 +1938,17 @@ static void init_tables(void)
|
||||
|
||||
|
||||
/* initialize ym2612 emulator(s) */
|
||||
int YM2612Init(double clock, int rate)
|
||||
void YM2612Init(double clock, int rate)
|
||||
{
|
||||
memset(&ym2612,0,sizeof(YM2612));
|
||||
init_tables();
|
||||
ym2612.OPN.ST.clock = clock;
|
||||
ym2612.OPN.ST.rate = rate;
|
||||
OPNSetPres(6*24); /* YM2612 prescaler is fixed to 1/6, one sample (6 mixed channels) is output for each 24 FM clocks */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* reset OPN registers */
|
||||
int YM2612ResetChip(void)
|
||||
void YM2612ResetChip(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -1982,9 +1986,6 @@ int YM2612ResetChip(void)
|
||||
OPNWriteReg(i ,0);
|
||||
OPNWriteReg(i|0x100,0);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ym2612 write */
|
||||
@ -2116,18 +2117,18 @@ void YM2612Update(long int *buffer, int length)
|
||||
advance_eg_channel(&ym2612.CH[5].SLOT[SLOT1]);
|
||||
}
|
||||
|
||||
/* 14-bit channel output */
|
||||
if (out_fm[0] > 8191) out_fm[0] = 8192;
|
||||
/* 14-bit DAC inputs (range is -8192;+8192) */
|
||||
if (out_fm[0] > 8192) out_fm[0] = 8192;
|
||||
else if (out_fm[0] < -8192) out_fm[0] = -8192;
|
||||
if (out_fm[1] > 8191) out_fm[1] = 8192;
|
||||
if (out_fm[1] > 8192) out_fm[1] = 8192;
|
||||
else if (out_fm[1] < -8192) out_fm[1] = -8192;
|
||||
if (out_fm[2] > 8191) out_fm[2] = 8192;
|
||||
if (out_fm[2] > 8192) out_fm[2] = 8192;
|
||||
else if (out_fm[2] < -8192) out_fm[2] = -8192;
|
||||
if (out_fm[3] > 8191) out_fm[3] = 8192;
|
||||
if (out_fm[3] > 8192) out_fm[3] = 8192;
|
||||
else if (out_fm[3] < -8192) out_fm[3] = -8192;
|
||||
if (out_fm[4] > 8191) out_fm[4] = 8192;
|
||||
if (out_fm[4] > 8192) out_fm[4] = 8192;
|
||||
else if (out_fm[4] < -8192) out_fm[4] = -8192;
|
||||
if (out_fm[5] > 8191) out_fm[5] = 8192;
|
||||
if (out_fm[5] > 8192) out_fm[5] = 8192;
|
||||
else if (out_fm[5] < -8192) out_fm[5] = -8192;
|
||||
|
||||
/* 6-channels mixing */
|
||||
|
@ -16,13 +16,8 @@
|
||||
#ifndef _H_YM2612_
|
||||
#define _H_YM2612_
|
||||
|
||||
/* compiler dependence */
|
||||
#ifndef INLINE
|
||||
#define INLINE static __inline__
|
||||
#endif
|
||||
|
||||
extern int YM2612Init(double clock, int rate);
|
||||
extern int YM2612ResetChip(void);
|
||||
extern void YM2612Init(double clock, int rate);
|
||||
extern void YM2612ResetChip(void);
|
||||
extern void YM2612Update(long int *buffer, int length);
|
||||
extern void YM2612Write(unsigned int a, unsigned int v);
|
||||
extern unsigned int YM2612Read(void);
|
||||
|
Loading…
Reference in New Issue
Block a user