From e42ad156b52280f73c5ebeaa5e98639b686f9534 Mon Sep 17 00:00:00 2001 From: Nigel Barnes Date: Sat, 21 Mar 2020 02:17:36 +0000 Subject: bus/coco: Added CoCo PSG cartridge device. [Roberto Fernandez, Nigel Barnes, Ed Snider] --- scripts/src/bus.lua | 2 + src/devices/bus/coco/coco_psg.cpp | 270 ++++++++++++++++++++++++++++++++++++++ src/devices/bus/coco/coco_psg.h | 58 ++++++++ src/devices/machine/intelfsh.cpp | 19 ++- src/devices/machine/intelfsh.h | 8 ++ src/mame/drivers/coco12.cpp | 2 + src/mame/drivers/dragon.cpp | 2 + 7 files changed, 357 insertions(+), 4 deletions(-) create mode 100644 src/devices/bus/coco/coco_psg.cpp create mode 100644 src/devices/bus/coco/coco_psg.h diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 7178b11b8fa..d98492a07de 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -3276,6 +3276,8 @@ if (BUSES["COCO"]~=null) then MAME_DIR .. "src/devices/bus/coco/coco_dwsock.h", MAME_DIR .. "src/devices/bus/coco/coco_t4426.cpp", MAME_DIR .. "src/devices/bus/coco/coco_t4426.h", + MAME_DIR .. "src/devices/bus/coco/coco_psg.cpp", + MAME_DIR .. "src/devices/bus/coco/coco_psg.h", MAME_DIR .. "src/devices/bus/coco/dragon_amtor.cpp", MAME_DIR .. "src/devices/bus/coco/dragon_amtor.h", MAME_DIR .. "src/devices/bus/coco/dragon_fdc.cpp", diff --git a/src/devices/bus/coco/coco_psg.cpp b/src/devices/bus/coco/coco_psg.cpp new file mode 100644 index 00000000000..4ca8c412d35 --- /dev/null +++ b/src/devices/bus/coco/coco_psg.cpp @@ -0,0 +1,270 @@ +// license:BSD-3-Clause +// copyright-holders:Roberto Fernandez,Nigel Barnes +// thanks-to:Ed Snider +/*************************************************************************** + + coco_psg.cpp + + Code for emulating the CoCo PSG. A banked switched ROM and RAM cartridge + with a YM2149 programmable sound generator and two digital Atari-compatible + joystick ports. + + Cartridge by Ed Snider. + + CoCo PSG site: + https://thezippsterzone.com/2018/05/08/coco-psg/ + + CoCo PSG manual: + https://thezippsterzone.com/wp-content/uploads/2018/05/coco-psg-users-manual.pdf + +***************************************************************************/ + +#include "emu.h" +#include "coco_psg.h" +#include "speaker.h" + + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +DEFINE_DEVICE_TYPE_PRIVATE(COCO_PSG, device_cococart_interface, coco_psg_device, "coco_psg", "CoCo PSG") + + +//------------------------------------------------- +// ROM( cocopsg ) +//------------------------------------------------- + +ROM_START(cocopsg) + ROM_REGION(0x80000, "flash", 0) + ROM_LOAD("psg_firmware_v1.bin", 0x0000, 0x80000, CRC(5de614f8) SHA1(9c7c8a5cc419ca1aca4d1c5e9f1195997c2bc95c)) +ROM_END + +//------------------------------------------------- +// rom_region - device-specific ROM region +//------------------------------------------------- + +const tiny_rom_entry *coco_psg_device::device_rom_region() const +{ + return ROM_NAME(cocopsg); +} + +//------------------------------------------------- +// INPUT_PORTS( cocopsg ) +//------------------------------------------------- + +static INPUT_PORTS_START(cocopsg) + PORT_START("GAMEPORT_A") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY PORT_PLAYER(1) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_PLAYER(1) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_PLAYER(1) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_PLAYER(1) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(1) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_PLAYER(1) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("GAMEPORT_B") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY PORT_PLAYER(2) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_PLAYER(2) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_PLAYER(2) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_PLAYER(2) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(2) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_PLAYER(2) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) +INPUT_PORTS_END + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +ioport_constructor coco_psg_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(cocopsg); +} + +//------------------------------------------------- +// device_add_mconfig - add device configuration +//------------------------------------------------- + +void coco_psg_device::device_add_mconfig(machine_config &config) +{ + SPEAKER(config, "speaker").front_center(); + YM2149(config, m_psg, 1_MHz_XTAL); + m_psg->port_a_read_callback().set_ioport("GAMEPORT_A"); + m_psg->port_b_read_callback().set_ioport("GAMEPORT_B"); + m_psg->add_route(ALL_OUTPUTS, "speaker", 1.0); + + SST_39SF040(config, "flash"); +} + + +//------------------------------------------------- +// coco_psg_device - constructor +//------------------------------------------------- + +coco_psg_device::coco_psg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, COCO_PSG, tag, owner, clock) + , device_cococart_interface(mconfig, *this) + , m_psg(*this, "psg") + , m_flash(*this, "flash") +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void coco_psg_device::device_start() +{ + m_sram = std::make_unique(0x80000); + + /* registers are set to a default of zero */ + m_bank[0] = 0x00; + m_bank[1] = 0x00; + m_control = 0x00; + + set_line_value(line::CART, line_value::Q); + + /* register for save states */ + save_item(NAME(m_bank)); + save_item(NAME(m_control)); + save_pointer(NAME(m_sram), 0x80000); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void coco_psg_device::device_reset() +{ + install_write_handler(0xb555, 0xb555, write8sm_delegate(*this, FUNC(coco_psg_device::flash5555_w))); + install_write_handler(0xbaaa, 0xbaaa, write8sm_delegate(*this, FUNC(coco_psg_device::flash2aaa_w))); +} + +void coco_psg_device::flash2aaa_w(offs_t offset, uint8_t data) +{ + if (BIT(m_control, 5) && BIT(m_control, 3)) + { + m_flash->write(0x2aaa, data); + } +} + +void coco_psg_device::flash5555_w(offs_t offset, uint8_t data) +{ + if (BIT(m_control, 5) && BIT(m_control, 3)) + { + m_flash->write(0x5555, data); + } +} + +//------------------------------------------------- +// scs_read +//------------------------------------------------- + +READ8_MEMBER(coco_psg_device::scs_read) +{ + uint8_t data = 0x00; + + switch (offset) + { + case 0x1a: + case 0x1b: + /* memory bank register */ + data = m_bank[BIT(offset, 0)]; + break; + + case 0x1f: + /* ym data port */ + data = m_psg->data_r(); + break; + } + + return data; +} + +//------------------------------------------------- +// scs_write +//------------------------------------------------- + +WRITE8_MEMBER(coco_psg_device::scs_write) +{ + switch (offset) + { + case 0x1a: + case 0x1b: + /* memory bank register */ + m_bank[BIT(offset, 0)] = data; + break; + + case 0x1d: + /* control register + BIT FUNCTION + 0 YM2149 MASTER CLOCK; 0=2MHz, 1=1MHz + 1 Gameport A SEL signal (pin 7 of controller port A) + 2 Gameport B SEL signal (pin 7 of controller port B) + 3 Write Enable (for FLASH/SRAM); 0=disabled, 1=enabled + 4 Autostart enable; 0=enabled, 1=disabled + 5 FLASH programming enable; 0=disabled, 1=enabled + 6 not used + 7 not used + */ + m_control = data; + + /* bit 0 - YM2149 MASTER CLOCK; 0=2MHz, 1=1MHz */ + if (BIT(data, 0)) + m_psg->set_pin26_low_w(); + else + m_psg->set_pin26_high_w(); + + /* bit 4 - Autostart enable; 0=enabled, 1=disabled */ + set_line_value(line::CART, BIT(data, 4) ? line_value::CLEAR : line_value::Q); + break; + + case 0x1e: + /* ym register select port*/ + m_psg->address_w(data & 0x0f); + break; + case 0x1f: + /* ym data port */ + m_psg->data_w(data); + break; + } +} + + +//------------------------------------------------- +// cts_read +//------------------------------------------------- + +READ8_MEMBER(coco_psg_device::cts_read) +{ + uint8_t data = 0x00; + + if (m_bank[BIT(offset, 13)] & 0x80) + { + data = m_sram[(offset & 0x1fff) | (m_bank[BIT(offset, 13)] & 0x3f) << 13]; + } + else + { + data = m_flash->read_raw((offset & 0x1fff) | (m_bank[BIT(offset, 13)] & 0x3f) << 13); + } + + return data; +} + +//------------------------------------------------- +// cts_write +//------------------------------------------------- + +WRITE8_MEMBER(coco_psg_device::cts_write) +{ + if (BIT(m_control, 3)) + { + if (m_bank[BIT(offset, 13)] & 0x80) + { + m_sram[(offset & 0x1fff) | (m_bank[BIT(offset, 13)] & 0x3f) << 13] = data; + } + } +} diff --git a/src/devices/bus/coco/coco_psg.h b/src/devices/bus/coco/coco_psg.h new file mode 100644 index 00000000000..fbf65af54c1 --- /dev/null +++ b/src/devices/bus/coco/coco_psg.h @@ -0,0 +1,58 @@ +// license:BSD-3-Clause +// copyright-holders:Roberto Fernandez,Nigel Barnes +#ifndef MAME_BUS_COCO_COCO_PSG_H +#define MAME_BUS_COCO_COCO_PSG_H + +#pragma once + +#include "cococart.h" +#include "machine/intelfsh.h" +#include "sound/ay8910.h" + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> coco_psg_device + +class coco_psg_device : + public device_t, + public device_cococart_interface +{ +public: + // construction/destruction + coco_psg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // optional information overrides + virtual void device_add_mconfig(machine_config &config) override; + virtual const tiny_rom_entry *device_rom_region() const override; + virtual ioport_constructor device_input_ports() const override; + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + virtual DECLARE_READ8_MEMBER(cts_read) override; + virtual DECLARE_WRITE8_MEMBER(cts_write) override; + virtual DECLARE_READ8_MEMBER(scs_read) override; + virtual DECLARE_WRITE8_MEMBER(scs_write) override; + +private: + required_device m_psg; + required_device m_flash; + + void flash2aaa_w(offs_t offset, uint8_t data); + void flash5555_w(offs_t offset, uint8_t data); + + std::unique_ptr m_sram; + uint8_t m_bank[2]; + uint8_t m_control; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(COCO_PSG, device_cococart_interface) + +#endif // MAME_BUS_COCO_COCO_PSG_H diff --git a/src/devices/machine/intelfsh.cpp b/src/devices/machine/intelfsh.cpp index 0ce7ed8dc53..8523eb61e24 100644 --- a/src/devices/machine/intelfsh.cpp +++ b/src/devices/machine/intelfsh.cpp @@ -101,6 +101,7 @@ DEFINE_DEVICE_TYPE(TMS_29F040, tms_29f040_device, "tms_29f DEFINE_DEVICE_TYPE(PANASONIC_MN63F805MNP, panasonic_mn63f805mnp_device, "panasonic_mn63f805mnp", "Panasonic MN63F805MNP Flash") DEFINE_DEVICE_TYPE(SANYO_LE26FV10N1TS, sanyo_le26fv10n1ts_device, "sanyo_le26fv10n1ts", "Sanyo LE26FV10N1TS Flash") DEFINE_DEVICE_TYPE(SST_28SF040, sst_28sf040_device, "sst_28sf040", "SST 28SF040 Flash") +DEFINE_DEVICE_TYPE(SST_39SF040, sst_39sf040_device, "sst_39sf040", "SST 39SF040 Flash") DEFINE_DEVICE_TYPE(SST_39VF020, sst_39vf020_device, "sst_39vf020", "SST 39VF020 Flash") DEFINE_DEVICE_TYPE(SST_49LF020, sst_49lf020_device, "sst_49lf020", "SST 49LF020 Flash") @@ -244,6 +245,13 @@ intelfsh_device::intelfsh_device(const machine_config &mconfig, device_type type m_device_id = 0x14; // m_sector_is_4k = true; 128kb? break; + case FLASH_SST_39SF040: + m_bits = 8; + m_size = 0x80000; + m_maker_id = MFG_SST; + m_device_id = 0xb7; + m_sector_is_4k = true; + break; case FLASH_SST_39VF020: m_bits = 8; m_size = 0x40000; @@ -448,6 +456,9 @@ sanyo_le26fv10n1ts_device::sanyo_le26fv10n1ts_device(const machine_config &mconf sst_28sf040_device::sst_28sf040_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : intelfsh8_device(mconfig, SST_28SF040, tag, owner, clock, FLASH_SST_28SF040) { } +sst_39sf040_device::sst_39sf040_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : intelfsh8_device(mconfig, SST_39SF040, tag, owner, clock, FLASH_SST_39SF040) { } + sst_39vf020_device::sst_39vf020_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : intelfsh8_device(mconfig, SST_39VF020, tag, owner, clock, FLASH_SST_39VF020) { } @@ -728,15 +739,15 @@ void intelfsh_device::write_full(uint32_t address, uint32_t data) logerror("Invalid flash mode byte %x\n", data & 0xff); else { - m_status = 0x80; - m_flash_mode = FM_READSTATUS; + m_status = 0x80; + m_flash_mode = FM_READSTATUS; } break; case 0x20: // block erase if (m_type == FLASH_SST_49LF020) logerror("Unknown flash mode byte %x\n", data & 0xff); else - m_flash_mode = FM_CLEARPART1; + m_flash_mode = FM_CLEARPART1; break; case 0x60: // set master lock m_flash_mode = FM_SETMASTER; @@ -912,7 +923,7 @@ void intelfsh_device::write_full(uint32_t address, uint32_t data) memset(&m_data[0x3C000], 0xff, 0x04000); } else - memset(&m_data[0], 0xff, m_size); + memset(&m_data[0], 0xff, m_size); m_status = 1 << 3; m_flash_mode = FM_ERASEAMD4; diff --git a/src/devices/machine/intelfsh.h b/src/devices/machine/intelfsh.h index dbab11362ae..cc9f3fb90ba 100644 --- a/src/devices/machine/intelfsh.h +++ b/src/devices/machine/intelfsh.h @@ -37,6 +37,7 @@ public: FLASH_PANASONIC_MN63F805MNP, FLASH_SANYO_LE26FV10N1TS, FLASH_SST_28SF040, + FLASH_SST_39SF040, FLASH_SST_39VF020, FLASH_SST_49LF020, FLASH_TMS_29F040, @@ -265,6 +266,12 @@ public: sst_28sf040_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); }; +class sst_39sf040_device : public intelfsh8_device +{ +public: + sst_39sf040_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); +}; + class sst_39vf020_device : public intelfsh8_device { public: @@ -375,6 +382,7 @@ DECLARE_DEVICE_TYPE(TMS_29F040, tms_29f040_device) DECLARE_DEVICE_TYPE(PANASONIC_MN63F805MNP, panasonic_mn63f805mnp_device) DECLARE_DEVICE_TYPE(SANYO_LE26FV10N1TS, sanyo_le26fv10n1ts_device) DECLARE_DEVICE_TYPE(SST_28SF040, sst_28sf040_device) +DECLARE_DEVICE_TYPE(SST_39SF040, sst_39sf040_device) DECLARE_DEVICE_TYPE(SST_39VF020, sst_39vf020_device) DECLARE_DEVICE_TYPE(SST_49LF020, sst_49lf020_device) diff --git a/src/mame/drivers/coco12.cpp b/src/mame/drivers/coco12.cpp index 5d13c85e4e8..c90c63578af 100644 --- a/src/mame/drivers/coco12.cpp +++ b/src/mame/drivers/coco12.cpp @@ -33,6 +33,7 @@ #include "bus/coco/coco_multi.h" #include "bus/coco/coco_orch90.h" #include "bus/coco/coco_pak.h" +#include "bus/coco/coco_psg.h" #include "bus/coco/coco_rs232.h" #include "bus/coco/coco_ssc.h" #include "bus/coco/coco_t4426.h" @@ -366,6 +367,7 @@ void coco_cart(device_slot_interface &device) device.option_add("banked_16k", COCO_PAK_BANKED); device.option_add("pak", COCO_PAK); device.option_add("multi", COCO_MULTIPAK); + device.option_add("ccpsg", COCO_PSG); } //------------------------------------------------- diff --git a/src/mame/drivers/dragon.cpp b/src/mame/drivers/dragon.cpp index 035f9527f2c..7e57356978a 100644 --- a/src/mame/drivers/dragon.cpp +++ b/src/mame/drivers/dragon.cpp @@ -29,6 +29,7 @@ #include "bus/coco/coco_ssc.h" #include "bus/coco/coco_orch90.h" #include "bus/coco/coco_gmc.h" +#include "bus/coco/coco_psg.h" //************************************************************************** @@ -179,6 +180,7 @@ void dragon_cart(device_slot_interface &device) device.option_add("orch90", COCO_ORCH90); device.option_add("gmc", COCO_PAK_GMC); device.option_add("pak", COCO_PAK); + device.option_add("ccpsg", COCO_PSG); device.option_add_internal("amtor", DRAGON_AMTOR); } -- cgit v1.2.3