From 00c9b62a2405b6c4120564845694e90da1346d8b Mon Sep 17 00:00:00 2001 From: Sergey Svishchev Date: Sat, 9 Dec 2017 02:46:23 +0300 Subject: [PATCH] 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 --- scripts/src/bus.lua | 2 + scripts/src/formats.lua | 12 + scripts/target/mame/mess.lua | 1 + src/devices/bus/a2bus/agat7langcard.cpp | 19 +- src/devices/bus/a2bus/agat7langcard.h | 4 +- src/devices/bus/a2bus/agat7ram.cpp | 27 +- src/devices/bus/a2bus/agat7ram.h | 4 +- src/devices/bus/a2bus/agat840k_hle.cpp | 449 ++++++++++++++++++++++++ src/devices/bus/a2bus/agat840k_hle.h | 99 ++++++ src/lib/formats/agat840k_hle_dsk.cpp | 59 ++++ src/lib/formats/agat840k_hle_dsk.h | 17 + src/mame/drivers/agat.cpp | 358 +++++++++++-------- 12 files changed, 878 insertions(+), 173 deletions(-) create mode 100644 src/devices/bus/a2bus/agat840k_hle.cpp create mode 100644 src/devices/bus/a2bus/agat840k_hle.h create mode 100644 src/lib/formats/agat840k_hle_dsk.cpp create mode 100644 src/lib/formats/agat840k_hle_dsk.h diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 4dbf4fe0ad0..28f07a10d68 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -1787,6 +1787,8 @@ if (BUSES["A2BUS"]~=null) then MAME_DIR .. "src/devices/bus/a2bus/agat7langcard.h", MAME_DIR .. "src/devices/bus/a2bus/agat7ram.cpp", 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/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 29a22b23ad0..6558ff859d2 100644 --- a/scripts/src/formats.lua +++ b/scripts/src/formats.lua @@ -185,6 +185,18 @@ if (FORMATS["AFS_DSK"]~=null or _OPTIONS["with-tools"]) then } end +-------------------------------------------------- +-- +--@src/lib/formats/agat840k_hle_dsk.h,FORMATS["AGAT840K_HLE_DSK"] = true +-------------------------------------------------- + +if (FORMATS["AGAT840K_HLE_DSK"]~=null or _OPTIONS["with-tools"]) then + files { + MAME_DIR.. "src/lib/formats/agat840k_hle_dsk.cpp", + MAME_DIR.. "src/lib/formats/agat840k_hle_dsk.h", + } +end + -------------------------------------------------- -- --@src/lib/formats/ami_dsk.h,FORMATS["AMI_DSK"] = true diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 65c89bc15ce..ea2ee8ef9ec 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -775,6 +775,7 @@ FORMATS["ACORN_DSK"] = true FORMATS["ADAM_CAS"] = true FORMATS["ADAM_DSK"] = true FORMATS["AFS_DSK"] = true +FORMATS["AGAT840K_HLE_DSK"] = true FORMATS["AMI_DSK"] = true FORMATS["AP2_DSK"] = true FORMATS["APD_DSK"] = true 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(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(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 m_d14; + required_device m_d15; + +private: + legacy_floppy_image_device *floppy_image(int drive); + legacy_floppy_image_device *m_floppy; + bool m_side; + + std::unique_ptr 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 + +#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 + agat.cpp - These are similar to Apple II (same bus architecture, keyboard and - floppy interface), but video controller is completely different. + Driver for Agat series of Soviet Apple II non-clones - 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 + 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 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; - } - - switch (offset & 0xf0) - { - case 0x20: - m_cassette_state ^= 1; - m_cassette->output(m_cassette_state ? 1.0f : -1.0f); - break; - - case 0x30: - m_speaker_state ^= 1; - m_speaker->level_w(m_speaker_state); - break; - - // XXX agat7: 0x4N -- enable timer interrupts, 0x5N -- disable (or vice versa depending on hw rev) - case 0x40: - m_agat7_interrupts = true; - break; - - case 0x50: - m_agat7_interrupts = false; - - 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; - } + return m_strobe ? (m_transchar | m_strobe) : 0; } -READ8_MEMBER(agat7_state::c000_r) +READ8_MEMBER(agat7_state::keyb_strobe_r) { - 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); + // 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; +} - 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; - - case 0x10: // reads any key down, clears strobe - { - uint8_t rv = m_transchar | (m_anykeydown ? 0x80 : 0x00); - m_strobe = 0; - return rv; - } - - case 0x60: // cassette in - case 0x68: - return m_cassette->input() > 0.0 ? 0x80 : 0; - - case 0x61: // button 0 - case 0x69: - return (m_joybuttons->read() & 0x10) ? 0x80 : 0; - - case 0x62: // button 1 - case 0x6a: - return (m_joybuttons->read() & 0x20) ? 0x80 : 0; - - case 0x63: // button 2 - case 0x6b: - return ((m_joybuttons->read() & 0x40) || (m_kbspecial->read() & 0x06)) ? 0 : 0x80; - - case 0x64: // joy 1 X axis - case 0x6c: - return (space.machine().time().as_double() < m_joystick_x1_time) ? 0x80 : 0; - - case 0x65: // joy 1 Y axis - case 0x6d: - return (space.machine().time().as_double() < m_joystick_y1_time) ? 0x80 : 0; - - case 0x66: // joy 2 X axis - case 0x6e: - return (space.machine().time().as_double() < m_joystick_x2_time) ? 0x80 : 0; - - case 0x67: // joy 2 Y axis - case 0x6f: - return (space.machine().time().as_double() < m_joystick_y2_time) ? 0x80 : 0; - - default: - do_io(space, offset); - break; - } +WRITE8_MEMBER(agat7_state::keyb_strobe_w) +{ + // clear keyboard latch + m_strobe = 0; +} +READ8_MEMBER(agat7_state::cassette_toggle_r) +{ + if (!machine().side_effect_disabled()) + cassette_toggle_w(space, offset, 0); return read_floatingbus(); } -WRITE8_MEMBER(agat7_state::c000_w) +WRITE8_MEMBER(agat7_state::cassette_toggle_w) { - logerror("%s: c000_w %04X <- %02X\n", machine().describe_context(), offset + 0xc000, data); + m_cassette_state ^= 1; + m_cassette->output(m_cassette_state ? 1.0f : -1.0f); +} +READ8_MEMBER(agat7_state::speaker_toggle_r) +{ + if (!machine().side_effect_disabled()) + speaker_toggle_w(space, offset, 0); + return read_floatingbus(); +} + +WRITE8_MEMBER(agat7_state::speaker_toggle_w) +{ + m_speaker_state ^= 1; + m_speaker->level_w(m_speaker_state); +} + +READ8_MEMBER(agat7_state::interrupts_on_r) +{ + if (!machine().side_effect_disabled()) + interrupts_on_w(space, offset, 0); + return read_floatingbus(); +} + +WRITE8_MEMBER(agat7_state::interrupts_on_w) +{ + m_agat7_interrupts = true; +} + +READ8_MEMBER(agat7_state::interrupts_off_r) +{ + if (!machine().side_effect_disabled()) + interrupts_off_w(space, offset, 0); + return read_floatingbus(); +} + +WRITE8_MEMBER(agat7_state::interrupts_off_w) +{ + m_agat7_interrupts = false; +} + +READ8_MEMBER(agat7_state::flags_r) +{ 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; + case 0: // cassette in + return m_cassette->input() > 0.0 ? 0x80 : 0; - default: - do_io(space, offset); - break; + case 1: // button 0 + return (m_joybuttons->read() & 0x10) ? 0x80 : 0; + + case 2: // button 1 + return (m_joybuttons->read() & 0x20) ? 0x80 : 0; + + case 3: // button 2 + return ((m_joybuttons->read() & 0x40) || !(m_kbspecial->read() & 0x06)) ? 0x80 : 0; + + case 4: // joy 1 X axis + return (space.machine().time().as_double() < m_joystick_x1_time) ? 0x80 : 0; + + case 5: // joy 1 Y axis + return (space.machine().time().as_double() < m_joystick_y1_time) ? 0x80 : 0; + + case 6: // joy 2 X axis + return (space.machine().time().as_double() < m_joystick_x2_time) ? 0x80 : 0; + + case 7: // joy 2 Y axis + return (space.machine().time().as_double() < m_joystick_y2_time) ? 0x80 : 0; } + + // this is never reached + return 0; +} + +READ8_MEMBER(agat7_state::controller_strobe_r) +{ + if (!machine().side_effect_disabled()) + controller_strobe_w(space, offset, 0); + return read_floatingbus(); +} + +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)