bus/cbus: drop PC9801 prefix for AMD-98 sound card

* make it output mono
* improve AY3 flip-flop mechanism
* add logmacro
This commit is contained in:
angelosa 2024-10-22 21:24:11 +02:00
parent 652dbc852e
commit 6a28bbbd53
7 changed files with 878 additions and 784 deletions

File diff suppressed because it is too large Load Diff

View File

@ -5250,6 +5250,8 @@ end
if (BUSES["CBUS"]~=null) then
files {
MAME_DIR .. "src/devices/bus/cbus/amd98.cpp",
MAME_DIR .. "src/devices/bus/cbus/amd98.h",
MAME_DIR .. "src/devices/bus/cbus/pc9801_26.cpp",
MAME_DIR .. "src/devices/bus/cbus/pc9801_26.h",
MAME_DIR .. "src/devices/bus/cbus/pc9801_55.cpp",
@ -5258,8 +5260,6 @@ if (BUSES["CBUS"]~=null) then
MAME_DIR .. "src/devices/bus/cbus/pc9801_86.h",
MAME_DIR .. "src/devices/bus/cbus/pc9801_118.cpp",
MAME_DIR .. "src/devices/bus/cbus/pc9801_118.h",
MAME_DIR .. "src/devices/bus/cbus/pc9801_amd98.cpp",
MAME_DIR .. "src/devices/bus/cbus/pc9801_amd98.h",
MAME_DIR .. "src/devices/bus/cbus/pc9801_snd.cpp",
MAME_DIR .. "src/devices/bus/cbus/pc9801_snd.h",
MAME_DIR .. "src/devices/bus/cbus/mpu_pc98.cpp",

View File

@ -2,16 +2,16 @@
// copyright-holders:Angelo Salese
/**************************************************************************************************
System Sacom AMD-98 (AmuseMent boarD)
System Sacom AMD-98 (AmuseMent boarD)
3 PSG chips, one of the first sound boards released for PC98
Superseded by later NEC in-house sound boards
3 PSG chips, one of the first sound boards released for PC98
Superseded by later NEC in-house sound boards
TODO:
- not sure if it's AY8910 or YM2203, from a PCB pic it looks with stock AY logos?
- Third AY (uses port B from BOTH AYs);
- PIT control;
- PCM section;
TODO:
- not sure if it's AY8910 or YM2203, from a PCB pic it looks with stock AY logos?
- f/f not completely understood;
- PIT control;
- PCM section;
===================================================================================================
@ -28,38 +28,49 @@
**************************************************************************************************/
#include "emu.h"
#include "bus/cbus/pc9801_amd98.h"
#include "bus/cbus/amd98.h"
#include "speaker.h"
#define LOG_LATCH (1U << 1) // Detailed AY3 latch setups
#define VERBOSE (LOG_GENERAL)
//#define LOG_OUTPUT_FUNC osd_printf_info
#include "logmacro.h"
#define LOGLATCH(...) LOGMASKED(LOG_LATCH, __VA_ARGS__)
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
// device type definition
DEFINE_DEVICE_TYPE(PC9801_AMD98, pc9801_amd98_device, "pc9801_amd98", "System Sacom AMD-98")
DEFINE_DEVICE_TYPE(AMD98, amd98_device, "amd98", "System Sacom AMD-98")
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void pc9801_amd98_device::device_add_mconfig(machine_config &config)
void amd98_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
// Assume mono, as per highway making engine noise from ay1 only
SPEAKER(config, "speaker").front_center();
AY8910(config, m_ay1, 1'996'800);
m_ay1->port_a_read_callback().set_ioport("OPN_PA1");
m_ay1->port_b_write_callback().set(FUNC(pc9801_amd98_device::ay3_address_w));
m_ay1->add_route(ALL_OUTPUTS, "lspeaker", 0.50);
m_ay1->port_b_write_callback().set(FUNC(amd98_device::ay3_address_w));
m_ay1->add_route(ALL_OUTPUTS, "speaker", 0.50);
AY8910(config, m_ay2, 1'996'800);
m_ay2->port_a_read_callback().set_ioport("OPN_PA2");
m_ay2->port_b_write_callback().set(FUNC(pc9801_amd98_device::ay3_data_latch_w));
m_ay2->add_route(ALL_OUTPUTS, "rspeaker", 0.50);
m_ay2->port_b_write_callback().set(FUNC(amd98_device::ay3_data_latch_w));
m_ay2->add_route(ALL_OUTPUTS, "speaker", 0.50);
AY8910(config, m_ay3, 1'996'800);
m_ay3->add_route(ALL_OUTPUTS, "lspeaker", 0.25);
m_ay3->add_route(ALL_OUTPUTS, "rspeaker", 0.25);
m_ay3->port_b_write_callback().set([this] (u8 data) {
LOG("AMD-98 DAC %02x\n", data);
});
m_ay3->add_route(ALL_OUTPUTS, "speaker", 0.25);
}
static INPUT_PORTS_START( pc9801_amd98 )
@ -84,7 +95,7 @@ static INPUT_PORTS_START( pc9801_amd98 )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
INPUT_PORTS_END
ioport_constructor pc9801_amd98_device::device_input_ports() const
ioport_constructor amd98_device::device_input_ports() const
{
return INPUT_PORTS_NAME( pc9801_amd98 );
}
@ -97,11 +108,11 @@ ioport_constructor pc9801_amd98_device::device_input_ports() const
//**************************************************************************
//-------------------------------------------------
// pc9801_amd98_device - constructor
// amd98_device - constructor
//-------------------------------------------------
pc9801_amd98_device::pc9801_amd98_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, PC9801_AMD98, tag, owner, clock)
amd98_device::amd98_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, AMD98, tag, owner, clock)
, m_bus(*this, DEVICE_SELF_OWNER)
, m_ay1(*this, "ay1")
, m_ay2(*this, "ay2")
@ -115,7 +126,7 @@ pc9801_amd98_device::pc9801_amd98_device(const machine_config &mconfig, const ch
// on this device
//-------------------------------------------------
void pc9801_amd98_device::device_validity_check(validity_checker &valid) const
void amd98_device::device_validity_check(validity_checker &valid) const
{
}
@ -123,7 +134,7 @@ void pc9801_amd98_device::device_validity_check(validity_checker &valid) const
// device_start - device-specific startup
//-------------------------------------------------
void pc9801_amd98_device::device_start()
void amd98_device::device_start()
{
}
@ -132,11 +143,11 @@ void pc9801_amd98_device::device_start()
// device_reset - device-specific reset
//-------------------------------------------------
void pc9801_amd98_device::device_reset()
void amd98_device::device_reset()
{
m_bus->install_io(0x00d8, 0x00df, read8sm_delegate(*this, FUNC(pc9801_amd98_device::read)), write8sm_delegate(*this, FUNC(pc9801_amd98_device::write)));
// Thexder access with following
m_bus->install_io(0x38d8, 0x38df, read8sm_delegate(*this, FUNC(pc9801_amd98_device::read)), write8sm_delegate(*this, FUNC(pc9801_amd98_device::write)));
m_bus->install_io(0x00d8, 0x00df, read8sm_delegate(*this, FUNC(amd98_device::read)), write8sm_delegate(*this, FUNC(amd98_device::write)));
// thexder access with following
m_bus->install_io(0x38d8, 0x38df, read8sm_delegate(*this, FUNC(amd98_device::read)), write8sm_delegate(*this, FUNC(amd98_device::write)));
}
@ -144,7 +155,7 @@ void pc9801_amd98_device::device_reset()
// READ/WRITE HANDLERS
//**************************************************************************
uint8_t pc9801_amd98_device::read(offs_t offset)
uint8_t amd98_device::read(offs_t offset)
{
switch(offset)
{
@ -154,12 +165,12 @@ uint8_t pc9801_amd98_device::read(offs_t offset)
return m_ay2->data_r();
}
logerror("%02x\n",offset);
LOG("AMD-98: unhandled %02x read\n", offset + 0xd8);
return 0xff;
}
void pc9801_amd98_device::write(offs_t offset, uint8_t data)
void amd98_device::write(offs_t offset, uint8_t data)
{
switch(offset)
{
@ -176,27 +187,34 @@ void pc9801_amd98_device::write(offs_t offset, uint8_t data)
m_ay2->data_w(data);
break;
default:
logerror("%02x %02x\n",offset,data);
LOG("AMD-98: unhandled %02x write %02x\n", offset + 0xd8, data);
}
}
void pc9801_amd98_device::ay3_address_w(uint8_t data)
void amd98_device::ay3_address_w(uint8_t data)
{
LOGLATCH("AMD-98 AY3 latch %02x\n", data);
m_ay3_latch = data;
}
void pc9801_amd98_device::ay3_data_latch_w(uint8_t data)
void amd98_device::ay3_data_latch_w(uint8_t data)
{
// TODO: this actually uses a flip flop mechanism, not quite sure about how it works yet
switch(data)
// TODO: actually goes 0 -> 1 -> 0
// TODO: thexder is the odd one: uses 0x00 -> 0x40 -> 0x47 (address) -> 0x40 -> 0x40 -> 0x43 (data) -> 0x40
if (!BIT(m_ay3_ff, 0) && BIT(data, 0))
{
case 0x47:
//logerror("%02x addr\n",m_ay3_latch);
m_ay3->address_w(m_ay3_latch);
break;
case 0x43:
//logerror("%02x data\n",m_ay3_latch);
m_ay3->data_w(m_ay3_latch);
break;
switch(data & 0xc2)
{
case 0x42:
LOG("AMD-98 AY3 write %02x address (f/f %02x)\n", m_ay3_latch, m_ay3_ff);
m_ay3->address_w(m_ay3_latch);
break;
case 0x40:
LOG("AMD-98 AY3 write %02x data (f/f %02x)\n", m_ay3_latch, m_ay3_ff);
m_ay3->data_w(m_ay3_latch);
break;
}
}
LOGLATCH("AMD-98 f/f %02x %02x\n", data, m_ay3_latch);
m_ay3_ff = data;
}

View File

@ -6,8 +6,8 @@
***************************************************************************/
#ifndef MAME_BUS_CBUS_PC9801_AMD98_H
#define MAME_BUS_CBUS_PC9801_AMD98_H
#ifndef MAME_BUS_CBUS_AMD98_H
#define MAME_BUS_CBUS_AMD98_H
#pragma once
@ -18,13 +18,13 @@
// TYPE DEFINITIONS
//**************************************************************************
// ======================> pc9801_amd98_device
// ======================> amd98_device
class pc9801_amd98_device : public device_t
class amd98_device : public device_t
{
public:
// construction/destruction
pc9801_amd98_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
amd98_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
static constexpr feature_type imperfect_features() { return feature::SOUND; }
@ -44,7 +44,7 @@ private:
void ay3_address_w(uint8_t data);
void ay3_data_latch_w(uint8_t data);
uint8_t m_ay3_latch;
uint8_t m_ay3_latch, m_ay3_ff;
required_device<pc9801_slot_device> m_bus;
required_device<ay8910_device> m_ay1;
@ -54,6 +54,6 @@ private:
};
// device type definition
DECLARE_DEVICE_TYPE(PC9801_AMD98, pc9801_amd98_device)
DECLARE_DEVICE_TYPE(AMD98, amd98_device)
#endif // MAME_BUS_CBUS_PC9801_AMD98_H
#endif // MAME_BUS_CBUS_AMD98_H

View File

@ -432,7 +432,7 @@ TIMER_CALLBACK_MEMBER(pc9801_86_device::dac_tick)
//
//**************************************************************************
DEFINE_DEVICE_TYPE(PC9801_SPEAKBOARD, pc9801_speakboard_device, "pc9801_spb", "NEC PC9801 SpeakBoard")
DEFINE_DEVICE_TYPE(PC9801_SPEAKBOARD, pc9801_speakboard_device, "pc9801_spb", "NEC PC-9801 SpeakBoard")
ROM_START( pc9801_spb )
ROM_REGION( 0x4000, "sound_bios", ROMREGION_ERASEFF )

View File

@ -605,7 +605,8 @@ uint8_t pc9801_state::f0_r(offs_t offset)
{
// iterate thru all devices to check if an AMD98 is present
// TODO: move to cbus
for (pc9801_amd98_device &amd98 : device_type_enumerator<pc9801_amd98_device>(machine().root_device()))
// TODO: is this really part of PC-98 spec or it's coming from the device itself, as dip/jumper?
for (amd98_device &amd98 : device_type_enumerator<amd98_device>(machine().root_device()))
{
logerror("%s: Read AMD98 ID %s\n", machine().describe_context(), amd98.tag());
return 0x18; // return the right ID
@ -1877,15 +1878,15 @@ static void pc9801_cbus_devices(device_slot_interface &device)
{
// official HW
// PC-9801-14
device.option_add("pc9801_26", PC9801_26);
device.option_add("pc9801_26", PC9801_26);
device.option_add("pc9801_55u", PC9801_55U);
device.option_add("pc9801_55l", PC9801_55L);
device.option_add("pc9801_86", PC9801_86);
device.option_add("pc9801_86", PC9801_86);
device.option_add("pc9801_118", PC9801_118);
device.option_add("pc9801_spb", PC9801_SPEAKBOARD);
// Spark Board
device.option_add("pc9801_amd98", PC9801_AMD98); // AmuseMent boarD
device.option_add("mpu_pc98", MPU_PC98);
device.option_add("amd98", AMD98);
device.option_add("mpu_pc98", MPU_PC98);
// doujinshi HW
// MAD Factory / Doujin Hard (同人ハード)

View File

@ -44,11 +44,11 @@
#include "video/upd7220.h"
#include "bus/cbus/amd98.h"
#include "bus/cbus/pc9801_26.h"
#include "bus/cbus/pc9801_55.h"
#include "bus/cbus/pc9801_86.h"
#include "bus/cbus/pc9801_118.h"
#include "bus/cbus/pc9801_amd98.h"
#include "bus/cbus/mpu_pc98.h"
#include "bus/cbus/pc9801_cbus.h"
#include "pc9801_kbd.h"