poly88, poly8813: Bus expansion

- Replace additional driver RAM with S-100 bus
- Convert Video Terminal Interface into a S-100 bus device
- Add skeleton S-100 bus device for SSSD disk controller
This commit is contained in:
AJR 2019-07-18 20:19:13 -04:00
parent 2992f29ec3
commit 63bda946e2
11 changed files with 656 additions and 226 deletions

View File

@ -1686,6 +1686,10 @@ if (BUSES["S100"]~=null) then
MAME_DIR .. "src/devices/bus/s100/nsmdsa.h",
MAME_DIR .. "src/devices/bus/s100/nsmdsad.cpp",
MAME_DIR .. "src/devices/bus/s100/nsmdsad.h",
MAME_DIR .. "src/devices/bus/s100/polyfdc.cpp",
MAME_DIR .. "src/devices/bus/s100/polyfdc.h",
MAME_DIR .. "src/devices/bus/s100/polyvti.cpp",
MAME_DIR .. "src/devices/bus/s100/polyvti.h",
MAME_DIR .. "src/devices/bus/s100/seals8k.cpp",
MAME_DIR .. "src/devices/bus/s100/seals8k.h",
MAME_DIR .. "src/devices/bus/s100/wunderbus.cpp",

View File

@ -2950,7 +2950,6 @@ files {
MAME_DIR .. "src/mame/drivers/poly88.cpp",
MAME_DIR .. "src/mame/includes/poly88.h",
MAME_DIR .. "src/mame/machine/poly88.cpp",
MAME_DIR .. "src/mame/video/poly88.cpp",
}
createMESSProjects(_target, _subtarget, "psion")

View File

@ -0,0 +1,108 @@
// license:BSD-3-Clause
// copyright-holders:AJR
/***************************************************************************
PolyMorphic Systems Disk Controller
This board controls up to three Shugart SA-400 drives using only
generic serial and parallel interface chips and TTL (and an onboard
4 MHz XTAL). No schematics for this board have been found.
****************************************************************************/
#include "emu.h"
#include "polyfdc.h"
#include "machine/i8255.h"
#include "machine/mc6852.h"
class poly_fdc_device : public device_t, public device_s100_card_interface
{
public:
// construction/destruction
poly_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
static constexpr feature_type unemulated_features() { return feature::DISK; }
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_add_mconfig(machine_config &config) override;
// device_s100_card_interface overrides
virtual u8 s100_sinp_r(offs_t offset) override;
virtual void s100_sout_w(offs_t offset, u8 data) override;
private:
void pa_w(u8 data);
u8 pb_r();
void pc_w(u8 data);
// object finders
required_device<mc6852_device> m_ssda;
required_device<i8255_device> m_ppi;
};
DEFINE_DEVICE_TYPE_PRIVATE(S100_POLY_FDC, device_s100_card_interface, poly_fdc_device, "polyfdc", "PolyMorphic Systems Disk Controller")
poly_fdc_device::poly_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, S100_POLY_FDC, tag, owner, clock)
, device_s100_card_interface(mconfig, *this)
, m_ssda(*this, "ssda")
, m_ppi(*this, "ppi")
{
}
void poly_fdc_device::device_start()
{
}
u8 poly_fdc_device::s100_sinp_r(offs_t offset)
{
if ((offset & 0xf000) == 0x2000)
{
if (BIT(offset, 11))
return m_ppi->read(offset & 3);
else
return m_ssda->read(offset & 1);
}
return 0xff;
}
void poly_fdc_device::s100_sout_w(offs_t offset, u8 data)
{
if ((offset & 0xf000) == 0x2000)
{
if (BIT(offset, 11))
m_ppi->write(offset & 3, data);
else
m_ssda->write(offset & 1, data);
}
}
void poly_fdc_device::pa_w(u8 data)
{
}
u8 poly_fdc_device::pb_r()
{
return 0xff;
}
void poly_fdc_device::pc_w(u8 data)
{
// Port B interrupt
m_bus->vi5_w(BIT(data, 0) ? ASSERT_LINE : CLEAR_LINE);
}
void poly_fdc_device::device_add_mconfig(machine_config &config)
{
MC6852(config, m_ssda, 4_MHz_XTAL / 4); // actual clock unknown
I8255(config, m_ppi);
m_ppi->out_pa_callback().set(FUNC(poly_fdc_device::pa_w));
m_ppi->in_pb_callback().set(FUNC(poly_fdc_device::pb_r));
m_ppi->out_pc_callback().set(FUNC(poly_fdc_device::pc_w));
m_ppi->tri_pc_callback().set_constant(0xfe);
}

View File

@ -0,0 +1,18 @@
// license:BSD-3-Clause
// copyright-holders:AJR
/**********************************************************************
PolyMorphic Systems Disk Controller
**********************************************************************/
#ifndef MAME_BUS_S100_POLYFDC_H
#define MAME_BUS_S100_POLYFDC_H
#pragma once
#include "bus/s100/s100.h"
DECLARE_DEVICE_TYPE(S100_POLY_FDC, device_s100_card_interface)
#endif // MAME_BUS_S100_POLYFDC_H

View File

