summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author Sergey Svishchev <shattered@users.noreply.github.com>2017-12-09 02:46:23 +0300
committer ajrhacker <ajrhacker@users.noreply.github.com>2017-12-08 18:46:23 -0500
commit00c9b62a2405b6c4120564845694e90da1346d8b (patch)
tree0f511487c087b53ecc87a424eba5fcd54013e49a /src
parent13a70d311857594b48f581943a832190b468809a (diff)
agat7: 840KB floppy HLE; minor fixes -> mark WORKING (#2912)
* agat7: add port_char definitions to allow access from Lua, &c (nw) * agat7: adapt "apple2: Break up handlers for C000-C07F range" (nw) * agat7: timer and vblank interrupts (nw) * agat7: HLE of 840KB floppy controller, read-only (nw) * agat7: memory expansion wip (nw) * agat7: update todo list, mark partially WORKING
Diffstat (limited to 'src')
-rw-r--r--src/devices/bus/a2bus/agat7langcard.cpp19
-rw-r--r--src/devices/bus/a2bus/agat7langcard.h4
-rw-r--r--src/devices/bus/a2bus/agat7ram.cpp27
-rw-r--r--src/devices/bus/a2bus/agat7ram.h4
-rw-r--r--src/devices/bus/a2bus/agat840k_hle.cpp449
-rw-r--r--src/devices/bus/a2bus/agat840k_hle.h99
-rw-r--r--src/lib/formats/agat840k_hle_dsk.cpp59
-rw-r--r--src/lib/formats/agat840k_hle_dsk.h17
-rw-r--r--src/mame/drivers/agat.cpp340
9 files changed, 854 insertions, 164 deletions
diff --git a/src/devices/bus/a2bus/agat7langcard.cpp b/src/devices/bus/a2bus/agat7langcard.cpp
index 9bb00b38c60..b4d2a168f38 100644
--- a/src/devices/bus/a2bus/agat7langcard.cpp
+++ b/src/devices/bus/a2bus/agat7langcard.cpp
@@ -10,6 +10,9 @@
#include "agat7langcard.h"
+//#define VERBOSE 1
+#include "logmacro.h"
+
/***************************************************************************
PARAMETERS
***************************************************************************/
@@ -30,7 +33,7 @@ DEFINE_DEVICE_TYPE(A2BUS_AGAT7LANGCARD, a2bus_agat7langcard_device, "a7lang", "A
a2bus_agat7langcard_device::a2bus_agat7langcard_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_inh_state(0), m_last_offset(0), m_dxxx_bank(0), m_main_bank(0)
+ device_a2bus_card_interface(mconfig, *this), m_inh_state(0), m_dxxx_bank(0), m_main_bank(0), m_csr(0)
{
}
@@ -48,13 +51,13 @@ void a2bus_agat7langcard_device::device_start()
// set_a2bus_device makes m_slot valid
set_a2bus_device();
- memset(m_ram, 0, 32*1024);
+ memset(m_ram, 0, 32 * 1024);
save_item(NAME(m_inh_state));
save_item(NAME(m_ram));
save_item(NAME(m_dxxx_bank));
save_item(NAME(m_main_bank));
- save_item(NAME(m_last_offset));
+ save_item(NAME(m_csr));
}
void a2bus_agat7langcard_device::device_reset()
@@ -62,7 +65,7 @@ void a2bus_agat7langcard_device::device_reset()
m_inh_state = INH_NONE;
m_dxxx_bank = 0;
m_main_bank = 0;
- m_last_offset = -1;
+ m_csr = 0;
m_mode = 0;
}
@@ -70,7 +73,7 @@ void a2bus_agat7langcard_device::do_io(int offset)
{
int old_inh_state = m_inh_state;
- m_last_offset = offset;
+ m_csr = offset & 0x7f;
m_inh_state = INH_WRITE;
m_dxxx_bank = 0;
@@ -91,13 +94,11 @@ void a2bus_agat7langcard_device::do_io(int offset)
recalc_slot_inh();
}
-#if 1
- logerror("LC: (ofs %02x) new state %c%c dxxx=%04x main=%05x\n",
+ LOG("LC: (ofs %02x) new state %c%c dxxx=%04x main=%05x\n",
offset,
(m_inh_state & INH_READ) ? 'R' : 'x',
(m_inh_state & INH_WRITE) ? 'W' : 'x',
m_dxxx_bank, m_main_bank);
-#endif
}
@@ -107,7 +108,7 @@ void a2bus_agat7langcard_device::do_io(int offset)
uint8_t a2bus_agat7langcard_device::read_cnxx(address_space &space, uint8_t offset)
{
- return m_last_offset < 0 ? 0x80 : (0x80 | m_last_offset);
+ return (0x80 | m_csr);
}
diff --git a/src/devices/bus/a2bus/agat7langcard.h b/src/devices/bus/a2bus/agat7langcard.h
index 13647abfb11..be3a650a222 100644
--- a/src/devices/bus/a2bus/agat7langcard.h
+++ b/src/devices/bus/a2bus/agat7langcard.h
@@ -47,11 +47,11 @@ private:
void do_io(int offset);
int m_inh_state;
- int m_last_offset;
int m_dxxx_bank;
int m_main_bank;
- uint8_t m_ram[32*1024];
+ uint8_t m_ram[32 * 1024];
uint8_t m_mode;
+ uint8_t m_csr;
};
// device type definition
diff --git a/src/devices/bus/a2bus/agat7ram.cpp b/src/devices/bus/a2bus/agat7ram.cpp
index dde0260db3f..51bbabb792c 100644
--- a/src/devices/bus/a2bus/agat7ram.cpp
+++ b/src/devices/bus/a2bus/agat7ram.cpp
@@ -10,6 +10,9 @@
#include "agat7ram.h"
+//#define VERBOSE 1
+#include "logmacro.h"
+
/***************************************************************************
PARAMETERS
***************************************************************************/
@@ -30,7 +33,7 @@ DEFINE_DEVICE_TYPE(A2BUS_AGAT7RAM, a2bus_agat7ram_device, "a7ram", "Agat-7 32K R
a2bus_agat7ram_device::a2bus_agat7ram_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_inh_state(0), m_last_offset(0), m_main_bank(0)
+ device_a2bus_card_interface(mconfig, *this), m_inh_state(0), m_main_bank(0), m_csr(0)
{
}
@@ -48,32 +51,32 @@ void a2bus_agat7ram_device::device_start()
// set_a2bus_device makes m_slot valid
set_a2bus_device();
- memset(m_ram, 0, 32*1024);
+ memset(m_ram, 0, 32 * 1024);
save_item(NAME(m_inh_state));
save_item(NAME(m_ram));
save_item(NAME(m_main_bank));
- save_item(NAME(m_last_offset));
+ save_item(NAME(m_csr));
}
void a2bus_agat7ram_device::device_reset()
{
m_inh_state = INH_NONE;
m_main_bank = 0;
- m_last_offset = -1;
+ m_csr = 0;
}
void a2bus_agat7ram_device::do_io(int offset)
{
int old_inh_state = m_inh_state;
- m_last_offset = offset;
+ m_csr = offset & 0x7f;
m_inh_state = INH_NONE;
m_main_bank = 0;
if (offset & 0x8)
{
- m_inh_state = INH_READ|INH_WRITE;
+ m_inh_state = INH_READ | INH_WRITE;
}
if (offset & 0x1)
@@ -86,13 +89,11 @@ void a2bus_agat7ram_device::do_io(int offset)
recalc_slot_inh();
}
-#if 1
- logerror("RAM: (ofs %02x) new state %c%c main=%05x\n",
+ LOG("RAM: (ofs %02x) new state %c%c main=%05x\n",
offset,
(m_inh_state & INH_READ) ? 'R' : 'x',
(m_inh_state & INH_WRITE) ? 'W' : 'x',
m_main_bank);
-#endif
}
@@ -102,7 +103,7 @@ void a2bus_agat7ram_device::do_io(int offset)
uint8_t a2bus_agat7ram_device::read_cnxx(address_space &space, uint8_t offset)
{
- return m_last_offset < 0 ? 0 : (m_last_offset & 0x7f);
+ return m_csr;
}
@@ -125,12 +126,10 @@ uint8_t a2bus_agat7ram_device::read_inh_rom(address_space &space, uint16_t offse
void a2bus_agat7ram_device::write_inh_rom(address_space &space, uint16_t offset, uint8_t data)
{
// are writes enabled?
- if (!(m_inh_state & INH_WRITE))
+ if ((m_inh_state & INH_WRITE) && !BIT(m_csr, 4))
{
- return;
+ m_ram[(offset & 0x3fff) + m_main_bank] = data;
}
-
- m_ram[(offset & 0x3fff) + m_main_bank] = data;
}
int a2bus_agat7ram_device::inh_type()
diff --git a/src/devices/bus/a2bus/agat7ram.h b/src/devices/bus/a2bus/agat7ram.h
index e30aaf7b94b..3476e738179 100644
--- a/src/devices/bus/a2bus/agat7ram.h
+++ b/src/devices/bus/a2bus/agat7ram.h
@@ -47,9 +47,9 @@ private:
void do_io(int offset);
int m_inh_state;
- int m_last_offset;
int m_main_bank;
- uint8_t m_ram[32*1024];
+ uint8_t m_ram[32 * 1024];
+ uint8_t m_csr;
};
// device type definition
diff --git a/src/devices/bus/a2bus/agat840k_hle.cpp b/src/devices/bus/a2bus/agat840k_hle.cpp
new file mode 100644
index 00000000000..a27d3d95ceb
--- /dev/null
+++ b/src/devices/bus/a2bus/agat840k_hle.cpp
@@ -0,0 +1,449 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/*********************************************************************
+
+ agat840k_hle.cpp
+
+ High-level simulation of the Agat 840K floppy controller card
+
+ 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 "emu.h"
+#include "imagedev/flopdrv.h"
+#include "formats/agat840k_hle_dsk.h"
+#include "agat840k_hle.h"
+
+//#define VERBOSE 1
+#include "logmacro.h"
+
+
+/***************************************************************************
+ PARAMETERS
+***************************************************************************/
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(A2BUS_AGAT840K_HLE, a2bus_agat840k_hle_device, "agat840k_hle", "Agat 840K floppy card")
+
+#define AGAT840K_ROM_REGION "agat840k_hle_rom"
+
+
+ROM_START( agat840k_hle )
+ ROM_REGION(0x100, AGAT840K_ROM_REGION, 0)
+ // "Zagorsk" variant
+ ROM_LOAD( "teac.rom", 0x0000, 0x0100, CRC(94266928) SHA1(5d369bad6cdd6a70b0bb16480eba69640de87a2e) )
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+static const floppy_interface agat840k_hle_floppy_interface =
+{
+ FLOPPY_STANDARD_5_25_DSHD,
+ LEGACY_FLOPPY_OPTIONS_NAME(agat840k_hle),
+ "floppy_5_25"
+};
+
+MACHINE_CONFIG_MEMBER( a2bus_agat840k_hle_device::device_add_mconfig )
+ MCFG_DEVICE_ADD(FLOPPY_0, LEGACY_FLOPPY, 0)
+ MCFG_LEGACY_FLOPPY_CONFIG(agat840k_hle_floppy_interface)
+ MCFG_LEGACY_FLOPPY_IDX_CB(WRITELINE(a2bus_agat840k_hle_device, index_0_w))
+ MCFG_DEVICE_ADD(FLOPPY_1, LEGACY_FLOPPY, 0)
+ MCFG_LEGACY_FLOPPY_CONFIG(agat840k_hle_floppy_interface)
+ MCFG_LEGACY_FLOPPY_IDX_CB(WRITELINE(a2bus_agat840k_hle_device, index_1_w))
+
+ MCFG_DEVICE_ADD("d14", I8255, 0)
+ // PA not connected
+ MCFG_I8255_IN_PORTB_CB(READ8(a2bus_agat840k_hle_device, d14_i_b)) // status signals from drive
+ MCFG_I8255_OUT_PORTC_CB(WRITE8(a2bus_agat840k_hle_device, d14_o_c)) // control
+
+ MCFG_DEVICE_ADD("d15", I8255, 0)
+ MCFG_I8255_IN_PORTA_CB(READ8(a2bus_agat840k_hle_device, d15_i_a)) // read data
+// MCFG_I8255_OUT_PORTB_CB(WRITE8(a2bus_agat840k_hle_device, d15_o_b)) // write data
+ MCFG_I8255_IN_PORTC_CB(READ8(a2bus_agat840k_hle_device, d15_i_c))
+ MCFG_I8255_OUT_PORTC_CB(WRITE8(a2bus_agat840k_hle_device, d15_o_c))
+MACHINE_CONFIG_END
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *a2bus_agat840k_hle_device::device_rom_region() const
+{
+ return ROM_NAME(agat840k_hle);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+a2bus_agat840k_hle_device::a2bus_agat840k_hle_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")
+ , m_rom(nullptr)
+{
+}
+
+a2bus_agat840k_hle_device::a2bus_agat840k_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_agat840k_hle_device(mconfig, A2BUS_AGAT840K_HLE, tag, owner, clock)
+{
+}
+
+WRITE_LINE_MEMBER(a2bus_agat840k_hle_device::index_0_w)
+{
+ index_callback(0, state);
+}
+
+WRITE_LINE_MEMBER(a2bus_agat840k_hle_device::index_1_w)
+{
+ index_callback(1, state);
+}
+
+void a2bus_agat840k_hle_device::index_callback(int unit, int state)
+{
+ if (unit != m_unit) return;
+
+ LOG("index: unit %d state %d (%s)\n", unit, state, m_seen_magic ? "MAGIC" : "magic");
+
+#if 0
+ if (!state && !m_seen_magic)
+ {
+ m_seen_magic = true;
+ m_count_read = 0;
+ m_count_write = 0;
+ m_d15->pc4_w(0); // latch data into port A
+ m_d15->pc4_w(1);
+ m_timer_wait->adjust(attotime::from_usec(m_waittime), 0, attotime::from_usec(m_waittime));
+ }
+#endif
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void a2bus_agat840k_hle_device::device_start()
+{
+ // set_a2bus_device makes m_slot valid
+ set_a2bus_device();
+
+ m_rom = device().machine().root_device().memregion(this->subtag(AGAT840K_ROM_REGION).c_str())->base();
+
+ m_mxcs = MXCSR_SYNC;
+
+ m_timer_wait = timer_alloc(TIMER_ID_WAIT);
+ m_timer_seek = timer_alloc(TIMER_ID_SEEK);
+
+ m_seektime = 6000; // 6 ms, per es5323.txt
+ m_waittime = 32; // 16 bits x 2 us
+}
+
+void a2bus_agat840k_hle_device::device_reset()
+{
+ u8 buf[256];
+
+ for (int i = 0; i < 2; i++)
+ {
+ legacy_floppy_image_device *img = floppy_image(i);
+ if (img)
+ {
+ img->floppy_drive_set_ready_state(FLOPPY_DRIVE_READY, 0);
+ img->floppy_drive_set_rpm(300.);
+ img->floppy_drive_seek(-img->floppy_drive_get_current_track());
+ }
+ }
+ m_floppy = floppy_image(0);
+
+ // generate track images in memory, using default volume ID and gap padding bytes
+ int t = 0;
+ for (auto &elem : m_tracks)
+ {
+ elem = std::make_unique<uint16_t[]>(6250);
+
+ for (int i = 0; i < 13; i++)
+ {
+ elem[i] = 0xaa;
+ }
+ for (int j = 0; j < 21; j++)
+ {
+ int k, cksum = 0, s = (j * 1) % 21;
+
+ m_floppy->floppy_drive_read_sector_data(t & 1, s, buf, 256);
+
+#define BAUX 22
+#define BLOB (256 + 19 + BAUX)
+
+ for (k = 0; k < 256; k++)
+ {
+ if (cksum > 255) { cksum++; cksum &= 255; }
+ cksum += buf[k];
+ elem[13 + (BLOB * j) + 17 + k] = buf[k];
+ }
+ cksum &= 255;
+
+ elem[13 + (BLOB * j) + 0] = 0xa4;
+ elem[13 + (BLOB * j) + 1] = 0x80ff; // desync
+ elem[13 + (BLOB * j) + 2] = 0x95;
+ elem[13 + (BLOB * j) + 3] = 0x6a;
+ elem[13 + (BLOB * j) + 4] = 0x40fe; // volume id
+ elem[13 + (BLOB * j) + 5] = t;
+ elem[13 + (BLOB * j) + 6] = s;
+ elem[13 + (BLOB * j) + 7] = 0x5a;
+ elem[13 + (BLOB * j) + 8] = 0xaa;
+ elem[13 + (BLOB * j) + 9] = 0xaa;
+ elem[13 + (BLOB * j) + 10] = 0xaa;
+ elem[13 + (BLOB * j) + 11] = 0xaa;
+ elem[13 + (BLOB * j) + 12] = 0xaa;
+ elem[13 + (BLOB * j) + 13] = 0xa4;
+ elem[13 + (BLOB * j) + 14] = 0x80ff; // desync
+ elem[13 + (BLOB * j) + 15] = 0x6a;
+ elem[13 + (BLOB * j) + 16] = 0x95;
+ elem[13 + (BLOB * j) + 17 + 256] = cksum + 0x2000;
+ elem[13 + (BLOB * j) + 17 + 257] = 0x5a;
+
+ // gap3
+ for (k = 0; k < BAUX; k++)
+ {
+ elem[13 + (BLOB * j) + 17 + 258 + k] = 0xaa;
+ }
+ }
+#undef BAUX
+#undef BLOB
+
+ t++;
+ if ((t & 1) == 0)
+ {
+ m_floppy->floppy_drive_seek(1);
+ }
+ }
+ m_floppy->floppy_drive_seek(-m_floppy->floppy_drive_get_current_track());
+
+ m_mxcs |= MXCSR_SYNC;
+ m_mxcs &= ~MXCSR_TR;
+}
+
+void a2bus_agat840k_hle_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case TIMER_ID_WAIT:
+ {
+ m_count_read++;
+ m_count_read %= 6250;
+ m_d15->pc4_w(0);
+ m_d15->pc4_w(1);
+ if (BIT(m_tracks[(2 * m_floppy->floppy_drive_get_current_track()) + m_side][m_count_read], 15))
+ m_mxcs &= ~MXCSR_SYNC;
+ }
+ break;
+
+ case TIMER_ID_SEEK:
+ m_floppy->floppy_stp_w(1);
+ m_floppy->floppy_stp_w(0);
+ break;
+ }
+}
+
+
+/*-------------------------------------------------
+ read_c0nx - called for reads from this card's c0nx space
+-------------------------------------------------*/
+
+uint8_t a2bus_agat840k_hle_device::read_c0nx(address_space &space, uint8_t offset)
+{
+ u8 data;
+
+ switch (offset)
+ {
+ case 0: case 1: case 2: case 3:
+ data = m_d14->read(space, offset);
+ break;
+
+ case 4: case 5: case 6: case 7:
+ data = m_d15->read(space, offset - 4);
+ break;
+
+ default:
+ data = 0xff;
+ break;
+ }
+
+ return data;
+}
+
+
+/*-------------------------------------------------
+ write_c0nx - called for writes to this card's c0nx space
+-------------------------------------------------*/
+
+void a2bus_agat840k_hle_device::write_c0nx(address_space &space, uint8_t offset, uint8_t data)
+{
+ switch (offset)
+ {
+ case 0: case 1: case 2: case 3:
+ m_d14->write(space, offset, data);
+ break;
+
+ case 4: case 5: case 6: case 7:
+ m_d15->write(space, offset - 4, data);
+ break;
+
+ case 8: // write desync
+ break;
+
+ case 9: // step
+ LOG("step at %11.6f\n", machine().time().as_double());
+ m_seen_magic = false;
+ m_timer_wait->adjust(attotime::from_usec(m_seektime), 0, attotime::from_usec(m_waittime));
+ m_floppy->floppy_stp_w(1);
+ m_floppy->floppy_stp_w(0);
+ break;
+
+ case 10: // reset desync flipflop
+ m_mxcs |= MXCSR_SYNC;
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*-------------------------------------------------
+ read_cnxx - called for reads from this card's c0nx space
+-------------------------------------------------*/
+
+uint8_t a2bus_agat840k_hle_device::read_cnxx(address_space &space, uint8_t offset)
+{
+ return m_rom[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;
+ }
+ return subdevice<legacy_floppy_image_device>(floppy_name);
+}
+
+// all signals active low. write support not implemented; WPT is always active.
+READ8_MEMBER(a2bus_agat840k_hle_device::d14_i_b)
+{
+ u8 data = 0x03; // one drive present, because drive select is broken
+
+ m_floppy->floppy_drive_set_ready_state(FLOPPY_DRIVE_READY, 1);
+
+ data |= (m_floppy->floppy_index_r() << 4) ^ 0x10;
+// data |= m_floppy->floppy_wpt_r() << 5;
+ data |= m_floppy->floppy_tk00_r() << 6;
+ data |= m_floppy->floppy_ready_r() << 7;
+
+ LOG("status A: %s %s (t %d) %s %s\n", BIT(data, 7) ? "ready" : "READY", BIT(data, 6) ? "tk00" : "TK00",
+ m_floppy->floppy_drive_get_current_track(),
+ 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_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)
+ m_floppy->floppy_ds1_w(m_unit != 1);
+ else
+ m_floppy->floppy_ds0_w(m_unit != 0);
+
+ m_floppy->floppy_drtn_w(!BIT(data, 2));
+ m_side = BIT(data, 4);
+ m_floppy->floppy_wtg_w(!BIT(data, 6));
+ m_floppy->floppy_mon_w(!BIT(data, 7)); // tied to 'drive select', 'motor on' and 'head load'
+
+ if (!BIT(data, 7))
+ {
+ m_seen_magic = false;
+ m_timer_wait->adjust(attotime::never);
+ }
+ else
+ {
+ m_d15->pc4_w(0);
+ m_d15->pc4_w(1);
+ m_timer_wait->adjust(attotime::from_usec(m_waittime), 0, attotime::from_usec(m_waittime));
+ }
+
+ LOG("D14 C <- %02X (unit %d side %d drtn %d wtg %d mon %d)\n",
+ data, m_unit, m_side, !BIT(data, 2), !BIT(data, 6), !BIT(data, 7));
+}
+
+// data are latched in by write to PC4
+READ8_MEMBER(a2bus_agat840k_hle_device::d15_i_a)
+{
+ u16 data = 0;
+
+ data = m_tracks[(2 * m_floppy->floppy_drive_get_current_track()) + m_side][m_count_read];
+ LOG("sector data: %02x @ %4d (head %d track %2d)%s\n", data & 0xff, m_count_read,
+ m_side, m_floppy->floppy_drive_get_current_track(),
+ BIT(data, 14) ? " volume" : (BIT(data, 13) ? " cksum" : ""));
+
+ return data & 0xff;
+}
+
+// C0x6
+//
+// b6 AL desync detected
+// b7 AH read or write data ready
+READ8_MEMBER(a2bus_agat840k_hle_device::d15_i_c)
+{
+ LOG("status B: @ %4d %s %s (%s)\n", m_count_read,
+ BIT(m_mxcs, 7) ? "ready" : "READY", BIT(m_mxcs, 6) ? "SYNC" : "sync",
+ m_seen_magic ? "MAGIC" : "magic");
+
+ 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_agat840k_hle_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/agat840k_hle.h b/src/devices/bus/a2bus/agat840k_hle.h
new file mode 100644
index 00000000000..42a1f2cc8c4
--- /dev/null
+++ b/src/devices/bus/a2bus/agat840k_hle.h
@@ -0,0 +1,99 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/*********************************************************************
+
+ agat840k_hle.h
+
+ High-level simulation of the Agat 840K floppy controller card
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2BUS_AGAT840K_HLE_H
+#define MAME_BUS_A2BUS_AGAT840K_HLE_H
+
+#pragma once
+
+#include "a2bus.h"
+#include "machine/i8255.h"
+
+
+#define MXCSR_SYNC 0x40
+#define MXCSR_TR 0x80
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_agat840k_hle_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_agat840k_hle_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_WRITE_LINE_MEMBER(index_0_w);
+ DECLARE_WRITE_LINE_MEMBER(index_1_w);
+
+ void index_callback(int unit, int state);
+
+protected:
+ // construction/destruction
+ a2bus_agat840k_hle_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(address_space &space, uint8_t offset) override;
+ virtual void write_c0nx(address_space &space, uint8_t offset, uint8_t data) override;
+ virtual uint8_t read_cnxx(address_space &space, uint8_t offset) override;
+
+ enum
+ {
+ TIMER_ID_WAIT = 0,
+ TIMER_ID_SEEK
+ };
+
+ required_device<i8255_device> m_d14;
+ required_device<i8255_device> m_d15;
+
+private:
+ legacy_floppy_image_device *floppy_image(int drive);
+ legacy_floppy_image_device *m_floppy;
+ bool m_side;
+
+ std::unique_ptr<uint16_t[]> m_tracks[160];
+ int m_count_read;
+ int m_count_write;
+ bool m_seen_magic;
+ int m_current_track;
+
+ u8 m_mxcs;
+ int m_unit;
+ int m_state;
+
+ int m_seektime;
+ int m_waittime;
+
+ emu_timer *m_timer_wait = nullptr;
+ emu_timer *m_timer_seek = nullptr;
+
+ uint8_t *m_rom;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(A2BUS_AGAT840K_HLE, a2bus_agat840k_hle_device)
+
+#endif // MAME_BUS_A2BUS_AGAT840K_HLE_H
diff --git a/src/lib/formats/agat840k_hle_dsk.cpp b/src/lib/formats/agat840k_hle_dsk.cpp
new file mode 100644
index 00000000000..52cdd4668be
--- /dev/null
+++ b/src/lib/formats/agat840k_hle_dsk.cpp
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/**********************************************************************
+
+ formats/agat840k_hle_dsk.cpp
+
+ Agat 840KB floppies -- high level simulation (sector-level images)
+
+ 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/agat840k_hle_dsk.h"
+
+
+static FLOPPY_IDENTIFY(agat840k_hle_dsk_identify)
+{
+ switch (floppy_image_size(floppy))
+ {
+ case 860160:
+ *vote = 100;
+ break;
+
+ case 860164:
+ case 860288:
+ *vote = 99;
+ break;
+
+ default:
+ *vote = 0;
+ break;
+ }
+
+ return FLOPPY_ERROR_SUCCESS;
+}
+
+static FLOPPY_CONSTRUCT(agat840k_hle_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(agat840k_hle)
+ LEGACY_FLOPPY_OPTION(agat840k_hle_dsk, "ds9,dsk,raw", "Agat 840K DSK image",
+ agat840k_hle_dsk_identify, agat840k_hle_dsk_construct, nullptr, nullptr)
+LEGACY_FLOPPY_OPTIONS_END
+
diff --git a/src/lib/formats/agat840k_hle_dsk.h b/src/lib/formats/agat840k_hle_dsk.h
new file mode 100644
index 00000000000..dad245e3335
--- /dev/null
+++ b/src/lib/formats/agat840k_hle_dsk.h
@@ -0,0 +1,17 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/*********************************************************************
+
+ formats/agat840k_hle_dsk.h
+
+*********************************************************************/
+
+#ifndef AGAT840K_HLE_DSK_H_
+#define AGAT840K_HLE_DSK_H_
+
+#include "flopimg.h"
+#include "formats/basicdsk.h"
+
+LEGACY_FLOPPY_OPTIONS_EXTERN(agat840k_hle);
+
+#endif /* AGAT840K_HLE_DSK_H_ */
diff --git a/src/mame/drivers/agat.cpp b/src/mame/drivers/agat.cpp
index 62f111e7255..9299a474805 100644
--- a/src/mame/drivers/agat.cpp
+++ b/src/mame/drivers/agat.cpp
@@ -2,18 +2,51 @@
// copyright-holders:R. Belmont, Sergey Svishchev
/***************************************************************************
- agat.c
- Skeleton driver for Agat series of Soviet Apple II non-clones
-
- These are similar to Apple II (same bus architecture, keyboard and
- floppy interface), but video controller is completely different.
-
- To do:
- - native keyboards (at least two variants)
- - 840K floppy controller (MFM encoding, but track layout is unique)
- - agat7: 64K and 128K onboard memory configurations
- - agat9
- - 3rd party slot devices
+ agat.cpp
+
+ Driver for Agat series of Soviet Apple II non-clones
+
+ These are similar to Apple II (same bus architecture, keyboard
+ and floppy interface), but native video controllers are different.
+
+ agat7 supports Apple (40col, HGR and DHR) video modes with add-on
+ card; agat9 has built-in support for 40col and HGR. Palette in
+ Apple modes is different and pixel stretching is not done.
+
+ To do (common):
+ - native keyboard (at least two variants)
+ - 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_effect_disabled()
+ - softlists
+
+ To do (agat7):
+ - hw variant: 16 colors
+ - hw variant: 256-char chargen
+ - hw variant: 64K and 128K onboard memory
+ - "500hz" interrupt breakage
+ - 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
+ - mouse via parallel port
+ - hw revisions and agat9a model (via http://agatcomp.ru/Images/case.shtml)
+
+ 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
+
+ Slot devices -- 3rd party:
+ - Nippel Clock (uses mc146818)
+ - Nippel mouse -- http://agatcomp.ru/Images/new_mouse.shtml
+ - Sprite Card-93 (uses fd1793)
+ - others
************************************************************************/
@@ -27,6 +60,7 @@
#include "bus/a2bus/a2diskii.h"
#include "bus/a2bus/agat7langcard.h"
#include "bus/a2bus/agat7ram.h"
+#include "bus/a2bus/agat840k_hle.h"
#include "screen.h"
#include "softlist.h"
@@ -78,14 +112,12 @@ public:
required_device<address_map_bank_device> m_upperbank;
TIMER_DEVICE_CALLBACK_MEMBER(ay3600_repeat);
- TIMER_DEVICE_CALLBACK_MEMBER(agat_timer);
- TIMER_DEVICE_CALLBACK_MEMBER(agat_vblank);
+ TIMER_DEVICE_CALLBACK_MEMBER(timer_irq);
+ INTERRUPT_GEN_MEMBER(agat_vblank);
virtual void machine_start() override;
virtual void machine_reset() override;
- DECLARE_READ8_MEMBER(c000_r);
- DECLARE_WRITE8_MEMBER(c000_w);
DECLARE_READ8_MEMBER(c080_r);
DECLARE_WRITE8_MEMBER(c080_w);
DECLARE_READ8_MEMBER(c100_r);
@@ -106,6 +138,20 @@ public:
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);
+ DECLARE_WRITE8_MEMBER(cassette_toggle_w);
+ DECLARE_READ8_MEMBER(speaker_toggle_r);
+ DECLARE_WRITE8_MEMBER(speaker_toggle_w);
+ DECLARE_READ8_MEMBER(interrupts_on_r);
+ DECLARE_WRITE8_MEMBER(interrupts_on_w);
+ DECLARE_READ8_MEMBER(interrupts_off_r);
+ DECLARE_WRITE8_MEMBER(interrupts_off_w);
+ DECLARE_READ8_MEMBER(flags_r);
+ DECLARE_READ8_MEMBER(controller_strobe_r);
+ DECLARE_WRITE8_MEMBER(controller_strobe_w);
private:
int m_speaker_state;
@@ -291,120 +337,123 @@ void agat7_state::machine_reset()
/***************************************************************************
I/O
***************************************************************************/
-// most softswitches don't care about read vs write, so handle them here
-void agat7_state::do_io(address_space &space, int offset)
+
+READ8_MEMBER(agat7_state::keyb_data_r)
{
- if (machine().side_effect_disabled())
- {
- return;
- }
+ return m_strobe ? (m_transchar | m_strobe) : 0;
+}
- switch (offset & 0xf0)
- {
- case 0x20:
- m_cassette_state ^= 1;
- m_cassette->output(m_cassette_state ? 1.0f : -1.0f);
- break;
+READ8_MEMBER(agat7_state::keyb_strobe_r)
+{
+ // reads any key down, clears strobe
+ uint8_t rv = m_transchar | (m_anykeydown ? 0x80 : 0x00);
+ if (!machine().side_effect_disabled())
+ m_strobe = 0;
+ return rv;
+}
- case 0x30:
- m_speaker_state ^= 1;
- m_speaker->level_w(m_speaker_state);
- break;
+WRITE8_MEMBER(agat7_state::keyb_strobe_w)
+{
+ // clear keyboard latch
+ m_strobe = 0;
+}
- // XXX agat7: 0x4N -- enable timer interrupts, 0x5N -- disable (or vice versa depending on hw rev)
- case 0x40:
- m_agat7_interrupts = true;
- break;
+READ8_MEMBER(agat7_state::cassette_toggle_r)
+{
+ if (!machine().side_effect_disabled())
+ cassette_toggle_w(space, offset, 0);
+ return read_floatingbus();
+}
- case 0x50:
- m_agat7_interrupts = false;
+WRITE8_MEMBER(agat7_state::cassette_toggle_w)
+{
+ m_cassette_state ^= 1;
+ m_cassette->output(m_cassette_state ? 1.0f : -1.0f);
+}
- case 0x70:
- 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();
- m_joystick_x2_time = machine().time().as_double() + m_x_calibration * m_joy2x->read();
- m_joystick_y2_time = machine().time().as_double() + m_y_calibration * m_joy2y->read();
- break;
- }
+READ8_MEMBER(agat7_state::speaker_toggle_r)
+{
+ if (!machine().side_effect_disabled())
+ speaker_toggle_w(space, offset, 0);
+ return read_floatingbus();
}
-READ8_MEMBER(agat7_state::c000_r)
+WRITE8_MEMBER(agat7_state::speaker_toggle_w)
{
- if (offset)
- logerror("%s: c000_r %04X == %02X\n", machine().describe_context(), offset+0xc000, 0);
- else if (m_strobe)
- logerror("%s: c000_r %04X == %02X\n", machine().describe_context(), offset+0xc000, m_transchar | m_strobe);
+ m_speaker_state ^= 1;
+ m_speaker->level_w(m_speaker_state);
+}
- switch (offset)
- {
- // keyboard latch. NB: agat7 returns 0 if latch is clear, agat9 returns char code.
- case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
- case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
- return m_strobe ? (m_transchar | m_strobe) : 0;
+READ8_MEMBER(agat7_state::interrupts_on_r)
+{
+ if (!machine().side_effect_disabled())
+ interrupts_on_w(space, offset, 0);
+ return read_floatingbus();
+}
- case 0x10: // reads any key down, clears strobe
- {
- uint8_t rv = m_transchar | (m_anykeydown ? 0x80 : 0x00);
- m_strobe = 0;
- return rv;
- }
+WRITE8_MEMBER(agat7_state::interrupts_on_w)
+{
+ m_agat7_interrupts = true;
+}
- case 0x60: // cassette in
- case 0x68:
- return m_cassette->input() > 0.0 ? 0x80 : 0;
+READ8_MEMBER(agat7_state::interrupts_off_r)
+{
+ if (!machine().side_effect_disabled())
+ interrupts_off_w(space, offset, 0);
+ return read_floatingbus();
+}
- case 0x61: // button 0
- case 0x69:
- return (m_joybuttons->read() & 0x10) ? 0x80 : 0;
+WRITE8_MEMBER(agat7_state::interrupts_off_w)
+{
+ m_agat7_interrupts = false;
+}
+
+READ8_MEMBER(agat7_state::flags_r)
+{
+ switch (offset)
+ {
+ case 0: // cassette in
+ return m_cassette->input() > 0.0 ? 0x80 : 0;
- case 0x62: // button 1
- case 0x6a:
- return (m_joybuttons->read() & 0x20) ? 0x80 : 0;
+ case 1: // button 0
+ return (m_joybuttons->read() & 0x10) ? 0x80 : 0;
- case 0x63: // button 2
- case 0x6b:
- return ((m_joybuttons->read() & 0x40) || (m_kbspecial->read() & 0x06)) ? 0 : 0x80;
+ case 2: // button 1
+ return (m_joybuttons->read() & 0x20) ? 0x80 : 0;
- case 0x64: // joy 1 X axis
- case 0x6c:
- return (space.machine().time().as_double() < m_joystick_x1_time) ? 0x80 : 0;
+ case 3: // button 2
+ return ((m_joybuttons->read() & 0x40) || !(m_kbspecial->read() & 0x06)) ? 0x80 : 0;
- case 0x65: // joy 1 Y axis
- case 0x6d:
- return (space.machine().time().as_double() < m_joystick_y1_time) ? 0x80 : 0;
+ case 4: // joy 1 X axis
+ return (space.machine().time().as_double() < m_joystick_x1_time) ? 0x80 : 0;
- case 0x66: // joy 2 X axis
- case 0x6e:
- return (space.machine().time().as_double() < m_joystick_x2_time) ? 0x80 : 0;
+ case 5: // joy 1 Y axis
+ return (space.machine().time().as_double() < m_joystick_y1_time) ? 0x80 : 0;
- case 0x67: // joy 2 Y axis
- case 0x6f:
- return (space.machine().time().as_double() < m_joystick_y2_time) ? 0x80 : 0;
+ case 6: // joy 2 X axis
+ return (space.machine().time().as_double() < m_joystick_x2_time) ? 0x80 : 0;
- default:
- do_io(space, offset);
- break;
+ case 7: // joy 2 Y axis
+ return (space.machine().time().as_double() < m_joystick_y2_time) ? 0x80 : 0;
}
- return read_floatingbus();
+ // this is never reached
+ return 0;
}
-WRITE8_MEMBER(agat7_state::c000_w)
+READ8_MEMBER(agat7_state::controller_strobe_r)
{
- logerror("%s: c000_w %04X <- %02X\n", machine().describe_context(), offset + 0xc000, data);
-
- switch (offset)
- {
- // clear keyboard latch
- case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
- case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
- m_strobe = 0;
- break;
+ if (!machine().side_effect_disabled())
+ controller_strobe_w(space, offset, 0);
+ return read_floatingbus();
+}
- default:
- do_io(space, offset);
- break;
- }
+WRITE8_MEMBER(agat7_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();
+ m_joystick_x2_time = machine().time().as_double() + m_x_calibration * m_joy2x->read();
+ m_joystick_y2_time = machine().time().as_double() + m_y_calibration * m_joy2y->read();
}
READ8_MEMBER(agat7_state::c080_r)
@@ -479,7 +528,7 @@ WRITE8_MEMBER(agat7_state::c100_w)
m_cnxx_slot = slotnum;
}
- m_slotdevice[slotnum]->write_cnxx(space, offset&0xff, data);
+ m_slotdevice[slotnum]->write_cnxx(space, offset & 0xff, data);
}
}
@@ -633,7 +682,14 @@ WRITE8_MEMBER(agat7_state::agat7_ram_w)
static ADDRESS_MAP_START( agat7_map, AS_PROGRAM, 8, agat7_state )
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x0000, 0xbfff) AM_READWRITE(agat7_ram_r, agat7_ram_w)
- AM_RANGE(0xc000, 0xc07f) AM_READWRITE(c000_r, c000_w)
+ AM_RANGE(0xc000, 0xc000) AM_MIRROR(0xf) AM_READ(keyb_data_r) AM_WRITENOP
+ AM_RANGE(0xc010, 0xc010) AM_MIRROR(0xf) AM_READWRITE(keyb_strobe_r, keyb_strobe_w)
+ AM_RANGE(0xc020, 0xc020) AM_MIRROR(0xf) AM_READWRITE(cassette_toggle_r, cassette_toggle_w)
+ AM_RANGE(0xc030, 0xc030) AM_MIRROR(0xf) AM_READWRITE(speaker_toggle_r, speaker_toggle_w)
+ AM_RANGE(0xc040, 0xc040) AM_MIRROR(0xf) AM_READWRITE(interrupts_on_r, interrupts_on_w)
+ AM_RANGE(0xc050, 0xc050) AM_MIRROR(0xf) AM_READWRITE(interrupts_off_r, interrupts_off_w)
+ AM_RANGE(0xc060, 0xc067) AM_MIRROR(0x8) AM_READ(flags_r) AM_WRITENOP
+ AM_RANGE(0xc070, 0xc070) AM_MIRROR(0xf) AM_READWRITE(controller_strobe_r, controller_strobe_w)
AM_RANGE(0xc080, 0xc0ef) AM_READWRITE(c080_r, c080_w)
AM_RANGE(0xc0f0, 0xc0ff) AM_READWRITE(agat7_membank_r, agat7_membank_w)
AM_RANGE(0xc100, 0xc6ff) AM_READWRITE(c100_r, c100_w)
@@ -725,20 +781,20 @@ static const uint8_t a2_key_remap[0x40][4] =
{ 0x1a,0x1a,0x1a,0x1a }, /* Down */
{ 0x10,0x10,0x10,0x10 }, /* KP1 */
{ 0x0d,0x0d,0x0d,0x0d }, /* Enter 31 */
- { 0x11,0x11,0x11,0x11 },
- { 0x12,0x12,0x12,0x12 },
- { 0x13,0x13,0x13,0x13 },
- { 0x14,0x14,0x14,0x14 },
- { 0x1c,0x1c,0x1c,0x1c },
- { 0x1d,0x1d,0x1d,0x1d },
- { 0x1e,0x1e,0x1e,0x1e },
- { 0x1f,0x1f,0x1f,0x1f },
- { 0x01,0x01,0x01,0x01 },
- { 0x02,0x02,0x02,0x02 },
- { 0x03,0x03,0x03,0x03 },
- { 0x04,0x04,0x04,0x04 },
- { 0x05,0x05,0x05,0x05 },
- { 0x06,0x06,0x06,0x06 },
+ { 0x11,0x11,0x11,0x11 }, /* KP2 */
+ { 0x12,0x12,0x12,0x12 }, /* KP3 */
+ { 0x13,0x13,0x13,0x13 }, /* KP4 */
+ { 0x14,0x14,0x14,0x14 }, /* KP5 */
+ { 0x1c,0x1c,0x1c,0x1c }, /* KP6 */
+ { 0x1d,0x1d,0x1d,0x1d }, /* KP7 */
+ { 0x1e,0x1e,0x1e,0x1e }, /* KP8 */
+ { 0x1f,0x1f,0x1f,0x1f }, /* KP9 */
+ { 0x01,0x01,0x01,0x01 }, /* KP0 */
+ { 0x02,0x02,0x02,0x02 }, /* KP. */
+ { 0x03,0x03,0x03,0x03 }, /* KP= */
+ { 0x04,0x04,0x04,0x04 }, /* PF1 */
+ { 0x05,0x05,0x05,0x05 }, /* PF2 */
+ { 0x06,0x06,0x06,0x06 }, /* PF3 */
};
WRITE_LINE_MEMBER(agat7_state::ay3600_data_ready_w)
@@ -777,19 +833,28 @@ TIMER_DEVICE_CALLBACK_MEMBER(agat7_state::ay3600_repeat)
}
}
-TIMER_DEVICE_CALLBACK_MEMBER(agat7_state::agat_timer)
+INTERRUPT_GEN_MEMBER(agat7_state::agat_vblank)
{
if (m_agat7_interrupts)
{
- m_maincpu->set_input_line(M6502_IRQ_LINE, ASSERT_LINE);
+ m_maincpu->set_input_line(M6502_NMI_LINE, PULSE_LINE);
}
}
-TIMER_DEVICE_CALLBACK_MEMBER(agat7_state::agat_vblank)
+TIMER_DEVICE_CALLBACK_MEMBER(agat7_state::timer_irq)
{
if (m_agat7_interrupts)
{
- m_maincpu->set_input_line(M6502_NMI_LINE, ASSERT_LINE);
+ switch (param & 0x3f)
+ {
+ case 0:
+ m_maincpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE);
+ break;
+
+ case 0x20:
+ m_maincpu->set_input_line(M6502_IRQ_LINE, ASSERT_LINE);
+ break;
+ }
}
}
@@ -833,8 +898,8 @@ static INPUT_PORTS_START( agat7_joystick )
PORT_CODE_DEC(JOYCODE_Y_UP_SWITCH) PORT_CODE_INC(JOYCODE_Y_DOWN_SWITCH)
PORT_START("joystick_buttons")
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_PLAYER(1) PORT_CODE(KEYCODE_0_PAD) PORT_CODE(JOYCODE_BUTTON1)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_PLAYER(1) PORT_CODE(KEYCODE_ENTER_PAD)PORT_CODE(JOYCODE_BUTTON2)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_PLAYER(1) PORT_CODE(KEYCODE_0_PAD) PORT_CODE(JOYCODE_BUTTON1) PORT_CHAR(UCHAR_MAMEKEY(0_PAD))
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_PLAYER(1) PORT_CODE(KEYCODE_ENTER_PAD)PORT_CODE(JOYCODE_BUTTON2) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD))
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_PLAYER(2) PORT_CODE(JOYCODE_BUTTON1)
INPUT_PORTS_END
@@ -879,7 +944,7 @@ static INPUT_PORTS_START( agat7_common )
PORT_BIT(0x040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('U') PORT_CHAR('u')
PORT_BIT(0x080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('I') PORT_CHAR('i')
PORT_BIT(0x100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('O') PORT_CHAR('o')
- PORT_BIT(0x200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('P') PORT_CHAR('@')
+ PORT_BIT(0x200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('P') PORT_CHAR('p')
PORT_START("X2")
PORT_BIT(0x001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('D') PORT_CHAR('d')
@@ -890,8 +955,8 @@ static INPUT_PORTS_START( agat7_common )
PORT_BIT(0x020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('K') PORT_CHAR('k')
PORT_BIT(0x040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('L') PORT_CHAR('l')
PORT_BIT(0x080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR('+')
- PORT_BIT(0x100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(UTF8_LEFT) PORT_CODE(KEYCODE_LEFT)
- PORT_BIT(0x200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(UTF8_RIGHT) PORT_CODE(KEYCODE_RIGHT)
+ PORT_BIT(0x100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(UTF8_LEFT) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
+ PORT_BIT(0x200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(UTF8_RIGHT) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
PORT_START("X3")
PORT_BIT(0x001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') PORT_CHAR('z')
@@ -912,8 +977,8 @@ static INPUT_PORTS_START( agat7_common )
PORT_BIT(0x008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CODE(KEYCODE_ESC) PORT_CHAR(27)
PORT_BIT(0x010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('A') PORT_CHAR('a')
PORT_BIT(0x020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
- PORT_BIT(0x040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(UTF8_UP) PORT_CODE(KEYCODE_UP)
- PORT_BIT(0x080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(UTF8_DOWN) PORT_CODE(KEYCODE_DOWN)
+ PORT_BIT(0x040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(UTF8_UP) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
+ PORT_BIT(0x080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(UTF8_DOWN) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
PORT_BIT(0x100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Num 1") PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD))
PORT_BIT(0x200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
@@ -932,8 +997,8 @@ static INPUT_PORTS_START( agat7_common )
PORT_START("X6")
PORT_BIT(0x001, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Num =") PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD))
PORT_BIT(0x002, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF1") PORT_CODE(KEYCODE_SLASH_PAD) PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD))
- PORT_BIT(0x004, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF2") PORT_CODE(KEYCODE_ASTERISK)
- PORT_BIT(0x008, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF3") PORT_CODE(KEYCODE_MINUS_PAD)
+ PORT_BIT(0x004, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF2") PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR(UCHAR_MAMEKEY(ASTERISK))
+ PORT_BIT(0x008, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF3") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD))
PORT_BIT(0x010, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_BIT(0x020, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_BIT(0x040, IP_ACTIVE_HIGH, IPT_UNUSED)
@@ -972,7 +1037,7 @@ static INPUT_PORTS_START( agat7_common )
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Control") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2)
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RESET") PORT_CODE(KEYCODE_F12)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RESET") PORT_CODE(KEYCODE_F12) PORT_CHAR(UCHAR_MAMEKEY(F12))
INPUT_PORTS_END
static INPUT_PORTS_START(agat7)
@@ -991,7 +1056,7 @@ static SLOT_INTERFACE_START(agat7_cards)
SLOT_INTERFACE("a7lang", A2BUS_AGAT7LANGCARD) // Agat-7 RAM Language Card -- decimal 3.089.119
SLOT_INTERFACE("a7ram", A2BUS_AGAT7RAM) // Agat-7 32K RAM Card -- decimal 3.089.119-01, KR565RU6D chips
SLOT_INTERFACE("a7fdc", A2BUS_AGAT7_FDC) // Disk II clone -- decimal 3.089.105
- // 840K floppy controller -- decimal 7.104.351
+ SLOT_INTERFACE("a7fdc840", A2BUS_AGAT840K_HLE) // 840K floppy controller -- decimal 7.104.351 or 3.089.023?
// Serial-parallel card -- decimal 3.089.106
// Printer card (agat9) -- decimal 3.089.174
@@ -1007,8 +1072,9 @@ SLOT_INTERFACE_END
static MACHINE_CONFIG_START( agat7 )
MCFG_CPU_ADD("maincpu", M6502, XTAL_14_3MHz / 14)
MCFG_CPU_PROGRAM_MAP(agat7_map)
+ MCFG_CPU_VBLANK_INT_DRIVER(A7_VIDEO_TAG ":a7screen", agat7_state, agat_vblank)
- MCFG_TIMER_DRIVER_ADD_PERIODIC("agat7irq", agat7_state, agat_timer, attotime::from_hz(500))
+ MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", agat7_state, timer_irq, A7_VIDEO_TAG ":a7screen", 0, 1)
MCFG_DEVICE_ADD(A7_VIDEO_TAG, AGAT7VIDEO, 0)
@@ -1111,5 +1177,5 @@ ROM_START( agat9 )
ROM_END
// YEAR NAME PARENT COMPAT MACHINE INPUT STATE INIT COMPANY FULLNAME FLAGS
-COMP( 1983, agat7, apple2, 0, agat7, agat7, agat7_state, 0, "Agat", "Agat-7", MACHINE_NOT_WORKING)
+COMP( 1983, agat7, apple2, 0, agat7, agat7, agat7_state, 0, "Agat", "Agat-7", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_CONTROLS)
COMP( 1984, agat9, apple2, 0, agat7, agat7, agat7_state, 0, "Agat", "Agat-9", MACHINE_NOT_WORKING)