mirror of
https://github.com/holub/mame
synced 2025-07-04 01:18:59 +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:
|
Notes:
|
||||||
|
|
||||||
This emulation is based on Charles MacDonald's analysis of Enri's schematics
|
The FM Unit add-on was released for the Mark III, so compatible games were
|
||||||
of the FM unit hardware.
|
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
|
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
|
(the game Fushigi no Oshiro Pit Pot is a known example) has control problems
|
||||||
when the FM Sound Unit is attached (real hardware behavior).
|
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"
|
#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 )
|
static MACHINE_CONFIG_FRAGMENT( fm_config )
|
||||||
MCFG_SOUND_ADD("ym2413", YM2413, XTAL_10_738635MHz/3)
|
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)
|
MCFG_SOUND_ROUTE(ALL_OUTPUTS, ":mono", 1.00)
|
||||||
MACHINE_CONFIG_END
|
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_t(mconfig, SEGA_FM_UNIT, "Sega FM Sound Unit", tag, owner, clock, "sega_fm_unit", __FILE__),
|
||||||
device_sg1000_expansion_slot_interface(mconfig, *this),
|
device_sg1000_expansion_slot_interface(mconfig, *this),
|
||||||
m_ym(*this, "ym2413"),
|
m_ym(*this, "ym2413"),
|
||||||
|
m_psg(*this, ":segapsg"),
|
||||||
m_audio_control(0)
|
m_audio_control(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -78,6 +99,8 @@ void sega_fm_unit_device::device_start()
|
|||||||
|
|
||||||
READ8_MEMBER(sega_fm_unit_device::peripheral_r)
|
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)
|
if (offset <= 3)
|
||||||
{
|
{
|
||||||
return m_audio_control & 0x01;
|
return m_audio_control & 0x01;
|
||||||
@ -95,20 +118,28 @@ WRITE8_MEMBER(sega_fm_unit_device::peripheral_w)
|
|||||||
switch (offset)
|
switch (offset)
|
||||||
{
|
{
|
||||||
case 0: // register port
|
case 0: // register port
|
||||||
if (m_audio_control == 0x01)
|
|
||||||
{
|
|
||||||
m_ym->write(space, 0, data & 0x3f);
|
m_ym->write(space, 0, data & 0x3f);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 1: // data port
|
case 1: // data port
|
||||||
if (m_audio_control == 0x01)
|
|
||||||
{
|
|
||||||
m_ym->write(space, 1, data);
|
m_ym->write(space, 1, data);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 2: // control port
|
case 2: // control port
|
||||||
case 3: // mirror
|
case 3: // mirror
|
||||||
m_audio_control = data & 0x01;
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "sound/ym2413.h"
|
#include "sound/ym2413.h"
|
||||||
|
#include "sound/sn76496.h"
|
||||||
#include "sg1000exp.h"
|
#include "sg1000exp.h"
|
||||||
|
|
||||||
|
|
||||||
@ -44,6 +45,7 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
required_device<ym2413_device> m_ym;
|
required_device<ym2413_device> m_ym;
|
||||||
|
optional_device<segapsg_device> m_psg;
|
||||||
UINT8 m_audio_control;
|
UINT8 m_audio_control;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -890,6 +890,8 @@ static MACHINE_CONFIG_DERIVED( smsj, sms1_kr )
|
|||||||
MCFG_CPU_IO_MAP(smsj_io)
|
MCFG_CPU_IO_MAP(smsj_io)
|
||||||
|
|
||||||
MCFG_SOUND_ADD("ym2413", YM2413, XTAL_10_738635MHz/3)
|
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)
|
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
|
||||||
MACHINE_CONFIG_END
|
MACHINE_CONFIG_END
|
||||||
|
|
||||||
|
@ -458,6 +458,22 @@ READ8_MEMBER(sms_state::sms_input_port_dd_r)
|
|||||||
WRITE8_MEMBER(sms_state::smsj_audio_control_w)
|
WRITE8_MEMBER(sms_state::smsj_audio_control_w)
|
||||||
{
|
{
|
||||||
m_smsj_audio_control = data & 0x03;
|
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)
|
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)
|
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);
|
//logerror("data_port_w %x %x\n", offset, data);
|
||||||
m_ym->write(space, 1, data);
|
m_ym->write(space, 1, data);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
WRITE8_MEMBER(sms_state::sms_psg_w)
|
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);
|
m_psg_sms->write(space, offset, data, mem_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user