@ -0,0 +1,329 @@
// license:BSD-3-Clause
// copyright-holders:Miodrag Milanovic, AJR
/***************************************************************************
PolyMorphic Systems Video Terminal Interface
Original implementation by Miodrag Milanovic
Converted to S-100 bus device by AJR
This video and keyboard interface board was a primary component of
PolyMorphic's System 88, but was also sold for use in other S-100
systems.
Any generic keyboard with a parallel ASCII interface can be used.
The actual keyboard provided by PolyMorphic Systems is almost entirely
based on TTL/LSTTL components.
The video timing circuit has no fixed dot clock, which is instead
generated by a VCO connected to a user-adjustable potentiometer. The
blanking and sync frequencies, on the other hand, are divisions of
either pin 49 of the S-100 bus or an optionally installable 2 MHz XTAL.
****************************************************************************/
#include "emu.h"
#include "polyvti.h"
#include "machine/i8212.h"
#include "machine/keyboard.h"
#include "emupal.h"
#include "screen.h"
class poly_vti_device : public device_t, public device_s100_card_interface
{
static const u8 s_mcm6571a_shift[];
public:
// construction/destruction
poly_vti_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
// device-level overrides
virtual void device_start() override;
virtual ioport_constructor device_input_ports() const override;
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
// device_s100_card_interface overrides
virtual u8 s100_smemr_r(offs_t offset) override;
virtual void s100_mwrt_w(offs_t offset, u8 data) override;
virtual u8 s100_sinp_r(offs_t offset) override;
private:
u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void kbd_put(u8 data);
DECLARE_WRITE_LINE_MEMBER(kbd_int_w);
// object finders
required_device<i8212_device> m_kbdlatch;
required_region_ptr<u8> m_FNT;
required_ioport m_address;
// internal state
std::unique_ptr<u8[]> m_video_ram;
};
DEFINE_DEVICE_TYPE_PRIVATE(S100_POLY_VTI, device_s100_card_interface, poly_vti_device, "polyvti", "PolyMorphic Systems Video Terminal Interface")
poly_vti_device::poly_vti_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, S100_POLY_VTI, tag, owner, clock)
, device_s100_card_interface(mconfig, *this)
, m_kbdlatch(*this, "kbdlatch")
, m_FNT(*this, "chargen")
, m_address(*this, "ADDRESS")
{
}
void poly_vti_device::device_start()
{
m_video_ram = make_unique_clear<u8[]>(0x400);
save_pointer(NAME(m_video_ram), 0x400);
}
const u8 poly_vti_device::s_mcm6571a_shift[] =
{
0,1,1,0,0,0,1,0,0,0,0,1,0,0,0,0,
1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,
1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0
};
u32 poly_vti_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
for (int y = 0; y < 16; y++)
{
u16 addr = y*64;
int xpos = 0;
for (int x = 0; x < 64; x++)
{
u8 code = m_video_ram[addr + x];
if ((code & 0x80)==0)
{
for (int j = 0; j < 15; j++)
{
u8 l = j/5;
for (int b = 0; b < 10; b++)
{
u8 r = b/5;
if (l==0 && r==0)
bitmap.pix16(y*15+j, xpos+b ) = BIT(code,5) ? 0 : 1;
if (l==0 && r==1)
bitmap.pix16(y*15+j, xpos+b ) = BIT(code,2) ? 0 : 1;
if (l==1 && r==0)
bitmap.pix16(y*15+j, xpos+b ) = BIT(code,4) ? 0 : 1;
if (l==1 && r==1)
bitmap.pix16(y*15+j, xpos+b ) = BIT(code,1) ? 0 : 1;
if (l==2 && r==0)
bitmap.pix16(y*15+j, xpos+b ) = BIT(code,3) ? 0 : 1;
if (l==2 && r==1)
bitmap.pix16(y*15+j, xpos+b ) = BIT(code,0) ? 0 : 1;
}
}
}
else
{
for (int j = 0; j < 15; j++)
{
code &= 0x7f;
int l = 0;
if (s_mcm6571a_shift[code]==0)
{
if (j < 9)
l = m_FNT[code*16 + j];
}
else
{
if ((j > 2) && (j < 12))
l = m_FNT[code*16 + j - 3];
}
for (int b = 0; b < 7; b++)
bitmap.pix16(y*15+j, xpos+b ) = (l >> (6-b)) & 1;
bitmap.pix16(y*15+j, xpos+7 ) = 0;
bitmap.pix16(y*15+j, xpos+8 ) = 0;
bitmap.pix16(y*15+j, xpos+9 ) = 0;
}
}
xpos += 10;
}
}
return 0;
}
u8 poly_vti_device::s100_smemr_r(offs_t offset)
{
if ((offset & 0xfc00) >> 10 == m_address->read())
return m_video_ram[offset & 0x3ff];
return 0xff;
}
void poly_vti_device::s100_mwrt_w(offs_t offset, u8 data)
{
if ((offset & 0xfc00) >> 10 == m_address->read())
m_video_ram[offset & 0x3ff] = data;
}
u8 poly_vti_device::s100_sinp_r(offs_t offset)
{
if ((offset & 0xfc00) >> 10 == m_address->read())
return m_kbdlatch->read(machine().dummy_space(), 0);
return 0xff;
}
void poly_vti_device::kbd_put(u8 data)
{
if (data)
{
if (data==8)
data=127; // fix backspace
m_kbdlatch->strobe(machine().dummy_space(), 0, data);
}
}
WRITE_LINE_MEMBER(poly_vti_device::kbd_int_w)
{
// TODO: jumper selectable
m_bus->vi2_w(state);
}
static INPUT_PORTS_START(polyvti)
PORT_START("ADDRESS")
PORT_DIPNAME(0x3f, 0x3e, "Address Range") PORT_DIPLOCATION("SW:2,3,4,5,6,7")
PORT_DIPSETTING(0x00, "0000-03FF")
PORT_DIPSETTING(0x01, "0400-07FF")
PORT_DIPSETTING(0x02, "0800-0BFF")
PORT_DIPSETTING(0x03, "0C00-0FFF")
PORT_DIPSETTING(0x04, "1000-13FF")
PORT_DIPSETTING(0x05, "1400-17FF")
PORT_DIPSETTING(0x06, "1800-1BFF")
PORT_DIPSETTING(0x07, "1C00-1FFF")
PORT_DIPSETTING(0x08, "2000-23FF")
PORT_DIPSETTING(0x09, "2400-27FF")
PORT_DIPSETTING(0x0a, "2800-2BFF")
PORT_DIPSETTING(0x0b, "2C00-2FFF")
PORT_DIPSETTING(0x0c, "3000-33FF")
PORT_DIPSETTING(0x0d, "3400-37FF")
PORT_DIPSETTING(0x0e, "3800-3BFF")
PORT_DIPSETTING(0x0f, "3C00-3FFF")
PORT_DIPSETTING(0x10, "4000-43FF")
PORT_DIPSETTING(0x11, "4400-47FF")
PORT_DIPSETTING(0x12, "4800-4BFF")
PORT_DIPSETTING(0x13, "4C00-4FFF")
PORT_DIPSETTING(0x14, "5000-53FF")
PORT_DIPSETTING(0x15, "5400-57FF")
PORT_DIPSETTING(0x16, "5800-5BFF")
PORT_DIPSETTING(0x17, "5C00-5FFF")
PORT_DIPSETTING(0x18, "6000-63FF")
PORT_DIPSETTING(0x19, "6400-67FF")
PORT_DIPSETTING(0x1a, "6800-6BFF")
PORT_DIPSETTING(0x1b, "6C00-6FFF")
PORT_DIPSETTING(0x1c, "7000-73FF")
PORT_DIPSETTING(0x1d, "7400-77FF")
PORT_DIPSETTING(0x1e, "7800-7BFF")
PORT_DIPSETTING(0x1f, "7C00-7FFF")
PORT_DIPSETTING(0x20, "8000-83FF")
PORT_DIPSETTING(0x21, "8400-87FF")
PORT_DIPSETTING(0x22, "8800-8BFF")
PORT_DIPSETTING(0x23, "8C00-8FFF")
PORT_DIPSETTING(0x24, "9000-93FF")
PORT_DIPSETTING(0x25, "9400-97FF")
PORT_DIPSETTING(0x26, "9800-9BFF")
PORT_DIPSETTING(0x27, "9C00-9FFF")
PORT_DIPSETTING(0x28, "A000-A3FF")
PORT_DIPSETTING(0x29, "A400-A7FF")
PORT_DIPSETTING(0x2a, "A800-ABFF")
PORT_DIPSETTING(0x2b, "AC00-AFFF")
PORT_DIPSETTING(0x2c, "B000-B3FF")
PORT_DIPSETTING(0x2d, "B400-B7FF")
PORT_DIPSETTING(0x2e, "B800-BBFF")
PORT_DIPSETTING(0x2f, "BC00-BFFF")
PORT_DIPSETTING(0x30, "C000-C3FF")
PORT_DIPSETTING(0x31, "C400-C7FF")
PORT_DIPSETTING(0x32, "C800-CBFF")
PORT_DIPSETTING(0x33, "CC00-CFFF")
PORT_DIPSETTING(0x34, "D000-D3FF")
PORT_DIPSETTING(0x35, "D400-D7FF")
PORT_DIPSETTING(0x36, "D800-DBFF")
PORT_DIPSETTING(0x37, "DC00-DFFF")
PORT_DIPSETTING(0x38, "E000-E3FF")
PORT_DIPSETTING(0x39, "E400-E7FF")
PORT_DIPSETTING(0x3a, "E800-EBFF")
PORT_DIPSETTING(0x3b, "EC00-EFFF")
PORT_DIPSETTING(0x3c, "F000-F3FF")
PORT_DIPSETTING(0x3d, "F400-F7FF")
PORT_DIPSETTING(0x3e, "F800-FBFF")
PORT_DIPSETTING(0x3f, "FC00-FFFF")
PORT_START("UNUSED")
PORT_DIPNAME(1, 1, DEF_STR(Unused)) PORT_DIPLOCATION("SW:1")
PORT_DIPSETTING(1, DEF_STR(Off))
PORT_DIPSETTING(0, DEF_STR(On))
INPUT_PORTS_END
ioport_constructor poly_vti_device::device_input_ports() const
{
return INPUT_PORTS_NAME(polyvti);
}
/* F4 Character Displayer */
static const gfx_layout vti_charlayout =
{
8, 16, /* text = 7 x 9 */
128, /* 128 characters */
1, /* 1 bits per pixel */
{ 0 }, /* no bitplanes */
/* x offsets */
{ 0, 1, 2, 3, 4, 5, 6, 7 },
/* y offsets */
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8 },
8*16 /* every char takes 16 bytes */
};
static GFXDECODE_START(gfx_vti)
GFXDECODE_ENTRY("chargen", 0x0000, vti_charlayout, 0, 1)
GFXDECODE_END
void poly_vti_device::device_add_mconfig(machine_config &config)
{
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_refresh_hz(60);
screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
screen.set_size(64*10, 16*15);
screen.set_visarea(0, 64*10-1, 0, 16*15-1);
screen.set_screen_update(FUNC(poly_vti_device::screen_update));
screen.set_palette("palette");
GFXDECODE(config, "gfxdecode", "palette", gfx_vti);
PALETTE(config, "palette", palette_device::MONOCHROME);
generic_keyboard_device &keyboard(GENERIC_KEYBOARD(config, "keyboard", 0));
keyboard.set_keyboard_callback(FUNC(poly_vti_device::kbd_put));
I8212(config, m_kbdlatch);
m_kbdlatch->md_rd_callback().set_constant(0);
m_kbdlatch->int_wr_callback().set(FUNC(poly_vti_device::kbd_int_w));
}
ROM_START(polyvti)
ROM_REGION(0x800, "chargen", 0)
ROM_LOAD("6571.bin", 0x0000, 0x0800, CRC(5a25144b) SHA1(7b9fee0c8ef2605b85d12b6d9fe8feb82418c63a))
ROM_END
const tiny_rom_entry *poly_vti_device::device_rom_region() const
{
return ROM_NAME(polyvti);
}

