summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/machine/c1541.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mess/machine/c1541.c')
-rw-r--r--src/mess/machine/c1541.c1030
1 files changed, 1030 insertions, 0 deletions
diff --git a/src/mess/machine/c1541.c b/src/mess/machine/c1541.c
new file mode 100644
index 00000000000..86447186f70
--- /dev/null
+++ b/src/mess/machine/c1541.c
@@ -0,0 +1,1030 @@
+/**********************************************************************
+
+ Commodore 1540/1541/1541C/1541-II Single Disk Drive emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+/*
+
+ TODO:
+
+ - c1540 fails to load the directory intermittently
+
+ - hardware extensions
+ - Dolphin-DOS 2.0
+ - Dolphin-DOS 3.0
+ - Professional-DOS
+ - Prologic-DOS
+
+*/
+
+/*
+
+ 1540/1541/1541A/SX-64 Parts
+
+ Location Part Number Description
+ 2016 2K x 8 bit Static RAM (short board)
+ UA2-UB3 2114 (4) 1K x 4 bit Static RAM (long board)
+ 325572-01 64H105 40 pin Gate Array (short board)
+ 325302-01 2364-130 ROM DOS 2.6 C000-DFFF
+ 325303-01 2364-131 ROM DOS 2.6 (1540) E000-FFFF
+ 901229-01 2364-173 ROM DOS 2.6 rev. 0 E000-FFFF
+ 901229-03 2364-197 ROM DOS 2.6 rev. 1 E000-FFFF
+ 901229-05 8K ROM DOS 2.6 rev. 2 E000-FFFF
+ 6502 CPU
+ 6522 (2) VIA
+ drive Alps DFB111M25A
+ drive Alps FDM2111-B2
+ drive Newtronics D500
+
+ 1541B/1541C Parts
+
+ Location Part Number Description
+ UA3 2016 2K x 8 bit Static RAM
+ UC2 6502 CPU
+ UC1, UC3 6522 (2) CIA
+ UC4 251828-02 64H156 42 pin Gate Array
+ UC5 251829-01 64H157 20 pin Gate Array
+ UD1 * 251853-01 R/W Hybrid
+ UD1 * 251853-02 R/W Hybrid
+ UA2 251968-01 27128 EPROM DOS 2.6 rev. 3 C000-FFFF
+ drive Newtronics D500
+ * Not interchangeable.
+
+ 1541-II Parts
+
+ Location Part Number Description
+ U5 2016-15 2K x 8 bit Static RAM
+ U12 SONY CX20185 R/W Amp.
+ U3 6502A CPU
+ U6, U8 6522 (2) CIA
+ U10 251828-01 64H156 40 pin Gate Array
+ U4 251968-03 16K ROM DOS 2.6 rev. 4 C000-FFFF
+ drive Chinon FZ-501M REV A
+ drive Digital System DS-50F
+ drive Newtronics D500
+ drive Safronic DS-50F
+
+ ...
+
+ PCB Assy # 1540008-01
+ Schematic # 1540001
+ Original "Long" Board
+ Has 4 discreet 2114 RAMs
+ ALPS Drive only
+
+ PCB Assy # 1540048
+ Schematic # 1540049
+ Referred to as the CR board
+ Changed to 2048 x 8 bit RAM pkg.
+ A 40 pin Gate Array is used
+ Alps Drive (-01)
+ Newtronics Drive (-03)
+
+ PCB Assy # 250442-01
+ Schematic # 251748
+ Termed the 1541 A
+ Just one jumper change to accommodate both types of drive
+
+ PCB Assy # 250446-01
+ Schematic # 251748 (See Notes)
+ Termed the 1541 A-2
+ Just one jumper change to accommodate both types of drive
+
+ ...
+
+ VIC1541 1540001-01 Very early version, long board.
+ 1540001-03 As above, only the ROMs are different.
+ 1540008-01
+
+ 1541 1540048-01 Shorter board with a 40 pin gate array, Alps mech.
+ 1540048-03 As above, but Newtronics mech.
+ 1540049 Similar to above
+ 1540050 Similar to above, Alps mechanism.
+
+ SX64 250410-01 Design most similar to 1540048-01, Alps mechanism.
+
+ 1541 251777 Function of bridge rects. reversed, Newtronics mech.
+ 251830 Same as above
+
+ 1541A 250442-01 Alps or Newtronics drive selected by a jumper.
+ 1541A2 250446-01 A 74LS123 replaces the 9602 at UD4.
+ 1541B 250448-01 Same as the 1541C, but in a case like the 1541.
+ 1541C 250448-01 Short board, new 40/42 pin gate array, 20 pin gate
+ array and a R/W hybrid chip replace many components.
+ Uses a Newtronics drive with optical trk 0 sensor.
+ 1541C 251854 As above, single DOS ROM IC, trk 0 sensor, 30 pin
+ IC for R/W ampl & stepper motor control (like 1541).
+
+ 1541-II A complete redesign using the 40 pin gate array
+ from the 1451C and a Sony R/W hybrid, but not the
+ 20 pin gate array, single DOS ROM IC.
+
+ NOTE: These system boards are the 60 Hz versions.
+ The -02 and -04 boards are probably the 50 Hz versions.
+
+ The ROMs appear to be completely interchangeable. For instance, the
+ first version of ROM for the 1541-II contained the same code as the
+ last version of the 1541. I copy the last version of the 1541-II ROM
+ into two 68764 EPROMs and use them in my original 1541 (long board).
+ Not only do they work, but they work better than the originals.
+
+
+ http://www.amiga-stuff.com/hardware/cbmboards.html
+
+*/
+
+#include "c1541.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define M6502_TAG "ucd5"
+#define M6522_0_TAG "uab1"
+#define M6522_1_TAG "ucd4"
+#define C64H156_TAG "64h156"
+
+
+enum
+{
+ LED_POWER = 0,
+ LED_ACT
+};
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type C1540 = &device_creator<c1540_device>;
+const device_type C1541 = &device_creator<c1541_device>;
+const device_type C1541C = &device_creator<c1541c_device>;
+const device_type C1541II = &device_creator<c1541ii_device>;
+const device_type SX1541 = &device_creator<sx1541_device>;
+const device_type FSD2 = &device_creator<fsd2_device>;
+const device_type C1541_DOLPHIN_DOS = &device_creator<c1541_dolphin_dos_device>;
+const device_type C1541_PROFESSIONAL_DOS_V1 = &device_creator<c1541_professional_dos_v1_device>;
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void base_c1541_device::device_config_complete()
+{
+ switch (m_variant)
+ {
+ case TYPE_1540:
+ m_shortname = "c1540";
+ break;
+
+ default:
+ case TYPE_1541:
+ m_shortname = "c1541";
+ break;
+
+ case TYPE_1541C:
+ m_shortname = "c1541c";
+ break;
+
+ case TYPE_1541II:
+ m_shortname = "c1541ii";
+ break;
+
+ case TYPE_SX1541:
+ m_shortname = "sx1541";
+ break;
+
+ case TYPE_FSD2:
+ m_shortname = "fsd2";
+ break;
+
+ case TYPE_1541_DOLPHIN_DOS:
+ m_shortname = "c1541dd";
+ break;
+
+ case TYPE_1541_PROFESSIONAL_DOS_V1:
+ m_shortname = "c1541pd";
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// ROM( c1540 )
+//-------------------------------------------------
+
+ROM_START( c1540 )
+ ROM_REGION( 0x4000, M6502_TAG, 0 )
+ ROM_LOAD( "325302-01.uab4", 0x0000, 0x2000, CRC(29ae9752) SHA1(8e0547430135ba462525c224e76356bd3d430f11) )
+ ROM_LOAD( "325303-01.uab5", 0x2000, 0x2000, CRC(10b39158) SHA1(56dfe79b26f50af4e83fd9604857756d196516b9) )
+ROM_END
+
+
+//-------------------------------------------------
+// ROM( c1541 )
+//-------------------------------------------------
+
+ROM_START( c1541 )
+ ROM_REGION( 0x8000, M6502_TAG, 0 )
+ ROM_LOAD( "325302-01.uab4", 0x0000, 0x2000, CRC(29ae9752) SHA1(8e0547430135ba462525c224e76356bd3d430f11) )
+
+ ROM_DEFAULT_BIOS("r6")
+ ROM_SYSTEM_BIOS( 0, "r1", "Revision 1" )
+ ROMX_LOAD( "901229-01.uab5", 0x2000, 0x2000, CRC(9a48d3f0) SHA1(7a1054c6156b51c25410caec0f609efb079d3a77), ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS( 1, "r2", "Revision 2" )
+ ROMX_LOAD( "901229-02.uab5", 0x2000, 0x2000, CRC(b29bab75) SHA1(91321142e226168b1139c30c83896933f317d000), ROM_BIOS(2) )
+ ROM_SYSTEM_BIOS( 2, "r3", "Revision 3" )
+ ROMX_LOAD( "901229-03.uab5", 0x2000, 0x2000, CRC(9126e74a) SHA1(03d17bd745066f1ead801c5183ac1d3af7809744), ROM_BIOS(3) )
+ ROM_SYSTEM_BIOS( 3, "r4", "Revision 4" )
+ ROMX_LOAD( "901229-04.uab5", 0x2000, 0x2000, NO_DUMP, ROM_BIOS(4) )
+ ROM_SYSTEM_BIOS( 4, "r5", "Revision 5" )
+ ROMX_LOAD( "901229-05 ae.uab5", 0x2000, 0x2000, CRC(361c9f37) SHA1(f5d60777440829e46dc91285e662ba072acd2d8b), ROM_BIOS(5) )
+ ROM_SYSTEM_BIOS( 5, "r6", "Revision 6" )
+ ROMX_LOAD( "901229-06 aa.uab5", 0x2000, 0x2000, CRC(3a235039) SHA1(c7f94f4f51d6de4cdc21ecbb7e57bb209f0530c0), ROM_BIOS(6) )
+ ROM_SYSTEM_BIOS( 6, "jiffydos", "JiffyDOS v6.01" )
+ ROMX_LOAD( "jiffydos 1541.uab5", 0x2000, 0x2000, CRC(bc7e4aeb) SHA1(db6cfaa6d9b78d58746c811de29f3b1f44d99ddf), ROM_BIOS(7) )
+ ROM_SYSTEM_BIOS( 7, "speeddos", "SpeedDOS-Plus+" )
+ ROMX_LOAD( "speed-dosplus.uab5", 0x0000, 0x4000, CRC(f9db1eac) SHA1(95407e59a9c1d26a0e4bcf2c244cfe8942576e2c), ROM_BIOS(8) )
+ ROM_SYSTEM_BIOS( 8, "rolo27", "Rolo DOS v2.7" )
+ ROMX_LOAD( "rolo27.uab5", 0x0000, 0x2000, CRC(171c7962) SHA1(04c892c4b3d7c74750576521fa081f07d8ca8557), ROM_BIOS(9) )
+ ROM_SYSTEM_BIOS( 9, "tt34", "TurboTrans v3.4" )
+ ROMX_LOAD( "ttd34.uab5", 0x0000, 0x8000, CRC(518d34a1) SHA1(4d6ffdce6ab122e9627b0a839861687bcd4e03ec), ROM_BIOS(10) )
+ROM_END
+
+
+//-------------------------------------------------
+// ROM( c1541c )
+//-------------------------------------------------
+
+ROM_START( c1541c )
+ ROM_REGION( 0x4000, M6502_TAG, 0 )
+ ROM_DEFAULT_BIOS("r2")
+ ROM_SYSTEM_BIOS( 0, "r1", "Revision 1" )
+ ROMX_LOAD( "251968-01.ua2", 0x0000, 0x4000, CRC(1b3ca08d) SHA1(8e893932de8cce244117fcea4c46b7c39c6a7765), ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS( 1, "r2", "Revision 2" )
+ ROMX_LOAD( "251968-02.ua2", 0x0000, 0x4000, CRC(2d862d20) SHA1(38a7a489c7bbc8661cf63476bf1eb07b38b1c704), ROM_BIOS(2) )
+ROM_END
+
+
+//-------------------------------------------------
+// ROM( c1541ii )
+//-------------------------------------------------
+
+ROM_START( c1541ii )
+ ROM_REGION( 0x8000, M6502_TAG, 0 )
+ ROM_LOAD( "251968-03.u4", 0x0000, 0x4000, CRC(899fa3c5) SHA1(d3b78c3dbac55f5199f33f3fe0036439811f7fb3) )
+
+ ROM_DEFAULT_BIOS("r1")
+ ROM_SYSTEM_BIOS( 0, "r1", "Revision 1" )
+ ROMX_LOAD( "355640-01.u4", 0x0000, 0x4000, CRC(57224cde) SHA1(ab16f56989b27d89babe5f89c5a8cb3da71a82f0), ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS( 1, "jiffydos", "JiffyDOS v6.01" )
+ ROMX_LOAD( "jiffydos 1541-ii.u4", 0x0000, 0x4000, CRC(dd409902) SHA1(b1a5b826304d3df2a27d7163c6a81a532e040d32), ROM_BIOS(2) )
+ROM_END
+
+
+//-------------------------------------------------
+// ROM( sx1541 )
+//-------------------------------------------------
+
+ROM_START( sx1541 )
+ ROM_REGION( 0x4000, M6502_TAG, 0 )
+ ROM_LOAD( "325302-01.uab4", 0x0000, 0x2000, CRC(29ae9752) SHA1(8e0547430135ba462525c224e76356bd3d430f11) )
+
+ ROM_DEFAULT_BIOS("r5")
+ ROM_SYSTEM_BIOS( 0, "r5", "Revision 5" )
+ ROMX_LOAD( "901229-05 ae.uab5", 0x2000, 0x2000, CRC(361c9f37) SHA1(f5d60777440829e46dc91285e662ba072acd2d8b), ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS( 1, "jiffydos", "JiffyDOS v6.01" )
+ ROMX_LOAD( "jiffydos sx1541", 0x0000, 0x4000, CRC(783575f6) SHA1(36ccb9ff60328c4460b68522443ecdb7f002a234), ROM_BIOS(2) )
+ ROM_SYSTEM_BIOS( 2, "flash", "1541 FLASH!" )
+ ROMX_LOAD( "1541 flash.uab5", 0x2000, 0x2000, CRC(22f7757e) SHA1(86a1e43d3d22b35677064cca400a6bd06767a3dc), ROM_BIOS(3) )
+ROM_END
+
+
+//-------------------------------------------------
+// ROM( fsd2 )
+//-------------------------------------------------
+
+ROM_START( fsd2 )
+ ROM_REGION( 0x4000, M6502_TAG, 0 ) // data lines D3 and D4 are swapped
+ ROM_DEFAULT_BIOS("fsd2")
+ ROM_SYSTEM_BIOS( 0, "ra", "Revision A" )
+ ROMX_LOAD( "fsd2a.u3", 0x0000, 0x4000, CRC(edf18265) SHA1(47a7c4bdcc20ecc5e59d694b151f493229becaea), ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS( 1, "rb", "Revision B" )
+ ROMX_LOAD( "fsd2b.u3", 0x0000, 0x4000, CRC(b39e4600) SHA1(991132fcc6e70e9a428062ae76055a150f2f7ac6), ROM_BIOS(2) )
+ ROM_SYSTEM_BIOS( 2, "jiffydos", "JiffyDOS v5.0" )
+ ROMX_LOAD( "jiffydos v5.0.u3", 0x0000, 0x4000, CRC(46c3302c) SHA1(e3623658cb7af30c9d3bce2ba3b6ad5ee89ac1b8), ROM_BIOS(3) )
+ROM_END
+
+
+//-------------------------------------------------
+// ROM( c1541dd )
+//-------------------------------------------------
+
+ROM_START( c1541dd )
+ ROM_REGION( 0x8000, M6502_TAG, 0 )
+ ROM_LOAD( "dd20.bin", 0x0000, 0x8000, CRC(94c7fe19) SHA1(e4d5b9ad6b719dd988276214aa4536d3525d313c) )
+ROM_END
+
+
+//-------------------------------------------------
+// ROM( c1541pd )
+//-------------------------------------------------
+
+ROM_START( c1541pd )
+ ROM_REGION( 0x6000, M6502_TAG, 0 )
+ ROM_LOAD( "325302-01.uab4", 0x0000, 0x2000, CRC(29ae9752) SHA1(8e0547430135ba462525c224e76356bd3d430f11) )
+ ROM_LOAD( "professionaldos-v1-floppy-expansion-eprom-27128.bin", 0x2000, 0x4000, CRC(c9abf072) SHA1(2b26adc1f4192b6ca1514754f73c929087b24426) )
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *base_c1541_device::device_rom_region() const
+{
+ switch (m_variant)
+ {
+ case TYPE_1540:
+ return ROM_NAME( c1540 );
+
+ default:
+ case TYPE_1541:
+ return ROM_NAME( c1541 );
+
+ case TYPE_1541C:
+ return ROM_NAME( c1541c );
+
+ case TYPE_1541II:
+ return ROM_NAME( c1541ii );
+
+ case TYPE_SX1541:
+ return ROM_NAME( sx1541 );
+
+ case TYPE_FSD2: // aka Excelerator PLUS / Oceanic OC-118N
+ return ROM_NAME( fsd2 );
+
+ case TYPE_1541_DOLPHIN_DOS:
+ return ROM_NAME( c1541dd );
+
+ case TYPE_1541_PROFESSIONAL_DOS_V1:
+ return ROM_NAME( c1541pd );
+ }
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( c1541_mem )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( c1541_mem, AS_PROGRAM, 8, base_c1541_device )
+ AM_RANGE(0x0000, 0x07ff) AM_MIRROR(0x6000) AM_RAM
+ AM_RANGE(0x1800, 0x180f) AM_MIRROR(0x63f0) AM_DEVREADWRITE(M6522_0_TAG, via6522_device, read, write)
+ AM_RANGE(0x1c00, 0x1c0f) AM_MIRROR(0x63f0) AM_DEVREADWRITE(M6522_1_TAG, via6522_device, read, write)
+ AM_RANGE(0x8000, 0xbfff) AM_MIRROR(0x4000) AM_ROM AM_REGION(M6502_TAG, 0)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( c1541dd_mem )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( c1541dd_mem, AS_PROGRAM, 8, base_c1541_device )
+ AM_RANGE(0x0000, 0x07ff) AM_MIRROR(0x6000) AM_RAM
+ AM_RANGE(0x1800, 0x180f) AM_MIRROR(0x63f0) AM_DEVREADWRITE(M6522_0_TAG, via6522_device, read, write)
+ AM_RANGE(0x1c00, 0x1c0f) AM_MIRROR(0x63f0) AM_DEVREADWRITE(M6522_1_TAG, via6522_device, read, write)
+ AM_RANGE(0x8000, 0x9fff) AM_RAM
+ AM_RANGE(0xa000, 0xffff) AM_ROM AM_REGION(M6502_TAG, 0x2000)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( c1541pd_mem )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( c1541pd_mem, AS_PROGRAM, 8, base_c1541_device )
+ AM_RANGE(0x0000, 0x07ff) AM_MIRROR(0x6000) AM_RAM
+ AM_RANGE(0x1800, 0x180f) AM_MIRROR(0x63f0) AM_DEVREADWRITE(M6522_0_TAG, via6522_device, read, write)
+ AM_RANGE(0x1c00, 0x1c0f) AM_MIRROR(0x63f0) AM_DEVREADWRITE(M6522_1_TAG, via6522_device, read, write)
+ AM_RANGE(0x8000, 0x9fff) AM_ROM AM_REGION(M6502_TAG, 0x4000)
+ AM_RANGE(0xa000, 0xbfff) AM_RAM
+ AM_RANGE(0xc000, 0xffff) AM_ROM AM_REGION(M6502_TAG, 0x0000)
+ AM_RANGE(0xe000, 0xffff) AM_ROM AM_REGION(M6502_TAG, 0x2000)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// via6522_interface via0_intf
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( base_c1541_device::via0_irq_w )
+{
+ m_via0_irq = state;
+
+ m_maincpu->set_input_line(INPUT_LINE_IRQ0, (m_via0_irq || m_via1_irq) ? ASSERT_LINE : CLEAR_LINE);
+}
+
+READ8_MEMBER( base_c1541_device::via0_pa_r )
+{
+ // dummy read to acknowledge ATN IN interrupt
+ return m_parallel_data;
+}
+
+WRITE8_MEMBER( base_c1541_device::via0_pa_w )
+{
+ if (m_other != NULL)
+ {
+ m_other->parallel_data_w(data);
+ }
+}
+
+READ8_MEMBER( base_c1541_device::via0_pb_r )
+{
+ /*
+
+ bit description
+
+ PB0 DATA IN
+ PB1
+ PB2 CLK IN
+ PB3
+ PB4
+ PB5 J1
+ PB6 J2
+ PB7 ATN IN
+
+ */
+
+ UINT8 data = 0;
+
+ // data in
+ data = !m_bus->data_r() && !m_ga->atn_r();
+
+ // clock in
+ data |= !m_bus->clk_r() << 2;
+
+ // serial bus address
+ data |= (m_address - 8) << 5;
+
+ // attention in
+ data |= !m_bus->atn_r() << 7;
+
+ return data;
+}
+
+WRITE8_MEMBER( base_c1541_device::via0_pb_w )
+{
+ /*
+
+ bit description
+
+ PB0
+ PB1 DATA OUT
+ PB2
+ PB3 CLK OUT
+ PB4 ATNA
+ PB5
+ PB6
+ PB7
+
+ */
+
+ // data out
+ m_data_out = BIT(data, 1);
+
+ // attention acknowledge
+ m_ga->atna_w(BIT(data, 4));
+
+ // clock out
+ m_bus->clk_w(this, !BIT(data, 3));
+}
+
+READ_LINE_MEMBER( base_c1541_device::atn_in_r )
+{
+ return !m_bus->atn_r();
+}
+
+WRITE_LINE_MEMBER( base_c1541_device::via0_ca2_w )
+{
+ if (m_other != NULL)
+ {
+ m_other->parallel_strobe_w(state);
+ }
+}
+
+static const via6522_interface c1541_via0_intf =
+{
+ DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, base_c1541_device, via0_pa_r),
+ DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, base_c1541_device, via0_pb_r),
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, base_c1541_device, atn_in_r),
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+
+ DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, base_c1541_device, via0_pa_w),
+ DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, base_c1541_device, via0_pb_w),
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, base_c1541_device, via0_ca2_w),
+ DEVCB_NULL,
+
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, base_c1541_device, via0_irq_w)
+};
+
+
+//-------------------------------------------------
+// via6522_interface c1541c_via0_intf
+//-------------------------------------------------
+
+READ8_MEMBER( c1541c_device::via0_pa_r )
+{
+ /*
+
+ bit description
+
+ PA0 TR00 SENCE
+ PA1
+ PA2
+ PA3
+ PA4
+ PA5
+ PA6
+ PA7
+
+ */
+
+ return !floppy_tk00_r(m_image);
+}
+
+static const via6522_interface c1541c_via0_intf =
+{
+ DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, c1541c_device, via0_pa_r),
+ DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, base_c1541_device, via0_pb_r),
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, base_c1541_device, atn_in_r),
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+
+ DEVCB_NULL,
+ DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, base_c1541_device, via0_pb_w),
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, base_c1541_device, via0_irq_w)
+};
+
+
+//-------------------------------------------------
+// via6522_interface via1_intf
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( base_c1541_device::via1_irq_w )
+{
+ m_via1_irq = state;
+
+ m_maincpu->set_input_line(INPUT_LINE_IRQ0, (m_via0_irq || m_via1_irq) ? ASSERT_LINE : CLEAR_LINE);
+}
+
+READ8_MEMBER( base_c1541_device::via1_pb_r )
+{
+ /*
+
+ bit signal description
+
+ PB0
+ PB1
+ PB2
+ PB3
+ PB4 WPS write protect sense
+ PB5
+ PB6
+ PB7 SYNC SYNC detect line
+
+ */
+
+ UINT8 data = 0;
+
+ // write protect sense
+ data |= !floppy_wpt_r(m_image) << 4;
+
+ // SYNC detect line
+ data |= m_ga->sync_r() << 7;
+
+ return data;
+}
+
+WRITE8_MEMBER( base_c1541_device::via1_pb_w )
+{
+ /*
+
+ bit signal description
+
+ PB0 STP0 stepping motor bit 0
+ PB1 STP1 stepping motor bit 1
+ PB2 MTR motor ON/OFF
+ PB3 ACT drive 0 LED
+ PB4
+ PB5 DS0 density select 0
+ PB6 DS1 density select 1
+ PB7 SYNC SYNC detect line
+
+ */
+
+ // spindle motor
+ m_ga->mtr_w(BIT(data, 2));
+
+ // stepper motor
+ m_ga->stp_w(data & 0x03);
+
+ // activity LED
+ output_set_led_value(LED_ACT, BIT(data, 3));
+
+ // density select
+ m_ga->ds_w((data >> 5) & 0x03);
+}
+
+static const via6522_interface c1541_via1_intf =
+{
+ DEVCB_DEVICE_MEMBER(C64H156_TAG, c64h156_device, yb_r),
+ DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, base_c1541_device, via1_pb_r),
+ DEVCB_DEVICE_LINE_MEMBER(C64H156_TAG, c64h156_device, byte_r),
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+
+ DEVCB_DEVICE_MEMBER(C64H156_TAG, c64h156_device, yb_w),
+ DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, base_c1541_device, via1_pb_w),
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_DEVICE_LINE_MEMBER(C64H156_TAG, c64h156_device, soe_w),
+ DEVCB_DEVICE_LINE_MEMBER(C64H156_TAG, c64h156_device, oe_w),
+
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, base_c1541_device, via1_irq_w)
+};
+
+
+//-------------------------------------------------
+// C64H156_INTERFACE( ga_intf )
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( base_c1541_device::atn_w )
+{
+ set_iec_data();
+}
+
+WRITE_LINE_MEMBER( base_c1541_device::byte_w )
+{
+ m_maincpu->set_input_line(M6502_SET_OVERFLOW, state);
+
+ m_via1->write_ca1(state);
+}
+
+static C64H156_INTERFACE( ga_intf )
+{
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, base_c1541_device, atn_w),
+ DEVCB_NULL,
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, base_c1541_device, byte_w)
+};
+
+
+//-------------------------------------------------
+// LEGACY_FLOPPY_OPTIONS( c1541 )
+//-------------------------------------------------
+
+LEGACY_FLOPPY_OPTIONS_START( c1541 )
+ LEGACY_FLOPPY_OPTION( c1541, "g64", "Commodore 1541 GCR Disk Image", g64_dsk_identify, g64_dsk_construct, NULL, NULL )
+ LEGACY_FLOPPY_OPTION( c1541, "d64", "Commodore 1541 Disk Image", d64_dsk_identify, d64_dsk_construct, NULL, NULL )
+LEGACY_FLOPPY_OPTIONS_END
+
+
+//-------------------------------------------------
+// floppy_interface c1541_floppy_interface
+//-------------------------------------------------
+
+const floppy_interface c1541_floppy_interface =
+{
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ FLOPPY_STANDARD_5_25_SSDD,
+ LEGACY_FLOPPY_OPTIONS_NAME(c1541),
+ "floppy_5_25",
+ NULL
+};
+
+
+//-------------------------------------------------
+// MACHINE_DRIVER( c1541 )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_FRAGMENT( c1541 )
+ MCFG_CPU_ADD(M6502_TAG, M6502, XTAL_16MHz/16)
+ MCFG_CPU_PROGRAM_MAP(c1541_mem)
+ MCFG_QUANTUM_PERFECT_CPU(M6502_TAG)
+
+ MCFG_VIA6522_ADD(M6522_0_TAG, XTAL_16MHz/16, c1541_via0_intf)
+ MCFG_VIA6522_ADD(M6522_1_TAG, XTAL_16MHz/16, c1541_via1_intf)
+
+ MCFG_LEGACY_FLOPPY_DRIVE_ADD(FLOPPY_0, c1541_floppy_interface)
+ MCFG_64H156_ADD(C64H156_TAG, XTAL_16MHz, ga_intf)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// MACHINE_DRIVER( c1541c )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_FRAGMENT( c1541c )
+ MCFG_CPU_ADD(M6502_TAG, M6502, XTAL_16MHz/16)
+ MCFG_CPU_PROGRAM_MAP(c1541_mem)
+ MCFG_QUANTUM_PERFECT_CPU(M6502_TAG)
+
+ MCFG_VIA6522_ADD(M6522_0_TAG, XTAL_16MHz/16, c1541c_via0_intf)
+ MCFG_VIA6522_ADD(M6522_1_TAG, XTAL_16MHz/16, c1541_via1_intf)
+
+ MCFG_LEGACY_FLOPPY_DRIVE_ADD(FLOPPY_0, c1541_floppy_interface)
+ MCFG_64H156_ADD(C64H156_TAG, XTAL_16MHz, ga_intf)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// MACHINE_DRIVER( c1541dd )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_FRAGMENT( c1541dd )
+ MCFG_CPU_ADD(M6502_TAG, M6502, XTAL_16MHz/16)
+ MCFG_CPU_PROGRAM_MAP(c1541dd_mem)
+ MCFG_QUANTUM_PERFECT_CPU(M6502_TAG)
+
+ MCFG_VIA6522_ADD(M6522_0_TAG, XTAL_16MHz/16, c1541_via0_intf)
+ MCFG_VIA6522_ADD(M6522_1_TAG, XTAL_16MHz/16, c1541_via1_intf)
+
+ MCFG_LEGACY_FLOPPY_DRIVE_ADD(FLOPPY_0, c1541_floppy_interface)
+ MCFG_64H156_ADD(C64H156_TAG, XTAL_16MHz, ga_intf)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// MACHINE_DRIVER( c1541pd )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_FRAGMENT( c1541pd )
+ MCFG_CPU_ADD(M6502_TAG, M6502, XTAL_16MHz/16)
+ MCFG_CPU_PROGRAM_MAP(c1541pd_mem)
+ MCFG_QUANTUM_PERFECT_CPU(M6502_TAG)
+
+ MCFG_VIA6522_ADD(M6522_0_TAG, XTAL_16MHz/16, c1541_via0_intf)
+ MCFG_VIA6522_ADD(M6522_1_TAG, XTAL_16MHz/16, c1541_via1_intf)
+
+ MCFG_LEGACY_FLOPPY_DRIVE_ADD(FLOPPY_0, c1541_floppy_interface)
+ MCFG_64H156_ADD(C64H156_TAG, XTAL_16MHz, ga_intf)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor base_c1541_device::device_mconfig_additions() const
+{
+ switch (m_variant)
+ {
+ default:
+ return MACHINE_CONFIG_NAME( c1541 );
+
+ case TYPE_1541C:
+ return MACHINE_CONFIG_NAME( c1541c );
+
+ case TYPE_1541_DOLPHIN_DOS:
+ return MACHINE_CONFIG_NAME( c1541dd );
+
+ case TYPE_1541_PROFESSIONAL_DOS_V1:
+ return MACHINE_CONFIG_NAME( c1541pd );
+ }
+}
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// set_iec_data -
+//-------------------------------------------------
+
+inline void base_c1541_device::set_iec_data()
+{
+ int data = !m_data_out && !m_ga->atn_r();
+
+ m_bus->data_w(this, data);
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// base_c1541_device - constructor
+//-------------------------------------------------
+
+base_c1541_device::base_c1541_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT32 variant)
+ : device_t(mconfig, type, name, tag, owner, clock),
+ device_cbm_iec_interface(mconfig, *this),
+ device_c64_floppy_parallel_interface(mconfig, *this),
+ m_maincpu(*this, M6502_TAG),
+ m_via0(*this, M6522_0_TAG),
+ m_via1(*this, M6522_1_TAG),
+ m_ga(*this, C64H156_TAG),
+ m_image(*this, FLOPPY_0),
+ m_data_out(1),
+ m_via0_irq(CLEAR_LINE),
+ m_via1_irq(CLEAR_LINE),
+ m_variant(variant)
+{
+}
+
+
+//-------------------------------------------------
+// c1540_device - constructor
+//-------------------------------------------------
+
+c1540_device::c1540_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ :base_c1541_device(mconfig, C1540, "C1540", tag, owner, clock, TYPE_1540) { }
+
+
+//-------------------------------------------------
+// c1541_device - constructor
+//-------------------------------------------------
+
+c1541_device::c1541_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ :base_c1541_device(mconfig, C1541, "C1541", tag, owner, clock, TYPE_1541) { }
+
+
+//-------------------------------------------------
+// c1541c_device - constructor
+//-------------------------------------------------
+
+c1541c_device::c1541c_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ :base_c1541_device(mconfig, C1541C, "C1541C", tag, owner, clock, TYPE_1541C) { }
+
+
+//-------------------------------------------------
+// c1541ii_device - constructor
+//-------------------------------------------------
+
+c1541ii_device::c1541ii_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ :base_c1541_device(mconfig, C1541II, "C1541-II", tag, owner, clock, TYPE_1541II) { }
+
+
+//-------------------------------------------------
+// sx1541_device - constructor
+//-------------------------------------------------
+
+sx1541_device::sx1541_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ :base_c1541_device(mconfig, SX1541, "SX1541", tag, owner, clock, TYPE_SX1541) { }
+
+
+//-------------------------------------------------
+// fsd2_device - constructor
+//-------------------------------------------------
+
+fsd2_device::fsd2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ :base_c1541_device(mconfig, FSD2, "FSD-2", tag, owner, clock, TYPE_FSD2) { }
+
+
+//-------------------------------------------------
+// c1541_dolphin_dos_device - constructor
+//-------------------------------------------------
+
+c1541_dolphin_dos_device::c1541_dolphin_dos_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ :base_c1541_device(mconfig, C1541_DOLPHIN_DOS, "C1541 Dolphin-DOS 2.0", tag, owner, clock, TYPE_1541_DOLPHIN_DOS) { }
+
+
+//-------------------------------------------------
+// c1541_professional_dos_v1_device - constructor
+//-------------------------------------------------
+
+c1541_professional_dos_v1_device::c1541_professional_dos_v1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ :base_c1541_device(mconfig, C1541_PROFESSIONAL_DOS_V1, "C1541 Professional-DOS v1", tag, owner, clock, TYPE_1541_PROFESSIONAL_DOS_V1) { }
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void base_c1541_device::device_start()
+{
+ // install image callbacks
+ floppy_install_unload_proc(m_image, base_c1541_device::on_disk_change);
+ floppy_install_load_proc(m_image, base_c1541_device::on_disk_change);
+
+ // register for state saving
+ save_item(NAME(m_data_out));
+ save_item(NAME(m_via0_irq));
+ save_item(NAME(m_via1_irq));
+}
+
+void fsd2_device::device_start()
+{
+ base_c1541_device::device_start();
+
+ // decrypt ROM
+ UINT8 *rom = memregion(M6502_TAG)->base();
+
+ for (offs_t offset = 0; offset < 0x4000; offset++)
+ {
+ UINT8 data = BITSWAP8(rom[offset], 7, 6, 5, 3, 4, 2, 1, 0);
+
+ rom[offset] = data;
+ }
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void base_c1541_device::device_reset()
+{
+ m_maincpu->reset();
+
+ m_via0->reset();
+ m_via1->reset();
+}
+
+
+//-------------------------------------------------
+// iec_atn_w -
+//-------------------------------------------------
+
+void base_c1541_device::cbm_iec_atn(int state)
+{
+ m_via0->write_ca1(!state);
+ m_ga->atni_w(!state);
+
+ set_iec_data();
+}
+
+
+//-------------------------------------------------
+// iec_reset_w -
+//-------------------------------------------------
+
+void base_c1541_device::cbm_iec_reset(int state)
+{
+ if (!state)
+ {
+ device_reset();
+ }
+}
+
+
+//-------------------------------------------------
+// parallel_data_w -
+//-------------------------------------------------
+
+void base_c1541_device::parallel_data_w(UINT8 data)
+{
+ m_parallel_data = data;
+}
+
+
+//-------------------------------------------------
+// parallel_strobe_w -
+//-------------------------------------------------
+
+void base_c1541_device::parallel_strobe_w(int state)
+{
+ m_via0->write_cb1(state);
+}
+
+
+//-------------------------------------------------
+// on_disk_change -
+//-------------------------------------------------
+
+void base_c1541_device::on_disk_change(device_image_interface &image)
+{
+ base_c1541_device *c1541 = static_cast<base_c1541_device *>(image.device().owner());
+
+ int wp = floppy_wpt_r(image);
+ c1541->m_ga->on_disk_changed(wp);
+}