summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/trs/dgnalpha.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/trs/dgnalpha.cpp')
-rw-r--r--src/mame/trs/dgnalpha.cpp388
1 files changed, 388 insertions, 0 deletions
diff --git a/src/mame/trs/dgnalpha.cpp b/src/mame/trs/dgnalpha.cpp
new file mode 100644
index 00000000000..e0a7ddeb2d2
--- /dev/null
+++ b/src/mame/trs/dgnalpha.cpp
@@ -0,0 +1,388 @@
+// license:BSD-3-Clause
+// copyright-holders:Nathan Woods
+/***************************************************************************
+
+ Dragon Alpha
+
+ The Dragon Alpha was a prototype in development when Dragon Data went bust,
+ it is basically an enhanced Dragon 64, with built in modem, disk system, and
+ graphical boot rom.
+
+ It has the following extra hardware :-
+ A third 6821 PIA mapped between FF24 and FF27
+ An AY-8912, connected to the PIA.
+
+ Port A of the PIA is connected as follows :-
+
+ b0 BDIR of AY8912
+ b1 BC1 of AY8912
+ b2 Rom select, High= boot rom, low=BASIC rom
+ b3..7 not used.
+
+ Port B
+ b0..7 connected to D0..7 of the AY8912.
+
+ CB1 DRQ of WD2797.
+
+ /irqa
+ /irqb both connected to 6809 FIRQ.
+
+
+ The analog outputs of the AY-8912 are connected to the standard sound multiplexer.
+ The AY8912 output port is used as follows :-
+
+ b0..b3 /DS0../DS3 for the drive interface (through an inverter first).
+ b4 /motor for the drive interface (through an inverter first).
+ b5..b7 not used as far as I can tell.
+
+ A 6850 for the modem.
+
+ A WD2797, used as an internal disk interface, this is however connected in a slightly strange
+ way that I am yet to completely determine.
+ 19/10/2004, WD2797 is mapped between FF2C and FF2F, however the order of the registers is
+ reversed so the command Register is at the highest address instead of the lowest. The Data
+ request pin is connected to CB1(pin 18) of PIA2, to cause an firq, the INTRQ, is connected via
+ an inverter to the 6809's NMI.
+
+ All these are as yet un-emulated.
+
+ 29-Oct-2004, AY-8912 is now emulated.
+ 30-Oct-2004, Internal disk interface now emulated, Normal DragonDos rom replaced with a re-assembled
+ version, that talks to the alpha hardware (verified on a clone of the real machine).
+
+Dragon Alpha code added 21-Oct-2004,
+ Phill Harvey-Smith (afra@aurigae.demon.co.uk)
+
+ Added AY-8912 and FDC code 30-Oct-2004.
+
+Fixed Dragon Alpha NMI enable/disable, following circuit traces on a real machine.
+ P.Harvey-Smith, 11-Aug-2005.
+
+Re-implemented Alpha NMI enable/disable, using direct PIA reads, rather than
+keeping track of it in a variable in the driver.
+ P.Harvey-Smith, 25-Sep-2006.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "dragon.h"
+
+#include "imagedev/floppy.h"
+#include "machine/wd_fdc.h"
+#include "sound/ay8910.h"
+
+#include "softlist_dev.h"
+
+#include "formats/dmk_dsk.h"
+#include "formats/sdf_dsk.h"
+#include "formats/vdk_dsk.h"
+
+
+namespace {
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+/* devices */
+#define WD2797_TAG "wd2797"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class dragon_alpha_state : public dragon64_state
+{
+public:
+ dragon_alpha_state(const machine_config &mconfig, device_type type, const char *tag) :
+ dragon64_state(mconfig, type, tag),
+ m_pia_2(*this, "pia2"),
+ m_ay8912(*this, "ay8912"),
+ m_fdc(*this, WD2797_TAG),
+ m_floppy(*this, WD2797_TAG ":%u", 0U),
+ m_nmis(*this, "nmis")
+ {
+ }
+
+ void dgnalpha(machine_config &config);
+
+private:
+ static void dragon_formats(format_registration &fr);
+
+ /* pia2 */
+ void pia2_pa_w(uint8_t data);
+
+ /* psg */
+ uint8_t psg_porta_read();
+ void psg_porta_write(uint8_t data);
+
+ /* fdc */
+ void fdc_intrq_w(int state);
+ void fdc_drq_w(int state);
+
+ void dgnalpha_io1(address_map &map) ATTR_COLD;
+
+ required_device<pia6821_device> m_pia_2;
+ required_device<ay8912_device> m_ay8912;
+ required_device<wd2797_device> m_fdc;
+ required_device_array<floppy_connector, 4> m_floppy;
+ required_device<input_merger_device> m_nmis;
+
+ /* modem */
+ uint8_t modem_r(offs_t offset);
+ void modem_w(offs_t offset, uint8_t data);
+};
+
+
+
+//**************************************************************************
+// ADDRESS MAPS
+//**************************************************************************
+
+void dragon_alpha_state::dgnalpha_io1(address_map &map)
+{
+ // $FF20-$FF3F
+ map(0x00, 0x03).mirror(0x10).r(m_pia_1, FUNC(pia6821_device::read)).w(FUNC(coco12_state::ff20_write));
+ map(0x04, 0x07).mirror(0x10).rw(m_pia_2, FUNC(pia6821_device::read), FUNC(pia6821_device::write));
+ map(0x08, 0x0b).mirror(0x10).rw(FUNC(dragon_alpha_state::modem_r), FUNC(dragon_alpha_state::modem_w));
+ map(0x0c, 0x0c).mirror(0x10).rw(m_fdc, FUNC(wd2797_device::data_r), FUNC(wd2797_device::data_w));
+ map(0x0d, 0x0d).mirror(0x10).rw(m_fdc, FUNC(wd2797_device::sector_r), FUNC(wd2797_device::sector_w));
+ map(0x0e, 0x0e).mirror(0x10).rw(m_fdc, FUNC(wd2797_device::track_r), FUNC(wd2797_device::track_w));
+ map(0x0f, 0x0f).mirror(0x10).rw(m_fdc, FUNC(wd2797_device::status_r), FUNC(wd2797_device::cmd_w));
+}
+
+
+/***************************************************************************
+ MODEM
+***************************************************************************/
+
+//-------------------------------------------------
+// modem_r
+//-------------------------------------------------
+
+uint8_t dragon_alpha_state::modem_r(offs_t offset)
+{
+ return 0xFF;
+}
+
+
+
+//-------------------------------------------------
+// modem_w
+//-------------------------------------------------
+
+void dragon_alpha_state::modem_w(offs_t offset, uint8_t data)
+{
+}
+
+
+
+/***************************************************************************
+ PIA2 ($FF24-$FF28) on Dragon Alpha/Professional
+
+ PIA2 PA0 bcdir to AY-8912
+ PIA2 PA1 bc0 to AY-8912
+ PIA2 PA2 Rom switch, 0=basic rom, 1=boot rom.
+ PIA2 PA3-PA7 Unknown/unused ?
+ PIA2 PB0-PB7 connected to D0..7 of the AY8912.
+ CB1 DRQ from WD2797 disk controller.
+***************************************************************************/
+
+//-------------------------------------------------
+// pia2_pa_w
+//-------------------------------------------------
+
+void dragon_alpha_state::pia2_pa_w(uint8_t data)
+{
+ uint8_t ddr = ~m_pia_2->port_b_z_mask();
+
+ /* If bit 2 of the pia2 ddra is 1 then this pin is an output so use it */
+ /* to control the paging of the boot and basic roms */
+ /* Otherwise it set as an input, with an internal pull-up so it should */
+ /* always be high (enabling boot rom) */
+ /* PIA FIXME if (pia_get_ddr_a(2) & 0x04) */
+ if(ddr & 0x04)
+ {
+ page_rom(data & 0x04 ? true : false); /* bit 2 controls boot or basic rom */
+ }
+
+ /* Bits 0 and 1 for pia2 port a control the BCDIR and BC1 lines of the */
+ /* AY-8912 */
+ switch (data & 0x03)
+ {
+ case 0x00: /* Inactive, do nothing */
+ break;
+ case 0x01: /* Write to selected port */
+ m_ay8912->data_w(m_pia_2->b_output());
+ break;
+ case 0x02: /* Read from selected port */
+ m_pia_2->portb_w(m_ay8912->data_r());
+ break;
+ case 0x03: /* Select port to write to */
+ m_ay8912->address_w(m_pia_2->b_output());
+ break;
+ }
+}
+
+
+
+/***************************************************************************
+ AY8912
+***************************************************************************/
+
+//-------------------------------------------------
+// psg_porta_read
+//-------------------------------------------------
+
+uint8_t dragon_alpha_state::psg_porta_read()
+{
+ return 0;
+}
+
+
+
+//-------------------------------------------------
+// psg_porta_read
+//-------------------------------------------------
+
+void dragon_alpha_state::psg_porta_write(uint8_t data)
+{
+ /* Bits 0..3 are the drive select lines for the internal floppy interface */
+ /* Bit 4 is the motor on, in the real hardware these are inverted on their way to the drive */
+ /* Bits 5,6,7 are connected to /DDEN, ENP and 5/8 on the WD2797 */
+
+ floppy_image_device *floppy = nullptr;
+
+ for (int n = 0; n < 4; n++)
+ if (BIT(data, n))
+ floppy = m_floppy[n]->get_device();
+
+ m_fdc->set_floppy(floppy);
+
+ // todo: turning the motor on with bit 4 isn't giving the drive enough
+ // time to spin up, how does it work in hardware?
+ for (auto &f : m_floppy)
+ if (f->get_device()) f->get_device()->mon_w(0);
+
+ m_fdc->dden_w(BIT(data, 5));
+}
+
+/***************************************************************************
+ FDC
+***************************************************************************/
+
+//-------------------------------------------------
+// fdc_intrq_w - The NMI line on the Alpha is gated
+// through IC16 (early PLD), and is gated by pia2 CA2
+//-------------------------------------------------
+
+void dragon_alpha_state::fdc_intrq_w(int state)
+{
+ if (state)
+ {
+ if (m_pia_2->ca2_output_z())
+ m_nmis->in_w<1>(1);
+ }
+ else
+ {
+ m_nmis->in_w<1>(0);
+ }
+}
+
+
+
+//-------------------------------------------------
+// fdc_drq_w - The DRQ line goes through pia2 CB1,
+// in exactly the same way as DRQ from DragonDos
+// does for pia1 CB1
+//-------------------------------------------------
+
+void dragon_alpha_state::fdc_drq_w(int state)
+{
+ m_pia_2->cb1_w(state ? ASSERT_LINE : CLEAR_LINE);
+}
+
+
+void dragon_alpha_state::dragon_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_VDK_FORMAT);
+ fr.add(FLOPPY_DMK_FORMAT);
+ fr.add(FLOPPY_SDF_FORMAT);
+}
+
+static void dragon_alpha_floppies(device_slot_interface &device)
+{
+ device.option_add("dd", FLOPPY_35_DD);
+}
+
+
+void dragon_alpha_state::dgnalpha(machine_config &config)
+{
+ dragon_base(config);
+
+ // internal ram
+ RAM(config, RAM_TAG).set_default_size("64K");
+
+ sam().set_addrmap(1, &dragon_alpha_state::d64_rom0);
+ sam().set_addrmap(2, &dragon_alpha_state::d64_rom1);
+ sam().set_addrmap(4, &dragon_alpha_state::d64_io0);
+ sam().set_addrmap(5, &dragon_alpha_state::dgnalpha_io1);
+
+ // input merger
+ INPUT_MERGER_ANY_HIGH(config, m_nmis).output_handler().set_inputline(m_maincpu, INPUT_LINE_NMI);
+
+ // cartridge
+ COCOCART_SLOT(config, m_cococart, DERIVED_CLOCK(1, 1), &dragon_alpha_state::dragon_cart, nullptr);
+ m_cococart->cart_callback().set([this] (int state) { cart_w(state != 0); }); // lambda because name is overloaded
+ m_cococart->nmi_callback().set(m_nmis, FUNC(input_merger_device::in_w<0>));
+ m_cococart->halt_callback().set_inputline(m_maincpu, INPUT_LINE_HALT);
+
+ // acia
+ mos6551_device &acia(MOS6551(config, "acia", 0));
+ acia.set_xtal(1.8432_MHz_XTAL);
+
+ // floppy
+ WD2797(config, m_fdc, 4_MHz_XTAL/4);
+ m_fdc->intrq_wr_callback().set(FUNC(dragon_alpha_state::fdc_intrq_w));
+ m_fdc->drq_wr_callback().set(FUNC(dragon_alpha_state::fdc_drq_w));
+
+ FLOPPY_CONNECTOR(config, WD2797_TAG ":0", dragon_alpha_floppies, "dd", dragon_alpha_state::dragon_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, WD2797_TAG ":1", dragon_alpha_floppies, "dd", dragon_alpha_state::dragon_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, WD2797_TAG ":2", dragon_alpha_floppies, nullptr, dragon_alpha_state::dragon_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, WD2797_TAG ":3", dragon_alpha_floppies, nullptr, dragon_alpha_state::dragon_formats).enable_sound(true);
+
+ // sound hardware
+ AY8912(config, m_ay8912, 4_MHz_XTAL/4);
+ m_ay8912->port_a_read_callback().set(FUNC(dragon_alpha_state::psg_porta_read));
+ m_ay8912->port_a_write_callback().set(FUNC(dragon_alpha_state::psg_porta_write));
+ m_ay8912->add_route(ALL_OUTPUTS, "speaker", 0.75);
+
+ // pia 2
+ PIA6821(config, m_pia_2);
+ m_pia_2->writepa_handler().set(FUNC(dragon_alpha_state::pia2_pa_w));
+ m_pia_2->irqa_handler().set(m_firqs, FUNC(input_merger_device::in_w<2>));
+ m_pia_2->irqb_handler().set(m_firqs, FUNC(input_merger_device::in_w<3>));
+
+ // software lists
+ SOFTWARE_LIST(config, "dgnalpha_flop_list").set_original("dgnalpha_flop");
+ SOFTWARE_LIST(config, "dragon_flex_list").set_original("dragon_flex");
+ SOFTWARE_LIST(config, "dragon_os9_list").set_original("dragon_os9");
+}
+
+ROM_START(dgnalpha)
+ ROM_REGION(0x10000,"maincpu",0)
+ ROM_DEFAULT_BIOS("boot10")
+ ROM_SYSTEM_BIOS(0, "boot10", "Boot v1.0")
+ ROMX_LOAD("alpha_bt_10.rom", 0x2000, 0x2000, CRC(c3dab585) SHA1(4a5851aa66eb426e9bb0bba196f1e02d48156068), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "boot04", "Boot v0.4")
+ ROMX_LOAD("alpha_bt_04.rom", 0x2000, 0x2000, CRC(d6172b56) SHA1(69ea376dbc7418f69e9e809b448d22a4de012344), ROM_BIOS(1))
+ ROM_LOAD("alpha_ba.rom", 0x8000, 0x4000, CRC(84f68bf9) SHA1(1983b4fb398e3dd9668d424c666c5a0b3f1e2b69))
+ROM_END
+
+} // anonymous namespace
+
+
+COMP( 1984, dgnalpha, dragon32, 0, dgnalpha, dragon, dragon_alpha_state, empty_init, "Dragon Data Ltd", "Dragon Professional (Alpha)", 0 )