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 if (BUSES["CBUS"]~=null) then
files { 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.cpp",
MAME_DIR .. "src/devices/bus/cbus/pc9801_26.h", MAME_DIR .. "src/devices/bus/cbus/pc9801_26.h",
MAME_DIR .. "src/devices/bus/cbus/pc9801_55.cpp", 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_86.h",
MAME_DIR .. "src/devices/bus/cbus/pc9801_118.cpp", 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_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.cpp",
MAME_DIR .. "src/devices/bus/cbus/pc9801_snd.h", MAME_DIR .. "src/devices/bus/cbus/pc9801_snd.h",
MAME_DIR .. "src/devices/bus/cbus/mpu_pc98.cpp", MAME_DIR .. "src/devices/bus/cbus/mpu_pc98.cpp",

View File

@ -2,16 +2,16 @@
// copyright-holders:Angelo Salese // 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 3 PSG chips, one of the first sound boards released for PC98
Superseded by later NEC in-house sound boards Superseded by later NEC in-house sound boards
TODO: TODO:
- not sure if it's AY8910 or YM2203, from a PCB pic it looks with stock AY logos? - 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); - f/f not completely understood;
- PIT control; - PIT control;
- PCM section; - PCM section;
=================================================================================================== ===================================================================================================
@ -28,38 +28,49 @@
**************************************************************************************************/ **************************************************************************************************/
#include "emu.h" #include "emu.h"
#include "bus/cbus/pc9801_amd98.h" #include "bus/cbus/amd98.h"
#include "speaker.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 // GLOBAL VARIABLES
//************************************************************************** //**************************************************************************
// device type definition // 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 // 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(); // Assume mono, as per highway making engine noise from ay1 only
SPEAKER(config, "rspeaker").front_right(); SPEAKER(config, "speaker").front_center();
AY8910(config, m_ay1, 1'996'800); AY8910(config, m_ay1, 1'996'800);
m_ay1->port_a_read_callback().set_ioport("OPN_PA1"); 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->port_b_write_callback().set(FUNC(amd98_device::ay3_address_w));
m_ay1->add_route(ALL_OUTPUTS, "lspeaker", 0.50); m_ay1->add_route(ALL_OUTPUTS, "speaker", 0.50);
AY8910(config, m_ay2, 1'996'800); AY8910(config, m_ay2, 1'996'800);
m_ay2->port_a_read_callback().set_ioport("OPN_PA2"); 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->port_b_write_callback().set(FUNC(amd98_device::ay3_data_latch_w));
m_ay2->add_route(ALL_OUTPUTS, "rspeaker", 0.50); m_ay2->add_route(ALL_OUTPUTS, "speaker", 0.50);
AY8910(config, m_ay3, 1'996'800); AY8910(config, m_ay3, 1'996'800);
m_ay3->add_route(ALL_OUTPUTS, "lspeaker", 0.25); m_ay3->port_b_write_callback().set([this] (u8 data) {
m_ay3->add_route(ALL_OUTPUTS, "rspeaker", 0.25); LOG("AMD-98 DAC %02x\n", data);
});
m_ay3->add_route(ALL_OUTPUTS, "speaker", 0.25);
} }
static INPUT_PORTS_START( pc9801_amd98 ) static INPUT_PORTS_START( pc9801_amd98 )
@ -84,7 +95,7 @@ static INPUT_PORTS_START( pc9801_amd98 )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
INPUT_PORTS_END 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 ); 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) amd98_device::amd98_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, PC9801_AMD98, tag, owner, clock) : device_t(mconfig, AMD98, tag, owner, clock)
, m_bus(*this, DEVICE_SELF_OWNER) , m_bus(*this, DEVICE_SELF_OWNER)
, m_ay1(*this, "ay1") , m_ay1(*this, "ay1")
, m_ay2(*this, "ay2") , m_ay2(*this, "ay2")
@ -115,7 +126,7 @@ pc9801_amd98_device::pc9801_amd98_device(const machine_config &mconfig, const ch
// on this device // 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 // 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 // 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))); m_bus->install_io(0x00d8, 0x00df, read8sm_delegate(*this, FUNC(amd98_device::read)), write8sm_delegate(*this, FUNC(amd98_device::write)));
// Thexder access with following // 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(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 // READ/WRITE HANDLERS
//************************************************************************** //**************************************************************************
uint8_t pc9801_amd98_device::read(offs_t offset) uint8_t amd98_device::read(offs_t offset)
{ {
switch(offset) switch(offset)
{ {
@ -154,12 +165,12 @@ uint8_t pc9801_amd98_device::read(offs_t offset)
return m_ay2->data_r(); return m_ay2->data_r();
} }
logerror("%02x\n",offset); LOG("AMD-98: unhandled %02x read\n", offset + 0xd8);
return 0xff; 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) switch(offset)
{ {
@ -176,27 +187,34 @@ void pc9801_amd98_device::write(offs_t offset, uint8_t data)
m_ay2->data_w(data); m_ay2->data_w(data);
break; break;
default: 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; 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 // TODO: actually goes 0 -> 1 -> 0
switch(data) // 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: switch(data & 0xc2)
//logerror("%02x addr\n",m_ay3_latch); {
m_ay3->address_w(m_ay3_latch); case 0x42:
break; LOG("AMD-98 AY3 write %02x address (f/f %02x)\n", m_ay3_latch, m_ay3_ff);
case 0x43: m_ay3->address_w(m_ay3_latch);
//logerror("%02x data\n",m_ay3_latch); break;
m_ay3->data_w(m_ay3_latch); case 0x40:
break; 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 #ifndef MAME_BUS_CBUS_AMD98_H
#define MAME_BUS_CBUS_PC9801_AMD98_H #define MAME_BUS_CBUS_AMD98_H
#pragma once #pragma once
@ -18,13 +18,13 @@
// TYPE DEFINITIONS // TYPE DEFINITIONS
//************************************************************************** //**************************************************************************
// ======================> pc9801_amd98_device // ======================> amd98_device
class pc9801_amd98_device : public device_t class amd98_device : public device_t
{ {
public: public:
// construction/destruction // 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; } static constexpr feature_type imperfect_features() { return feature::SOUND; }
@ -44,7 +44,7 @@ private:
void ay3_address_w(uint8_t data); void ay3_address_w(uint8_t data);
void ay3_data_latch_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<pc9801_slot_device> m_bus;
required_device<ay8910_device> m_ay1; required_device<ay8910_device> m_ay1;
@ -54,6 +54,6 @@ private:
}; };
// device type definition // 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_START( pc9801_spb )
ROM_REGION( 0x4000, "sound_bios", ROMREGION_ERASEFF ) 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 // iterate thru all devices to check if an AMD98 is present
// TODO: move to cbus // 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()); logerror("%s: Read AMD98 ID %s\n", machine().describe_context(), amd98.tag());
return 0x18; // return the right ID return 0x18; // return the right ID
@ -1877,15 +1878,15 @@ static void pc9801_cbus_devices(device_slot_interface &device)
{ {
// official HW // official HW
// PC-9801-14 // 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_55u", PC9801_55U);
device.option_add("pc9801_55l", PC9801_55L); 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_118", PC9801_118);
device.option_add("pc9801_spb", PC9801_SPEAKBOARD); device.option_add("pc9801_spb", PC9801_SPEAKBOARD);
// Spark Board // Spark Board
device.option_add("pc9801_amd98", PC9801_AMD98); // AmuseMent boarD device.option_add("amd98", AMD98);
device.option_add("mpu_pc98", MPU_PC98); device.option_add("mpu_pc98", MPU_PC98);
// doujinshi HW // doujinshi HW
// MAD Factory / Doujin Hard (同人ハード) // MAD Factory / Doujin Hard (同人ハード)

View File

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