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