View File

@ -0,0 +1,18 @@
// license:BSD-3-Clause
// copyright-holders:AJR
/**********************************************************************
PolyMorphic Systems Video Terminal Interface
**********************************************************************/
#ifndef MAME_BUS_S100_POLYVTI_H
#define MAME_BUS_S100_POLYVTI_H
#pragma once
#include "bus/s100/s100.h"
DECLARE_DEVICE_TYPE(S100_POLY_VTI, device_s100_card_interface)
#endif // MAME_BUS_S100_POLYVTI_H

View File

@ -228,6 +228,7 @@ public:
}
s100_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
// device-level overrides
virtual void device_start() override;

View File

@ -10,9 +10,7 @@ Poly-88 driver by Miodrag Milanovic
All input must be UPPERcase.
ToDo:
- POLY88 - Polyphase format not working because 8251 device doesn't support sync.
- POLY8813 - Schematic shows a 8251 on the main board.
- POLY8813 - Schematic of FDC shows a mc6852 and i8255, no dedicated fdc chip.
- Polyphase format not working because 8251 device doesn't support sync.
Poly-8813 is a disk-based computer with 3 mini-floppy drives.
@ -45,119 +43,87 @@ at least some models of the Poly-88 are known to have used.)
#include "emu.h"
#include "includes/poly88.h"
#include "bus/s100/polyfdc.h"
#include "bus/s100/polyvti.h"
#include "bus/s100/seals8k.h"
#include "cpu/i8085/i8085.h"
//#include "bus/s100/s100.h"
#include "imagedev/cassette.h"
#include "machine/keyboard.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
void poly88_state::poly88_mem(address_map &map)
void poly88_state::s100_mem(address_map &map)
{
map.unmap_value_high();
map(0x0000, 0x03ff).rom(); // Monitor ROM
map(0x0400, 0x0bff).rom(); // ROM Expansion
map(0x0c00, 0x0dff).ram().mirror(0x200); // System RAM (mirrored)
map(0x1000, 0x1fff).rom(); // System Expansion area
map(0x2000, 0x3fff).ram(); // Minimal user RAM area
map(0x4000, 0xf7ff).ram();
map(0xf800, 0xfbff).ram().share("video_ram"); // Video RAM
map(0x0000, 0xffff).rw(FUNC(poly88_state::mem_r), FUNC(poly88_state::mem_w));
}
void poly88_state::s100_io(address_map &map)
{
map(0x00, 0xff).rw(FUNC(poly88_state::in_r), FUNC(poly88_state::out_w));
}
void poly88_state::poly88_io(address_map &map)
{
map.unmap_value_high();
map.global_mask(0xff);
map(0x00, 0x01).rw(m_usart, FUNC(i8251_device::read), FUNC(i8251_device::write));
map(0x04, 0x04).w(FUNC(poly88_state::baud_rate_w));
map(0x08, 0x08).w(FUNC(poly88_state::intr_w));
map(0xf8, 0xf8).r(FUNC(poly88_state::keyboard_r));
}
void poly88_state::poly8813_mem(address_map &map)
{
map.unmap_value_high();
map(0x0000, 0x03ff).rom(); // Monitor ROM
map(0x0400, 0x0bff).rom(); // Disk System ROM
map(0x0c00, 0x0fff).ram(); // System RAM
map(0x1800, 0x1bff).ram().share("video_ram"); // Video RAM
map(0x2000, 0xffff).ram(); // RAM
map(0x00, 0x01).mirror(2).rw(m_usart, FUNC(i8251_device::read), FUNC(i8251_device::write));
map(0x04, 0x04).mirror(3).w(FUNC(poly88_state::baud_rate_w));
map(0x08, 0x08).mirror(3).w(FUNC(poly88_state::intr_w));
}
void poly88_state::poly8813_io(address_map &map)
{
map.unmap_value_high();
map.global_mask(0xff);
map(0x00, 0x01).rw(m_usart, FUNC(i8251_device::read), FUNC(i8251_device::write));
map(0x04, 0x04).w(FUNC(poly88_state::baud_rate_w));
map(0x00, 0x01).mirror(2).rw(m_usart, FUNC(i8251_device::read), FUNC(i8251_device::write));
map(0x04, 0x04).mirror(3).w(FUNC(poly88_state::baud_rate_w));
map(0x08, 0x0b); //.r(ROM on for CPM).w(RTC reset);
map(0x0c, 0x0f); //.r(ROM off for CPM).w(Single-step trigger);
map(0x18, 0x18).r(FUNC(poly88_state::keyboard_r));
map(0x20, 0x2f);//single-density fdc
}
/* Input ports */
static INPUT_PORTS_START( poly88 )
PORT_START("CONFIG")
PORT_CONFNAME( 0x80, 0x00, "Tape Mode")
PORT_CONFNAME(0x80, 0x00, "Tape Mode")
PORT_CONFSETTING( 0x00, "Byte (300 baud)")
PORT_CONFSETTING( 0x80, "Polyphase (2400 baud)")
PORT_START("ONBOARD")
PORT_CONFNAME(7, 0, "Onboard Addresses")
PORT_CONFSETTING(0, "0000-0FFF (M), 00-0F (I/O)") // jumper J
PORT_CONFSETTING(4, "8000-8FFF (M), 80-8F (I/O)") // jumper S
PORT_CONFSETTING(7, "E000-EFFF (M), E0-EF (I/O)") // jumper T
INPUT_PORTS_END
void poly88_state::kbd_put(u8 data)
static void poly88_s100_devices(device_slot_interface &device)
{
if (data)
{
if (data==8)
data=127; // fix backspace
m_last_code = data;
m_int_vector = 0xef;
m_maincpu->set_input_line(0, HOLD_LINE);
}
device.option_add("vti", S100_POLY_VTI);
device.option_add("8ksc", S100_8K_SC);
device.option_add("8kscbb", S100_8K_SC_BB);
device.option_add("polyfdc", S100_POLY_FDC);
}
DEVICE_INPUT_DEFAULTS_START(poly88_vti_1800)
DEVICE_INPUT_DEFAULTS("ADDRESS", 0x3f, 0x06) // 1800-1FFF
DEVICE_INPUT_DEFAULTS_END
/* F4 Character Displayer */
static const gfx_layout poly88_charlayout =
{
8, 16, /* text = 7 x 9 */
128, /* 128 characters */
1, /* 1 bits per pixel */
{ 0 }, /* no bitplanes */
/* x offsets */
{ 0, 1, 2, 3, 4, 5, 6, 7 },
/* y offsets */
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8 },
8*16 /* every char takes 16 bytes */
};
static GFXDECODE_START( gfx_poly88 )
GFXDECODE_ENTRY( "chargen", 0x0000, poly88_charlayout, 0, 1 )
GFXDECODE_END
DEVICE_INPUT_DEFAULTS_START(poly88_8ksc_2000)
DEVICE_INPUT_DEFAULTS("DSW", 0xff, 0xfd) // 2000-3FFF
DEVICE_INPUT_DEFAULTS_END
void poly88_state::poly88(machine_config &config)
{
/* basic machine hardware */
I8080A(config, m_maincpu, 16.5888_MHz_XTAL / 9); // uses 8224 clock generator
m_maincpu->set_addrmap(AS_PROGRAM, &poly88_state::poly88_mem);
m_maincpu->set_addrmap(AS_IO, &poly88_state::poly88_io);
m_maincpu->set_vblank_int("screen", FUNC(poly88_state::poly88_interrupt));
m_maincpu->set_addrmap(AS_PROGRAM, &poly88_state::s100_mem);
m_maincpu->set_addrmap(AS_IO, &poly88_state::s100_io);
m_maincpu->set_irq_acknowledge_callback(FUNC(poly88_state::poly88_irq_callback));
/* video hardware */
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_refresh_hz(60);
screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
screen.set_size(64*10, 16*15);
screen.set_visarea(0, 64*10-1, 0, 16*15-1);
screen.set_screen_update(FUNC(poly88_state::screen_update_poly88));
screen.set_palette("palette");
ADDRESS_MAP_BANK(config, m_onboard_io);
m_onboard_io->set_addrmap(0, &poly88_state::poly88_io);
m_onboard_io->set_data_width(8);
m_onboard_io->set_addr_width(4);
GFXDECODE(config, "gfxdecode", "palette", gfx_poly88);
PALETTE(config, "palette", palette_device::MONOCHROME);
TIMER(config, "rtc").configure_periodic(FUNC(poly88_state::rtc_tick), attotime::from_hz(60)); // from AC power
/* audio hardware */
SPEAKER(config, "mono").front_center();
@ -179,45 +145,56 @@ void poly88_state::poly88(machine_config &config)
MM5307AA(config, m_brg, 16.5888_MHz_XTAL / 18);
m_brg->output_cb().set(FUNC(poly88_state::cassette_clock_w));
generic_keyboard_device &keyboard(GENERIC_KEYBOARD(config, "keyboard", 0));
keyboard.set_keyboard_callback(FUNC(poly88_state::kbd_put));
/* snapshot */
SNAPSHOT(config, "snapshot", "img", attotime::from_seconds(2)).set_load_callback(FUNC(poly88_state::snapshot_cb), this);
S100_BUS(config, m_s100, 16.5888_MHz_XTAL / 9);
m_s100->vi2().set(FUNC(poly88_state::vi2_w));
m_s100->vi5().set(FUNC(poly88_state::vi5_w));
S100_SLOT(config, m_s100_slot[0], poly88_s100_devices, "vti");
S100_SLOT(config, m_s100_slot[1], poly88_s100_devices, nullptr);
S100_SLOT(config, m_s100_slot[2], poly88_s100_devices, nullptr);
S100_SLOT(config, m_s100_slot[3], poly88_s100_devices, nullptr);
}
void poly88_state::poly8813(machine_config &config)
{
poly88(config);
m_maincpu->set_addrmap(AS_PROGRAM, &poly88_state::poly8813_mem);
m_maincpu->set_addrmap(AS_IO, &poly88_state::poly8813_io);
m_onboard_io->set_addrmap(0, &poly88_state::poly8813_io);
m_s100_slot[0]->set_option_device_input_defaults("vti", DEVICE_INPUT_DEFAULTS_NAME(poly88_vti_1800));
m_s100_slot[1]->set_default_option("8ksc");
m_s100_slot[1]->set_option_device_input_defaults("8ksc", DEVICE_INPUT_DEFAULTS_NAME(poly88_8ksc_2000));
m_s100_slot[2]->set_default_option("polyfdc");
// Poly-8813 backplane has 10 slots, but CPU uses one
S100_SLOT(config, m_s100_slot[4], poly88_s100_devices, nullptr);
S100_SLOT(config, m_s100_slot[5], poly88_s100_devices, nullptr);
S100_SLOT(config, m_s100_slot[6], poly88_s100_devices, nullptr);
S100_SLOT(config, m_s100_slot[7], poly88_s100_devices, nullptr);
S100_SLOT(config, m_s100_slot[8], poly88_s100_devices, nullptr);
}
/* ROM definition */
ROM_START( poly88 )
ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF )
ROM_REGION( 0xc00, "maincpu", ROMREGION_ERASEFF )
ROM_LOAD( "polymon4.bin", 0x0000, 0x0400, CRC(0baa1a4c) SHA1(c6cf4b89bdde200813d34aab08150d5f3025ce33))
ROM_LOAD( "tbasic_1.rom", 0x0400, 0x0400, CRC(ec22740e) SHA1(bc606c58ef5f046200bdf402eda66ec070464306))
ROM_LOAD( "tbasic_2.rom", 0x0800, 0x0400, CRC(f2619232) SHA1(eb6fb0356d2fb153111cfddf39eab10253cb4c53))
ROM_REGION( 0x800, "chargen", 0 )
ROM_LOAD( "6571.bin", 0x0000, 0x0800, CRC(5a25144b) SHA1(7b9fee0c8ef2605b85d12b6d9fe8feb82418c63a) )
ROM_END
ROM_START( poly8813 )
ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF )
ROM_REGION( 0xc00, "maincpu", ROMREGION_ERASEFF )
ROM_LOAD( "poly8813.27", 0x0000, 0x0400, CRC(0baa1a4c) SHA1(c6cf4b89bdde200813d34aab08150d5f3025ce33) )
ROM_LOAD( "poly8813.26", 0x0400, 0x0400, CRC(7011f3a3) SHA1(228eb54b9f62649b3b674e9f1bf21f2981e12c03) )
ROM_LOAD( "poly8813.25", 0x0800, 0x0400, CRC(9f7570e2) SHA1(767f2111b4eb856a077b1b4afe9209aca3866e52) )
//ROM_LOAD( "poly8813-1.bin", 0x0000, 0x0400, CRC(7fd980a0) SHA1(a71d5999deb4323a11db1c0ea0dcb1dacfaf47ef))
//ROM_LOAD( "poly8813-2.rom", 0x0400, 0x0400, CRC(1ad7c06c) SHA1(c96b8f03c184de58dbdcee18d297dbccf2d77176))
//ROM_LOAD( "poly8813-3.rom", 0x0800, 0x0400, CRC(3df57e5b) SHA1(5b0c4febfc7515fc07e63dcb21d0ab32bc6a2e46))
ROM_REGION( 0x800, "chargen", 0 )
ROM_LOAD( "6571.bin", 0x0000, 0x0800, CRC(5a25144b) SHA1(7b9fee0c8ef2605b85d12b6d9fe8feb82418c63a) )
ROM_END
/* Driver */
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
COMP( 1976, poly88, 0, 0, poly88, poly88, poly88_state, init_poly88, "PolyMorphic Systems", "Poly-88", 0 )
COMP( 1977, poly8813, poly88, 0, poly8813, poly88, poly88_state, init_poly88, "PolyMorphic Systems", "Poly-8813", MACHINE_NOT_WORKING )
COMP( 1976, poly88, 0, 0, poly88, poly88, poly88_state, empty_init, "PolyMorphic Systems", "Poly-88", 0 )
COMP( 1977, poly8813, poly88, 0, poly8813, poly88, poly88_state, empty_init, "PolyMorphic Systems", "Poly-8813", MACHINE_NOT_WORKING )

