// license:BSD-3-Clause
// copyright-holders:Sandro Ronco
/***************************************************************************
IQ-151
12/05/2009 Skeleton driver.
07/June/2011 Added screen & keyboard (by looking at the Z80 code)
This computer depends on RAM just happening to be certain values at powerup.
If the conditions are not met, it may crash.
Monitor Commands:
C Call (address)
D Dump memory, any key to dump more, Return to finish
F Fill memory (start, end, withwhat)
G Goto (address)
L Cassette load
M Move (source start, source end, destination)
R Run
S Edit memory
W Cassette save (start, end, goto (0 for null))
X Display/Edit registers
ToDo:
- Add whatever devices may exist.
- Line 32 does not scroll, should it show?
(could be reserved for a status line in a terminal mode)
- Note that the system checks for 3E at C000, if exist, jump to C000;
otherwise then checks for non-FF at C800, if so, jumps to C800. Could be
extra roms or some sort of boot device.
- Key beep sounds better if clock speed changed to 1MHz, but it is still
highly annoying. Press Ctrl-G to hear the 2-tone bell.
- Cassette support is tested only in the emulator (monitor, BASIC and AMOS),
needs to be tested with a real cassette dump.
****************************************************************************/
#include "emu.h"
#include "cpu/i8085/i8085.h"
#include "imagedev/cassette.h"
#include "machine/i8255.h"
#include "machine/pic8259.h"
#include "machine/timer.h"
#include "sound/spkrdev.h"
// cartridge slot
#include "bus/iq151/iq151.h"
#include "bus/iq151/rom.h"
#include "bus/iq151/disc2.h"
#include "bus/iq151/minigraf.h"
#include "bus/iq151/ms151a.h"
#include "bus/iq151/staper.h"
#include "bus/iq151/grafik.h"
#include "bus/iq151/video32.h"
#include "bus/iq151/video64.h"
#include "screen.h"
#include "softlist.h"
#include "speaker.h"
class iq151_state : public driver_device
{
public:
iq151_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_pic(*this, "pic8259")
, m_speaker(*this, "speaker")
, m_cassette(*this, "cassette")
, m_carts(*this, "slot%u", 1U)
, m_boot_bank(*this, "boot")
{ }
void iq151(machine_config &config);
DECLARE_INPUT_CHANGED_MEMBER(iq151_break);
private:
DECLARE_READ8_MEMBER(keyboard_row_r);
DECLARE_READ8_MEMBER(keyboard_column_r);
DECLARE_READ8_MEMBER(ppi_portc_r);
DECLARE_WRITE8_MEMBER(ppi_portc_w);
DECLARE_WRITE8_MEMBER(boot_bank_w);
DECLARE_READ8_MEMBER(cartslot_r);
DECLARE_WRITE8_MEMBER(cartslot_w);
DECLARE_READ8_MEMBER(cartslot_io_r);
DECLARE_WRITE8_MEMBER(cartslot_io_w);
virtual void machine_start() override;
virtual void machine_reset() override;
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
INTERRUPT_GEN_MEMBER(iq151_vblank_interrupt);
TIMER_DEVICE_CALLBACK_MEMBER(cassette_timer);
void iq151_io(address_map &map);
void iq151_mem(address_map &map);
required_device<cpu_device> m_maincpu;
required_device<pic8259_device> m_pic;
required_device<speaker_sound_device> m_speaker;
required_device<cassette_image_device> m_cassette;
required_device_array<iq151cart_slot_device, 5> m_carts;
required_memory_bank m_boot_bank;
uint8_t m_vblank_irq_state;
uint8_t m_cassette_clk;
uint8_t m_cassette_data;
};
READ8_MEMBER(iq151_state::keyboard_row_r)
{
char kbdrow[6];
uint8_t data = 0xff;
for (int i = 0; i < 8; i++)
{
sprintf(kbdrow,"X%X",i);
data &= ioport(kbdrow)->read();
}
return data;
}
READ8_MEMBER(iq151_state::keyboard_column_r)
{
char kbdrow[6];
uint8_t data = 0x00;
for (int i = 0; i < 8; i++)
{
sprintf(kbdrow,"X%X",i);
if (ioport(kbdrow)->read() == 0xff)
data |= (1 << i);
}
return data;
}
READ8_MEMBER(iq151_state::ppi_portc_r)
{
uint8_t data = 0x00;
if (m_cassette_data & 0x06)
{
// cassette read
data |= ((m_cassette_clk & 1) << 5);
data |= (m_cassette->input() > 0.00 ? 0x80 : 0x00);
}
else
{
// kb read
data = ioport("X8")->read();
}
return (data & 0xf0) | (m_cassette_data & 0x0f);
}
WRITE8_MEMBER(iq151_state::ppi_portc_w)
{
m_speaker->level_w(BIT(data, 3));
m_cassette_data = data;
}
WRITE8_MEMBER(iq151_state::boot_bank_w)
{
m_boot_bank->set_entry(data & 1);
}
//**************************************************************************
// Cartridge slot emulation
//**************************************************************************
READ8_MEMBER(iq151_state::cartslot_r)
{
uint8_t data = 0xff;
for (auto & elem : m_carts)
elem->read(offset, data);
return data;
}
WRITE8_MEMBER(iq151_state::cartslot_w)
{
for (auto & elem : m_carts)
elem->write(offset, data);
}
READ8_MEMBER(iq151_state::cartslot_io_r)
{
uint8_t data = 0xff;
for (auto & elem : m_carts)
elem->io_read(offset, data);
return data;
}
WRITE8_MEMBER(iq151_state::cartslot_io_w)
{
for (auto & elem : m_carts)
elem->io_write(offset, data);
}
void iq151_state::iq151_mem(address_map &map)
{
map.unmap_value_high();
map(0x0000, 0xffff).rw(this, FUNC(iq151_state::cartslot_r), FUNC(iq151_state::cartslot_w));
map(0x0000, 0x07ff).bankrw("boot");
map(0x0800, 0x7fff).ram();
map(0xf000, 0xffff).rom();
}
void iq151_state::iq151_io(address_map &map)
{
map.unmap_value_high();
map.global_mask(0xff);
map(0x00, 0xff).rw(this, FUNC(iq151_state::cartslot_io_r), FUNC(iq151_state::cartslot_io_w));
map(0x80, 0x80).w(this, FUNC(iq151_state::boot_bank_w));
map(0x84, 0x87).rw("ppi8255", FUNC(i8255_device::read), FUNC(i8255_device::write));
map(0x88, 0x89).rw(m_pic, FUNC(pic8259_device::read), FUNC(pic8259_device::write));
}
INPUT_CHANGED_MEMBER(iq151_state::iq151_break)
{
m_pic->ir5_w(newval & 1);
}
/* Input ports */
static INPUT_PORTS_START( iq151 )
PORT_START("X0")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("1 !") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("2 \"") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3 #") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("4 $") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("5 %") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("6 &") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&')
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("7 '") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('\'')
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8 (") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(')
PORT_START("X1")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('Q') PORT_CHAR('q')
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('W') PORT_CHAR('w')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('E') PORT_CHAR('e')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('R') PORT_CHAR('r')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) PORT_CHAR('T') PORT_CHAR('t')
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('Y') PORT_CHAR('y')
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) PORT_CHAR('U') PORT_CHAR('u')
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('I') PORT_CHAR('i')
PORT_START("X2")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('A') PORT_CHAR('a')
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('S') PORT_CHAR('s')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('D') PORT_CHAR('d')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('F') PORT_CHAR('f')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('G') PORT_CHAR('g')
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('H') PORT_CHAR('h')
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('J') PORT_CHAR('j')
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('K') PORT_CHAR('k')
PORT_START("X3")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') PORT_CHAR('z')
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('X') PORT_CHAR('x')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('C') PORT_CHAR('c')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('V') PORT_CHAR('v')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('B') PORT_CHAR('b')
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('N') PORT_CHAR('n')
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('M') PORT_CHAR('m')
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(", <") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
PORT_START("X4")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9 )") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')')
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('O') PORT_CHAR('o')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('L') PORT_CHAR('l')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(". >") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Enter") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Del") PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL))
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ins") PORT_CODE(KEYCODE_INSERT) PORT_CHAR(UCHAR_MAMEKEY(INSERT))
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F1") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
PORT_START("X5")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0')
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('P') PORT_CHAR('p')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("; +") PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR('+')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("/ ?") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\\ |") PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|')
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("DL") PORT_CODE(KEYCODE_F6)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Left") PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F2") PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
PORT_START("X6")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("^ ~") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('^') PORT_CHAR('~')
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("[ {") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("] }") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Down") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F5") PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("IL") PORT_CODE(KEYCODE_F7)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Home") PORT_CODE(KEYCODE_HOME) PORT_CHAR(UCHAR_MAMEKEY(HOME))
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F4") PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))
PORT_START("X7")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("- =") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('=')
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("@ `") PORT_CODE(KEYCODE_TILDE) PORT_CHAR('@') PORT_CHAR('`')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(": *") PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(':') PORT_CHAR('*')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("_") PORT_CODE(KEYCODE_END) // its actually some sort of graphic character
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Up") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Right") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F3") PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
PORT_START("X8")
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ctrl") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("FA") PORT_CODE(KEYCODE_RSHIFT) // Function A
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("FB") PORT_CODE(KEYCODE_RCONTROL) // Function B
PORT_START("BREAK")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("BREAK") PORT_CODE(KEYCODE_ESC) PORT_CHANGED_MEMBER(DEVICE_SELF, iq151_state, iq151_break, 0) PORT_CHAR(UCHAR_MAMEKEY(ESC))
INPUT_PORTS_END
INTERRUPT_GEN_MEMBER(iq151_state::iq151_vblank_interrupt)
{
m_pic->ir6_w(m_vblank_irq_state & 1);
m_vblank_irq_state ^= 1;
}
TIMER_DEVICE_CALLBACK_MEMBER(iq151_state::cassette_timer)
{
m_cassette_clk ^= 1;
m_cassette->output((m_cassette_data & 1) ^ (m_cassette_clk & 1) ? +1 : -1);
}
void iq151_state::machine_start()
{
uint8_t *RAM = memregion("maincpu")->base();
m_boot_bank->configure_entry(0, RAM + 0xf800);
m_boot_bank->configure_entry(1, RAM + 0x0000);
}
void iq151_state::machine_reset()
{
m_boot_bank->set_entry(0);
m_vblank_irq_state = 0;
}
// this machine don't have a built-in video controller, but uses external cartridge
uint32_t iq151_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
bitmap.fill(0, cliprect);
for (auto & elem : m_carts)
elem->video_update(bitmap, cliprect);
return 0;
}
static void iq151_cart(device_slot_interface &device)
{
device.option_add("video32", IQ151_VIDEO32); // video32
device.option_add("video64", IQ151_VIDEO64); // video64
device.option_add("grafik", IQ151_GRAFIK); // Grafik
device.option_add("disc2", IQ151_DISC2); // Disc 2
device.option_add("minigraf", IQ151_MINIGRAF); // Aritma Minigraf 0507
device.option_add("ms151a", IQ151_MS151A); // MS151A XY Plotter
device.option_add("staper", IQ151_STAPER); // STAPER
device.option_add("basic6", IQ151_BASIC6); // BASIC6
device.option_add("basicg", IQ151_BASICG); // BASICG
device.option_add("amos1", IQ151_AMOS1); // AMOS cart 1
device.option_add("amos2", IQ151_AMOS2); // AMOS cart 2
device.option_add("amos3", IQ151_AMOS3); // AMOS cart 3
}
MACHINE_CONFIG_START(iq151_state::iq151)
/* basic machine hardware */
MCFG_DEVICE_ADD("maincpu",I8080, XTAL(2'000'000))
MCFG_DEVICE_PROGRAM_MAP(iq151_mem)
MCFG_DEVICE_IO_MAP(iq151_io)
MCFG_DEVICE_VBLANK_INT_DRIVER("screen", iq151_state, iq151_vblank_interrupt)
MCFG_DEVICE_IRQ_ACKNOWLEDGE_DEVICE("pic8259", pic8259_device, inta_cb)
/* video hardware */
MCFG_SCREEN_ADD_MONOCHROME("screen", RASTER, rgb_t::green())
MCFG_SCREEN_REFRESH_RATE(50)
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
MCFG_SCREEN_UPDATE_DRIVER(iq151_state, screen_update)
MCFG_SCREEN_SIZE(64*8, 32*8)
MCFG_SCREEN_VISIBLE_AREA(0, 32*8-1, 0, 32*8-1)
MCFG_SCREEN_PALETTE("palette")
MCFG_PALETTE_ADD_MONOCHROME("palette")
/* sound hardware */
SPEAKER(config, "mono").front_center();
MCFG_DEVICE_ADD("speaker", SPEAKER_SOUND)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
MCFG_DEVICE_ADD("pic8259", PIC8259, 0)
MCFG_PIC8259_OUT_INT_CB(INPUTLINE("maincpu", 0))
MCFG_DEVICE_ADD("ppi8255", I8255, 0)
MCFG_I8255_IN_PORTA_CB(READ8(*this, iq151_state, keyboard_row_r))
MCFG_I8255_IN_PORTB_CB(READ8(*this, iq151_state, keyboard_column_r))
MCFG_I8255_IN_PORTC_CB(READ8(*this, iq151_state, ppi_portc_r))
MCFG_I8255_OUT_PORTC_CB(WRITE8(*this, iq151_state, ppi_portc_w))
MCFG_CASSETTE_ADD( "cassette" )
MCFG_CASSETTE_DEFAULT_STATE(CASSETTE_STOPPED)
MCFG_CASSETTE_INTERFACE("iq151_cass")
MCFG_TIMER_DRIVER_ADD_PERIODIC("cassette_timer", iq151_state, cassette_timer, attotime::from_hz(2000))
/* cartridge */
MCFG_DEVICE_ADD("slot1", IQ151CART_SLOT, 0)
MCFG_DEVICE_SLOT_INTERFACE(iq151_cart, nullptr, false)
MCFG_IQ151CART_SLOT_SCREEN_TAG("screen")
MCFG_IQ151CART_SLOT_OUT_IRQ0_CB(WRITELINE("pic8259", pic8259_device, ir0_w))
MCFG_IQ151CART_SLOT_OUT_IRQ1_CB(WRITELINE("pic8259", pic8259_device, ir1_w))
MCFG_IQ151CART_SLOT_OUT_IRQ2_CB(WRITELINE("pic8259", pic8259_device, ir2_w))
MCFG_IQ151CART_SLOT_OUT_IRQ3_CB(WRITELINE("pic8259", pic8259_device, ir3_w))
MCFG_IQ151CART_SLOT_OUT_IRQ4_CB(WRITELINE("pic8259", pic8259_device, ir4_w))
MCFG_DEVICE_ADD("slot2", IQ151CART_SLOT, 0)
MCFG_DEVICE_SLOT_INTERFACE(iq151_cart, nullptr, false)
MCFG_IQ151CART_SLOT_SCREEN_TAG("screen")
MCFG_IQ151CART_SLOT_OUT_IRQ0_CB(WRITELINE("pic8259", pic8259_device, ir0_w))
MCFG_IQ151CART_SLOT_OUT_IRQ1_CB(WRITELINE("pic8259", pic8259_device, ir1_w))
MCFG_IQ151CART_SLOT_OUT_IRQ2_CB(WRITELINE("pic8259", pic8259_device, ir2_w))
MCFG_IQ151CART_SLOT_OUT_IRQ3_CB(WRITELINE("pic8259", pic8259_device, ir3_w))
MCFG_IQ151CART_SLOT_OUT_IRQ4_CB(WRITELINE("pic8259", pic8259_device, ir4_w))
MCFG_DEVICE_ADD("slot3", IQ151CART_SLOT, 0)
MCFG_DEVICE_SLOT_INTERFACE(iq151_cart, nullptr, false)
MCFG_IQ151CART_SLOT_SCREEN_TAG("screen")
MCFG_IQ151CART_SLOT_OUT_IRQ0_CB(WRITELINE("pic8259", pic8259_device, ir0_w))
MCFG_IQ151CART_SLOT_OUT_IRQ1_CB(WRITELINE("pic8259", pic8259_device, ir1_w))
MCFG_IQ151CART_SLOT_OUT_IRQ2_CB(WRITELINE("pic8259", pic8259_device, ir2_w))
MCFG_IQ151CART_SLOT_OUT_IRQ3_CB(WRITELINE("pic8259", pic8259_device, ir3_w))
MCFG_IQ151CART_SLOT_OUT_IRQ4_CB(WRITELINE("pic8259", pic8259_device, ir4_w))
MCFG_DEVICE_ADD("slot4", IQ151CART_SLOT, 0)
MCFG_DEVICE_SLOT_INTERFACE(iq151_cart, nullptr, false)
MCFG_IQ151CART_SLOT_SCREEN_TAG("screen")
MCFG_IQ151CART_SLOT_OUT_IRQ0_CB(WRITELINE("pic8259", pic8259_device, ir0_w))
MCFG_IQ151CART_SLOT_OUT_IRQ1_CB(WRITELINE("pic8259", pic8259_device, ir1_w))
MCFG_IQ151CART_SLOT_OUT_IRQ2_CB(WRITELINE("pic8259", pic8259_device, ir2_w))
MCFG_IQ151CART_SLOT_OUT_IRQ3_CB(WRITELINE("pic8259", pic8259_device, ir3_w))
MCFG_IQ151CART_SLOT_OUT_IRQ4_CB(WRITELINE("pic8259", pic8259_device, ir4_w))
MCFG_DEVICE_ADD("slot5", IQ151CART_SLOT, 0)
MCFG_DEVICE_SLOT_INTERFACE(iq151_cart, "video32", false)
MCFG_IQ151CART_SLOT_SCREEN_TAG("screen")
MCFG_IQ151CART_SLOT_OUT_IRQ0_CB(WRITELINE("pic8259", pic8259_device, ir0_w))
MCFG_IQ151CART_SLOT_OUT_IRQ1_CB(WRITELINE("pic8259", pic8259_device, ir1_w))
MCFG_IQ151CART_SLOT_OUT_IRQ2_CB(WRITELINE("pic8259", pic8259_device, ir2_w))
MCFG_IQ151CART_SLOT_OUT_IRQ3_CB(WRITELINE("pic8259", pic8259_device, ir3_w))
MCFG_IQ151CART_SLOT_OUT_IRQ4_CB(WRITELINE("pic8259", pic8259_device, ir4_w))
/* Software lists */
MCFG_SOFTWARE_LIST_ADD("cart_list", "iq151_cart")
MCFG_SOFTWARE_LIST_ADD("flop_list", "iq151_flop")
MACHINE_CONFIG_END
/* ROM definition */
ROM_START( iq151 )
ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASE )
/* A number of bios versions here. The load address is shown for each */
ROM_SYSTEM_BIOS( 0, "orig", "Original" )
ROMX_LOAD( "iq151_monitor_orig.rom", 0xf000, 0x1000, CRC(acd10268) SHA1(4d75c73f155ed4dc2ac51a9c22232f869cca95e2),ROM_BIOS(1))
ROM_SYSTEM_BIOS( 1, "disasm", "Disassembler" )
ROMX_LOAD( "iq151_monitor_disasm.rom", 0xf000, 0x1000, CRC(45c2174e) SHA1(703e3271a124c3ef9330ae399308afd903316ab9),ROM_BIOS(2))
ROM_SYSTEM_BIOS( 2, "cpm", "CPM" )
ROMX_LOAD( "iq151_monitor_cpm.rom", 0xf000, 0x1000, CRC(26f57013) SHA1(4df396edc375dd2dd3c82c4d2affb4f5451066f1),ROM_BIOS(3))
ROM_SYSTEM_BIOS( 3, "cpmold", "CPM (old)" )
ROMX_LOAD( "iq151_monitor_cpm_old.rom", 0xf000, 0x1000, CRC(6743e1b7) SHA1(ae4f3b1ba2511a1f91c4e8afdfc0e5aeb0fb3a42),ROM_BIOS(4))
ROM_END
/* Driver */
// YEAR NAME PARENT COMPAT MACHINE INPUT STATE INIT COMPANY FULLNAME FLAGS
COMP( 198?, iq151, 0, 0, iq151, iq151, iq151_state, empty_init, "ZPA Novy Bor", "IQ-151", 0 )