summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author ajrhacker <ajrhacker@users.noreply.github.com>2019-07-04 14:46:16 -0400
committer GitHub <noreply@github.com>2019-07-04 14:46:16 -0400
commit5035b85be074696f9db409ae86137b1ab7ff51a8 (patch)
treeef3fced86a11c5ecb8b3f532d825dd211bd5a317
parent59f3d063f07d0f609ccc21b1413c9d98d7d1c6de (diff)
parenta152d1125fde01e80ab3e9cccd475a50c22c6316 (diff)
Merge pull request #5303 from shattered/_430d642ac2
agat: basic emulation of agat9 (video, apple compat mode, LLE floppy)
-rw-r--r--scripts/src/bus.lua2
-rw-r--r--scripts/src/formats.lua36
-rw-r--r--scripts/target/mame/mess.lua4
-rw-r--r--src/devices/bus/a2bus/a2diskii.cpp16
-rw-r--r--src/devices/bus/a2bus/a2diskii.h9
-rw-r--r--src/devices/bus/a2bus/agat840k_hle.cpp33
-rw-r--r--src/devices/bus/a2bus/agat_fdc.cpp488
-rw-r--r--src/devices/bus/a2bus/agat_fdc.h105
-rw-r--r--src/lib/formats/aim_dsk.cpp108
-rw-r--r--src/lib/formats/aim_dsk.h34
-rw-r--r--src/lib/formats/ds9_dsk.cpp156
-rw-r--r--src/lib/formats/ds9_dsk.h38
-rw-r--r--src/lib/formats/dvk_mx_dsk.cpp177
-rw-r--r--src/lib/formats/dvk_mx_dsk.h39
-rw-r--r--src/lib/formats/flopimg.cpp40
-rw-r--r--src/lib/formats/flopimg.h4
-rw-r--r--src/mame/drivers/agat.cpp747
-rw-r--r--src/mame/video/agat7.cpp38
-rw-r--r--src/mame/video/agat9.cpp715
-rw-r--r--src/mame/video/agat9.h96
-rw-r--r--src/tools/floptool.cpp9
21 files changed, 2709 insertions, 185 deletions
diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua
index 780df068e5c..e1bf27c50b9 100644
--- a/scripts/src/bus.lua
+++ b/scripts/src/bus.lua
@@ -2115,6 +2115,8 @@ if (BUSES["A2BUS"]~=null) then
MAME_DIR .. "src/devices/bus/a2bus/agat7ram.h",
MAME_DIR .. "src/devices/bus/a2bus/agat840k_hle.cpp",
MAME_DIR .. "src/devices/bus/a2bus/agat840k_hle.h",
+ MAME_DIR .. "src/devices/bus/a2bus/agat_fdc.cpp",
+ MAME_DIR .. "src/devices/bus/a2bus/agat_fdc.h",
MAME_DIR .. "src/devices/bus/a2bus/ssprite.cpp",
MAME_DIR .. "src/devices/bus/a2bus/ssprite.h",
MAME_DIR .. "src/devices/bus/a2bus/ssbapple.cpp",
diff --git a/scripts/src/formats.lua b/scripts/src/formats.lua
index 5b678c480af..5a5438a1694 100644
--- a/scripts/src/formats.lua
+++ b/scripts/src/formats.lua
@@ -199,6 +199,18 @@ end
--------------------------------------------------
--
+--@src/lib/formats/aim_dsk.h,FORMATS["AIM_DSK"] = true
+--------------------------------------------------
+
+if (FORMATS["AIM_DSK"]~=null or _OPTIONS["with-tools"]) then
+ files {
+ MAME_DIR.. "src/lib/formats/aim_dsk.cpp",
+ MAME_DIR.. "src/lib/formats/aim_dsk.h",
+ }
+end
+
+--------------------------------------------------
+--
--@src/lib/formats/ami_dsk.h,FORMATS["AMI_DSK"] = true
--------------------------------------------------
@@ -691,6 +703,18 @@ end
--------------------------------------------------
--
+--@src/lib/formats/ds9_dsk.h,FORMATS["DS9_DSK"] = true
+--------------------------------------------------
+
+if (FORMATS["DS9_DSK"]~=null or _OPTIONS["with-tools"]) then
+ files {
+ MAME_DIR.. "src/lib/formats/ds9_dsk.cpp",
+ MAME_DIR.. "src/lib/formats/ds9_dsk.h",
+ }
+end
+
+--------------------------------------------------
+--
--@src/lib/formats/sdf_dsk.h,FORMATS["SDF_DSK"] = true
--------------------------------------------------
@@ -727,6 +751,18 @@ end
--------------------------------------------------
--
+--@src/lib/formats/dvk_mx_dsk.h,FORMATS["DVK_MX_DSK"] = true
+--------------------------------------------------
+
+if (FORMATS["DVK_MX_DSK"]~=null or _OPTIONS["with-tools"]) then
+ files {
+ MAME_DIR.. "src/lib/formats/dvk_mx_dsk.cpp",
+ MAME_DIR.. "src/lib/formats/dvk_mx_dsk.h",
+ }
+end
+
+--------------------------------------------------
+--
--@src/lib/formats/esq16_dsk.h,FORMATS["ESQ16_DSK"] = true
--------------------------------------------------
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index 70fb3860743..f9415ed552f 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -884,6 +884,7 @@ FORMATS["ADAM_CAS"] = true
FORMATS["ADAM_DSK"] = true
FORMATS["AFS_DSK"] = true
FORMATS["AGAT840K_HLE_DSK"] = true
+FORMATS["AIM_DSK"] = true
FORMATS["AMI_DSK"] = true
FORMATS["AP2_DSK"] = true
FORMATS["APD_DSK"] = true
@@ -926,6 +927,7 @@ FORMATS["DCP_DSK"] = true
FORMATS["DIM_DSK"] = true
FORMATS["DIP_DSK"] = true
FORMATS["DMK_DSK"] = true
+FORMATS["DS9_DSK"] = true
FORMATS["SDF_DSK"] = true
FORMATS["EP64_DSK"] = true
FORMATS["DMV_DSK"] = true
@@ -1524,6 +1526,8 @@ files {
MAME_DIR .. "src/mame/includes/apple2.h",
MAME_DIR .. "src/mame/video/agat7.cpp",
MAME_DIR .. "src/mame/video/agat7.h",
+ MAME_DIR .. "src/mame/video/agat9.cpp",
+ MAME_DIR .. "src/mame/video/agat9.h",
}
createMESSProjects(_target, _subtarget, "akai")
diff --git a/src/devices/bus/a2bus/a2diskii.cpp b/src/devices/bus/a2bus/a2diskii.cpp
index 20aff173549..c67eb306837 100644
--- a/src/devices/bus/a2bus/a2diskii.cpp
+++ b/src/devices/bus/a2bus/a2diskii.cpp
@@ -26,6 +26,7 @@
DEFINE_DEVICE_TYPE(A2BUS_DISKII, a2bus_diskii_device, "a2diskii", "Apple Disk II controller")
DEFINE_DEVICE_TYPE(A2BUS_IWM_FDC, a2bus_iwmflop_device, "a2iwm_flop", "Apple IWM floppy card")
DEFINE_DEVICE_TYPE(A2BUS_AGAT7_FDC, a2bus_agat7flop_device, "agat7_flop", "Agat-7 140K floppy card")
+DEFINE_DEVICE_TYPE(A2BUS_AGAT9_FDC, a2bus_agat9flop_device, "agat9_flop", "Agat-9 140K floppy card")
#define DISKII_ROM_REGION "diskii_rom"
#define FDC_TAG "diskii_fdc"
@@ -57,6 +58,11 @@ ROM_START( agat7 )
ROM_LOAD( "shugart7.rom", 0x0000, 0x0100, CRC(c6e4850c) SHA1(71626d3d2d4bbeeac2b77585b45a5566d20b8d34) )
ROM_END
+ROM_START( agat9 )
+ ROM_REGION(0x100, DISKII_ROM_REGION, 0)
+ ROM_LOAD( "shugart9.rom", 0x0000, 0x0100, CRC(964a0ce2) SHA1(bf955189ebffe874c20ef649a3db8177dc16af61) )
+ROM_END
+
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
@@ -89,6 +95,11 @@ const tiny_rom_entry *a2bus_agat7flop_device::device_rom_region() const
return ROM_NAME( agat7 );
}
+const tiny_rom_entry *a2bus_agat9flop_device::device_rom_region() const
+{
+ return ROM_NAME( agat9 );
+}
+
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
@@ -115,6 +126,11 @@ a2bus_agat7flop_device::a2bus_agat7flop_device(const machine_config &mconfig, co
{
}
+a2bus_agat9flop_device::a2bus_agat9flop_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_floppy_device(mconfig, A2BUS_AGAT9_FDC, tag, owner, clock)
+{
+}
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
diff --git a/src/devices/bus/a2bus/a2diskii.h b/src/devices/bus/a2bus/a2diskii.h
index b159d2c5278..879744e8950 100644
--- a/src/devices/bus/a2bus/a2diskii.h
+++ b/src/devices/bus/a2bus/a2diskii.h
@@ -67,9 +67,18 @@ public:
virtual const tiny_rom_entry *device_rom_region() const override;
};
+class a2bus_agat9flop_device: public a2bus_floppy_device
+{
+public:
+ a2bus_agat9flop_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
// device type definition
DECLARE_DEVICE_TYPE(A2BUS_DISKII, a2bus_diskii_device)
DECLARE_DEVICE_TYPE(A2BUS_IWM_FDC, a2bus_iwmflop_device)
DECLARE_DEVICE_TYPE(A2BUS_AGAT7_FDC, a2bus_agat7flop_device)
+DECLARE_DEVICE_TYPE(A2BUS_AGAT9_FDC, a2bus_agat9flop_device)
#endif // MAME_BUS_A2BUS_A2DISKII_H
diff --git a/src/devices/bus/a2bus/agat840k_hle.cpp b/src/devices/bus/a2bus/agat840k_hle.cpp
index c95d66a09e9..c7262b633c5 100644
--- a/src/devices/bus/a2bus/agat840k_hle.cpp
+++ b/src/devices/bus/a2bus/agat840k_hle.cpp
@@ -326,24 +326,28 @@ uint8_t a2bus_agat840k_hle_device::read_cnxx(uint8_t offset)
legacy_floppy_image_device *a2bus_agat840k_hle_device::floppy_image(int drive)
{
- const char *floppy_name = nullptr;
-
- switch (drive)
- {
- case 0:
- floppy_name = FLOPPY_0;
- break;
- case 1:
- floppy_name = FLOPPY_1;
- break;
+ switch(drive) {
+ case 0 : return subdevice<legacy_floppy_image_device>(FLOPPY_0);
+ case 1 : return subdevice<legacy_floppy_image_device>(FLOPPY_1);
}
- return subdevice<legacy_floppy_image_device>(floppy_name);
+ return nullptr;
}
-// all signals active low. write support not implemented; WPT is always active.
+/*
+ * all signals active low. write support not implemented; WPT is always active.
+ *
+ * b0-b1 type of drive 2: 00 - ES 5323.01 "1000 KB", 01 - "500 KB", 10 - "250 KB", 11 - not present
+ * b2-b3 type of drive 1: -""-
+ * b4 INDEX/SECTOR
+ * b5 WRITE PROTECT
+ * b6 TRACK 0
+ * b7 READY
+ *
+ * C0x1
+ */
READ8_MEMBER(a2bus_agat840k_hle_device::d14_i_b)
{
- u8 data = 0x03; // one drive present, because drive select is broken
+ u8 data = 0x3;
m_floppy->floppy_drive_set_ready_state(FLOPPY_DRIVE_READY, 1);
@@ -373,7 +377,6 @@ READ8_MEMBER(a2bus_agat840k_hle_device::d14_i_b)
*/
WRITE8_MEMBER(a2bus_agat840k_hle_device::d14_o_c)
{
- // drive select is broken in legacy flopdrv.cpp -- floppy_get_drive
m_unit = BIT(data, 3);
m_floppy = floppy_image(m_unit);
if (m_unit)
@@ -402,6 +405,8 @@ WRITE8_MEMBER(a2bus_agat840k_hle_device::d14_o_c)
data, m_unit, m_side, !BIT(data, 2), !BIT(data, 6), !BIT(data, 7));
}
+// C0x4
+//
// data are latched in by write to PC4
READ8_MEMBER(a2bus_agat840k_hle_device::d15_i_a)
{
diff --git a/src/devices/bus/a2bus/agat_fdc.cpp b/src/devices/bus/a2bus/agat_fdc.cpp
new file mode 100644
index 00000000000..cb79d0cd699
--- /dev/null
+++ b/src/devices/bus/a2bus/agat_fdc.cpp
@@ -0,0 +1,488 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/*********************************************************************
+
+ agat_fdc.c
+
+ Implementation of the Agat 840K floppy controller card
+
+ Technical manual:
+ http://agatcomp.ru/Reading/serkov/hainfo/023-01to.shtml
+ http://agatcomp.ru/Reading/serkov/hainfo/023-01to1.shtml
+
+ Schematic:
+ http://agatcomp.ru/Reading/fl800k/FD840/TEAC_023-adj-HI.jpg
+
+ On-disk format:
+ https://github.com/sintech/AGAT/blob/master/docs/agat-840k-format.txt
+ http://www.torlus.com/floppy/forum/viewtopic.php?f=19&t=1385
+
+*********************************************************************/
+
+#include "emu.h"
+#include "agat_fdc.h"
+
+#include "formats/aim_dsk.h"
+#include "formats/ds9_dsk.h"
+
+
+#define LOG_LSS (1U << 1) // Show warnings
+#define LOG_SHIFT (1U << 2) // Shows shift register contents
+
+//#define VERBOSE (LOG_GENERAL | LOG_SHIFT | LOG_LSS)
+//#define VERBOSE (LOG_GENERAL)
+#include "logmacro.h"
+
+#define LOGLSS(...) LOGMASKED(LOG_LSS, __VA_ARGS__)
+#define LOGSHIFT(...) LOGMASKED(LOG_SHIFT, __VA_ARGS__)
+
+
+/***************************************************************************
+ PARAMETERS
+***************************************************************************/
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(A2BUS_AGAT_FDC, a2bus_agat_fdc_device, "agat_fdc", "Agat 840K floppy card")
+
+#define AGAT_FDC_ROM_REGION "agat_fdc_rom"
+#define AGAT_FDC_ROM_D6_REGION "agat_fdc_d6_rom"
+
+ROM_START( agat9 )
+ ROM_REGION(0x100, AGAT_FDC_ROM_REGION, 0)
+ // zagorsk
+ ROM_LOAD( "teac.rom", 0x0000, 0x0100, CRC(94266928) SHA1(5d369bad6cdd6a70b0bb16480eba69640de87a2e) )
+
+ ROM_REGION(0x200, AGAT_FDC_ROM_D6_REGION, 0)
+ ROM_LOAD( "d6encdec.bin", 0x0000, 0x0200, CRC(66e7e896) SHA1(b5305e82c81240a6fdc932a559b5493c59f302c6) )
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+FLOPPY_FORMATS_MEMBER( a2bus_agat_fdc_device::floppy_formats )
+ FLOPPY_DS9_FORMAT,
+ FLOPPY_AIM_FORMAT
+FLOPPY_FORMATS_END
+
+static void agat_floppies(device_slot_interface &device)
+{
+ device.option_add("525dsqd", FLOPPY_525_QD);
+}
+
+void a2bus_agat_fdc_device::device_add_mconfig (machine_config &config)
+{
+ FLOPPY_CONNECTOR(config, floppy0, agat_floppies, "525dsqd", a2bus_agat_fdc_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, floppy1, agat_floppies, "525dsqd", a2bus_agat_fdc_device::floppy_formats);
+
+ I8255(config, m_d14);
+ // PA not connected
+ m_d14->in_pb_callback().set(FUNC(a2bus_agat_fdc_device::d14_i_b)); // status signals from drive
+ m_d14->out_pc_callback().set(FUNC(a2bus_agat_fdc_device::d14_o_c)); // control
+
+ I8255(config, m_d15);
+ m_d15->in_pa_callback().set(FUNC(a2bus_agat_fdc_device::d15_i_a)); // read data
+// m_d15->out_pb_callback().set(FUNC(a2bus_agat_fdc_device::d15_o_b)); // write data
+ m_d15->in_pc_callback().set(FUNC(a2bus_agat_fdc_device::d15_i_c));
+ m_d15->out_pc_callback().set(FUNC(a2bus_agat_fdc_device::d15_o_c));
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *a2bus_agat_fdc_device::device_rom_region() const
+{
+ return ROM_NAME( agat9 );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+a2bus_agat_fdc_device::a2bus_agat_fdc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_a2bus_card_interface(mconfig, *this)
+ , m_d14(*this, "d14")
+ , m_d15(*this, "d15")
+ , floppy0(*this, "0")
+ , floppy1(*this, "1")
+ , m_rom(nullptr)
+ , m_rom_d6(nullptr)
+{
+}
+
+a2bus_agat_fdc_device::a2bus_agat_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_agat_fdc_device(mconfig, A2BUS_AGAT_FDC, tag, owner, clock)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void a2bus_agat_fdc_device::device_start()
+{
+ set_unscaled_clock((XTAL(14'300'000) / 14.0) * 4.0);
+
+ m_rom = device().machine().root_device().memregion(this->subtag(AGAT_FDC_ROM_REGION).c_str())->base();
+ m_rom_d6 = device().machine().root_device().memregion(this->subtag(AGAT_FDC_ROM_D6_REGION).c_str())->base();
+
+ floppy = nullptr;
+ if (floppy0)
+ {
+ floppy = floppy0->get_device();
+ }
+
+ m_mxcs = MXCSR_SYNC;
+
+ m_timer_lss = timer_alloc(TIMER_ID_LSS);
+ m_timer_motor = timer_alloc(TIMER_ID_MOTOR);
+
+ m_seektime = 6; // ms, per es5323.txt
+ m_waittime = 32; // us - 16 bits x 2 us
+}
+
+void a2bus_agat_fdc_device::device_reset()
+{
+ active = 0;
+ cycles = time_to_cycles(machine().time());
+ data_reg = 0x00;
+ address = 0xff;
+
+ m_mxcs |= MXCSR_SYNC;
+ m_mxcs &= ~MXCSR_TR;
+
+ // Just a timer to be sure that the lss is updated from time to
+ // time, so that there's no hiccup when it's talked to again.
+ m_timer_lss->adjust(attotime::from_msec(10), 0, attotime::from_msec(10));
+}
+
+void a2bus_agat_fdc_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case TIMER_ID_LSS:
+ lss_sync();
+ break;
+
+ case TIMER_ID_MOTOR:
+ active = 0;
+ floppy->mon_w(1);
+ break;
+ }
+}
+
+uint64_t a2bus_agat_fdc_device::time_to_cycles(const attotime &tm)
+{
+ // Clock is falling edges of the ~4Mhz clock
+
+ uint64_t cycles = tm.as_ticks(clock()*2);
+ cycles = (cycles+1) >> 1;
+ return cycles;
+}
+
+attotime a2bus_agat_fdc_device::cycles_to_time(uint64_t cycles)
+{
+ return attotime::from_ticks(cycles*2+1, clock()*2);
+}
+
+void a2bus_agat_fdc_device::lss_start()
+{
+ cycles = time_to_cycles(machine().time()) + 1;
+ data_reg = 0x00;
+ address = 0xff;
+ bits = 8;
+}
+
+void a2bus_agat_fdc_device::lss_sync()
+{
+ if(!active)
+ return;
+
+ attotime next_flux = floppy ? floppy->get_next_transition(cycles_to_time(cycles-1)) : attotime::never;
+ uint64_t cycles_limit = time_to_cycles(machine().time());
+ uint64_t cycles_next_flux = next_flux != attotime::never ? time_to_cycles(next_flux) : uint64_t(-1);
+ uint64_t cycles_next_flux_down = cycles_next_flux != uint64_t(-1) ? cycles_next_flux+1 : uint64_t(-1);
+
+ LOGLSS("LSS at %11.6f: %d (limit %d next %d) in %02x\n",
+ machine().time().as_double(), cycles, cycles_limit, cycles_next_flux, address);
+
+ if(cycles >= cycles_next_flux && cycles < cycles_next_flux_down)
+ address &= ~0x40;
+ else
+ address |= 0x40;
+
+ while (cycles < cycles_limit) {
+ uint64_t cycles_next_trans = cycles_limit;
+ if(cycles_next_trans > cycles_next_flux && cycles < cycles_next_flux)
+ {
+ cycles_next_trans = cycles_next_flux;
+ LOGLSS("lss: next_trans up (%d < %d; %d)\n", cycles, cycles_next_flux, cycles_limit);
+ }
+ if(cycles_next_trans > cycles_next_flux_down && cycles < cycles_next_flux_down)
+ {
+ cycles_next_trans = cycles_next_flux_down;
+ LOGLSS("lss: next_trans down (%d < %d; %d)\n", cycles, cycles_next_flux_down, cycles_limit);
+ }
+
+ while (cycles < cycles_next_trans) {
+ uint8_t opcode = m_rom_d6[address];
+
+ if (cycles_next_flux != uint64_t(-1))
+ {
+ LOGLSS("lss: %d (limit %d next %d) in %03x out %02x (addr %02x end %d bit %d sync %d)\n",
+ cycles, cycles_limit, cycles_next_flux, address, opcode,
+ opcode & 0x3f, BIT(opcode, 6), BIT(opcode, 5), BIT(opcode, 7));
+ }
+ if (!BIT(opcode, 6)) // end bit
+ {
+ data_reg <<= 1;
+ data_reg |= !BIT(opcode, 5);
+ LOGSHIFT("lss shift: %d (to %02x, %2d bits) at %d%s\n", BIT(opcode, 5), data_reg, bits, cycles,
+ BIT(opcode, 7) ? " (sync)":"");
+
+ if (BIT(opcode, 7) == BIT(opcode, 5)) // hack
+ {
+ bits++;
+ }
+ else
+ {
+ m_mxcs &= ~MXCSR_SYNC;
+ bits = 0;
+ }
+
+ if (bits == 16)
+ {
+ address |= 0x80;
+ m_d15->pc4_w(0);
+ m_d15->pc4_w(1);
+ bits = 8;
+ LOGSHIFT("lss data: %02x\n", data_reg);
+ }
+ else
+ {
+ address &= ~0x80;
+ }
+ }
+
+ address &= ~0x3f;
+ address |= (opcode & 0x3f);
+
+ cycles++;
+ }
+
+ if(cycles == cycles_next_flux)
+ address &= ~0x40;
+ else if(cycles == cycles_next_flux_down) {
+ address |= 0x40;
+ next_flux = floppy ? floppy->get_next_transition(cycles_to_time(cycles)) : attotime::never;
+ if (next_flux != attotime::never) {
+ cycles_next_flux = time_to_cycles(next_flux);
+ LOGLSS("lss next: %d cycles\n", cycles_next_flux+1-cycles_next_flux_down);
+ cycles_next_flux_down = cycles_next_flux+1;
+ } else {
+ cycles_next_flux = uint64_t(-1);
+ cycles_next_flux_down = uint64_t(-1);
+ }
+ }
+ }
+}
+
+/*-------------------------------------------------
+ read_c0nx - called for reads from this card's c0nx space
+-------------------------------------------------*/
+
+uint8_t a2bus_agat_fdc_device::read_c0nx(uint8_t offset)
+{
+ u8 data;
+
+ lss_sync();
+
+ switch (offset)
+ {
+ case 0: case 1: case 2: case 3:
+ data = m_d14->read(offset);
+ break;
+
+ case 4: case 5: case 6: case 7:
+ data = m_d15->read(offset - 4);
+ break;
+
+ default:
+ data = 0xff;
+ break;
+ }
+
+ return data;
+}
+
+
+/*-------------------------------------------------
+ write_c0nx - called for writes to this card's c0nx space
+-------------------------------------------------*/
+
+void a2bus_agat_fdc_device::write_c0nx(uint8_t offset, uint8_t data)
+{
+ lss_sync();
+
+ switch (offset)
+ {
+ case 0: case 1: case 2: case 3:
+ m_d14->write(offset, data);
+ break;
+
+ case 4: case 5: case 6: case 7:
+ m_d15->write(offset - 4, data);
+ break;
+
+ case 8: // D9.15 - write desync
+ break;
+
+ case 9: // D9.14 - step
+ LOG("step at %11.6f\n", machine().time().as_double());
+ if (floppy && active)
+ {
+ floppy->stp_w(1);
+ floppy->stp_w(0);
+ }
+ break;
+
+ case 10: // D9.13 - reset desync flipflop
+ m_mxcs |= MXCSR_SYNC;
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*-------------------------------------------------
+ read_cnxx - called for reads from this card's c0nx space
+-------------------------------------------------*/
+
+uint8_t a2bus_agat_fdc_device::read_cnxx(uint8_t offset)
+{
+ return m_rom[offset];
+}
+
+
+/*
+ * all signals active low. write support not implemented; WPT is always active.
+ *
+ * b0-b1 type of drive 2: 00 - ES 5323.01 "1000 KB", 01 - "500 KB", 10 - "250 KB", 11 - not present
+ * b2-b3 type of drive 1: -""-
+ * b4 INDEX/SECTOR
+ * b5 WRITE PROTECT
+ * b6 TRACK 0
+ * b7 READY
+ *
+ * C0x1
+ */
+READ8_MEMBER(a2bus_agat_fdc_device::d14_i_b)
+{
+ u8 data = 0x3;
+
+ // all signals active low
+ if (floppy)
+ {
+ data |= (floppy->idx_r() << 4) ^ 0x10;
+// data |= floppy->wpt_r() << 5;
+ data |= floppy->trk00_r() << 6;
+ data |= floppy->ready_r() << 7;
+ }
+ else
+ {
+ data |= 0xf0;
+ }
+
+ LOG("status A: %s %s (t %d) %s %s\n", BIT(data, 7) ? "ready" : "READY", BIT(data, 6) ? "tk00" : "TK00",
+ floppy ? floppy->get_cyl() : -1, BIT(data, 5) ? "wpt" : "WPT", BIT(data, 4) ? "index" : "INDEX");
+
+ return data;
+}
+
+/*
+ * b0 AH strong write precomp
+ * b1 -- NC
+ * b2 -- step direction (1 - inward, 0 - outward)
+ * b3 -- drive select (0 - drive 1, 1 - drive 2)
+ * b4 -- head select (0 - bottom, 1 - top)
+ * b5 AH write precomp off
+ * b6 AH write enable
+ * b7 AH motor on
+ *
+ * C0x2
+ */
+WRITE8_MEMBER(a2bus_agat_fdc_device::d14_o_c)
+{
+ m_unit = BIT(data, 3);
+
+ if (floppy)
+ {
+ floppy->dir_w(!BIT(data, 2));
+ floppy->ss_w(BIT(data, 4));
+// floppy->wtg_w(!BIT(data, 6));
+// floppy->mon_w(!BIT(data, 7)); // tied to 'drive select', 'motor on' and 'head load'
+ }
+ if (BIT(data, 7))
+ {
+ m_d15->pc4_w(0);
+ m_d15->pc4_w(1);
+ floppy->mon_w(0);
+ if (!active)
+ {
+ active = 1;
+ lss_start();
+ }
+ }
+#if 0
+ else
+ {
+ m_timer_motor->adjust(attotime::from_msec(1000));
+ }
+#endif
+
+ LOG("D14 C <- %02X (unit %d side %d drtn %d wtg %d mon %d)\n",
+ data, m_unit, BIT(data, 4), !BIT(data, 2), !BIT(data, 6), !BIT(data, 7));
+}
+
+// data are latched in by write to PC4
+READ8_MEMBER(a2bus_agat_fdc_device::d15_i_a)
+{
+ return data_reg;
+}
+
+// C0x6
+//
+// b6 AL desync detected
+// b7 AH read or write data ready
+READ8_MEMBER(a2bus_agat_fdc_device::d15_i_c)
+{
+ LOG("status B: @ %4d %s %s\n", 0,
+ BIT(m_mxcs, 7) ? "ready" : "READY", BIT(m_mxcs, 6) ? "SYNC" : "sync");
+
+ return m_mxcs;
+}
+
+// C0x7
+//
+// b0 -- connected to b7, set if m_intr[PORT_B]
+// b2 AH b7 = ready for write data
+// b3 -- connected to b7, set if m_intr[PORT_A]
+// b4 AH b7 = read data ready
+WRITE8_MEMBER(a2bus_agat_fdc_device::d15_o_c)
+{
+ if (BIT(data, 0) || BIT(data, 3))
+ {
+ m_mxcs |= MXCSR_TR;
+ }
+ else
+ {
+ m_mxcs &= ~MXCSR_TR;
+ }
+}
+
diff --git a/src/devices/bus/a2bus/agat_fdc.h b/src/devices/bus/a2bus/agat_fdc.h
new file mode 100644
index 00000000000..c4a304c9072
--- /dev/null
+++ b/src/devices/bus/a2bus/agat_fdc.h
@@ -0,0 +1,105 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/*********************************************************************
+
+ agat_fdc.h
+
+ Implementation of the Agat 840K floppy controller card
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2BUS_AGAT_FDC_H
+#define MAME_BUS_A2BUS_AGAT_FDC_H
+
+#pragma once
+
+#include "a2bus.h"
+#include "imagedev/floppy.h"
+#include "machine/i8255.h"
+
+
+#define MXCSR_SYNC 0x40
+#define MXCSR_TR 0x80
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_agat_fdc_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_agat_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_READ8_MEMBER(d14_i_b);
+ DECLARE_READ8_MEMBER(d15_i_a);
+ DECLARE_READ8_MEMBER(d15_i_c);
+ DECLARE_WRITE8_MEMBER(d14_o_c);
+ DECLARE_WRITE8_MEMBER(d15_o_b);
+ DECLARE_WRITE8_MEMBER(d15_o_c);
+
+ DECLARE_FLOPPY_FORMATS(floppy_formats);
+
+protected:
+ // construction/destruction
+ a2bus_agat_fdc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ // overrides of standard a2bus slot functions
+ virtual uint8_t read_c0nx(uint8_t offset) override;
+ virtual void write_c0nx(uint8_t offset, uint8_t data) override;
+ virtual uint8_t read_cnxx(uint8_t offset) override;
+
+ enum
+ {
+ TIMER_ID_LSS = 0,
+ TIMER_ID_SEEK,
+ TIMER_ID_MOTOR
+ };
+
+ required_device<i8255_device> m_d14;
+ required_device<i8255_device> m_d15;
+
+private:
+ required_device<floppy_connector> floppy0;
+ required_device<floppy_connector> floppy1;
+
+ uint64_t time_to_cycles(const attotime &tm);
+ attotime cycles_to_time(uint64_t cycles);
+
+ void lss_start();
+ void lss_sync();
+
+ floppy_image_device *floppy;
+ int active, bits;
+ uint8_t data_reg;
+ uint16_t address;
+ uint64_t cycles;
+
+ u8 m_mxcs;
+ int m_unit;
+ int m_state;
+
+ int m_seektime;
+ int m_waittime;
+
+ emu_timer *m_timer_lss;
+ emu_timer *m_timer_seek;
+ emu_timer *m_timer_motor;
+
+ uint8_t *m_rom;
+ uint8_t *m_rom_d6;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(A2BUS_AGAT_FDC, a2bus_agat_fdc_device)
+
+#endif // MAME_BUS_A2BUS_AGAT_FDC_H
diff --git a/src/lib/formats/aim_dsk.cpp b/src/lib/formats/aim_dsk.cpp
new file mode 100644
index 00000000000..3bc2c2b5b5f
--- /dev/null
+++ b/src/lib/formats/aim_dsk.cpp
@@ -0,0 +1,108 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/*********************************************************************
+
+ formats/aim_dsk.h
+
+ AIM disk images
+
+ References:
+ - http://www.torlus.com/floppy/forum/viewtopic.php?f=19&t=1385
+ - http://agatcomp.ru/Soft/agat.shtml
+
+*********************************************************************/
+
+#include <assert.h>
+
+#include "aim_dsk.h"
+
+
+aim_format::aim_format()
+{
+}
+
+
+const char *aim_format::name() const
+{
+ return "aim";
+}
+
+
+const char *aim_format::description() const
+{
+ return "AIM disk image";
+}
+
+
+const char *aim_format::extensions() const
+{
+ return "aim";
+}
+
+
+int aim_format::identify(io_generic *io, uint32_t form_factor)
+{
+ if (io_generic_size(io) == 2068480)
+ {
+ return 100;
+ }
+
+ return 0;
+}
+
+
+bool aim_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
+{
+ image->set_variant(floppy_image::DSQD);
+
+ const int tracks = 80;
+ const int track_size = 6464 * 2;
+ const int heads = 2;
+
+ for (int track = 0; track < tracks; track++)
+ {
+ for (int head = 0; head < heads; head++)
+ {
+ std::vector<uint8_t> track_data(track_size);
+ std::vector<uint32_t> raw_track_data;
+ int data_count = 0;
+ bool header = false;
+
+ // Read track
+ io_generic_read(io, &track_data[0], ( heads * track + head ) * track_size, track_size);
+
+ for (int offset = 0; offset < track_size; offset += 2)
+ {
+ switch (track_data[offset + 1] & 1)
+ {
+ case 0:
+ if (data_count == 0)
+ header = (track_data[offset] == 0x95) ? true : false;
+ data_count++;
+ mfm_w(raw_track_data, 8, track_data[offset]);
+ break;
+
+ case 1:
+ if (header && data_count < 11) // XXX hack
+ {
+ for (; data_count < 12; data_count++)
+ {
+ mfm_w(raw_track_data, 8, 0xaa);
+ }
+ }
+ raw_w(raw_track_data, 16, 0x8924);
+ raw_w(raw_track_data, 16, 0x5555);
+ data_count = 0;
+ break;
+ }
+ }
+
+ generate_track_from_levels(track, head, raw_track_data, 0, image);
+ }
+ }
+
+ return true;
+}
+
+
+const floppy_format_type FLOPPY_AIM_FORMAT = &floppy_image_format_creator<aim_format>;
diff --git a/src/lib/formats/aim_dsk.h b/src/lib/formats/aim_dsk.h
new file mode 100644
index 00000000000..75229875c69
--- /dev/null
+++ b/src/lib/formats/aim_dsk.h
@@ -0,0 +1,34 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/*********************************************************************
+
+ formats/aim_dsk.h
+
+ AIM disk images
+
+*********************************************************************/
+
+#ifndef AIM_DSK_H
+#define AIM_DSK_H
+
+#include "flopimg.h"
+
+/**************************************************************************/
+
+class aim_format : public floppy_image_format_t
+{
+public:
+ aim_format();
+
+ virtual int identify(io_generic *io, uint32_t form_factor) override;
+ virtual bool load(io_generic *io, uint32_t form_factor, floppy_image *image) override;
+
+ virtual const char *name() const override;
+ virtual const char *description() const override;
+ virtual const char *extensions() const override;
+ virtual bool supports_save() const override { return false; }
+};
+
+extern const floppy_format_type FLOPPY_AIM_FORMAT;
+
+#endif /* AIM_DSK_H */
diff --git a/src/lib/formats/ds9_dsk.cpp b/src/lib/formats/ds9_dsk.cpp
new file mode 100644
index 00000000000..578d01a2cca
--- /dev/null
+++ b/src/lib/formats/ds9_dsk.cpp
@@ -0,0 +1,156 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/**********************************************************************
+
+ formats/ds9_dsk.cpp
+
+ Floppies used by Agat-9 840KB controller
+
+ http://agatcomp.ru/Reading/docs/es5323.txt
+
+ https://github.com/sintech/AGAT/blob/master/docs/agat-840k-format.txt
+
+ http://www.torlus.com/floppy/forum/viewtopic.php?f=19&t=1385
+
+************************************************************************/
+
+#include <assert.h>
+
+#include "formats/ds9_dsk.h"
+
+
+static FLOPPY_IDENTIFY(ds9_dsk_identify)
+{
+ switch (floppy_image_size(floppy))
+ {
+ case (80 * 2 * 21 * 256):
+ case 860164:
+ case 860288:
+ *vote = 100;
+ break;
+
+ default:
+ *vote = 0;
+ break;
+ }
+
+ return FLOPPY_ERROR_SUCCESS;
+}
+
+static FLOPPY_CONSTRUCT(ds9_dsk_construct)
+{
+ struct basicdsk_geometry geometry;
+ memset(&geometry, 0, sizeof(geometry));
+ geometry.heads = 2;
+ geometry.first_sector_id = 0;
+ geometry.sector_length = 256;
+ geometry.tracks = 80;
+ geometry.sectors = 21;
+ return basicdsk_construct(floppy, &geometry);
+}
+
+LEGACY_FLOPPY_OPTIONS_START( ds9 )
+ LEGACY_FLOPPY_OPTION( ds9_dsk, "ds9,dsk,raw", "Agat 840K DSK image",
+ ds9_dsk_identify, ds9_dsk_construct, nullptr, nullptr)
+LEGACY_FLOPPY_OPTIONS_END
+
+// exactly 6500 bytes
+const floppy_image_format_t::desc_e ds9_format::ds9_desc[] = {
+ /* 01 */ { MFM, 0xaa, 32 }, // GAP1
+ /* 02 */ { SECTOR_LOOP_START, 0, 20 }, // 21 sectors
+ /* 03 */ { RAWBITS, 0x8924, 16 }, // sync mark: xA4, 2 us zero level interval, 0xFF
+ /* 04 */ { RAWBITS, 0x5555, 16 },
+ /* 05 */ { MFM, 0x95, 1 }, // address field prologue
+ /* 06 */ { MFM, 0x6a, 1 },
+ /* 07 */ { MFM, 0xfe, 1 }, // volume number
+ /* 08 */ { OFFSET_ID },
+ /* 09 */ { SECTOR_ID },
+ /* 10 */ { MFM, 0x5a, 1 }, // address field epilogue
+ /* 11 */ { MFM, 0xaa, 5 }, // GAP2 (min 4 bytes)
+ /* 12 */ { RAWBITS, 0x8924, 16 }, // sync mark
+ /* 13 */ { RAWBITS, 0x5555, 16 },
+ /* 14 */ { MFM, 0x6a, 1 }, // data field prologue
+ /* 15 */ { MFM, 0x95, 1 },
+ /* 16 */ { SECTOR_DATA_DS9, -1 },
+ /* 17 */ { MFM, 0x5a, 1 }, // data field epilogue
+ /* 18 */ { MFM, 0xaa, 33 }, // GAP3
+ /* 19 */ { SECTOR_LOOP_END },
+ /* 20 */ { END }
+};
+
+ds9_format::ds9_format()
+{
+}
+
+const char *ds9_format::name() const
+{
+ return "a9dsk";
+}
+
+const char *ds9_format::description() const
+{
+ return "Agat-9 840K floppy image";
+}
+
+const char *ds9_format::extensions() const
+{
+ return "ds9";
+}
+
+void ds9_format::find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count)
+{
+ uint32_t expected_size = 0;
+ uint64_t size = io_generic_size(io);
+
+ head_count = 2;
+ track_count = 80;
+ sector_count = 21;
+ expected_size = 256 * track_count * head_count * sector_count;
+
+ if (size >= expected_size) // standard format has 860160 bytes
+ return;
+
+ track_count = head_count = sector_count = 0;
+}
+
+int ds9_format::identify(io_generic *io, uint32_t form_factor)
+{
+ uint8_t track_count, head_count, sector_count;
+ find_size(io, track_count, head_count, sector_count);
+
+ if (track_count) return 50;
+
+ return 0;
+}
+
+bool ds9_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
+{
+ uint8_t track_count, head_count, sector_count;
+ find_size(io, track_count, head_count, sector_count);
+ if (track_count == 0) return false;
+
+ uint8_t sectdata[21 * 256];
+ desc_s sectors[21];
+ for (int i = 0; i < sector_count; i++)
+ {
+ sectors[i].data = sectdata + 256 * i;
+ sectors[i].size = 256;
+ sectors[i].sector_id = i;
+ }
+
+ int track_size = sector_count * 256;
+ for (int track = 0; track < track_count; track++)
+ {
+ for (int head = 0; head < head_count; head++)
+ {
+ io_generic_read(io, sectdata, (track * head_count + head) * track_size, track_size);
+ generate_track(ds9_desc, track, head, sectors, sector_count, 104000, image);
+ }
+ }
+
+ image->set_variant(floppy_image::DSQD);
+
+ return true;
+}
+
+const floppy_format_type FLOPPY_DS9_FORMAT = &floppy_image_format_creator<ds9_format>;
diff --git a/src/lib/formats/ds9_dsk.h b/src/lib/formats/ds9_dsk.h
new file mode 100644
index 00000000000..540c49a7ce7
--- /dev/null
+++ b/src/lib/formats/ds9_dsk.h
@@ -0,0 +1,38 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/*********************************************************************
+
+ formats/ds9_dsk.h
+
+*********************************************************************/
+
+#ifndef DS9_DSK_H_
+#define DS9_DSK_H_
+
+#include "flopimg.h"
+#include "formats/basicdsk.h"
+
+LEGACY_FLOPPY_OPTIONS_EXTERN(ds9);
+
+class ds9_format : public floppy_image_format_t
+{
+public:
+ ds9_format();
+
+ virtual int identify(io_generic *io, uint32_t form_factor) override;
+ virtual bool load(io_generic *io, uint32_t form_factor, floppy_image *image) override;
+
+ virtual const char *name() const override;
+ virtual const char *description() const override;
+ virtual const char *extensions() const override;
+ virtual bool supports_save() const override { return false; }
+
+ static const desc_e ds9_desc[];
+
+private:
+ void find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count);
+};
+
+extern const floppy_format_type FLOPPY_DS9_FORMAT;
+
+#endif /* DS9_DSK_H_ */
diff --git a/src/lib/formats/dvk_mx_dsk.cpp b/src/lib/formats/dvk_mx_dsk.cpp
new file mode 100644
index 00000000000..af7d883e4d6
--- /dev/null
+++ b/src/lib/formats/dvk_mx_dsk.cpp
@@ -0,0 +1,177 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/**********************************************************************
+
+ formats/dvk_mx_dsk.cpp
+
+ Floppies used by DVK MX: controller
+
+ http://torlus.com/floppy/forum/viewtopic.php?f=19&t=1384
+
+ Track format is almost entirely driver-dependent (only sync word
+ 0x00f3 is mandatory), because hardware always reads or writes
+ entire track. 'old' format is used by stock driver, 'new' --
+ by 3rd party one. Formatting tools produce yet other variants...
+
+ Floppy drives were 40- and 80-track, double-sided. 'new' driver
+ also supports single-sided floppies.
+
+************************************************************************/
+
+#include <assert.h>
+
+#include "flopimg.h"
+#include "formats/dvk_mx_dsk.h"
+
+const floppy_image_format_t::desc_e dvk_mx_format::dvk_mx_new_desc[] = {
+ /* 01 */ { FM, 0x00, 8*2 }, // eight 0x0000 words
+ /* 03 */ { FM, 0x00, 1 },
+ /* 02 */ { FM, 0xf3, 1 }, // word 0x00f3
+ /* 05 */ { FM, 0x00, 1 },
+ /* 04 */ { TRACK_ID_FM }, // track number word
+ /* 05 */ { SECTOR_LOOP_START, 0, 10 }, // 11 sectors
+ /* 07 */ { SECTOR_DATA_MX, -1 },
+ /* 10 */ { SECTOR_LOOP_END },
+ /* 13 */ { FM, 0x83, 1 },
+ /* 12 */ { OFFSET_ID_FM },
+ /* 15 */ { FM, 0x83, 1 },
+ /* 14 */ { OFFSET_ID_FM },
+ /* 17 */ { FM, 0x83, 1 },
+ /* 16 */ { OFFSET_ID_FM },
+ /* 18 */ { END }
+};
+
+const floppy_image_format_t::desc_e dvk_mx_format::dvk_mx_old_desc[] = {
+ /* 01 */ { FM, 0x00, 30*2 },
+ /* 03 */ { FM, 0x00, 1 },
+ /* 02 */ { FM, 0xf3, 1 }, // word 0x00f3
+ /* 05 */ { FM, 0x00, 1 },
+ /* 04 */ { TRACK_ID_FM }, // track number word
+ /* 06 */ { SECTOR_LOOP_START, 0, 10 }, // 11 sectors
+ /* 07 */ { SECTOR_DATA_MX, -1 },
+ /* 10 */ { SECTOR_LOOP_END },
+ /* 13 */ { FM, 0x83, 1 },
+ /* 11 */ { FM, 0x01, 1 },
+ /* 15 */ { FM, 0x83, 1 },
+ /* 14 */ { FM, 0x01, 1 },
+ /* 16 */ { END }
+};
+
+dvk_mx_format::dvk_mx_format()
+{
+}
+
+const char *dvk_mx_format::name() const
+{
+ return "mx";
+}
+
+const char *dvk_mx_format::description() const
+{
+ return "DVK MX: floppy image";
+}
+
+const char *dvk_mx_format::extensions() const
+{
+ return "mx";
+}
+
+bool dvk_mx_format::supports_save() const
+{
+ return false;
+}
+
+void dvk_mx_format::find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count)
+{
+ uint64_t size = io_generic_size(io);
+
+ switch (size)
+ {
+ case 112640:
+ track_count = 40;
+ sector_count = 11;
+ head_count = 1;
+ break;
+ case 225280:
+ track_count = 40;
+ sector_count = 11;
+ head_count = 2;
+ break;
+ case 450560:
+ track_count = 80;
+ sector_count = 11;
+ head_count = 2;
+ break;
+ default:
+ track_count = head_count = sector_count = 0;
+ break;
+ }
+}
+
+int dvk_mx_format::identify(io_generic *io, uint32_t form_factor)
+{
+ uint8_t track_count, head_count, sector_count;
+
+ find_size(io, track_count, head_count, sector_count);
+
+ if (track_count)
+ {
+ uint8_t sectdata[512];
+ io_generic_read(io, sectdata, 512, 512);
+ // check value in RT-11 home block. see src/tools/imgtool/modules/rt11.cpp
+ if (pick_integer_le(sectdata, 0724, 2) == 6)
+ return 100;
+ else
+ return 75;
+
+ }
+
+ return 0;
+}
+
+bool dvk_mx_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
+{
+ uint8_t track_count, head_count, sector_count;
+
+ find_size(io, track_count, head_count, sector_count);
+ if (track_count == 0) return false;
+
+ uint8_t sectdata[11 * 256];
+ desc_s sectors[11];
+ for (int i = 0; i < sector_count; i++)
+ {
+ sectors[i].data = sectdata + 256 * i;
+ sectors[i].size = 256;
+ sectors[i].sector_id = i;
+ }
+
+ int track_size = sector_count * 256;
+ for (int track = 0; track < track_count; track++)
+ {
+ for (int head = 0; head < head_count; head++)
+ {
+ io_generic_read(io, sectdata, (track * head_count + head) * track_size, track_size);
+ generate_track(dvk_mx_new_desc, track, head, sectors, sector_count, 45824, image);
+ }
+ }
+
+ if (head_count == 1)
+ {
+ image->set_variant(floppy_image::SSDD);
+ }
+ else
+ {
+ if (track_count > 40)
+ {
+ image->set_variant(floppy_image::DSQD);
+ }
+ else
+ {
+ image->set_variant(floppy_image::DSDD);
+ }
+ }
+
+ return true;
+}
+
+const floppy_format_type FLOPPY_DVK_MX_FORMAT = &floppy_image_format_creator<dvk_mx_format>;
diff --git a/src/lib/formats/dvk_mx_dsk.h b/src/lib/formats/dvk_mx_dsk.h
new file mode 100644
index 00000000000..a95b635588c
--- /dev/null
+++ b/src/lib/formats/dvk_mx_dsk.h
@@ -0,0 +1,39 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/*********************************************************************
+
+ formats/dvk_mx_dsk.h
+
+*********************************************************************/
+
+#ifndef DVK_MX_DSK_H_
+#define DVK_MX_DSK_H_
+
+#pragma once
+
+#include "flopimg.h"
+#include "imageutl.h"
+
+class dvk_mx_format : public floppy_image_format_t
+{
+public:
+ dvk_mx_format();
+
+ virtual int identify(io_generic *io, uint32_t form_factor) override;
+ virtual bool load(io_generic *io, uint32_t form_factor, floppy_image *image) override;
+
+ virtual const char *name() const override;
+ virtual const char *description() const override;
+ virtual const char *extensions() const override;
+ virtual bool supports_save() const override;
+
+ static const desc_e dvk_mx_old_desc[];
+ static const desc_e dvk_mx_new_desc[];
+
+private:
+ void find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count);
+};
+
+extern const floppy_format_type FLOPPY_DVK_MX_FORMAT;
+
+#endif /* DVK_MX_DSK_H_ */
diff --git a/src/lib/formats/flopimg.cpp b/src/lib/formats/flopimg.cpp
index 3d05ec38d03..ea812506f50 100644
--- a/src/lib/formats/flopimg.cpp
+++ b/src/lib/formats/flopimg.cpp
@@ -1038,6 +1038,7 @@ bool floppy_image_format_t::type_data_mfm(int type, int p1, const gen_crc_info *
type == SIZE_ID ||
type == OFFSET_ID_O ||
type == OFFSET_ID_E ||
+ type == OFFSET_ID_FM ||
type == SECTOR_ID_O ||
type == SECTOR_ID_E ||
type == REMAIN_O ||
@@ -1521,6 +1522,14 @@ void floppy_image_format_t::generate_track(const desc_e *desc, int track, int he
mfm_half_w(buffer, 6, track*2+head);
break;
+ case OFFSET_ID_FM:
+ fm_w(buffer, 8, track*2+head);
+ break;
+
+ case OFFSET_ID:
+ mfm_w(buffer, 8, track*2+head);
+ break;
+
case SECTOR_ID_O:
mfm_half_w(buffer, 7, sector_idx);
break;
@@ -1650,6 +1659,37 @@ void floppy_image_format_t::generate_track(const desc_e *desc, int track, int he
break;
}
+ case SECTOR_DATA_MX: {
+ const desc_s *csect = sect + (desc[index].p1 >= 0 ? desc[index].p1 : sector_idx);
+ uint16_t cksum = 0, data;
+ for(int i=0; i < csect->size; i+=2)
+ {
+ data = csect->data[i+1];
+ fm_w(buffer, 8, data);
+ data = (data << 8) | csect->data[i];
+ fm_w(buffer, 8, csect->data[i]);
+ cksum += data;
+ }
+ fm_w(buffer, 16, cksum);
+ break;
+ }
+
+ case SECTOR_DATA_DS9: {
+ const desc_s *csect = sect + (desc[index].p1 >= 0 ? desc[index].p1 : sector_idx);
+ uint8_t data;
+ int cksum = 0;
+ for(int i=0; i != csect->size; i++)
+ {
+ if (cksum > 255) { cksum++; cksum &= 255; }
+ data = csect->data[i];
+ mfm_w(buffer, 8, data);
+ cksum += data;
+ }
+ cksum &= 255;
+ mfm_w(buffer, 8, cksum);
+ break;
+ }
+
default:
printf("%d.%d.%d (%d) unhandled\n", desc[index].type, desc[index].p1, desc[index].p2, index);
break;
diff --git a/src/lib/formats/flopimg.h b/src/lib/formats/flopimg.h
index 8430ae8150b..d5edd6b0315 100644
--- a/src/lib/formats/flopimg.h
+++ b/src/lib/formats/flopimg.h
@@ -333,6 +333,8 @@ protected:
SECTOR_INFO_GCR6, //!< Sector info byte, gcr6-encoded
OFFSET_ID_O, //!< Offset (track*2+head) byte, odd bits, mfm-encoded
OFFSET_ID_E, //!< Offset (track*2+head) byte, even bits, mfm-encoded
+ OFFSET_ID_FM, //!< Offset (track*2+head) byte, fm-encoded
+ OFFSET_ID, //!< Offset (track*2+head) byte, mfm-encoded
SECTOR_ID_O, //!< Sector id byte, odd bits, mfm-encoded
SECTOR_ID_E, //!< Sector id byte, even bits, mfm-encoded
REMAIN_O, //!< Remaining sector count, odd bits, mfm-encoded, total sector count in p1
@@ -345,6 +347,8 @@ protected:
SECTOR_DATA_GCR5, //!< Sector data to gcr5-encode, which in p1, -1 for the current one per the sector id
SECTOR_DATA_MAC, //!< Transformed sector data + checksum, mac style, id in p1, -1 for the current one per the sector id
SECTOR_DATA_8N1, //!< Sector data to 8N1-encode, which in p1, -1 for the current one per the sector id
+ SECTOR_DATA_MX, //!< Sector data to MX-encode, which in p1, -1 for the current one per the sector id
+ SECTOR_DATA_DS9, //!< Sector data to DS9-encode, which in p1, -1 for the current one per the sector id
CRC_CCITT_START, //!< Start a CCITT CRC calculation, with the usual x^16 + x^12 + x^5 + 1 (11021) polynomial, p1 = crc id
CRC_CCITT_FM_START, //!< Start a CCITT CRC calculation, with the usual x^16 + x^12 + x^5 + 1 (11021) polynomial, p1 = crc id
diff --git a/src/mame/drivers/agat.cpp b/src/mame/drivers/agat.cpp
index 53f6011c7ce..0ca770fd1b4 100644
--- a/src/mame/drivers/agat.cpp
+++ b/src/mame/drivers/agat.cpp
@@ -15,10 +15,10 @@
To do (common):
- native keyboard (at least two variants)
+ - video: use palette rom
- video: text modes use 7x8 character cell and 224x256 raster
- video: vertical raster splits (used at least by Rapira)
- what is the state of devices at init and reset?
- - what do floating bus reads do?
- ignore debugger reads -- use side_effects_disabled()
- softlists
@@ -30,28 +30,48 @@
- what does write to C009 do? (basedos7.nib)
To do (agat9):
- - memory banking: what does write to C18x..C1Fx do?
- - memory expansion boards
- - apple2 video compat mode incl. language card emulation
- - 840K floppy controller: low level emulation, AIM format support
+ - accurate lc emulation (what do writes do? etc.)
+ - 840k floppy: support 2nd drive, writing, motor off, the rest of .aim format
+ - memory expansion boards, a2bus_inh_w
+ - hw variant: video status readback ("Moscow")
+ - hw variant: agat9a model (via http://agatcomp.ru/Images/case.shtml)
- mouse via parallel port
- - hw revisions and agat9a model (via http://agatcomp.ru/Images/case.shtml)
+ - does cassette output work?
+ - what do floating bus reads do?
+ - why prodos does not boot?
Slot devices -- 1st party:
- - agat7: apple2 video card (decimal 3.089.121) -- http://agatcomp.ru/Images/new_j121.shtml
- - agat7: serial-parallel card (decimal 3.089.10)6
- - agat9: printer card (decimal 3.089.17)4
+ - agat7: apple2 video card -- decimal 3.089.121 -- http://agatcomp.ru/Images/new_j121.shtml
+ - agat7: Serial-parallel card -- decimal 3.089.106
+ - agat9: Printer card -- decimal 3.089.174
Slot devices -- 3rd party:
- - Nippel Clock (uses mc146818)
- - Nippel mouse -- http://agatcomp.ru/Images/new_mouse.shtml
- - Sprite Card-93 (uses fd1793)
- - others
+ - agat7: Mymrin's color expansion (p. 254-255, port C112)
+ - IEEE-488, etc. via via http://agatcomp.ru/Reading/period/1s1995_35-usn1.shtml
+ - HDC, etc. via http://agatcomp.ru/Hard/losthard.shtml
+ - network cards -- via http://agatcomp.ru/Images/new_net.shtml
+ - sound cards (5-voice synth card, MIDI i/o card) via http://agatcomp.ru/Images/new_sound.shtml
+ - Nippel Clock (mc146818) -- https://archive.org/details/Nippel_Clock_Agat
+ - Nippel Mouse -- http://agatcomp.ru/Images/new_mouse.shtml
+ - Nippel ADC (digital oscilloscope) -- via http://agatcomp.ru/Images/new_IO.shtml
+ - Nippel Co-processor (R65C02 clone + dual-ported RAM) -- via http://agatcomp.ru/Images/new_IO.shtml
+ - Sprite Card-93 (fd1793)
+ - Sprite Programmable I/O (8035 + 8251 + 8253 + 8255) -- via http://agatcomp.ru/Images/new_IO.shtml
+ - Sprite Communication Extension (8251 + 8253 + mc146818) -- via http://agatcomp.ru/Images/new_misc.shtml
+
+ References for Agat-7:
+ - http://agatcomp.ru/Reading/docs_txt.shtml (first set of links) (1987)
+ - http://agatcomp.ru/Reading/docs_shtat.shtml (1989) -- in particular,
+ http://agatcomp.ru/Reading/docs/TO4_5-Hi.djvu
+
+ References for Agat-9:
+ - http://agatcomp.ru/Reading/docs_shtat.shtml#l2
************************************************************************/
#include "emu.h"
#include "video/agat7.h"
+#include "video/agat9.h"
#include "cpu/m6502/m6502.h"
@@ -68,6 +88,8 @@
#include "bus/a2bus/agat7ports.h"
#include "bus/a2bus/agat7ram.h"
#include "bus/a2bus/agat840k_hle.h"
+#include "bus/a2bus/agat_fdc.h"
+#include "cpu/m6502/r65c02.h"
#include "screen.h"
#include "softlist.h"
@@ -80,16 +102,17 @@
#define A7_CASSETTE_TAG "tape"
#define A7_UPPERBANK_TAG "inhbank"
#define A7_VIDEO_TAG "a7video"
+#define A9_VIDEO_TAG "a9video"
+
-class agat7_state : public driver_device
+class agat_base_state : public driver_device
{
public:
- agat7_state(const machine_config &mconfig, device_type type, const char *tag)
+ agat_base_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, A7_CPU_TAG)
, m_ram(*this, RAM_TAG)
, m_ay3600(*this, A7_KBDC_TAG)
- , m_video(*this, A7_VIDEO_TAG)
, m_a2bus(*this, "a2bus")
, m_joy1x(*this, "joystick_1_x")
, m_joy1y(*this, "joystick_1_y")
@@ -103,27 +126,13 @@ public:
, m_upperbank(*this, A7_UPPERBANK_TAG)
{ }
- void agat7(machine_config &config);
-
-private:
- required_device<cpu_device> m_maincpu;
- required_device<ram_device> m_ram;
- required_device<ay3600_device> m_ay3600;
- required_device<agat7video_device> m_video;
- required_device<a2bus_device> m_a2bus;
- required_ioport m_joy1x, m_joy1y, m_joy2x, m_joy2y, m_joybuttons;
- required_ioport m_kbspecial;
- required_ioport m_kbrepeat;
- required_device<speaker_sound_device> m_speaker;
- required_device<cassette_image_device> m_cassette;
- required_device<address_map_bank_device> m_upperbank;
-
- TIMER_DEVICE_CALLBACK_MEMBER(ay3600_repeat);
- TIMER_DEVICE_CALLBACK_MEMBER(timer_irq);
INTERRUPT_GEN_MEMBER(agat_vblank);
+ TIMER_DEVICE_CALLBACK_MEMBER(ay3600_repeat);
- virtual void machine_start() override;
- virtual void machine_reset() override;
+ DECLARE_READ_LINE_MEMBER(ay3600_shift_r);
+ DECLARE_READ_LINE_MEMBER(ay3600_control_r);
+ DECLARE_WRITE_LINE_MEMBER(ay3600_data_ready_w);
+ DECLARE_WRITE_LINE_MEMBER(ay3600_ako_w);
DECLARE_READ8_MEMBER(c080_r);
DECLARE_WRITE8_MEMBER(c080_w);
@@ -136,16 +145,11 @@ private:
DECLARE_WRITE_LINE_MEMBER(a2bus_irq_w);
DECLARE_WRITE_LINE_MEMBER(a2bus_nmi_w);
DECLARE_WRITE_LINE_MEMBER(a2bus_inh_w);
- DECLARE_READ_LINE_MEMBER(ay3600_shift_r);
- DECLARE_READ_LINE_MEMBER(ay3600_control_r);
- DECLARE_WRITE_LINE_MEMBER(ay3600_data_ready_w);
- DECLARE_WRITE_LINE_MEMBER(ay3600_ako_w);
DECLARE_READ8_MEMBER(agat7_membank_r);
DECLARE_WRITE8_MEMBER(agat7_membank_w);
DECLARE_READ8_MEMBER(agat7_ram_r);
DECLARE_WRITE8_MEMBER(agat7_ram_w);
- DECLARE_READ8_MEMBER(keyb_data_r);
DECLARE_READ8_MEMBER(keyb_strobe_r);
DECLARE_WRITE8_MEMBER(keyb_strobe_w);
DECLARE_READ8_MEMBER(cassette_toggle_r);
@@ -160,9 +164,22 @@ private:
DECLARE_READ8_MEMBER(controller_strobe_r);
DECLARE_WRITE8_MEMBER(controller_strobe_w);
- void agat7_map(address_map &map);
- void inhbank_map(address_map &map);
+protected:
+ required_device<cpu_device> m_maincpu;
+ required_device<ram_device> m_ram;
+ required_device<ay3600_device> m_ay3600;
+ required_device<a2bus_device> m_a2bus;
+ required_ioport m_joy1x, m_joy1y, m_joy2x, m_joy2y, m_joybuttons;
+ required_ioport m_kbspecial;
+ required_ioport m_kbrepeat;
+ required_device<speaker_sound_device> m_speaker;
+ required_device<cassette_image_device> m_cassette;
+ required_device<address_map_bank_device> m_upperbank;
+
+ virtual void machine_start() override;
+ virtual void machine_reset() override;
+protected:
int m_speaker_state;
int m_cassette_state;
@@ -178,9 +195,6 @@ private:
int m_inh_slot;
int m_cnxx_slot;
- bool m_page2;
- bool m_an0, m_an1, m_an2, m_an3;
-
uint8_t *m_ram_ptr;
int m_ram_size;
@@ -190,14 +204,77 @@ private:
device_a2bus_card_interface *m_slotdevice[8];
- bool m_agat7_interrupts;
+ bool m_agat_interrupts;
int m_agat7_membank;
int m_agat7_ram_slot;
- void do_io(address_space &space, int offset);
uint8_t read_floatingbus();
};
+class agat7_state : public agat_base_state
+{
+public:
+ agat7_state(const machine_config &mconfig, device_type type, const char *tag)
+ : agat_base_state(mconfig, type, tag)
+ , m_video(*this, A7_VIDEO_TAG)
+ { }
+
+ void agat7(machine_config &config);
+
+ optional_device<agat7video_device> m_video;
+
+ TIMER_DEVICE_CALLBACK_MEMBER(timer_irq);
+ DECLARE_READ8_MEMBER(keyb_data_r);
+
+ void agat7_map(address_map &map);
+ void inhbank_map(address_map &map);
+
+ virtual void machine_start() override;
+ virtual void machine_reset() override;
+
+private:
+};
+
+class agat9_state : public agat_base_state
+{
+public:
+ agat9_state(const machine_config &mconfig, device_type type, const char *tag)
+ : agat_base_state(mconfig, type, tag)
+ , m_video(*this, A9_VIDEO_TAG)
+ { }
+
+ void agat9(machine_config &config);
+
+ optional_device<agat9video_device> m_video;
+
+ TIMER_DEVICE_CALLBACK_MEMBER(timer_irq);
+ DECLARE_READ8_MEMBER(keyb_data_r);
+
+ void agat9_map(address_map &map);
+ void inhbank_map(address_map &map);
+
+ virtual void machine_start() override;
+ virtual void machine_reset() override;
+
+ DECLARE_READ8_MEMBER(c090_r);
+ DECLARE_WRITE8_MEMBER(c090_w);
+ DECLARE_READ8_MEMBER(c200_r);
+ DECLARE_WRITE8_MEMBER(c200_w);
+ DECLARE_WRITE8_MEMBER(apple_w);
+
+ DECLARE_READ8_MEMBER(agat9_membank_r);
+ DECLARE_WRITE8_MEMBER(agat9_membank_w);
+ DECLARE_READ8_MEMBER(agat9_upperbank_r);
+ DECLARE_WRITE8_MEMBER(agat9_upperbank_w);
+
+private:
+ int m_agat9_membank[16]; // 8 physical banks, but ram chip has 16 locations
+ int m_agat9_upperbank;
+ int m_agat9_lcbank;
+ bool m_agat9_prewrite;
+ bool m_apple;
+};
+
/***************************************************************************
PARAMETERS
***************************************************************************/
@@ -206,18 +283,18 @@ private:
#define JOYSTICK_SENSITIVITY 50
#define JOYSTICK_AUTOCENTER 80
-WRITE_LINE_MEMBER(agat7_state::a2bus_irq_w)
+WRITE_LINE_MEMBER(agat_base_state::a2bus_irq_w)
{
m_maincpu->set_input_line(M6502_IRQ_LINE, state);
}
-WRITE_LINE_MEMBER(agat7_state::a2bus_nmi_w)
+WRITE_LINE_MEMBER(agat_base_state::a2bus_nmi_w)
{
m_maincpu->set_input_line(INPUT_LINE_NMI, state);
}
// This code makes a ton of assumptions because we can guarantee a pre-IIe machine!
-WRITE_LINE_MEMBER(agat7_state::a2bus_inh_w)
+WRITE_LINE_MEMBER(agat_base_state::a2bus_inh_w)
{
if (state == ASSERT_LINE)
{
@@ -279,7 +356,7 @@ WRITE_LINE_MEMBER(agat7_state::a2bus_inh_w)
START/RESET
***************************************************************************/
-void agat7_state::machine_start()
+void agat_base_state::machine_start()
{
m_ram_ptr = m_ram->pointer();
m_ram_size = m_ram->size();
@@ -287,7 +364,6 @@ void agat7_state::machine_start()
m_speaker->level_w(m_speaker_state);
m_cassette_state = 0;
m_cassette->output(-1.0f);
- m_upperbank->set_bank(0);
m_inh_bank = 0;
// precalculate joystick time constants
@@ -300,6 +376,10 @@ void agat7_state::machine_start()
m_slotdevice[i] = m_a2bus->get_a2bus_card(i);
}
+ m_inh_slot = -1;
+ m_cnxx_slot = -1;
+ m_agat7_ram_slot = -1;
+
// setup save states
save_item(NAME(m_speaker_state));
save_item(NAME(m_cassette_state));
@@ -313,30 +393,74 @@ void agat7_state::machine_start()
save_item(NAME(m_inh_slot));
save_item(NAME(m_inh_bank));
save_item(NAME(m_cnxx_slot));
- save_item(NAME(m_page2));
- save_item(NAME(m_an0));
- save_item(NAME(m_an1));
- save_item(NAME(m_an2));
- save_item(NAME(m_an3));
save_item(NAME(m_anykeydown));
}
-void agat7_state::machine_reset()
+void agat7_state::machine_start()
{
- m_inh_slot = -1;
- m_cnxx_slot = -1;
- m_page2 = false;
- m_an0 = m_an1 = m_an2 = m_an3 = false;
- m_anykeydown = false;
+ agat_base_state::machine_start();
+
m_upperbank->set_bank(0);
- m_agat7_interrupts = false;
+}
+
+void agat9_state::machine_start()
+{
+ agat_base_state::machine_start();
+ logerror("start apple %d\n", m_apple);
+
+ m_upperbank->set_bank(1);
+ m_agat9_upperbank = 0;
+ m_agat9_lcbank = 0;
+ m_agat9_prewrite = false;
+ // reset only on power on
+ m_apple = false;
+}
+
+
+void agat_base_state::machine_reset()
+{
+ m_anykeydown = false;
+ m_agat_interrupts = false;
+}
+
+void agat7_state::machine_reset()
+{
+ agat_base_state::machine_reset();
+
m_agat7_membank = 0;
- m_agat7_ram_slot = -1;
+ m_upperbank->set_bank(0);
}
-/***************************************************************************
- VIDEO
-***************************************************************************/
+void agat9_state::machine_reset()
+{
+ agat_base_state::machine_reset();
+ logerror("reset apple %d\n", m_apple);
+
+ if (!m_apple)
+ {
+ m_agat9_membank[0] = 0x00;
+ m_agat9_membank[1] = 0x11;
+ m_agat9_membank[2] = 0x22;
+ m_agat9_membank[3] = 0x33;
+ m_agat9_membank[4] = 0x44;
+ m_agat9_membank[5] = 0x55;
+ m_agat9_membank[6] = 0x66;
+ m_agat9_membank[7] = 0x77;
+
+ membank("bank0")->set_base(m_ram_ptr + 0x0000);
+ membank("bank1")->set_base(m_ram_ptr + 0x2000);
+ membank("bank2")->set_base(m_ram_ptr + 0x4000);
+ membank("bank3")->set_base(m_ram_ptr + 0x6000);
+ membank("bank4")->set_base(m_ram_ptr + 0x8000);
+ membank("bank5")->set_base(m_ram_ptr + 0xa000);
+ membank("bank6")->set_base(m_ram_ptr + 0xc000);
+ membank("bank6a")->set_base(m_ram_ptr + 0xc000);
+ membank("bank7")->set_base(m_ram_ptr + 0xe000);
+ membank("bank7a")->set_base(m_ram_ptr + 0xe000);
+
+ m_upperbank->set_bank(1);
+ }
+}
/***************************************************************************
I/O
@@ -347,7 +471,12 @@ READ8_MEMBER(agat7_state::keyb_data_r)
return m_strobe ? (m_transchar | m_strobe) : 0;
}
-READ8_MEMBER(agat7_state::keyb_strobe_r)
+READ8_MEMBER(agat9_state::keyb_data_r)
+{
+ return m_transchar | m_strobe;
+}
+
+READ8_MEMBER(agat_base_state::keyb_strobe_r)
{
// reads any key down, clears strobe
uint8_t rv = m_transchar | (m_anykeydown ? 0x80 : 0x00);
@@ -356,63 +485,63 @@ READ8_MEMBER(agat7_state::keyb_strobe_r)
return rv;
}
-WRITE8_MEMBER(agat7_state::keyb_strobe_w)
+WRITE8_MEMBER(agat_base_state::keyb_strobe_w)
{
// clear keyboard latch
m_strobe = 0;
}
-READ8_MEMBER(agat7_state::cassette_toggle_r)
+READ8_MEMBER(agat_base_state::cassette_toggle_r)
{
if (!machine().side_effects_disabled())
cassette_toggle_w(space, offset, 0);
return read_floatingbus();
}
-WRITE8_MEMBER(agat7_state::cassette_toggle_w)
+WRITE8_MEMBER(agat_base_state::cassette_toggle_w)
{
m_cassette_state ^= 1;
m_cassette->output(m_cassette_state ? 1.0f : -1.0f);
}
-READ8_MEMBER(agat7_state::speaker_toggle_r)
+READ8_MEMBER(agat_base_state::speaker_toggle_r)
{
if (!machine().side_effects_disabled())
speaker_toggle_w(space, offset, 0);
return read_floatingbus();
}
-WRITE8_MEMBER(agat7_state::speaker_toggle_w)
+WRITE8_MEMBER(agat_base_state::speaker_toggle_w)
{
m_speaker_state ^= 1;
m_speaker->level_w(m_speaker_state);
}
-READ8_MEMBER(agat7_state::interrupts_on_r)
+READ8_MEMBER(agat_base_state::interrupts_on_r)
{
if (!machine().side_effects_disabled())
interrupts_on_w(space, offset, 0);
return read_floatingbus();
}
-WRITE8_MEMBER(agat7_state::interrupts_on_w)
+WRITE8_MEMBER(agat_base_state::interrupts_on_w)
{
- m_agat7_interrupts = true;
+ m_agat_interrupts = true;
}
-READ8_MEMBER(agat7_state::interrupts_off_r)
+READ8_MEMBER(agat_base_state::interrupts_off_r)
{
if (!machine().side_effects_disabled())
interrupts_off_w(space, offset, 0);
return read_floatingbus();
}
-WRITE8_MEMBER(agat7_state::interrupts_off_w)
+WRITE8_MEMBER(agat_base_state::interrupts_off_w)
{
- m_agat7_interrupts = false;
+ m_agat_interrupts = false;
}
-READ8_MEMBER(agat7_state::flags_r)
+READ8_MEMBER(agat_base_state::flags_r)
{
switch (offset)
{
@@ -445,14 +574,14 @@ READ8_MEMBER(agat7_state::flags_r)
return 0;
}
-READ8_MEMBER(agat7_state::controller_strobe_r)
+READ8_MEMBER(agat_base_state::controller_strobe_r)
{
if (!machine().side_effects_disabled())
controller_strobe_w(space, offset, 0);
return read_floatingbus();
}
-WRITE8_MEMBER(agat7_state::controller_strobe_w)
+WRITE8_MEMBER(agat_base_state::controller_strobe_w)
{
m_joystick_x1_time = machine().time().as_double() + m_x_calibration * m_joy1x->read();
m_joystick_y1_time = machine().time().as_double() + m_y_calibration * m_joy1y->read();
@@ -460,7 +589,7 @@ WRITE8_MEMBER(agat7_state::controller_strobe_w)
m_joystick_y2_time = machine().time().as_double() + m_y_calibration * m_joy2y->read();
}
-READ8_MEMBER(agat7_state::c080_r)
+READ8_MEMBER(agat_base_state::c080_r)
{
if (!machine().side_effects_disabled())
{
@@ -469,18 +598,19 @@ READ8_MEMBER(agat7_state::c080_r)
offset &= 0x7F;
slot = offset / 0x10;
- logerror("%s: c080_r %04X (slot %d) == %02X\n", machine().describe_context(), offset + 0xc080, slot, 0);
-
if (m_slotdevice[slot] != nullptr)
{
- return m_slotdevice[slot]->read_c0nx(offset % 0x10);
+ u8 data = m_slotdevice[slot]->read_c0nx(offset % 0x10);
+ logerror("%s: c080_r %04X (slot %d) == %02X\n", machine().describe_context(), offset + 0xc080, slot, data);
+ return data;
}
+
}
return read_floatingbus();
}
-WRITE8_MEMBER(agat7_state::c080_w)
+WRITE8_MEMBER(agat_base_state::c080_w)
{
int slot;
@@ -495,21 +625,22 @@ WRITE8_MEMBER(agat7_state::c080_w)
}
}
-READ8_MEMBER(agat7_state::c100_r)
+READ8_MEMBER(agat_base_state::c100_r)
{
int slotnum;
- uint8_t data = 0;
slotnum = ((offset >> 8) & 0xf) + 1;
if (m_slotdevice[slotnum] != nullptr)
{
+// u8 data;
+
if ((m_slotdevice[slotnum]->take_c800()) && (!machine().side_effects_disabled()))
{
m_cnxx_slot = slotnum;
}
- logerror("%s: c100_r %04X (slot %d) == %02X\n", machine().describe_context(), offset+0xc100, slotnum, data);
+// logerror("%s: c100_r %04X (slot %d) == %02X\n", machine().describe_context(), offset+0xc100, slotnum, data);
return m_slotdevice[slotnum]->read_cnxx(offset & 0xff);
}
@@ -517,7 +648,7 @@ READ8_MEMBER(agat7_state::c100_r)
return read_floatingbus();
}
-WRITE8_MEMBER(agat7_state::c100_w)
+WRITE8_MEMBER(agat_base_state::c100_w)
{
int slotnum;
@@ -536,10 +667,28 @@ WRITE8_MEMBER(agat7_state::c100_w)
}
}
-READ8_MEMBER(agat7_state::c800_r)
+READ8_MEMBER(agat9_state::c090_r)
+{
+ return c080_r(space, offset + 0x10);
+}
+
+WRITE8_MEMBER(agat9_state::c090_w)
+{
+ c080_w(space, offset + 0x10, data);
+}
+
+READ8_MEMBER(agat9_state::c200_r)
+{
+ return c100_r(space, offset + 0x0100);
+}
+
+WRITE8_MEMBER(agat9_state::c200_w)
{
-// logerror("%s: c800_r %04X (slot %d) == %02X\n", machine().describe_context(), offset+0xc800, m_cnxx_slot, 0);
+ c100_w(space, offset + 0x0100, data);
+}
+READ8_MEMBER(agat_base_state::c800_r)
+{
if (offset == 0x7ff)
{
if (!machine().side_effects_disabled())
@@ -558,10 +707,8 @@ READ8_MEMBER(agat7_state::c800_r)
return read_floatingbus();
}
-WRITE8_MEMBER(agat7_state::c800_w)
+WRITE8_MEMBER(agat_base_state::c800_w)
{
-// logerror("%s: c800_w %04X <- %02X\n", machine().describe_context(), offset+0xc800, data);
-
if (offset == 0x7ff)
{
if (!machine().side_effects_disabled())
@@ -578,7 +725,15 @@ WRITE8_MEMBER(agat7_state::c800_w)
}
}
-READ8_MEMBER(agat7_state::inh_r)
+WRITE8_MEMBER(agat9_state::apple_w)
+{
+ logerror("%s: c0f0_w %04X <- %02X (apple mode set)\n", machine().describe_context(), offset + 0xc0f0, data);
+
+ m_apple = true;
+ m_upperbank->set_bank(5); // XXX get current bank
+}
+
+READ8_MEMBER(agat_base_state::inh_r)
{
if (m_inh_slot != -1)
{
@@ -589,7 +744,7 @@ READ8_MEMBER(agat7_state::inh_r)
return read_floatingbus();
}
-WRITE8_MEMBER(agat7_state::inh_w)
+WRITE8_MEMBER(agat_base_state::inh_w)
{
if (m_inh_slot != -1)
{
@@ -597,8 +752,7 @@ WRITE8_MEMBER(agat7_state::inh_w)
}
}
-// XXX what does Agat do here?
-uint8_t agat7_state::read_floatingbus()
+uint8_t agat_base_state::read_floatingbus()
{
return 0xff;
}
@@ -609,23 +763,26 @@ uint8_t agat7_state::read_floatingbus()
/* onboard memory banking on Agat-7 */
-READ8_MEMBER(agat7_state::agat7_membank_r)
+READ8_MEMBER(agat_base_state::agat7_membank_r)
{
logerror("%s: c0f0_r %04X == %02X\n", machine().describe_context(), offset + 0xc0f0, 0xff);
- m_agat7_membank = offset;
+ if (!machine().side_effects_disabled())
+ {
+ m_agat7_membank = offset;
+ }
return 0xff;
}
-WRITE8_MEMBER(agat7_state::agat7_membank_w)
+WRITE8_MEMBER(agat_base_state::agat7_membank_w)
{
logerror("%s: c0f0_w %04X <- %02X\n", machine().describe_context(), offset + 0xc0f0, data);
m_agat7_membank = offset;
}
-READ8_MEMBER(agat7_state::agat7_ram_r)
+READ8_MEMBER(agat_base_state::agat7_ram_r)
{
if (offset < 32768)
{
@@ -650,11 +807,8 @@ READ8_MEMBER(agat7_state::agat7_ram_r)
return 0xff;
}
-WRITE8_MEMBER(agat7_state::agat7_ram_w)
+WRITE8_MEMBER(agat_base_state::agat7_ram_w)
{
-// if (offset > 0x7fff)
-// logerror("%s: ram %04X (bank %d slot %d) <- %02X\n", machine().describe_context(), offset, m_agat7_membank, m_agat7_ram_slot, data);
-
if (offset < 32768)
{
if (offset < m_ram_size)
@@ -677,7 +831,169 @@ WRITE8_MEMBER(agat7_state::agat7_ram_w)
}
/*
- * onboard RAM is at least 32K, up to 128K.
+ * onboard memory banking on Agat-9
+ *
+ * native mode: writes do the bankswitch, reads return current mapping mode
+ * apple2 mode: writes ignored ??, reads do language card emulation
+ * and return current mapping mode
+ */
+
+READ8_MEMBER(agat9_state::agat9_upperbank_r)
+{
+ if (machine().side_effects_disabled())
+ {
+ return read_floatingbus();
+ }
+
+ if (!m_apple)
+ {
+ logerror("%s: c080_r %04X == %02X\n", machine().describe_context(), 0xc080 + offset, m_agat9_upperbank);
+
+ return m_agat9_upperbank;
+ }
+
+ int rc;
+
+#if 0
+ if (BIT(offset, 2)) // select physical memory banks for LC emulation
+ {
+ int newbank = bitswap<8>(offset,7,6,5,4,3,1,0,2) & 14;
+ rc = newbank == m_agat9_lcbank ? (0xc0 + m_agat9_upperbank) : 0xc0;
+ m_agat9_lcbank = newbank;
+
+ membank("bank6")->set_base(m_ram_ptr + (newbank * 8192) + (BIT(m_agat9_upperbank, 3) * 4096));
+ membank("bank7")->set_base(m_ram_ptr + (newbank + 1) * 8192);
+
+ logerror("%s: c080_r %04X == %02X: select new map %d (mode %d d000 %s)\n", machine().describe_context(), offset + 0xc080,
+ newbank, 0xc0 + m_agat9_upperbank, m_agat9_upperbank & 8 ? "upper" : "lower");
+ }
+ else // select mapping modes
+#endif
+ {
+ m_agat9_upperbank = BIT(offset, 0) ? offset : (offset ^ 2);
+ rc = 0xc0 + m_agat9_upperbank;
+
+ // taken from ramcard16k.cpp
+ if (BIT(offset, 0))
+ {
+ if (m_agat9_prewrite == false)
+ {
+ m_agat9_prewrite = true;
+ m_upperbank->set_bank(4 + ((offset + 1) & 3)); // writes disabled
+ }
+ else
+ {
+ m_upperbank->set_bank(4 + (offset & 3));
+ }
+ }
+ else
+ {
+ m_agat9_prewrite = false;
+ m_upperbank->set_bank(4 + (offset & 3));
+ }
+
+ membank("bank6a")->set_base(m_ram_ptr + (m_agat9_membank[14] & 15) * 8192 + BIT(m_agat9_upperbank, 3) * 4096);
+
+ logerror("%s: c080_r %04X == %02X: select new mode %d (map %d d000 %s)\n", machine().describe_context(), offset + 0xc080,
+ rc, offset & 3, m_agat9_lcbank, m_agat9_upperbank & 8 ? "upper" : "lower");
+ }
+
+ return rc;
+}
+
+WRITE8_MEMBER(agat9_state::agat9_upperbank_w)
+{
+ logerror("%s: c080_w %04X <- %02X: select new mode %d (d000 %s)\n", machine().describe_context(), offset + 0xc080, data,
+ offset & 3, offset & 8 ? "upper" : "lower");
+
+ if (m_apple)
+ {
+ m_agat9_prewrite = false;
+ }
+ else
+ {
+ m_upperbank->set_bank(offset & 3);
+ m_agat9_upperbank = (offset & 3) ? (offset & 0xb) : (2 | (offset & 0xb));
+ m_agat9_upperbank |= 0x80; // ikp2-19176.aim passes
+
+ membank("bank6")->set_base(m_ram_ptr + (m_agat9_membank[6] & 15) * 8192 + BIT(m_agat9_upperbank, 3) * 4096);
+ }
+}
+
+READ8_MEMBER(agat9_state::agat9_membank_r)
+{
+ u8 data = 0;
+
+ data = m_agat9_membank[(offset >> 4)];
+
+ logerror("%s: c100_r %04X == %02X\n", machine().describe_context(), offset + 0xc100, data);
+
+ return data;
+}
+
+WRITE8_MEMBER(agat9_state::agat9_membank_w)
+{
+ logerror("%s: c100_w %04X <- %02X: bank %d va %04X = page %02d pa %05X (apple %d)\n", machine().describe_context(), offset + 0xc100, data,
+ (offset >> 4), 0x2000 * (offset >> 4), (offset & 15), (offset & 15) * 8192, m_apple);
+
+ m_agat9_membank[(offset >> 4)] = offset;
+
+ if (m_apple)
+ return;
+
+ int newbank = (offset & 15) * 8192;
+
+ switch (offset >> 4)
+ {
+ case 0:
+ membank("bank0")->set_base(m_ram_ptr + newbank);
+ break;
+
+ case 1:
+ membank("bank1")->set_base(m_ram_ptr + newbank);
+ break;
+
+ case 2:
+ membank("bank2")->set_base(m_ram_ptr + newbank);
+ break;
+
+ case 3:
+ membank("bank3")->set_base(m_ram_ptr + newbank);
+ break;
+
+ case 4:
+ membank("bank4")->set_base(m_ram_ptr + newbank);
+ break;
+
+ case 5:
+ membank("bank5")->set_base(m_ram_ptr + newbank);
+ break;
+
+ case 6:
+ membank("bank6")->set_base(m_ram_ptr + newbank + (BIT(m_agat9_upperbank, 3) * 4096));
+ break;
+
+ case 7:
+ membank("bank7")->set_base(m_ram_ptr + newbank);
+ break;
+
+ case 14:
+ membank("bank6a")->set_base(m_ram_ptr + newbank + (BIT(m_agat9_upperbank, 3) * 4096));
+ break;
+
+ case 15:
+ membank("bank7a")->set_base(m_ram_ptr + newbank);
+ break;
+
+ default:
+ logerror("membank %d UNIMP\n", (offset >> 4));
+ break;
+ }
+}
+
+
+/*
+ * agat7: onboard RAM is at least 32K, up to 128K.
* first 32K of onboard RAM are always mapped at 0.
* standard add-on RAM cards hold 32K (possibly up to 128K?)
* and are supported only on motherboards with 32K onboard.
@@ -698,7 +1014,7 @@ void agat7_state::agat7_map(address_map &map)
map(0xc080, 0xc0ef).rw(FUNC(agat7_state::c080_r), FUNC(agat7_state::c080_w));
map(0xc0f0, 0xc0ff).rw(FUNC(agat7_state::agat7_membank_r), FUNC(agat7_state::agat7_membank_w));
map(0xc100, 0xc6ff).rw(FUNC(agat7_state::c100_r), FUNC(agat7_state::c100_w));
- map(0xc700, 0xc7ff).rw("a7video", FUNC(agat7video_device::read), FUNC(agat7video_device::write));
+ map(0xc700, 0xc7ff).rw(A7_VIDEO_TAG, FUNC(agat7video_device::read), FUNC(agat7video_device::write));
map(0xc800, 0xcfff).rw(FUNC(agat7_state::c800_r), FUNC(agat7_state::c800_w));
map(0xd000, 0xffff).m(m_upperbank, FUNC(address_map_bank_device::amap8));
}
@@ -709,11 +1025,83 @@ void agat7_state::inhbank_map(address_map &map)
map(0x3000, 0x5fff).rw(FUNC(agat7_state::inh_r), FUNC(agat7_state::inh_w));
}
+/*
+ * agat9: onboard RAM is always 128K. language card emulation is built in.
+ * standard add-on RAM cards hold 128K, up to 4 cards are supported.
+ * both onboard and add-on RAM is split into 16K banks.
+ */
+void agat9_state::agat9_map(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x0000, 0x1fff).bankrw("bank0");
+ map(0x2000, 0x3fff).bankrw("bank1");
+ map(0x4000, 0x5fff).bankrw("bank2");
+ map(0x6000, 0x7fff).bankrw("bank3");
+ map(0x8000, 0x9fff).bankrw("bank4");
+ map(0xa000, 0xbfff).bankrw("bank5");
+ map(0xc000, 0xc000).mirror(0xf).r(FUNC(agat9_state::keyb_data_r)).nopw();
+ map(0xc010, 0xc010).mirror(0xf).rw(FUNC(agat9_state::keyb_strobe_r), FUNC(agat9_state::keyb_strobe_w));
+ map(0xc020, 0xc020).mirror(0xf).rw(FUNC(agat9_state::interrupts_off_r), FUNC(agat9_state::interrupts_off_w));
+ map(0xc030, 0xc030).mirror(0xf).rw(FUNC(agat9_state::speaker_toggle_r), FUNC(agat9_state::speaker_toggle_w));
+ map(0xc040, 0xc040).mirror(0xf).rw(FUNC(agat9_state::interrupts_on_r), FUNC(agat9_state::interrupts_on_w));
+ map(0xc050, 0xc05f).rw(A9_VIDEO_TAG, FUNC(agat9video_device::apple_read), FUNC(agat9video_device::apple_write));
+ map(0xc060, 0xc067).mirror(0x8).r(FUNC(agat9_state::flags_r)).nopw();
+ map(0xc070, 0xc070).mirror(0xf).rw(FUNC(agat9_state::controller_strobe_r), FUNC(agat9_state::controller_strobe_w));
+ map(0xc080, 0xc08f).rw(FUNC(agat9_state::agat9_upperbank_r), FUNC(agat9_state::agat9_upperbank_w));
+ map(0xc090, 0xc0ef).rw(FUNC(agat9_state::c090_r), FUNC(agat9_state::c090_w));
+ map(0xc0f0, 0xc0ff).w(FUNC(agat9_state::apple_w));
+ map(0xc100, 0xc1ff).rw(FUNC(agat9_state::agat9_membank_r), FUNC(agat9_state::agat9_membank_w));
+ map(0xc200, 0xc6ff).rw(FUNC(agat9_state::c200_r), FUNC(agat9_state::c200_w));
+ map(0xc700, 0xc7ff).rw(A9_VIDEO_TAG, FUNC(agat9video_device::read), FUNC(agat9video_device::write));
+ map(0xc800, 0xcfff).rw(FUNC(agat9_state::c800_r), FUNC(agat9_state::c800_w));
+ map(0xd000, 0xffff).m(m_upperbank, FUNC(address_map_bank_device::amap8));
+}
+
+void agat9_state::inhbank_map(address_map &map)
+{
+ // native mode
+
+ // map 0 -- C080/C088
+ map(0x00000, 0x00fff).bankr("bank6").nopw();
+ map(0x01000, 0x02fff).bankr("bank7").nopw();
+
+ // map 1 -- C081/C089
+ map(0x10000, 0x10fff).rom().region("maincpu", 0x1000).bankw("bank6");
+ map(0x11000, 0x12fff).rom().region("maincpu", 0x2000).bankw("bank7");
+
+ // map 2 -- C082/C08A -- only in apple mode (same as map 0 in agat mode)
+ map(0x20000, 0x20fff).bankr("bank6").nopw();
+ map(0x21000, 0x22fff).bankr("bank7").nopw();
+
+ // map 3 -- C083/C08B
+ map(0x30000, 0x30fff).bankrw("bank6");
+ map(0x31000, 0x32fff).bankrw("bank7");
+
+ // apple mode -- ROM is simulated by onboard RAM (logical banks 14 and 15)
+ // language card emulation can use onboard or add-on card memory
+
+ // map 0 -- C080/C088 -- rc C2/CA -- bank_r mapped to LC area
+ map(0x40000, 0x40fff).bankr("bank6a").nopw();
+ map(0x41000, 0x42fff).bankr("bank7a").nopw();
+
+ // map 1 -- C081/C089 -- rc C1/C9 -- bank_r mapped to apple ROM area, bank_w to LC area
+ map(0x50000, 0x50fff).bankr("bank6").bankw("bank6a");
+ map(0x51000, 0x52fff).bankr("bank7").bankw("bank7a");
+
+ // map 2 -- C082/C08A -- rc C0/C8 -- bank_r mapped to apple ROM area
+ map(0x60000, 0x60fff).bankr("bank6").nopw();
+ map(0x61000, 0x62fff).bankr("bank7").nopw();
+
+ // map 3 -- C083/C08B -- rc C3/CB -- banks mapped to LC area
+ map(0x70000, 0x70fff).bankrw("bank6a");
+ map(0x71000, 0x72fff).bankrw("bank7a");
+}
+
/***************************************************************************
KEYBOARD
***************************************************************************/
-READ_LINE_MEMBER(agat7_state::ay3600_shift_r)
+READ_LINE_MEMBER(agat_base_state::ay3600_shift_r)
{
// either shift key
if (m_kbspecial->read() & 0x06)
@@ -724,7 +1112,7 @@ READ_LINE_MEMBER(agat7_state::ay3600_shift_r)
return CLEAR_LINE;
}
-READ_LINE_MEMBER(agat7_state::ay3600_control_r)
+READ_LINE_MEMBER(agat_base_state::ay3600_control_r)
{
if (m_kbspecial->read() & 0x08)
{
@@ -803,7 +1191,7 @@ static const uint8_t a2_key_remap[0x40][4] =
{ 0x06,0x06,0x06,0x06 }, /* PF3 */
};
-WRITE_LINE_MEMBER(agat7_state::ay3600_data_ready_w)
+WRITE_LINE_MEMBER(agat_base_state::ay3600_data_ready_w)
{
if (state == ASSERT_LINE)
{
@@ -822,12 +1210,12 @@ WRITE_LINE_MEMBER(agat7_state::ay3600_data_ready_w)
}
}
-WRITE_LINE_MEMBER(agat7_state::ay3600_ako_w)
+WRITE_LINE_MEMBER(agat_base_state::ay3600_ako_w)
{
m_anykeydown = (state == ASSERT_LINE) ? true : false;
}
-TIMER_DEVICE_CALLBACK_MEMBER(agat7_state::ay3600_repeat)
+TIMER_DEVICE_CALLBACK_MEMBER(agat_base_state::ay3600_repeat)
{
// is the key still down?
if (m_anykeydown)
@@ -839,9 +1227,9 @@ TIMER_DEVICE_CALLBACK_MEMBER(agat7_state::ay3600_repeat)
}
}
-INTERRUPT_GEN_MEMBER(agat7_state::agat_vblank)
+INTERRUPT_GEN_MEMBER(agat_base_state::agat_vblank)
{
- if (m_agat7_interrupts)
+ if (m_agat_interrupts)
{
m_maincpu->pulse_input_line(M6502_NMI_LINE, attotime::zero);
}
@@ -849,7 +1237,7 @@ INTERRUPT_GEN_MEMBER(agat7_state::agat_vblank)
TIMER_DEVICE_CALLBACK_MEMBER(agat7_state::timer_irq)
{
- if (m_agat7_interrupts)
+ if (m_agat_interrupts)
{
switch (param & 0x3f)
{
@@ -864,6 +1252,23 @@ TIMER_DEVICE_CALLBACK_MEMBER(agat7_state::timer_irq)
}
}
+TIMER_DEVICE_CALLBACK_MEMBER(agat9_state::timer_irq)
+{
+ if (m_agat_interrupts)
+ {
+ switch (param & 0xf)
+ {
+ case 0:
+ m_maincpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE);
+ break;
+
+ case 8:
+ m_maincpu->set_input_line(M6502_IRQ_LINE, ASSERT_LINE);
+ break;
+ }
+ }
+}
+
/***************************************************************************
INPUT PORTS
***************************************************************************/
@@ -1058,29 +1463,28 @@ INPUT_PORTS_END
static void agat7_cards(device_slot_interface &device)
{
- // Standard cards
-
device.option_add("a7lang", A2BUS_AGAT7LANGCARD); // Agat-7 RAM Language Card -- decimal 3.089.119
device.option_add("a7ram", A2BUS_AGAT7RAM); // Agat-7 32K RAM Card -- decimal 3.089.119-01, KR565RU6D chips
device.option_add("a7fdc", A2BUS_AGAT7_FDC); // Disk II clone -- decimal 3.089.105
- device.option_add("a7fdc840", A2BUS_AGAT840K_HLE); // 840K floppy controller -- decimal 7.104.351 or 3.089.023?
+ device.option_add("a9fdchle", A2BUS_AGAT840K_HLE); // 840K floppy controller -- decimal 7.104.351 or 3.089.023?
+ device.option_add("a9fdc", A2BUS_AGAT_FDC); // 840K floppy controller LLE
device.option_add("a7ports", A2BUS_AGAT7_PORTS); // Serial-parallel card -- decimal 3.089.106
- // Printer card (agat9) -- decimal 3.089.174
-
- // 3rd party cards
+}
- // Programmable i/o (8035 + 8251 + 8253 + 8255)
- // Card-93 floppy controller (KR1818VG93-based)
- // Nippel ADC (digital oscilloscope)
- // Nippel Clock (mc146818)
- // Nippel Co-processor (R65C02 clone + dual-ported RAM)
+static void agat9_cards(device_slot_interface &device)
+{
+// device.option_add("a9ram", A2BUS_AGAT9RAM); // Agat-9 128K RAM Card -- decimal 3.089.170
+ device.option_add("diskii", A2BUS_DISKII); /* Disk II Controller Card */
+ device.option_add("a9fdc140", A2BUS_AGAT9_FDC); // Disk II clone -- decimal 3.089.173 (reworked for agat9)
+ device.option_add("a9fdchle", A2BUS_AGAT840K_HLE); // 840K floppy controller -- decimal 7.104.351 or 3.089.023?
+ device.option_add("a9fdc", A2BUS_AGAT_FDC); // 840K floppy controller LLE
}
void agat7_state::agat7(machine_config &config)
{
M6502(config, m_maincpu, XTAL(14'300'000) / 14);
m_maincpu->set_addrmap(AS_PROGRAM, &agat7_state::agat7_map);
- m_maincpu->set_vblank_int(A7_VIDEO_TAG ":a7screen", FUNC(agat7_state::agat_vblank));
+ m_maincpu->set_vblank_int(A7_VIDEO_TAG ":a7screen", FUNC(agat_base_state::agat_vblank));
TIMER(config, "scantimer").configure_scanline(FUNC(agat7_state::timer_irq), A7_VIDEO_TAG ":a7screen", 0, 1);
@@ -1107,23 +1511,24 @@ void agat7_state::agat7(machine_config &config)
m_ay3600->x6().set_ioport("X6");
m_ay3600->x7().set_ioport("X7");
m_ay3600->x8().set_ioport("X8");
- m_ay3600->shift().set(FUNC(agat7_state::ay3600_shift_r));
- m_ay3600->control().set(FUNC(agat7_state::ay3600_control_r));
- m_ay3600->data_ready().set(FUNC(agat7_state::ay3600_data_ready_w));
- m_ay3600->ako().set(FUNC(agat7_state::ay3600_ako_w));
+ m_ay3600->shift().set(FUNC(agat_base_state::ay3600_shift_r));
+ m_ay3600->control().set(FUNC(agat_base_state::ay3600_control_r));
+ m_ay3600->data_ready().set(FUNC(agat_base_state::ay3600_data_ready_w));
+ m_ay3600->ako().set(FUNC(agat_base_state::ay3600_ako_w));
/* repeat timer. 10 Hz per Mymrin's book */
- TIMER(config, "repttmr").configure_periodic(FUNC(agat7_state::ay3600_repeat), attotime::from_hz(10));
+ TIMER(config, "repttmr").configure_periodic(FUNC(agat_base_state::ay3600_repeat), attotime::from_hz(10));
/*
* slot 0 is reserved for SECAM encoder or Apple II compat card.
* slot 1 always holds the CPU card.
+ * most of the software expects a7lang in slot 2 and a7ram in slot 6.
*/
A2BUS(config, m_a2bus, 0);
m_a2bus->set_space(m_maincpu, AS_PROGRAM);
- m_a2bus->irq_w().set(FUNC(agat7_state::a2bus_irq_w));
- m_a2bus->nmi_w().set(FUNC(agat7_state::a2bus_nmi_w));
- m_a2bus->inh_w().set(FUNC(agat7_state::a2bus_inh_w));
+ m_a2bus->irq_w().set(FUNC(agat_base_state::a2bus_irq_w));
+ m_a2bus->nmi_w().set(FUNC(agat_base_state::a2bus_nmi_w));
+ m_a2bus->inh_w().set(FUNC(agat_base_state::a2bus_inh_w));
m_a2bus->dma_w().set_inputline(m_maincpu, INPUT_LINE_HALT);
A2BUS_SLOT(config, "sl2", m_a2bus, agat7_cards, "a7lang");
A2BUS_SLOT(config, "sl3", m_a2bus, agat7_cards, "a7fdc");
@@ -1135,6 +1540,62 @@ void agat7_state::agat7(machine_config &config)
m_cassette->set_default_state(CASSETTE_STOPPED | CASSETTE_SPEAKER_ENABLED | CASSETTE_MOTOR_ENABLED);
}
+void agat9_state::agat9(machine_config &config)
+{
+ R65C02(config, m_maincpu, XTAL(14'300'000) / 14);
+ m_maincpu->set_addrmap(AS_PROGRAM, &agat9_state::agat9_map);
+ m_maincpu->set_vblank_int(A9_VIDEO_TAG ":a9screen", FUNC(agat_base_state::agat_vblank));
+
+ TIMER(config, "scantimer").configure_scanline(FUNC(agat9_state::timer_irq), A9_VIDEO_TAG ":a9screen", 0, 1);
+
+ AGAT9VIDEO(config, m_video, RAM_TAG, "gfx1");
+
+ RAM(config, m_ram).set_default_size("128K").set_default_value(0);
+
+ /* sound hardware */
+ SPEAKER(config, "mono").front_center();
+ SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 1.00);
+
+ /* /INH banking */
+ ADDRESS_MAP_BANK(config, m_upperbank).set_map(&agat9_state::inhbank_map).set_options(ENDIANNESS_LITTLE, 8, 32, 0x10000);
+
+ /* keyboard controller -- XXX must be replaced */
+ AY3600(config, m_ay3600, 0);
+ m_ay3600->x0().set_ioport("X0");
+ m_ay3600->x1().set_ioport("X1");
+ m_ay3600->x2().set_ioport("X2");
+ m_ay3600->x3().set_ioport("X3");
+ m_ay3600->x4().set_ioport("X4");
+ m_ay3600->x5().set_ioport("X5");
+ m_ay3600->x6().set_ioport("X6");
+ m_ay3600->x7().set_ioport("X7");
+ m_ay3600->x8().set_ioport("X8");
+ m_ay3600->shift().set(FUNC(agat_base_state::ay3600_shift_r));
+ m_ay3600->control().set(FUNC(agat_base_state::ay3600_control_r));
+ m_ay3600->data_ready().set(FUNC(agat_base_state::ay3600_data_ready_w));
+ m_ay3600->ako().set(FUNC(agat_base_state::ay3600_ako_w));
+
+ /* repeat timer. 10 Hz per Mymrin's book */
+ TIMER(config, "repttmr").configure_periodic(FUNC(agat_base_state::ay3600_repeat), attotime::from_hz(10));
+
+ A2BUS(config, m_a2bus, 0);
+ m_a2bus->set_space(m_maincpu, AS_PROGRAM);
+ m_a2bus->irq_w().set(FUNC(agat_base_state::a2bus_irq_w));
+ m_a2bus->nmi_w().set(FUNC(agat_base_state::a2bus_nmi_w));
+ m_a2bus->inh_w().set(FUNC(agat_base_state::a2bus_inh_w));
+ m_a2bus->dma_w().set_inputline(m_maincpu, INPUT_LINE_HALT);
+ // slot 0 does not exist
+ A2BUS_SLOT(config, "sl1", m_a2bus, agat9_cards, nullptr);
+ A2BUS_SLOT(config, "sl2", m_a2bus, agat9_cards, nullptr); // a9ram
+ A2BUS_SLOT(config, "sl3", m_a2bus, agat9_cards, nullptr); // printer->mouse
+ A2BUS_SLOT(config, "sl4", m_a2bus, agat9_cards, nullptr); // printer
+ A2BUS_SLOT(config, "sl5", m_a2bus, agat9_cards, "a9fdc");
+ A2BUS_SLOT(config, "sl6", m_a2bus, agat9_cards, "a9fdc140");
+
+ CASSETTE(config,m_cassette);
+ m_cassette->set_default_state(CASSETTE_STOPPED);
+}
+
/***************************************************************************
@@ -1164,20 +1625,26 @@ ROM_END
ROM_START( agat9 )
ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF )
+
ROM_SYSTEM_BIOS( 0, "v1", "Version 1" )
+ ROMX_LOAD("monitor9.rom", 0x3000, 0x0800, CRC(b90bb66a) SHA1(02217f0785913b41fc25eabcff70fa814799c69a), ROM_BIOS(0))
ROMX_LOAD("monitor9.rom", 0x3800, 0x0800, CRC(b90bb66a) SHA1(02217f0785913b41fc25eabcff70fa814799c69a), ROM_BIOS(0))
ROM_SYSTEM_BIOS( 1, "v2", "Version 2" )
+ ROMX_LOAD("monitor91.rom", 0x3000, 0x0800, CRC(89b10fc1) SHA1(7fe1ede32b5525255f82597ca9c3c2034c5996fa), ROM_BIOS(1))
ROMX_LOAD("monitor91.rom", 0x3800, 0x0800, CRC(89b10fc1) SHA1(7fe1ede32b5525255f82597ca9c3c2034c5996fa), ROM_BIOS(1))
+
// Floppy controllers
ROM_LOAD( "shugart9.rom", 0x4500, 0x0100, CRC(964a0ce2) SHA1(bf955189ebffe874c20ef649a3db8177dc16af61))
ROM_LOAD( "teac.rom", 0x4500, 0x0100, CRC(94266928) SHA1(5d369bad6cdd6a70b0bb16480eba69640de87a2e))
+
// Printer card
ROM_LOAD( "cm6337.rom", 0x8000, 0x0100, CRC(73be16ec) SHA1(ead1abbef5b86f1def0b956147d5b267f0d544b5))
ROM_LOAD( "cm6337p.rom", 0x8100, 0x0800, CRC(9120f11f) SHA1(78107653491e88d5ea12e07367c4c028771a4aca))
+
ROM_REGION(0x0800,"gfx1",0)
ROM_LOAD( "agathe9.fnt", 0x0000, 0x0800, CRC(8c55c984) SHA1(5a5a202000576b88b4ae2e180dd2d1b9b337b594))
ROM_END
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
COMP( 1983, agat7, apple2, 0, agat7, agat7, agat7_state, empty_init, "Agat", "Agat-7", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_CONTROLS)
-COMP( 1984, agat9, apple2, 0, agat7, agat7, agat7_state, empty_init, "Agat", "Agat-9", MACHINE_NOT_WORKING)
+COMP( 1988, agat9, apple2, 0, agat9, agat7, agat9_state, empty_init, "Agat", "Agat-9", MACHINE_NOT_WORKING)
diff --git a/src/mame/video/agat7.cpp b/src/mame/video/agat7.cpp
index bfce6c81b96..657e98644e9 100644
--- a/src/mame/video/agat7.cpp
+++ b/src/mame/video/agat7.cpp
@@ -94,7 +94,9 @@ void agat7video_device::device_reset()
READ8_MEMBER(agat7video_device::read)
{
- do_io(offset);
+ if(!machine().side_effects_disabled())
+ do_io(offset);
+
return 0;
}
@@ -110,7 +112,7 @@ void agat7video_device::do_io(int offset)
{
case 0:
m_video_mode = GRAPHICS_LORES;
- m_start_address = (offset) << 9;
+ m_start_address = (offset & 0x30) << 9;
logerror("offset %04X, video mode 0 (GRAPHICS_LORES)\n", m_start_address);
break;
@@ -134,7 +136,7 @@ void agat7video_device::do_io(int offset)
case 3:
m_video_mode = GRAPHICS_MONO;
- m_start_address = ((offset & 0x3f) - 0x03) << 9;
+ m_start_address = ((offset - 0x03) & 0x30) << 9;
logerror("offset %04X, video mode 3 (GRAPHICS_MONO)\n", m_start_address);
break;
}
@@ -184,14 +186,12 @@ void agat7video_device::text_update_lores(screen_device &screen, bitmap_ind16 &b
address = m_start_address + (col * 2) + (row * 8);
ch = m_ram_dev->read(address);
attr = m_ram_dev->read(address + 1);
+ fg = bitswap<8>(attr,7,6,5,3,4,2,1,0) & 15;
if (BIT(attr, 5)) {
- fg = bitswap<8>(attr,7,6,5,3,4,2,1,0) & 15;
- bg = 0;
+ plot_text_character(bitmap, col * 16, row, 2, ch, m_char_ptr, m_char_size, fg, bg);
} else {
- fg = 0;
- bg = bitswap<8>(attr,7,6,5,3,4,2,1,0) & 15;
+ plot_text_character(bitmap, col * 16, row, 2, ch, m_char_ptr, m_char_size, bg, fg);
}
- plot_text_character(bitmap, col * 16, row, 2, ch, m_char_ptr, m_char_size, fg, bg);
}
}
}
@@ -352,25 +352,3 @@ uint32_t agat7video_device::screen_update(screen_device &screen, bitmap_ind16 &b
return 0;
}
-
-#if 0
-static const rgb_t agat7_palette[] =
-{
- rgb_t::black(),
- rgb_t(0xFF, 0x00, 0x00), /* White */
- rgb_t(0x00, 0xFF, 0x00), /* White */
- rgb_t(0xFF, 0xFF, 0x00), /* White */
- rgb_t(0x00, 0x00, 0xFF), /* White */
- rgb_t(0xFF, 0x00, 0xFF), /* White */
- rgb_t(0xFF, 0xFF, 0x00), /* White */
- rgb_t(0xFF, 0xFF, 0xFF), /* White */
- rgb_t::black(),
- rgb_t(0x7F, 0x00, 0x00), /* White */
- rgb_t(0x00, 0x7F, 0x00), /* White */
- rgb_t(0x7F, 0x7F, 0x00), /* White */
- rgb_t(0x00, 0x00, 0x7F), /* White */
- rgb_t(0x7F, 0x00, 0x7F), /* White */
- rgb_t(0x7F, 0x7F, 0x00), /* White */
- rgb_t(0x7F, 0x7F, 0x7F) /* White */
-};
-#endif
diff --git a/src/mame/video/agat9.cpp b/src/mame/video/agat9.cpp
new file mode 100644
index 00000000000..0584907e8db
--- /dev/null
+++ b/src/mame/video/agat9.cpp
@@ -0,0 +1,715 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/*********************************************************************
+
+ agat9video.cpp
+
+ Implementation of Agat-9 onboard video.
+
+ 6 native video modes:
+ - 32x32 color text
+ - 64x32 mono text with reverse video
+ - 128x128 16 color graphics
+ - 256x256 4 color graphics
+ - 256x256 and 512x256 mono graphics
+
+ 2 apple video modes: 40col text and HGR.
+
+ C7xx: video mode select
+
+*********************************************************************/
+
+#include "emu.h"
+#include "video/agat9.h"
+
+#include "screen.h"
+
+
+#define BLACK 0
+#define RED 1
+#define GREEN 2
+#define YELLOW 3
+#define BLUE 4
+#define PURPLE 5
+#define CYAN 6
+#define WHITE 7
+
+
+/***************************************************************************
+ PARAMETERS
+***************************************************************************/
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(AGAT9VIDEO, agat9video_device, "agat9video", "Agat-9 Video")
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void agat9video_device::device_add_mconfig(machine_config &config)
+{
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_raw(XTAL(10'500'000), 672, 0, 512, 312, 0, 256);
+ m_screen->set_screen_update(FUNC(agat9video_device::screen_update));
+ m_screen->set_palette(DEVICE_SELF);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+agat9video_device::agat9video_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, AGAT9VIDEO, tag, owner, clock),
+ device_palette_interface(mconfig, *this),
+ m_screen(*this, "a9screen"),
+ m_ram_dev(*this, finder_base::DUMMY_TAG),
+ m_char_region(*this, finder_base::DUMMY_TAG),
+ m_char_ptr(nullptr),
+ m_char_size(0),
+ m_start_address(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void agat9video_device::device_start()
+{
+ int i, j;
+ uint16_t c;
+
+ static const uint8_t hires_artifact_color_table[] =
+ {
+ BLACK, PURPLE, GREEN, WHITE,
+ BLACK, BLUE, RED, WHITE
+ };
+
+ m_char_ptr = m_char_region->base();
+ m_char_size = m_char_region->bytes();
+
+ /* 2^3 dependent pixels * 2 color sets * 2 offsets */
+ m_hires_artifact_map = std::make_unique<uint16_t[]>(8 * 2 * 2);
+
+ /* build hires artifact map */
+ for (i = 0; i < 8; i++)
+ {
+ for (j = 0; j < 2; j++)
+ {
+ if (i & 0x02)
+ {
+ if ((i & 0x05) != 0)
+ c = 3;
+ else
+ c = j ? 2 : 1;
+ }
+ else
+ {
+ c = 0;
+ }
+ m_hires_artifact_map[0 + j * 8 + i] = hires_artifact_color_table[(c + 0) % 8];
+ m_hires_artifact_map[16 + j * 8 + i] = hires_artifact_color_table[(c + 4) % 8];
+ }
+ }
+
+ // per http://agatcomp.ru/Reading/IiO/87-2-077.djvu
+ for (int i = 0; 8 > i; ++i)
+ {
+ set_pen_color(i + 0, rgb_t(BIT(i, 0) ? 0xff : 0, BIT(i, 1) ? 0xff : 0, BIT(i, 2) ? 0xff : 0));
+ set_pen_color(i + 8, rgb_t(BIT(i, 0) ? 0x7f : 0, BIT(i, 1) ? 0x7f : 0, BIT(i, 2) ? 0x7f : 0));
+ }
+
+ save_item(NAME(m_start_address));
+
+ save_item(NAME(m_page2));
+ save_item(NAME(m_flash));
+ save_item(NAME(m_mix));
+ save_item(NAME(m_graphics));
+}
+
+void agat9video_device::device_reset()
+{
+ // XXX to be confirmed
+ m_video_mode = TEXT_LORES;
+ m_start_address = 0x7800;
+ m_mode = palette_index = 0;
+
+ // apple
+ m_page2 = false;
+ m_flash = false;
+ m_mix = false;
+ m_graphics = false;
+}
+
+
+READ8_MEMBER(agat9video_device::read)
+{
+ if(!machine().side_effects_disabled())
+ do_io(offset);
+ // XXX only 'Moscow' revision
+ return m_mode;
+}
+
+WRITE8_MEMBER(agat9video_device::write)
+{
+ do_io(offset);
+}
+
+READ8_MEMBER(agat9video_device::apple_read)
+{
+ logerror("%s: %04x read (%s)\n", machine().describe_context(), 0xc050 + offset, offset<8?"apple":"palette");
+
+ if(!machine().side_effects_disabled())
+ do_apple_io(offset);
+ // XXX
+ return m_mode;
+}
+
+WRITE8_MEMBER(agat9video_device::apple_write)
+{
+ logerror("%s: %04x write (%s)\n", machine().describe_context(), 0xc050 + offset, offset<8?"apple":"palette");
+
+ do_apple_io(offset);
+}
+
+void agat9video_device::do_apple_io(int offset)
+{
+ if (offset < 0x8)
+ {
+ m_video_mode = APPLE;
+ m_screen->set_visible_area(0, 280-1, 0, 192-1);
+ }
+
+ switch (offset)
+ {
+ case 0x0:
+ m_graphics = true;
+ break;
+
+ case 0x1:
+ m_graphics = false;
+ break;
+
+ case 0x2:
+ m_mix = false;
+ break;
+
+ case 0x3:
+ m_mix = true;
+ break;
+
+ case 0x4:
+ m_page2 = false;
+ break;
+
+ case 0x5:
+ m_page2 = true;
+ break;
+
+ case 0x8:
+ palette_index &= 0xfe;
+ break;
+
+ case 0x9:
+ palette_index |= 0x01;
+ break;
+
+ case 0xa:
+ palette_index &= 0xfd;
+ break;
+
+ case 0xb:
+ palette_index |= 0x02;
+ break;
+ }
+}
+
+void agat9video_device::do_io(int offset)
+{
+ logerror("%s: %04x access, ", machine().describe_context(), 0xc700 + offset);
+
+ m_mode = offset;
+
+ m_screen->set_visible_area(0, 2*256-1, 0, 256-1);
+
+ switch (offset & 3)
+ {
+ case 0:
+ // 256x256, 4 colors, 64 bytes per scanline, 0x4000 page length, odd scanlines at 0x2000
+ m_video_mode = GRAPHICS_COLOR_HIRES;
+ m_start_address = ((offset & 0x60) << 9) + ((offset & 0x08) << 13);
+ logerror("offset %04X, video mode 0 (COLOR_HIRES)\n", m_start_address);
+ break;
+
+ case 1:
+ // 128x128, 16 colors, 64 bytes per scanline, 0x2000 page length, linear
+ m_video_mode = GRAPHICS_COLOR_LORES;
+ m_start_address = ((offset & 0x70) << 9) + ((offset & 0x08) << 13);
+ logerror("offset %04X, video mode 1 (COLOR_LORES)\n", m_start_address);
+ break;
+
+ // b6..b4 == page number, b3..b2 == subpage number
+ case 2:
+ // 64x32, 0x1000 page length
+ if (offset > 0x80)
+ {
+ m_video_mode = TEXT_HIRES;
+ m_start_address = (offset - 0x82) << 9;
+ logerror("offset %04X, video mode 2 (TEXT_HIRES)\n", m_start_address);
+ }
+ // 32x32, 0x1000 page length
+ else
+ {
+ m_video_mode = TEXT_LORES;
+ m_start_address = (offset - 0x02) << 9;
+ logerror("offset %04X, video mode 2 (TEXT_LORES)\n", m_start_address);
+ }
+ break;
+
+ case 3:
+ // 512x256, 64 bytes per scanline, 0x4000 page length, odd scanlines at 0x2000
+ if (offset > 0x80)
+ {
+ m_video_mode = GRAPHICS_MONO_HIRES;
+ m_start_address = ((offset & 0x60) << 9) + ((offset & 0x08) << 13);
+ logerror("offset %04X, video mode 3 (MONO_HIRES)\n", m_start_address);
+ }
+ // 256x256, 32 bytes per scanline, 0x2000 page length, linear
+ else
+ {
+ m_video_mode = GRAPHICS_MONO_LORES;
+ m_start_address = ((offset & 0x70) << 9) + ((offset & 0x08) << 13);
+ logerror("offset %04X, video mode 3 (MONO_LORES)\n", m_start_address);
+ }
+ break;
+ }
+}
+
+
+void agat9video_device::plot_text_character(bitmap_ind16 &bitmap, int xpos, int ypos, int xscale, uint32_t code,
+ const uint8_t *textgfx_data, uint32_t textgfx_datalen, int fg, int bg)
+{
+ int x, y, i;
+ const uint8_t *chardata;
+ uint16_t color;
+
+ /* look up the character data */
+ chardata = &textgfx_data[(code * 8)];
+
+ for (y = 0; y < 8; y++)
+ {
+ for (x = 0; x < 8; x++)
+ {
+ color = (chardata[y] & (1 << (7 - x))) ? fg : bg;
+
+ for (i = 0; i < xscale; i++)
+ {
+ bitmap.pix16(ypos + y, xpos + (x * xscale) + i) = color;
+ }
+ }
+ }
+}
+
+int color_1_p[4] =
+{
+ 0, 4, 0, 5
+};
+
+int color_2_p[4][2] =
+{
+ { 0, 7 },
+ { 7, 0 },
+ { 0, 2 },
+ { 2, 0 },
+};
+
+void agat9video_device::text_update_lores(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow)
+{
+ int row, col;
+ uint32_t address;
+ uint8_t ch, attr;
+ int fg = 0;
+ int bg = color_1_p[palette_index];
+
+ beginrow = std::max(beginrow, cliprect.min_y - (cliprect.min_y % 8));
+ endrow = std::min(endrow, cliprect.max_y - (cliprect.max_y % 8) + 7);
+
+ for (row = beginrow; row <= endrow; row += 8)
+ {
+ for (col = 0; col < 32; col++)
+ {
+ /* calculate address */
+ address = m_start_address + (col * 2) + (row * 8);
+ ch = m_ram_dev->read(address);
+ attr = m_ram_dev->read(address + 1);
+ fg = bitswap<8>(attr,7,6,5,3,4,2,1,0) & 15;
+ if (BIT(attr, 5)) {
+ plot_text_character(bitmap, col * 16, row, 2, ch, m_char_ptr, m_char_size, fg, bg);
+ } else {
+ plot_text_character(bitmap, col * 16, row, 2, ch, m_char_ptr, m_char_size, bg, fg);
+ }
+ }
+ }
+}
+
+void agat9video_device::text_update_hires(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow)
+{
+ int row, col;
+ uint32_t address;
+ uint8_t ch;
+ int fg, bg;
+
+ beginrow = std::max(beginrow, cliprect.min_y - (cliprect.min_y % 8));
+ endrow = std::min(endrow, cliprect.max_y - (cliprect.max_y % 8) + 7);
+
+ if (m_start_address & 0x800)
+ {
+ fg = color_2_p[palette_index][1];
+ bg = color_2_p[palette_index][0];
+ }
+ else
+ {
+ fg = color_2_p[palette_index][0];
+ bg = color_2_p[palette_index][1];
+ }
+
+ for (row = beginrow; row <= endrow; row += 8)
+ {
+ for (col = 0; col < 64; col++)
+ {
+ /* calculate address */
+ address = m_start_address + col + (row * 8);
+ ch = m_ram_dev->read(address);
+ plot_text_character(bitmap, col * 8, row, 1, ch, m_char_ptr, m_char_size, fg, bg);
+ }
+ }
+}
+
+void agat9video_device::graph_update_mono_lores(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow)
+{
+ int row, col, b;
+ uint32_t address;
+ uint16_t *p;
+ uint8_t gfx, v;
+ int fg = 7, bg = 0;
+
+ beginrow = std::max(beginrow, cliprect.min_y - (cliprect.min_y % 8));
+ endrow = std::min(endrow, cliprect.max_y - (cliprect.max_y % 8) + 7);
+
+ for (row = beginrow; row <= endrow; row++)
+ {
+ p = &bitmap.pix16(row);
+ for (col = 0; col < 32; col++)
+ {
+ address = m_start_address + col + (row * 0x20);
+ gfx = m_ram_dev->read(address);
+
+ for (b = 0; b < 8; b++)
+ {
+ v = (gfx & 0x80) >> 7;
+ v = color_2_p[palette_index][v];
+ gfx <<= 1;
+ *(p++) = v ? fg : bg;
+ *(p++) = v ? fg : bg;
+ }
+ }
+ }
+}
+
+void agat9video_device::graph_update_mono_hires(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow)
+{
+ int row, col, b;
+ uint32_t address;
+ uint16_t *p;
+ uint8_t gfx, v;
+ int fg = 7, bg = 0;
+
+ beginrow = std::max(beginrow, cliprect.min_y - (cliprect.min_y % 8));
+ endrow = std::min(endrow, cliprect.max_y - (cliprect.max_y % 8) + 7);
+
+ for (row = beginrow; row <= endrow; row++)
+ {
+ p = &bitmap.pix16(row);
+ for (col = 0; col < 64; col++)
+ {
+ address = m_start_address + col + ((row / 2) * 0x40) + 0x2000 * (row & 1);
+ gfx = m_ram_dev->read(address);
+
+ for (b = 0; b < 8; b++)
+ {
+ v = (gfx & 0x80) >> 7;
+ v = color_2_p[palette_index][v];
+ gfx <<= 1;
+ *(p++) = v ? fg : bg;
+ }
+ }
+ }
+}
+
+int color_4_p[4][4] =
+{
+ { 0, 1, 2, 4 },
+ { 7, 1, 2, 4 },
+ { 0, 0, 2, 4 },
+ { 0, 1, 0, 4 }
+};
+
+void agat9video_device::graph_update_color_hires(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow)
+{
+ int row, col, b;
+ uint32_t address;
+ uint16_t *p;
+ uint8_t gfx, v;
+
+ beginrow = std::max(beginrow, cliprect.min_y - (cliprect.min_y % 8));
+ endrow = std::min(endrow, cliprect.max_y - (cliprect.max_y % 8) + 7);
+
+ for (row = beginrow; row <= endrow; row++)
+ {
+ p = &bitmap.pix16(row);
+ for (col = 0; col < 0x40; col++)
+ {
+ address = m_start_address + col + ((row / 2) * 0x40) + 0x2000 * (row & 1);
+ gfx = m_ram_dev->read(address);
+
+ for (b = 0; b < 4; b++)
+ {
+ v = (gfx & 0xc0) >> 6;
+ v = color_4_p[palette_index][v];
+ gfx <<= 2;
+ *(p++) = v;
+ *(p++) = v;
+ }
+ }
+ }
+}
+
+void agat9video_device::graph_update_color_lores(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow)
+{
+ int row, col, b;
+ uint32_t address;
+ uint16_t *p;
+ uint8_t gfx, v;
+
+ beginrow = std::max(beginrow, cliprect.min_y - (cliprect.min_y % 8));
+ endrow = std::min(endrow, cliprect.max_y - (cliprect.max_y % 8) + 7);
+
+ for (row = beginrow; row <= endrow; row++)
+ {
+ p = &bitmap.pix16(row);
+ for (col = 0; col < 0x40; col++)
+ {
+ address = m_start_address + col + ((row / 2) * 0x40);
+ gfx = m_ram_dev->read(address);
+
+ for (b = 0; b < 2; b++)
+ {
+ v = (gfx & 0xf0) >> 4;
+ gfx <<= 4;
+ *(p++) = v;
+ *(p++) = v;
+ *(p++) = v;
+ *(p++) = v;
+ }
+ }
+ }
+}
+
+// Apple ][ video modes
+
+void agat9video_device::plot_text_character_apple(bitmap_ind16 &bitmap, int xpos, int ypos, int xscale, uint32_t code,
+ const uint8_t *textgfx_data, uint32_t textgfx_datalen, int fg, int bg)
+{
+ int x, y, i;
+ const uint8_t *chardata;
+ uint16_t color;
+
+ if ((code >= 0x40) && (code <= 0x7f))
+ {
+ code &= 0x3f;
+
+ if (m_flash)
+ {
+ i = fg;
+ fg = bg;
+ bg = i;
+ }
+ }
+
+ /* look up the character data */
+ chardata = &textgfx_data[(code * 8)];
+
+ for (y = 0; y < 8; y++)
+ {
+ for (x = 0; x < 7; x++)
+ {
+ color = (chardata[y] & (1 << (6 - x))) ? fg : bg;
+
+ for (i = 0; i < xscale; i++)
+ {
+ bitmap.pix16(ypos + y, xpos + (x * xscale) + i) = color;
+ }
+ }
+ }
+}
+
+void agat9video_device::text_update_apple(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow)
+{
+ int row, col;
+ uint32_t start_address;
+ uint32_t address;
+ int fg, bg;
+
+ start_address = m_page2 ? 0x800 : 0x400;
+
+ fg = color_2_p[palette_index][1];
+ bg = color_2_p[palette_index][0];
+
+ beginrow = std::max(beginrow, cliprect.min_y - (cliprect.min_y % 8));
+ endrow = std::min(endrow, cliprect.max_y - (cliprect.max_y % 8) + 7);
+
+ for (row = beginrow; row <= endrow; row += 8)
+ {
+ for (col = 0; col < 40; col++)
+ {
+ /* calculate address */
+ address = start_address + ((((row/8) & 0x07) << 7) | (((row/8) & 0x18) * 5 + col));
+ plot_text_character_apple(bitmap, col * 7, row, 1, m_ram_dev->read(address),
+ m_char_ptr, m_char_size, fg, bg);
+ }
+ }
+}
+
+void agat9video_device::hgr_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow)
+{
+ int row, col, b, va;
+ int offset;
+ uint8_t vram_row[42];
+ uint16_t v;
+ uint16_t *p;
+ uint32_t w;
+ uint16_t *artifact_map_ptr;
+ int begincol = 0, endcol = 40;
+
+ /* sanity checks */
+ if (beginrow < cliprect.min_y)
+ beginrow = cliprect.min_y;
+ if (endrow > cliprect.max_y)
+ endrow = cliprect.max_y;
+ if (endrow < beginrow)
+ return;
+
+ // we generate 2 pixels per "column" so adjust
+ if (begincol < (cliprect.min_x/7))
+ begincol = (cliprect.min_x/7);
+ if (endcol > (cliprect.max_x/7))
+ endcol = (cliprect.max_x/7);
+ if (cliprect.max_x > 39*7)
+ endcol = 40;
+ if (endcol < begincol)
+ return;
+
+ va = m_page2 ? 0x4000 : 0x2000;
+
+ vram_row[0] = 0;
+ vram_row[41] = 0;
+
+ for (row = beginrow; row <= endrow; row++)
+ {
+ for (col = begincol; col < endcol; col++)
+ {
+ offset = ((((row / 8) & 0x07) << 7) | (((row / 8) & 0x18) * 5 + col)) | ((row & 7) << 10);
+ vram_row[1 + col] = m_ram_dev->read(va + offset);
+ }
+
+ p = &bitmap.pix16(row);
+
+ /*
+ * p. 50 of technical manual:
+ *
+ * 1. a 'zero' bit is always drawn as 'black' pixel
+ * 2. two consecutive 'one' bits are always drawn as 'white' pixel, even bits from different bytes
+ * 3. even pixels can be 'black', 'purple' (5) or 'blue' (4)
+ * 4. odd pixels can be 'black', 'green' (2) or 'red' (1)
+ * 5. bit 7 affects color of pixels in this byte. zero = 'blue' or 'red', one = 'purple' or 'green'.
+ */
+ for (col = 0; col < 40; col++)
+ {
+ w = (((uint32_t) vram_row[col+0] & 0x7f) << 0)
+ | (((uint32_t) vram_row[col+1] & 0x7f) << 7)
+ | (((uint32_t) vram_row[col+2] & 0x7f) << 14);
+
+ artifact_map_ptr = &m_hires_artifact_map[((vram_row[col + 1] & 0x80) >> 7) * 16];
+
+ for (b = 0; b < 7; b++)
+ {
+ v = artifact_map_ptr[((w >> (b + 7 - 1)) & 0x07) | (((b ^ col) & 0x01) << 3)];
+ *(p++) = v;
+ }
+ }
+ }
+}
+
+
+uint32_t agat9video_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ switch (m_video_mode)
+ {
+ case APPLE: // from apple2e.cpp
+ // always update the flash timer here so it's smooth regardless of mode switches
+ m_flash = ((machine().time() * 4).seconds() & 1) ? true : false;
+
+ if (m_graphics)
+ {
+ if (m_mix)
+ {
+ hgr_update(screen, bitmap, cliprect, 0, 159);
+ text_update_apple(screen, bitmap, cliprect, 160, 191);
+ }
+ else
+ {
+ hgr_update(screen, bitmap, cliprect, 0, 191);
+ }
+ }
+ else
+ {
+ text_update_apple(screen, bitmap, cliprect, 0, 191);
+ }
+ break;
+
+ case TEXT_LORES:
+ text_update_lores(screen, bitmap, cliprect, 0, 255);
+ break;
+
+ case TEXT_HIRES:
+ text_update_hires(screen, bitmap, cliprect, 0, 255);
+ break;
+
+ case GRAPHICS_MONO_LORES:
+ graph_update_mono_lores(screen, bitmap, cliprect, 0, 255);
+ break;
+
+ case GRAPHICS_MONO_HIRES:
+ graph_update_mono_hires(screen, bitmap, cliprect, 0, 255);
+ break;
+
+ case GRAPHICS_COLOR_LORES:
+ graph_update_color_lores(screen, bitmap, cliprect, 0, 255);
+ break;
+
+ case GRAPHICS_COLOR_HIRES:
+ graph_update_color_hires(screen, bitmap, cliprect, 0, 255);
+ break;
+
+ default:
+ graph_update_mono_lores(screen, bitmap, cliprect, 0, 255);
+ break;
+ }
+
+ return 0;
+}
diff --git a/src/mame/video/agat9.h b/src/mame/video/agat9.h
new file mode 100644
index 00000000000..de61581e13b
--- /dev/null
+++ b/src/mame/video/agat9.h
@@ -0,0 +1,96 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/*********************************************************************
+
+ agat9video.h
+
+ Implementation of Agat-9 onboard video.
+
+*********************************************************************/
+
+#ifndef MAME_VIDEO_AGAT9_H
+#define MAME_VIDEO_AGAT9_H
+
+#pragma once
+
+#include "machine/ram.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class agat9video_device : public device_t, public device_palette_interface
+{
+public:
+ template <typename T, typename U>
+ agat9video_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&ram_tag, U &&char_tag)
+ : agat9video_device(mconfig, tag, owner, (uint32_t)0)
+ {
+ m_ram_dev.set_tag(std::forward<T>(ram_tag));
+ m_char_region.set_tag(std::forward<U>(char_tag));
+ }
+
+ agat9video_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_READ8_MEMBER(read);
+ DECLARE_WRITE8_MEMBER(write);
+ DECLARE_READ8_MEMBER(apple_read);
+ DECLARE_WRITE8_MEMBER(apple_write);
+
+ bool m_page2;
+ bool m_flash;
+ bool m_mix;
+ bool m_graphics;
+ std::unique_ptr<uint16_t[]> m_hires_artifact_map;
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual u32 palette_entries() const override { return 16; }
+
+ void text_update_lores(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow);
+ void text_update_hires(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow);
+ void graph_update_mono_lores(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow);
+ void graph_update_mono_hires(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow);
+ void graph_update_color_lores(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow);
+ void graph_update_color_hires(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow);
+
+ void text_update_apple(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow);
+ void hgr_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow);
+
+private:
+ void do_io(int offset);
+ void do_apple_io(int offset);
+
+ void plot_text_character(bitmap_ind16 &bitmap, int xpos, int ypos, int xscale, uint32_t code, const uint8_t *textgfx_data, uint32_t textgfx_datalen, int fg, int bg);
+ void plot_text_character_apple(bitmap_ind16 &bitmap, int xpos, int ypos, int xscale, uint32_t code, const uint8_t *textgfx_data, uint32_t textgfx_datalen, int fg, int bg);
+
+ uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+
+ required_device<screen_device> m_screen;
+ required_device<ram_device> m_ram_dev;
+ required_memory_region m_char_region;
+
+ uint8_t *m_char_ptr;
+ int m_char_size;
+ uint32_t m_start_address;
+ enum {
+ TEXT_LORES = 0,
+ TEXT_HIRES,
+ GRAPHICS_COLOR_LORES,
+ GRAPHICS_COLOR_HIRES,
+ GRAPHICS_MONO_LORES,
+ GRAPHICS_MONO_HIRES,
+ APPLE
+ } m_video_mode;
+ int m_mode;
+ int palette_index;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(AGAT9VIDEO, agat9video_device)
+
+#endif // MAME_VIDEO_AGAT9_H
diff --git a/src/tools/floptool.cpp b/src/tools/floptool.cpp
index a5ebceb8925..7c2f9d23e56 100644
--- a/src/tools/floptool.cpp
+++ b/src/tools/floptool.cpp
@@ -51,6 +51,10 @@
#include "formats/hpi_dsk.h"
+#include "formats/dvk_mx_dsk.h"
+#include "formats/aim_dsk.h"
+
+
static floppy_format_type floppy_formats[] = {
FLOPPY_MFI_FORMAT,
FLOPPY_DFI_FORMAT,
@@ -89,7 +93,10 @@ static floppy_format_type floppy_formats[] = {
FLOPPY_APPLIX_FORMAT,
- FLOPPY_HPI_FORMAT
+ FLOPPY_HPI_FORMAT,
+
+ FLOPPY_DVK_MX_FORMAT,
+ FLOPPY_AIM_FORMAT
};
void CLIB_DECL ATTR_PRINTF(1,2) logerror(const char *format, ...)