mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
sms.cpp: fix Out Run sound in FM mode [Enik Land]
This commit is contained in:
parent
980588badf
commit
3d850be071
@ -11,13 +11,31 @@ Release data from the Sega Retro project:
|
||||
|
||||
Notes:
|
||||
|
||||
This emulation is based on Charles MacDonald's analysis of Enri's schematics
|
||||
of the FM unit hardware.
|
||||
The FM Unit add-on was released for the Mark III, so compatible games were
|
||||
released only for that console and the Japanese SMS, that has the FM chip
|
||||
built-in. The games play FM sound only when detect the FM hardware. The normal
|
||||
PSG sound is replaced, except when sampled voices, not supported by the FM
|
||||
chip, are played. Some games released for western SMS versions also contain FM
|
||||
code, that is played on a Mark III / SMSJ when connected through a cartridge
|
||||
adapter.
|
||||
|
||||
The IO address map (read/write ports) is based on Charles MacDonald's analysis
|
||||
of Enri's schematics of the FM unit hardware.
|
||||
|
||||
Any software that access controllers through IO ports $C0/$C1 instead $DC/$DD
|
||||
(the game Fushigi no Oshiro Pit Pot is a known example) has control problems
|
||||
when the FM Sound Unit is attached (real hardware behavior).
|
||||
|
||||
TODO:
|
||||
|
||||
- Confirm the assumption that PSG and FM sound are not mixed by the FM unit
|
||||
and there is only FM sound when the unit is enabled. Two evidences that were
|
||||
observed: every time a game with FM sound plays sampled voices through PSG,
|
||||
the game disables/enables the FM chip before/after playing the PSG sound, and
|
||||
a user reported, on the topic of the SMSPower Forums where the PSG/FM mixing
|
||||
control of the SMSJ was discovered, that the hack that adds FM sound to Sonic
|
||||
SMS version is not playing PSG sound on his Mark III with the FM unit.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "fm_unit.h"
|
||||
@ -33,6 +51,8 @@ const device_type SEGA_FM_UNIT = &device_creator<sega_fm_unit_device>;
|
||||
|
||||
static MACHINE_CONFIG_FRAGMENT( fm_config )
|
||||
MCFG_SOUND_ADD("ym2413", YM2413, XTAL_10_738635MHz/3)
|
||||
// if this output gain is changed, the gain set when unmute the output need
|
||||
// to be changed too, probably along the gain set for SMSJ/SMSKRFM drivers.
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, ":mono", 1.00)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
@ -56,6 +76,7 @@ sega_fm_unit_device::sega_fm_unit_device(const machine_config &mconfig, const ch
|
||||
device_t(mconfig, SEGA_FM_UNIT, "Sega FM Sound Unit", tag, owner, clock, "sega_fm_unit", __FILE__),
|
||||
device_sg1000_expansion_slot_interface(mconfig, *this),
|
||||
m_ym(*this, "ym2413"),
|
||||
m_psg(*this, ":segapsg"),
|
||||
m_audio_control(0)
|
||||
{
|
||||
}
|
||||
@ -78,6 +99,8 @@ void sega_fm_unit_device::device_start()
|
||||
|
||||
READ8_MEMBER(sega_fm_unit_device::peripheral_r)
|
||||
{
|
||||
// the value previously written to the control port is returned on all
|
||||
// active read offsets.
|
||||
if (offset <= 3)
|
||||
{
|
||||
return m_audio_control & 0x01;
|
||||
@ -95,20 +118,28 @@ WRITE8_MEMBER(sega_fm_unit_device::peripheral_w)
|
||||
switch (offset)
|
||||
{
|
||||
case 0: // register port
|
||||
if (m_audio_control == 0x01)
|
||||
{
|
||||
m_ym->write(space, 0, data & 0x3f);
|
||||
}
|
||||
m_ym->write(space, 0, data & 0x3f);
|
||||
break;
|
||||
case 1: // data port
|
||||
if (m_audio_control == 0x01)
|
||||
{
|
||||
m_ym->write(space, 1, data);
|
||||
}
|
||||
m_ym->write(space, 1, data);
|
||||
break;
|
||||
case 2: // control port
|
||||
case 3: // mirror
|
||||
m_audio_control = data & 0x01;
|
||||
if (m_audio_control == 0x01)
|
||||
{
|
||||
m_ym->set_output_gain(0, 1.0);
|
||||
// assume the PSG output is muted when FM is active.
|
||||
// Out Run need this. Needs confirmation (see TODO).
|
||||
if (m_psg.found())
|
||||
m_psg->set_output_gain(0, 0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ym->set_output_gain(0, 0.0);
|
||||
if (m_psg.found())
|
||||
m_psg->set_output_gain(0, 1.0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include "emu.h"
|
||||
#include "sound/ym2413.h"
|
||||
#include "sound/sn76496.h"
|
||||
#include "sg1000exp.h"
|
||||
|
||||
|
||||
@ -44,6 +45,7 @@ protected:
|
||||
|
||||
private:
|
||||
required_device<ym2413_device> m_ym;
|
||||
optional_device<segapsg_device> m_psg;
|
||||
UINT8 m_audio_control;
|
||||
};
|
||||
|
||||
|
@ -890,6 +890,8 @@ static MACHINE_CONFIG_DERIVED( smsj, sms1_kr )
|
||||
MCFG_CPU_IO_MAP(smsj_io)
|
||||
|
||||
MCFG_SOUND_ADD("ym2413", YM2413, XTAL_10_738635MHz/3)
|
||||
// if this output gain is changed, the gain set when unmute the output need
|
||||
// to be changed too, probably along the gain set for the Mark III FM Unit.
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
@ -458,6 +458,22 @@ READ8_MEMBER(sms_state::sms_input_port_dd_r)
|
||||
WRITE8_MEMBER(sms_state::smsj_audio_control_w)
|
||||
{
|
||||
m_smsj_audio_control = data & 0x03;
|
||||
|
||||
/* Mute settings:
|
||||
0,0 : PSG only (power-on default)
|
||||
0,1 : FM only
|
||||
1,0 : Both PSG and FM disabled
|
||||
1,1 : Both PSG and FM enabled
|
||||
*/
|
||||
if (m_smsj_audio_control == 0x00 || m_smsj_audio_control == 0x03)
|
||||
m_psg_sms->set_output_gain(0, 1.0);
|
||||
else
|
||||
m_psg_sms->set_output_gain(0, 0.0);
|
||||
|
||||
if (m_smsj_audio_control == 0x01 || m_smsj_audio_control == 0x03)
|
||||
m_ym->set_output_gain(0, 1.0);
|
||||
else
|
||||
m_ym->set_output_gain(0, 0.0);
|
||||
}
|
||||
|
||||
|
||||
@ -492,29 +508,19 @@ READ8_MEMBER(sms_state::smsj_audio_control_r)
|
||||
|
||||
WRITE8_MEMBER(sms_state::smsj_ym2413_register_port_w)
|
||||
{
|
||||
if (m_smsj_audio_control == 0x01 || m_smsj_audio_control == 0x03)
|
||||
m_ym->write(space, 0, data & 0x3f);
|
||||
m_ym->write(space, 0, data & 0x3f);
|
||||
}
|
||||
|
||||
|
||||
WRITE8_MEMBER(sms_state::smsj_ym2413_data_port_w)
|
||||
{
|
||||
if (m_smsj_audio_control == 0x01 || m_smsj_audio_control == 0x03)
|
||||
{
|
||||
//logerror("data_port_w %x %x\n", offset, data);
|
||||
m_ym->write(space, 1, data);
|
||||
}
|
||||
//logerror("data_port_w %x %x\n", offset, data);
|
||||
m_ym->write(space, 1, data);
|
||||
}
|
||||
|
||||
|
||||
WRITE8_MEMBER(sms_state::sms_psg_w)
|
||||
{
|
||||
if (m_is_smsj)
|
||||
{
|
||||
if (m_smsj_audio_control != 0x00 && m_smsj_audio_control != 0x03)
|
||||
return;
|
||||
}
|
||||
|
||||
m_psg_sms->write(space, offset, data, mem_mask);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user