View File

@ -10,6 +10,8 @@
#pragma once
#include "bus/s100/s100.h"
#include "machine/bankdev.h"
#include "machine/i8251.h"
#include "machine/mm5307.h"
#include "imagedev/cassette.h"
@ -21,50 +23,66 @@ class poly88_state : public driver_device
public:
poly88_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_video_ram(*this, "video_ram")
, m_maincpu(*this, "maincpu")
, m_onboard_io(*this, "onboard_io")
, m_s100(*this, "s100")
, m_s100_slot(*this, "s100:%u", 1U)
, m_usart(*this, "usart")
, m_brg(*this, "brg")
, m_cassette(*this, "cassette")
, m_onboard_rom(*this, "maincpu")
, m_linec(*this, "CONFIG")
, m_onboard_config(*this, "ONBOARD")
{ }
void poly88(machine_config &config);
void poly8813(machine_config &config);
void init_poly88();
protected:
virtual void machine_start() override;
virtual void machine_reset() override;
private:
required_shared_ptr<uint8_t> m_video_ram;
uint8_t *m_FNT;
uint8_t m_last_code;
uint8_t m_int_vector;
bool is_onboard(offs_t offset);
uint8_t mem_r(offs_t offset);
void mem_w(offs_t offset, uint8_t data);
uint8_t in_r(offs_t offset);
void out_w(offs_t offset, uint8_t data);
void baud_rate_w(uint8_t data);
uint8_t keyboard_r();
void intr_w(uint8_t data);
bool m_dtr, m_rts, m_txd, m_rxd, m_cassold;
u8 m_cass_data[4];
virtual void machine_reset() override;
virtual void video_start() override;
uint32_t screen_update_poly88(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
INTERRUPT_GEN_MEMBER(poly88_interrupt);
TIMER_DEVICE_CALLBACK_MEMBER(kansas_r);
DECLARE_WRITE_LINE_MEMBER(cassette_clock_w);
void kbd_put(u8 data);
TIMER_DEVICE_CALLBACK_MEMBER(rtc_tick);
DECLARE_WRITE_LINE_MEMBER(vi2_w);
DECLARE_WRITE_LINE_MEMBER(vi5_w);
DECLARE_WRITE_LINE_MEMBER(usart_ready_w);
IRQ_CALLBACK_MEMBER(poly88_irq_callback);
DECLARE_SNAPSHOT_LOAD_MEMBER(snapshot_cb);
void poly8813_io(address_map &map);
void poly8813_mem(address_map &map);
void poly88_io(address_map &map);
void s100_mem(address_map &map);
void s100_io(address_map &map);
void poly88_mem(address_map &map);
void poly88_io(address_map &map);
void poly8813_mem(address_map &map);
void poly8813_io(address_map &map);
required_device<cpu_device> m_maincpu;
required_device<address_map_bank_device> m_onboard_io;
required_device<s100_bus_device> m_s100;
optional_device_array<s100_slot_device, 9> m_s100_slot;
required_device<i8251_device> m_usart;
required_device<mm5307_device> m_brg;
required_device<cassette_image_device> m_cassette;
required_region_ptr<u8> m_onboard_rom;
required_ioport m_linec;
required_ioport m_onboard_config;
uint8_t m_int_vector;
bool m_dtr, m_rts, m_txd, m_rxd, m_cassold;
u8 m_cass_data[4];
std::unique_ptr<u8[]> m_onboard_ram;
bool m_onboard_disable;
};
#endif // MAME_INCLUDES_POLY88_H

