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
This commit is contained in:
Sergey Svishchev 2017-12-09 02:46:23 +03:00 committed by ajrhacker
parent 13a70d3118
commit 00c9b62a24
12 changed files with 878 additions and 173 deletions

View File

@ -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",

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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

View File

@ -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_ */

View File

@ -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<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;
}
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)