View File

@ -13,11 +13,60 @@
#include "includes/poly88.h"
bool poly88_state::is_onboard(offs_t offset)
{
return (offset & 0xf000) == m_onboard_config->read() << 13;
}
uint8_t poly88_state::mem_r(offs_t offset)
{
if (!m_onboard_disable && is_onboard(offset))
{
if ((offset & 0xfff) >= 0xc00)
return m_onboard_ram[offset & 0x1ff]; // mirrored
else
return m_onboard_rom[offset & 0xfff];
}
else
return m_s100->smemr_r(offset);
}
void poly88_state::mem_w(offs_t offset, uint8_t data)
{
if (!m_onboard_disable && is_onboard(offset))
{
if ((offset & 0xfff) >= 0xc00)
m_onboard_ram[offset & 0x1ff] = data; // mirrored
}
else
m_s100->mwrt_w(offset, data);
}
uint8_t poly88_state::in_r(offs_t offset)
{
offset |= offset << 8;
if (is_onboard(offset))
return m_onboard_io->read8(offset & 0x0f);
else
return m_s100->sinp_r(offset);
}
void poly88_state::out_w(offs_t offset, uint8_t data)
{
offset |= offset << 8;
if (is_onboard(offset))
m_onboard_io->write8(offset & 0x0f, data);
else
m_s100->sout_w(offset, data);
}
// bits 0-3 baud rate; bit 4 (0=cassette, 1=rs232); bit 5 (1=disable rom and ram)
void poly88_state::baud_rate_w(uint8_t data)
{
logerror("poly88_baud_rate_w %02x\n",data);
m_brg->control_w(data & 15);
m_onboard_disable = BIT(data, 5);
}
IRQ_CALLBACK_MEMBER(poly88_state::poly88_irq_callback)
@ -104,42 +153,53 @@ WRITE_LINE_MEMBER(poly88_state::cassette_clock_w)
}
void poly88_state::init_poly88()
void poly88_state::machine_start()
{
m_onboard_ram = make_unique_clear<u8[]>(0x200);
}
void poly88_state::machine_reset()
{
m_last_code = 0;
m_usart->write_rxd(1);
m_usart->write_cts(0);
m_brg->control_w(0);
m_onboard_disable = false;
m_dtr = m_rts = m_txd = m_rxd = m_cassold = 1;
}
INTERRUPT_GEN_MEMBER(poly88_state::poly88_interrupt)
TIMER_DEVICE_CALLBACK_MEMBER(poly88_state::rtc_tick)
{
m_int_vector = 0xf7;
device.execute().set_input_line(0, HOLD_LINE);
m_maincpu->set_input_line(0, HOLD_LINE);
}
WRITE_LINE_MEMBER(poly88_state::vi2_w)
{
if (state == ASSERT_LINE)
{
m_int_vector = 0xef;
m_maincpu->set_input_line(0, HOLD_LINE);
}
}
WRITE_LINE_MEMBER(poly88_state::vi5_w)
{
if (state == ASSERT_LINE)
{
m_int_vector = 0xd7;
m_maincpu->set_input_line(0, HOLD_LINE);
}
}
WRITE_LINE_MEMBER(poly88_state::usart_ready_w)
{
if (state)
{
m_int_vector = 0xe7;
m_int_vector = 0xdf;
m_maincpu->set_input_line(0, HOLD_LINE);
}
}
uint8_t poly88_state::keyboard_r()
{
uint8_t retVal = m_last_code;
m_maincpu->set_input_line(0, CLEAR_LINE);
m_last_code = 0x00;
return retVal;
}
void poly88_state::intr_w(uint8_t data)
{
m_maincpu->set_input_line(0, CLEAR_LINE);

View File

@ -1,102 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Miodrag Milanovic
/***************************************************************************
Poly-88 video by Miodrag Milanovic
18/05/2009 Initial implementation
****************************************************************************/
#include "emu.h"
#include "includes/poly88.h"
static const uint8_t mcm6571a_shift[] =
{
0,1,1,0,0,0,1,0,0,0,0,1,0,0,0,0,
1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,
1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0
};
void poly88_state::video_start()
{
m_FNT = memregion("chargen")->base();
}
uint32_t poly88_state::screen_update_poly88(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
int x,y,j,b;
uint16_t addr;
int xpos;
uint8_t l,r;
for(y = 0; y < 16; y++ )
{
addr = y*64;
xpos = 0;
for(x = 0; x < 64; x++ )
{
uint8_t code = m_video_ram[addr + x];
if ((code & 0x80)==0)
{
for(j = 0; j < 15; j++ )
{
l = j/5;
for(b = 0; b < 10; b++ )
{
r = b/5;
if (l==0 && r==0)
bitmap.pix16(y*15+j, xpos+b ) = BIT(code,5) ? 0 : 1;
if (l==0 && r==1)
bitmap.pix16(y*15+j, xpos+b ) = BIT(code,2) ? 0 : 1;
if (l==1 && r==0)
bitmap.pix16(y*15+j, xpos+b ) = BIT(code,4) ? 0 : 1;
if (l==1 && r==1)
bitmap.pix16(y*15+j, xpos+b ) = BIT(code,1) ? 0 : 1;
if (l==2 && r==0)
bitmap.pix16(y*15+j, xpos+b ) = BIT(code,3) ? 0 : 1;
if (l==2 && r==1)
bitmap.pix16(y*15+j, xpos+b ) = BIT(code,0) ? 0 : 1;
}
}
}
else
{
for(j = 0; j < 15; j++ )
{
code &= 0x7f;
l = 0;
if (mcm6571a_shift[code]==0)
{
if (j < 9)
l = m_FNT[code*16 + j];
}
else
{
if ((j > 2) && (j < 12))
l = m_FNT[code*16 + j - 3];
}
for(b = 0; b < 7; b++ )
bitmap.pix16(y*15+j, xpos+b ) = (l >> (6-b)) & 1;
bitmap.pix16(y*15+j, xpos+7 ) = 0;
bitmap.pix16(y*15+j, xpos+8 ) = 0;
bitmap.pix16(y*15+j, xpos+9 ) = 0;
}
}
xpos += 10;
}
}
return 0;
}