summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/devices/bus/amiga/keyboard/a500.cpp267
-rw-r--r--src/devices/bus/amiga/keyboard/a500.h22
-rw-r--r--src/devices/bus/amiga/keyboard/keyboard.cpp3
-rw-r--r--src/devices/cpu/clipper/clipper.cpp1401
-rw-r--r--src/devices/cpu/clipper/clipper.h296
-rw-r--r--src/devices/cpu/clipper/clipperd.cpp351
-rw-r--r--src/devices/cpu/drcbec.cpp2
-rw-r--r--src/devices/cpu/sh4/sh4.cpp287
-rw-r--r--src/devices/cpu/tms1000/tms1k_base.cpp2
-rw-r--r--src/devices/machine/netlist.cpp4
-rw-r--r--src/devices/sound/saa1099.cpp8
-rw-r--r--src/devices/sound/saa1099.h4
-rw-r--r--src/devices/video/hlcd0515.cpp119
-rw-r--r--src/devices/video/hlcd0515.h21
-rw-r--r--src/devices/video/huc6261.cpp53
-rw-r--r--src/devices/video/huc6261.h8
-rw-r--r--src/devices/video/huc6271.cpp65
-rw-r--r--src/devices/video/huc6271.h57
-rw-r--r--src/devices/video/huc6272.cpp102
-rw-r--r--src/devices/video/huc6272.h17
-rw-r--r--src/lib/netlist/analog/nld_twoterm.cpp34
-rw-r--r--src/lib/netlist/analog/nld_twoterm.h35
-rw-r--r--src/lib/netlist/devices/nld_4020.cpp2
-rw-r--r--src/lib/netlist/devices/nld_4066.cpp2
-rw-r--r--src/lib/netlist/devices/nld_4316.cpp2
-rw-r--r--src/lib/netlist/devices/nld_74166.cpp2
-rw-r--r--src/lib/netlist/devices/nld_7493.cpp6
-rw-r--r--src/lib/netlist/devices/nld_9310.cpp29
-rw-r--r--src/lib/netlist/devices/nld_9316.cpp30
-rw-r--r--src/lib/netlist/devices/nld_mm5837.cpp2
-rw-r--r--src/lib/netlist/devices/nld_ne555.cpp2
-rw-r--r--src/lib/netlist/devices/nld_system.cpp4
-rw-r--r--src/lib/netlist/devices/nld_truthtable.cpp3
-rw-r--r--src/lib/netlist/devices/nlid_proxy.cpp4
-rw-r--r--src/lib/netlist/devices/nlid_system.h2
-rw-r--r--src/lib/netlist/documentation/mainpage.dox.h1
-rw-r--r--src/lib/netlist/nl_base.cpp69
-rw-r--r--src/lib/netlist/nl_base.h152
-rw-r--r--src/lib/netlist/nl_config.h67
-rw-r--r--src/lib/netlist/nl_factory.h15
-rw-r--r--src/lib/netlist/nl_lists.h69
-rw-r--r--src/lib/netlist/nl_setup.cpp20
-rw-r--r--src/lib/netlist/nl_setup.h4
-rw-r--r--src/lib/netlist/nl_time.h69
-rw-r--r--src/lib/netlist/plib/pconfig.h142
-rw-r--r--src/lib/netlist/plib/pfunction.cpp110
-rw-r--r--src/lib/netlist/plib/pfunction.h22
-rw-r--r--src/lib/netlist/plib/plists.h1
-rw-r--r--src/lib/netlist/plib/pstring.cpp21
-rw-r--r--src/lib/netlist/plib/pstring.h36
-rw-r--r--src/lib/netlist/plib/putil.cpp2
-rw-r--r--src/lib/netlist/plib/putil.h2
-rw-r--r--src/lib/netlist/prg/nltool.cpp12
-rw-r--r--src/lib/netlist/prg/nlwav.cpp17
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver.cpp34
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver.h26
-rw-r--r--src/lib/netlist/solver/nld_ms_direct.h2
-rw-r--r--src/lib/netlist/solver/nld_ms_gcr.h83
-rw-r--r--src/lib/netlist/solver/nld_ms_gmres.h2
-rw-r--r--src/lib/netlist/solver/nld_solver.cpp52
-rw-r--r--src/lib/netlist/solver/nld_solver.h4
-rw-r--r--src/lib/util/unicode.cpp2
-rw-r--r--src/mame/drivers/aristmk5.cpp265
-rw-r--r--src/mame/drivers/fccpu20.cpp4
-rw-r--r--src/mame/drivers/hh_cop400.cpp1
-rw-r--r--src/mame/drivers/hh_hmcs40.cpp12
-rw-r--r--src/mame/drivers/hh_tms1k.cpp158
-rw-r--r--src/mame/drivers/hh_ucom4.cpp1
-rw-r--r--src/mame/drivers/interpro.cpp348
-rw-r--r--src/mame/drivers/naomi.cpp36
-rw-r--r--src/mame/drivers/neodriv.hxx43
-rw-r--r--src/mame/drivers/novag6502.cpp6
-rw-r--r--src/mame/drivers/pcfx.cpp5
-rw-r--r--src/mame/drivers/suprnova.cpp41
-rw-r--r--src/mame/includes/interpro.h131
-rw-r--r--src/mame/includes/naomi.h16
-rw-r--r--src/mame/layout/cnsector.lay12
-rw-r--r--src/mame/machine/cammu.cpp181
-rw-r--r--src/mame/machine/cammu.h91
-rw-r--r--src/mame/machine/interpro_ioga.cpp691
-rw-r--r--src/mame/machine/interpro_ioga.h255
-rw-r--r--src/mame/machine/interpro_mcga.cpp89
-rw-r--r--src/mame/machine/interpro_mcga.h45
-rw-r--r--src/mame/machine/interpro_sga.cpp88
-rw-r--r--src/mame/machine/interpro_sga.h71
-rw-r--r--src/mame/machine/namco_c148.cpp8
-rw-r--r--src/mame/mame.lst23
-rw-r--r--src/mame/mess.flt1
-rw-r--r--src/mame/video/powervr2.cpp1
-rw-r--r--src/osd/modules/render/bgfx/shaders/shader.mk2
-rw-r--r--src/osd/modules/sound/pa_sound.cpp2
-rw-r--r--src/tools/unidasm.cpp2
92 files changed, 5987 insertions, 926 deletions
diff --git a/src/devices/bus/amiga/keyboard/a500.cpp b/src/devices/bus/amiga/keyboard/a500.cpp
index dc2598a1711..dce046099c4 100644
--- a/src/devices/bus/amiga/keyboard/a500.cpp
+++ b/src/devices/bus/amiga/keyboard/a500.cpp
@@ -19,14 +19,15 @@
// DEVICE DEFINITIONS
//**************************************************************************
-const device_type A500_KBD = &device_creator<a500_kbd_device>;
+const device_type A500_KBD_US = &device_creator<a500_kbd_us_device>;
+const device_type A500_KBD_DE = &device_creator<a500_kbd_de_device>;
//-------------------------------------------------
// machine_config_additions - device-specific
// machine configurations
//-------------------------------------------------
-static ADDRESS_MAP_START( mpu6500_map, AS_PROGRAM, 8, a500_kbd_device )
+static ADDRESS_MAP_START( mpu6500_map, AS_PROGRAM, 8, a500_kbd_us_device )
ADDRESS_MAP_GLOBAL_MASK(0xfff)
AM_RANGE(0x000, 0x03f) AM_RAM
AM_RANGE(0x080, 0x080) AM_READWRITE(port_a_r, port_a_w)
@@ -48,7 +49,7 @@ static MACHINE_CONFIG_FRAGMENT( kbd_pcb )
MCFG_CPU_PROGRAM_MAP(mpu6500_map)
MACHINE_CONFIG_END
-machine_config_constructor a500_kbd_device::device_mconfig_additions() const
+machine_config_constructor a500_kbd_us_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME(kbd_pcb);
}
@@ -62,7 +63,7 @@ ROM_START( kbd_pcb )
ROM_LOAD("328191-02.ic1", 0x000, 0x800, CRC(4a3fc332) SHA1(83b21d0c8b93fc9b9b3b287fde4ec8f3badac5a2))
ROM_END
-const tiny_rom_entry *a500_kbd_device::device_rom_region() const
+const tiny_rom_entry *a500_kbd_us_device::device_rom_region() const
{
return ROM_NAME(kbd_pcb);
}
@@ -74,17 +75,17 @@ const tiny_rom_entry *a500_kbd_device::device_rom_region() const
static INPUT_PORTS_START( a500_us_keyboard )
PORT_START("special")
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LWIN) PORT_CHAR(UCHAR_MAMEKEY(LWIN)) PORT_NAME("Left Amiga") PORT_CHANGED_MEMBER(DEVICE_SELF, a500_kbd_device, check_reset, nullptr)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LWIN) PORT_CHAR(UCHAR_MAMEKEY(LWIN)) PORT_NAME("Left Amiga") PORT_CHANGED_MEMBER(DEVICE_SELF, a500_kbd_us_device, check_reset, nullptr)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_MAMEKEY(LALT))
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2) PORT_NAME("Ctrl") PORT_CHANGED_MEMBER(DEVICE_SELF, a500_kbd_device, check_reset, nullptr)
- PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RWIN) PORT_CHAR(UCHAR_MAMEKEY(RWIN)) PORT_NAME("Right Amiga") PORT_CHANGED_MEMBER(DEVICE_SELF, a500_kbd_device, check_reset, nullptr)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2) PORT_NAME("Ctrl") PORT_CHANGED_MEMBER(DEVICE_SELF, a500_kbd_us_device, check_reset, nullptr)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RWIN) PORT_CHAR(UCHAR_MAMEKEY(RWIN)) PORT_NAME("Right Amiga") PORT_CHANGED_MEMBER(DEVICE_SELF, a500_kbd_us_device, check_reset, nullptr)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_MAMEKEY(RALT))
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
PORT_START("row_d6")
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR(UCHAR_MAMEKEY(ASTERISK))
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_END) PORT_NAME("Unused")
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_NAME("Caps Lock")
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR(9)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~')
@@ -98,7 +99,7 @@ static INPUT_PORTS_START( a500_us_keyboard )
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
- PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_HOME) PORT_NAME("(")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_HOME) PORT_CHAR('(')
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
@@ -158,7 +159,7 @@ static INPUT_PORTS_START( a500_us_keyboard )
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')
- PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_PGUP) PORT_NAME(")")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_PGUP) PORT_CHAR(')')
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
@@ -183,7 +184,7 @@ static INPUT_PORTS_START( a500_us_keyboard )
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_START("row_c4")
- PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7_PAD) PORT_CHAR('7') PORT_CHAR('&')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD))
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
@@ -205,7 +206,7 @@ static INPUT_PORTS_START( a500_us_keyboard )
PORT_START("row_c2")
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD))
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_PGDN) PORT_NAME("Unused")
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9))
@@ -233,22 +234,189 @@ static INPUT_PORTS_START( a500_us_keyboard )
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
INPUT_PORTS_END
-ioport_constructor a500_kbd_device::device_input_ports() const
+ioport_constructor a500_kbd_us_device::device_input_ports() const
{
return INPUT_PORTS_NAME( a500_us_keyboard );
}
+static INPUT_PORTS_START( a500_de_keyboard )
+ PORT_START("special")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LWIN) PORT_CHAR(UCHAR_MAMEKEY(LWIN)) PORT_NAME("Left Amiga") PORT_CHANGED_MEMBER(DEVICE_SELF, a500_kbd_us_device, check_reset, nullptr)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_MAMEKEY(LALT))
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2) PORT_NAME("Ctrl") PORT_CHANGED_MEMBER(DEVICE_SELF, a500_kbd_us_device, check_reset, nullptr)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RWIN) PORT_CHAR(UCHAR_MAMEKEY(RWIN)) PORT_NAME("Right Amiga") PORT_CHANGED_MEMBER(DEVICE_SELF, a500_kbd_us_device, check_reset, nullptr)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_MAMEKEY(RALT))
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
+
+ PORT_START("row_d6")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR(UCHAR_MAMEKEY(ASTERISK))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_NAME("Caps Lock")
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR(9)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('\'') PORT_CHAR('~')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("row_d5")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('y') PORT_CHAR('Y')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_HOME) PORT_CHAR('[') PORT_CHAR('{')
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("row_d4")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("row_d3")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR(0x00a7) // ยง
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("row_d2")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("row_d1")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("row_d0")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('z') PORT_CHAR('Z')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("row_c7")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_PGUP) PORT_CHAR(']') PORT_CHAR('}')
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("row_c6")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("row_c5")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH_PAD) PORT_CHAR('/')
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("row_c4")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('-') PORT_CHAR('_')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(0x00f6) PORT_CHAR(0x00d6) // รถ ร–
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("row_c3")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0x00e4) PORT_CHAR(0x00c4) // รค ร„
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x00fc) PORT_CHAR(0x00dc) // รผ รœ
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR(0x00df) PORT_CHAR('?') // รŸ
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("row_c2")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('#') PORT_CHAR('^')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('+') PORT_CHAR('*')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(0x00b4) PORT_CHAR('`') // ยด
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("row_c1")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL))
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F12) PORT_CHAR('\\') PORT_CHAR('|')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("row_c0")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F11) PORT_NAME("Help")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+INPUT_PORTS_END
+
+ioport_constructor a500_kbd_de_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( a500_de_keyboard );
+}
+
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
-// a500_kbd_device - constructor
+// a500_kbd_us_device - constructor
//-------------------------------------------------
-a500_kbd_device::a500_kbd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, A500_KBD, "Amiga 500 Keyboard (U.S./Canada)", tag, owner, clock, "a500_kbd", __FILE__),
+a500_kbd_us_device::a500_kbd_us_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, A500_KBD_US, "Amiga 500 Keyboard (U.S./Canada)", tag, owner, clock, "a500_kbd_us", __FILE__),
device_amiga_keyboard_interface(mconfig, *this),
m_mpu(*this, "ic1"),
m_special(*this, "special"),
@@ -264,14 +432,41 @@ a500_kbd_device::a500_kbd_device(const machine_config &mconfig, const char *tag,
m_latch(0xffff),
m_counter(0xffff),
m_control(0x00)
-{
-}
+{}
+
+a500_kbd_us_device::a500_kbd_us_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock,
+ device_type type, const char *name, const char *shortname) :
+ device_t(mconfig, type, name, tag, owner, clock, shortname, __FILE__),
+ device_amiga_keyboard_interface(mconfig, *this),
+ m_mpu(*this, "ic1"),
+ m_special(*this, "special"),
+ m_row_d(*this, "row_d%u", 0),
+ m_row_c(*this, "row_c%u", 0),
+ m_timer(nullptr),
+ m_watchdog(nullptr),
+ m_reset(nullptr),
+ m_kdat(1),
+ m_kclk(1),
+ m_port_c(0xff),
+ m_port_d(0xff),
+ m_latch(0xffff),
+ m_counter(0xffff),
+ m_control(0x00)
+{}
+
+//-------------------------------------------------
+// a500_kbd_de_device - constructor
+//-------------------------------------------------
+
+a500_kbd_de_device::a500_kbd_de_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a500_kbd_us_device(mconfig, tag, owner, clock, A500_KBD_DE, "Amiga 500 Keyboard (Germany/Austria)", "a500_kbd_de")
+{}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
-void a500_kbd_device::device_start()
+void a500_kbd_us_device::device_start()
{
// allocate timers
m_timer = timer_alloc(0, nullptr);
@@ -292,7 +487,7 @@ void a500_kbd_device::device_start()
// device_reset - device-specific reset
//-------------------------------------------------
-void a500_kbd_device::device_reset()
+void a500_kbd_us_device::device_reset()
{
// stack starts 0
m_mpu->set_state_int(M6502_S, 0);
@@ -309,7 +504,7 @@ void a500_kbd_device::device_reset()
m_watchdog->adjust(attotime::from_msec(54));
}
-void a500_kbd_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
+void a500_kbd_us_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
{
switch (tid)
{
@@ -359,7 +554,7 @@ void a500_kbd_device::device_timer(emu_timer &timer, device_timer_id tid, int pa
// IMPLEMENTATION
//**************************************************************************
-INPUT_CHANGED_MEMBER( a500_kbd_device::check_reset )
+INPUT_CHANGED_MEMBER( a500_kbd_us_device::check_reset )
{
uint8_t keys = m_special->read();
@@ -371,7 +566,7 @@ INPUT_CHANGED_MEMBER( a500_kbd_device::check_reset )
}
}
-void a500_kbd_device::update_irqs()
+void a500_kbd_us_device::update_irqs()
{
if ((m_control & PA1_INT_ENABLED) && (m_control & PA1_NEGATIVE_EDGE))
m_mpu->set_input_line(M6502_IRQ_LINE, ASSERT_LINE);
@@ -386,7 +581,7 @@ void a500_kbd_device::update_irqs()
m_mpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE);
}
-READ8_MEMBER( a500_kbd_device::port_a_r )
+READ8_MEMBER( a500_kbd_us_device::port_a_r )
{
uint8_t data = 0xfc;
@@ -404,7 +599,7 @@ READ8_MEMBER( a500_kbd_device::port_a_r )
return data;
}
-WRITE8_MEMBER( a500_kbd_device::port_a_w )
+WRITE8_MEMBER( a500_kbd_us_device::port_a_w )
{
// look for pa0 edge
if (!m_kdat && BIT(data, 0))
@@ -434,18 +629,18 @@ WRITE8_MEMBER( a500_kbd_device::port_a_w )
}
}
-WRITE8_MEMBER( a500_kbd_device::port_b_w )
+WRITE8_MEMBER( a500_kbd_us_device::port_b_w )
{
// caps lock led
machine().output().set_value("led0", BIT(data, 7));
}
-WRITE8_MEMBER( a500_kbd_device::port_c_w )
+WRITE8_MEMBER( a500_kbd_us_device::port_c_w )
{
m_port_c = data;
}
-WRITE8_MEMBER( a500_kbd_device::port_d_w )
+WRITE8_MEMBER( a500_kbd_us_device::port_d_w )
{
// reset watchdog on 0 -> 1 transition
if (!BIT(m_port_d, 7) && BIT(data, 7))
@@ -454,7 +649,7 @@ WRITE8_MEMBER( a500_kbd_device::port_d_w )
m_port_d = data;
}
-WRITE8_MEMBER( a500_kbd_device::latch_w )
+WRITE8_MEMBER( a500_kbd_us_device::latch_w )
{
if (offset == 0)
{
@@ -468,7 +663,7 @@ WRITE8_MEMBER( a500_kbd_device::latch_w )
}
}
-READ8_MEMBER( a500_kbd_device::counter_r )
+READ8_MEMBER( a500_kbd_us_device::counter_r )
{
if (!space.debugger_access())
{
@@ -482,7 +677,7 @@ READ8_MEMBER( a500_kbd_device::counter_r )
return m_counter >> 0;
}
-WRITE8_MEMBER( a500_kbd_device::transfer_latch_w )
+WRITE8_MEMBER( a500_kbd_us_device::transfer_latch_w )
{
m_control &= ~COUNTER_OVERFLOW;
update_irqs();
@@ -493,30 +688,30 @@ WRITE8_MEMBER( a500_kbd_device::transfer_latch_w )
m_counter = m_latch;
}
-WRITE8_MEMBER( a500_kbd_device::clear_pa0_detect )
+WRITE8_MEMBER( a500_kbd_us_device::clear_pa0_detect )
{
m_control &= ~PA0_POSITIVE_EDGE;
update_irqs();
}
-WRITE8_MEMBER( a500_kbd_device::clear_pa1_detect )
+WRITE8_MEMBER( a500_kbd_us_device::clear_pa1_detect )
{
m_control &= ~PA1_NEGATIVE_EDGE;
update_irqs();
}
-READ8_MEMBER( a500_kbd_device::control_r )
+READ8_MEMBER( a500_kbd_us_device::control_r )
{
return m_control;
}
-WRITE8_MEMBER( a500_kbd_device::control_w )
+WRITE8_MEMBER( a500_kbd_us_device::control_w )
{
m_control = data;
update_irqs();
}
-WRITE_LINE_MEMBER( a500_kbd_device::kdat_w )
+WRITE_LINE_MEMBER( a500_kbd_us_device::kdat_w )
{
// detect positive edge
if (state && !m_kdat)
diff --git a/src/devices/bus/amiga/keyboard/a500.h b/src/devices/bus/amiga/keyboard/a500.h
index 5ac849a4d81..5af5f62ee5a 100644
--- a/src/devices/bus/amiga/keyboard/a500.h
+++ b/src/devices/bus/amiga/keyboard/a500.h
@@ -41,13 +41,15 @@
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> a500_kbd_device
+// ======================> a500_kbd_us_device
-class a500_kbd_device : public device_t, public device_amiga_keyboard_interface
+class a500_kbd_us_device : public device_t, public device_amiga_keyboard_interface
{
public:
// construction/destruction
- a500_kbd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ a500_kbd_us_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ a500_kbd_us_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock,
+ device_type type, const char *name, const char *shortname);
// from host
virtual DECLARE_WRITE_LINE_MEMBER(kdat_w) override;
@@ -118,7 +120,19 @@ private:
uint8_t m_control;
};
+// ======================> a500_kbd_de_device
+
+class a500_kbd_de_device : public a500_kbd_us_device
+{
+public:
+ a500_kbd_de_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual ioport_constructor device_input_ports() const override;
+};
+
// device type definition
-extern const device_type A500_KBD;
+extern const device_type A500_KBD_US;
+extern const device_type A500_KBD_DE;
#endif // DEVICES_BUS_AMIGA_KEYBOARD_A500_H
diff --git a/src/devices/bus/amiga/keyboard/keyboard.cpp b/src/devices/bus/amiga/keyboard/keyboard.cpp
index e6b92ff00e7..c9d9bc95ce9 100644
--- a/src/devices/bus/amiga/keyboard/keyboard.cpp
+++ b/src/devices/bus/amiga/keyboard/keyboard.cpp
@@ -104,6 +104,7 @@ device_amiga_keyboard_interface::~device_amiga_keyboard_interface()
//**************************************************************************
SLOT_INTERFACE_START( amiga_keyboard_devices )
- SLOT_INTERFACE("a500_us", A500_KBD)
+ SLOT_INTERFACE("a500_us", A500_KBD_US)
+ SLOT_INTERFACE("a500_de", A500_KBD_DE)
SLOT_INTERFACE("a1200_us", A1200_KBD)
SLOT_INTERFACE_END
diff --git a/src/devices/cpu/clipper/clipper.cpp b/src/devices/cpu/clipper/clipper.cpp
new file mode 100644
index 00000000000..3c4741d39dd
--- /dev/null
+++ b/src/devices/cpu/clipper/clipper.cpp
@@ -0,0 +1,1401 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * An implementation of the Fairchild/Intergraph CLIPPER CPU family.
+ *
+ * Primary source: http://bitsavers.trailing-edge.com/pdf/fairchild/clipper/Clipper_Instruction_Set_Oct85.pdf
+ *
+ * TODO:
+ * - save/restore state
+ * - unimplemented instructions
+ * - C100, C300, C400 variants
+ * - correct boot logic
+ * - condition codes for multiply instructions
+ * - most cpu traps/faults
+ * - instruction timing
+ * - big endian support (not present in the wild)
+ */
+
+#include "emu.h"
+#include "debugger.h"
+#include "clipper.h"
+
+#define VERBOSE 0
+#if VERBOSE
+#define LOG_INTERRUPT(...) logerror(__VA_ARGS__)
+#else
+#define LOG_INTERRUPT(...)
+#endif
+
+const device_type CLIPPER_C100 = &device_creator<clipper_c100_device>;
+const device_type CLIPPER_C300 = &device_creator<clipper_c300_device>;
+const device_type CLIPPER_C400 = &device_creator<clipper_c400_device>;
+
+clipper_c100_device::clipper_c100_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : clipper_device(mconfig, CLIPPER_C100, "C100 CLIPPER", tag, owner, clock, "C100", __FILE__) { }
+
+clipper_c300_device::clipper_c300_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : clipper_device(mconfig, CLIPPER_C300, "C300 CLIPPER", tag, owner, clock, "C300", __FILE__) { }
+
+clipper_c400_device::clipper_c400_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : clipper_device(mconfig, CLIPPER_C400, "C400 CLIPPER", tag, owner, clock, "C400", __FILE__) { }
+
+clipper_device::clipper_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, const char *shortname, const char *source)
+ : cpu_device(mconfig, type, name, tag, owner, clock, shortname, source),
+ m_pc(0),
+ m_r(m_rs),
+ m_insn_config("insn", ENDIANNESS_LITTLE, 32, 32, 0),
+ m_data_config("data", ENDIANNESS_LITTLE, 32, 32, 0),
+ m_insn(nullptr),
+ m_data(nullptr),
+ m_icount(0)
+{
+}
+
+// rotate helpers to replace MSVC intrinsics
+inline u32 rotl32(u32 x, u8 shift)
+{
+ shift &= 31;
+ return (x << shift) | (x >> ((32 - shift) & 31));
+}
+
+inline u32 rotr32(u32 x, u8 shift)
+{
+ shift &= 31;
+ return (x >> shift) | (x << ((32 - shift) & 31));
+}
+
+inline u64 rotl64(u64 x, u8 shift)
+{
+ shift &= 63;
+ return (x << shift) | (x >> ((64 - shift) & 63));
+}
+
+inline u64 rotr64(u64 x, u8 shift)
+{
+ shift &= 63;
+ return (x >> shift) | (x << ((64 - shift) & 63));
+}
+
+void clipper_device::device_start()
+{
+ // get our address spaces
+ m_insn = &space(AS_PROGRAM);
+ m_data = &space(AS_DATA);
+
+ // set our instruction counter
+ m_icountptr = &m_icount;
+
+ //save_item(NAME(m_pc));
+
+ state_add(STATE_GENPC, "GENPC", m_pc).noshow();
+ state_add(STATE_GENPCBASE, "CURPC", m_pc).noshow();
+ state_add(STATE_GENSP, "GENSP", m_r[15]).noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_psw).mask(0xf).formatstr("%4s").noshow();
+
+ state_add(CLIPPER_PC, "pc", m_pc);
+ state_add(CLIPPER_PSW, "psw", m_psw);
+ state_add(CLIPPER_SSW, "ssw", m_ssw);
+
+ state_add(CLIPPER_R0, "r0", m_r[0]);
+ state_add(CLIPPER_R1, "r1", m_r[1]);
+ state_add(CLIPPER_R2, "r2", m_r[2]);
+ state_add(CLIPPER_R3, "r3", m_r[3]);
+ state_add(CLIPPER_R4, "r4", m_r[4]);
+ state_add(CLIPPER_R5, "r5", m_r[5]);
+ state_add(CLIPPER_R6, "r6", m_r[6]);
+ state_add(CLIPPER_R7, "r7", m_r[7]);
+ state_add(CLIPPER_R8, "r8", m_r[8]);
+ state_add(CLIPPER_R9, "r9", m_r[9]);
+ state_add(CLIPPER_R10, "r10", m_r[10]);
+ state_add(CLIPPER_R11, "r11", m_r[11]);
+ state_add(CLIPPER_R12, "r12", m_r[12]);
+ state_add(CLIPPER_R13, "r13", m_r[13]);
+ state_add(CLIPPER_R14, "r14", m_r[14]);
+ state_add(CLIPPER_R15, "r15", m_r[15]);
+
+ state_add(CLIPPER_F0, "f0", m_f[0]);
+ state_add(CLIPPER_F1, "f1", m_f[1]);
+ state_add(CLIPPER_F2, "f2", m_f[2]);
+ state_add(CLIPPER_F3, "f3", m_f[3]);
+ state_add(CLIPPER_F4, "f4", m_f[4]);
+ state_add(CLIPPER_F5, "f5", m_f[5]);
+ state_add(CLIPPER_F6, "f6", m_f[6]);
+ state_add(CLIPPER_F7, "f7", m_f[7]);
+
+ // C400 has 8 additional floating point registers
+ if (type() == CLIPPER_C400)
+ {
+ state_add(CLIPPER_F8, "f8", m_f[8]);
+ state_add(CLIPPER_F9, "f9", m_f[9]);
+ state_add(CLIPPER_F10, "f10", m_f[10]);
+ state_add(CLIPPER_F11, "f11", m_f[11]);
+ state_add(CLIPPER_F12, "f12", m_f[12]);
+ state_add(CLIPPER_F13, "f13", m_f[13]);
+ state_add(CLIPPER_F14, "f14", m_f[14]);
+ state_add(CLIPPER_F15, "f15", m_f[15]);
+ }
+}
+
+void clipper_device::device_reset()
+{
+ /*
+ * From C300 documentation, on reset:
+ * psw: T cleared, BIG set from hardware, others undefined
+ * ssw: EI, TP, M, U, K, KU, UU, P cleared, ID set from hardware, others undefined
+ */
+ m_psw = 0;
+ m_ssw = 0;
+
+ m_r = SSW(U) ? m_ru : m_rs;
+
+ // we'll opt to clear the integer and floating point registers too
+ memset(m_r, 0, sizeof(s32)*16);
+ memset(m_f, 0, sizeof(m_f));
+
+ // FIXME: figure out how to branch to the boot code properly
+ m_pc = 0x7f100000;
+ m_irq = 0;
+ m_nmi = 0;
+}
+
+void clipper_device::state_string_export(const device_state_entry &entry, std::string &str) const
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ str = string_format("%c%c%c%c",
+ PSW(C) ? 'C' : '.',
+ PSW(V) ? 'V' : '.',
+ PSW(Z) ? 'Z' : '.',
+ PSW(N) ? 'N' : '.');
+ break;
+ }
+}
+
+void clipper_device::execute_run()
+{
+ u16 insn;
+
+ // check for non-maskable and prioritised interrupts
+ if (m_nmi)
+ {
+ // acknowledge non-maskable interrupt
+ standard_irq_callback(INPUT_LINE_NMI);
+
+ LOG_INTERRUPT("non-maskable interrupt - current pc = 0x%08x\n", m_pc);
+ m_pc = intrap(EXCEPTION_INTERRUPT_BASE, m_pc);
+ }
+ else if (SSW(EI) && m_irq)
+ {
+ // FIXME: sample interrupt vector from the bus without acknowledging the interrupt
+ u8 ivec = standard_irq_callback(-1);
+ LOG_INTERRUPT("received prioritised interrupt with vector 0x%04x\n", ivec);
+
+ // allow equal/higher priority interrupts
+ if ((ivec >> 4) <= SSW(IL))
+ {
+ // acknowledge interrupt
+ standard_irq_callback(INPUT_LINE_IRQ0);
+
+ LOG_INTERRUPT("accepting interrupt vector 0x%04x - current pc = %08x\n", ivec, m_pc);
+ m_pc = intrap(EXCEPTION_INTERRUPT_BASE + ivec * 8, m_pc);
+ }
+ }
+
+ while (m_icount > 0) {
+
+ debugger_instruction_hook(this, m_pc);
+
+ // fetch instruction word
+ insn = m_insn->read_word(m_pc + 0);
+
+ decode_instruction(insn);
+
+ // decode and execute instruction, return next pc
+ m_pc = execute_instruction();
+
+ // FIXME: some instructions take longer (significantly) than one cycle
+ // and also the timings are often slower for the C100 and C300
+ m_icount--;
+ }
+}
+
+void clipper_device::execute_set_input(int inputnum, int state)
+{
+ switch (inputnum)
+ {
+ case INPUT_LINE_IRQ0:
+ m_irq = state;
+ break;
+
+ case INPUT_LINE_NMI:
+ m_nmi = state;
+ break;
+ }
+}
+
+/*
+ * The CLIPPER has a true Harvard architecture. In the InterPro, these are tied back together
+ * again by the MMU, which then directs the access to one of 3 address spaces: main, i/o or boot.
+ */
+const address_space_config *clipper_device::memory_space_config(address_spacenum spacenum) const
+{
+ switch (spacenum)
+ {
+ case AS_PROGRAM: return &m_insn_config;
+ case AS_DATA: return &m_data_config;
+ default: break;
+ }
+
+ return nullptr;
+}
+
+/*
+ * This function decodes instruction operands and computes effective addresses (for
+ * instructions with addressing modes). The results are contained in the m_info
+ * structure to simplify passing between here and execute_instruction().
+ */
+void clipper_device::decode_instruction (u16 insn)
+{
+ // decode the primary parcel
+ m_info.opcode = insn >> 8;
+ m_info.subopcode = insn & 0xff;
+ m_info.r1 = (insn & 0x00f0) >> 4;
+ m_info.r2 = insn & 0x000f;
+
+ // initialise the other fields
+ m_info.imm = 0;
+ m_info.macro = 0;
+ m_info.size = 0;
+ m_info.address = 0;
+
+ if ((insn & 0xf800) == 0x3800)
+ {
+ // instruction has a 16 bit immediate operand
+
+ // fetch 16 bit immediate and sign extend
+ m_info.imm = (s16)m_insn->read_word(m_pc + 2);
+ m_info.size = 4;
+ }
+ else if ((insn & 0xd300) == 0x8300)
+ {
+ // instruction has an immediate operand, either 16 or 32 bit
+ if (insn & 0x0080)
+ {
+ // fetch 16 bit immediate and sign extend
+ m_info.imm = (s16)m_insn->read_word(m_pc + 2);
+ m_info.size = 4;
+ }
+ else
+ {
+ // fetch 32 bit immediate and sign extend
+ m_info.imm = (s32)m_insn->read_dword_unaligned(m_pc + 2);
+ m_info.size = 6;
+ }
+ }
+ else if ((insn & 0xc000) == 0x4000)
+ {
+ // instructions with addresses
+ if (insn & 0x0100)
+ {
+ // instructions with complex modes
+ u16 temp;
+
+ switch (insn & 0x00f0)
+ {
+ case ADDR_MODE_PC32:
+ m_info.address = m_pc + (s32)m_insn->read_dword_unaligned(m_pc + 2);
+ m_info.size = 6;
+ break;
+
+ case ADDR_MODE_ABS32:
+ m_info.address = m_insn->read_dword_unaligned(m_pc + 2);
+ m_info.size = 6;
+ break;
+
+ case ADDR_MODE_REL32:
+ m_info.r2 = m_insn->read_word(m_pc + 2) & 0xf;
+ m_info.address = m_r[insn & 0xf] + (s32)m_insn->read_dword_unaligned(m_pc + 4);
+ m_info.size = 8;
+ break;
+
+ case ADDR_MODE_PC16:
+ m_info.address = m_pc + (s16)m_insn->read_word(m_pc + 2);
+ m_info.size = 4;
+ break;
+
+ case ADDR_MODE_REL12:
+ temp = m_insn->read_word(m_pc + 2);
+
+ m_info.r2 = temp & 0xf;
+ m_info.address = m_r[insn & 0xf] + ((s16)temp >> 4);
+ m_info.size = 4;
+ break;
+
+ case ADDR_MODE_ABS16:
+ m_info.address = (s16)m_insn->read_word(m_pc + 2);
+ m_info.size = 4;
+ break;
+
+ case ADDR_MODE_PCX:
+ temp = m_insn->read_word(m_pc + 2);
+
+ m_info.r2 = temp & 0xf;
+ m_info.address = m_pc + m_r[(temp >> 4) & 0xf];
+ m_info.size = 4;
+ break;
+
+ case ADDR_MODE_RELX:
+ temp = m_insn->read_word(m_pc + 2);
+
+ m_info.r2 = temp & 0xf;
+ m_info.address = m_r[insn & 0xf] + m_r[(temp >> 4) & 0xf];
+ m_info.size = 4;
+ break;
+
+ default:
+ logerror("illegal addressing mode pc = 0x%08x\n", m_pc);
+ machine().debug_break();
+ break;
+ }
+ }
+ else
+ {
+ // relative addressing mode
+ m_info.address = m_r[m_info.r1];
+ m_info.size = 2;
+ }
+ }
+ else if ((insn & 0xfd00) == 0xb400)
+ {
+ // macro instructions
+ m_info.macro = m_insn->read_word(m_pc + 2);
+ m_info.size = 4;
+ }
+ else
+ // all other instruction formats are 16 bits
+ m_info.size = 2;
+}
+
+int clipper_device::execute_instruction ()
+{
+ // the address of the next instruction
+ u32 next_pc;
+
+ // next instruction follows the current one by default, but
+ // may be changed for branch, call or trap instructions
+ next_pc = m_pc + m_info.size;
+
+ switch (m_info.opcode)
+ {
+ case 0x00: // noop
+ break;
+
+ case 0x10:
+ // movwp: move word to processor register
+ // treated as a noop if target ssw in user mode
+ // R1 == 3 means "fast" mode - avoids pipeline flush
+ if (R1 == 0)
+ m_psw = m_r[R2];
+ else if (!SSW(U) && (R1 == 1 || R1 == 3))
+ {
+ m_ssw = m_r[R2];
+ m_r = SSW(U) ? m_ru : m_rs;
+ }
+ // FLAGS: CVZN
+ break;
+ case 0x11:
+ // movpw: move processor register to word
+ switch (R1)
+ {
+ case 0: m_r[R2] = m_psw; break;
+ case 1: m_r[R2] = m_ssw; break;
+ }
+ break;
+ case 0x12:
+ // calls: call supervisor
+ next_pc = intrap(EXCEPTION_SUPERVISOR_CALL_BASE + (m_info.subopcode & 0x7f) * 8, next_pc);
+ break;
+ case 0x13:
+ // ret: return from subroutine
+ next_pc = m_data->read_dword(m_r[R2]);
+ m_r[R2] += 4;
+ // TRAPS: C,U,A,P,R
+ break;
+ case 0x14:
+ // pushw: push word
+ m_r[R1] -= 4;
+ m_data->write_dword(m_r[R1], m_r[R2]);
+ // TRAPS: A,P,W
+ break;
+
+ case 0x16:
+ // popw: pop word
+ m_r[R2] = m_data->read_dword(m_r[R1]);
+ m_r[R1] += 4;
+ // TRAPS: C,U,A,P,R
+ break;
+
+ case 0x20:
+ // adds: add single floating
+ *((float *)&m_f[R2]) += *((float *)&m_f[R1]);
+ // TRAPS: F_IVUX
+ break;
+ case 0x21:
+ // subs: subtract single floating
+ *((float *)&m_f[R2]) -= *((float *)&m_f[R1]);
+ // TRAPS: F_IVUX
+ break;
+ case 0x22:
+ // addd: add double floating
+ m_f[R2] += m_f[R1];
+ // TRAPS: F_IVUX
+ break;
+ case 0x23:
+ // subd: subtract double floating
+ m_f[R2] -= m_f[R1];
+ // TRAPS: F_IVUX
+ break;
+ case 0x24:
+ // movs: move single floating
+ *((float *)&m_f[R2]) = *((float *)&m_f[R1]);
+ break;
+ case 0x25:
+ // cmps: compare single floating
+ FLAGS(0, 0, *((float *)&m_f[R2]) == *((float *)&m_f[R1]), *((float *)&m_f[R2]) < *((float *)&m_f[R1]))
+ break;
+ case 0x26:
+ // movd: move double floating
+ m_f[R2] = m_f[R1];
+ break;
+ case 0x27:
+ // cmpd: compare double floating
+ FLAGS(0, 0, m_f[R2] == m_f[R1], m_f[R2] < m_f[R1])
+ // FLAGS: 00ZN
+ break;
+ case 0x28:
+ // muls: multiply single floating
+ *((float *)&m_f[R2]) *= *((float *)&m_f[R1]);
+ // TRAPS: F_IVUX
+ break;
+ case 0x29:
+ // divs: divide single floating
+ *((float *)&m_f[R2]) /= *((float *)&m_f[R1]);
+ // TRAPS: F_IVDUX
+ break;
+ case 0x2a:
+ // muld: multiply double floating
+ m_f[R2] *= m_f[R1];
+ // TRAPS: F_IVUX
+ break;
+ case 0x2b:
+ // divd: divide double floating
+ m_f[R2] /= m_f[R1];
+ // TRAPS: F_IVDUX
+ break;
+ case 0x2c:
+ // movsw: move single floating to word
+ m_r[R2] = *((s32 *)&m_f[R1]);
+ break;
+ case 0x2d:
+ // movws: move word to single floating
+ *((s32 *)&m_f[R2]) = m_r[R1];
+ break;
+ case 0x2e:
+ // movdl: move double floating to longword
+ ((double *)m_r)[R2 >> 1] = m_f[R1];
+ break;
+ case 0x2f:
+ // movld: move longword to double floating
+ m_f[R2] = ((double *)m_r)[R1 >> 1];
+ break;
+ case 0x30:
+ // shaw: shift arithmetic word
+ if (m_r[R1] > 0)
+ {
+ // save the bits that will be shifted out plus new sign bit
+ s32 v = m_r[R2] >> (31 - m_r[R1]);
+
+ m_r[R2] <<= m_r[R1];
+
+ // overflow is set if sign changes during shift
+ FLAGS(0, v != 0 && v != -1, m_r[R2] == 0, m_r[R2] < 0)
+ }
+ else
+ {
+ m_r[R2] >>= -m_r[R1];
+ FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0)
+ }
+ // FLAGS: 0VZN
+ break;
+ case 0x31:
+ // shal: shift arithmetic longword
+ if (m_r[R1] > 0)
+ {
+ // save the bits that will be shifted out plus new sign bit
+ s64 v = ((s64 *)m_r)[R2 >> 1] >> (63 - m_r[R1]);
+
+ ((s64 *)m_r)[R2 >> 1] <<= m_r[R1];
+
+ // overflow is set if sign changes during shift
+ FLAGS(0, v != 0 && v != -1, ((s64 *)m_r)[R2 >> 1] == 0, ((s64 *)m_r)[R2 >> 1] < 0)
+ }
+ else
+ {
+ ((s64 *)m_r)[R2 >> 1] >>= -m_r[R1];
+ FLAGS(0, 0, ((s64 *)m_r)[R2 >> 1] == 0, ((s64 *)m_r)[R2 >> 1] < 0)
+ }
+ // FLAGS: 0VZN
+ break;
+ case 0x32:
+ // shlw: shift logical word
+ if (m_r[R1] > 0)
+ m_r[R2] <<= m_r[R1];
+ else
+ ((u32 *)m_r)[R2] >>= -m_r[R1];
+ // FLAGS: 00ZN
+ FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0);
+ break;
+ case 0x33:
+ // shll: shift logical longword
+ if (m_r[R1] > 0)
+ ((u64 *)m_r)[R2 >> 1] <<= m_r[R1];
+ else
+ ((u64 *)m_r)[R2 >> 1] >>= -m_r[R1];
+ // FLAGS: 00ZN
+ FLAGS(0, 0, ((s64 *)m_r)[R2 >> 1] == 0, ((s64 *)m_r)[R2 >> 1] < 0);
+ break;
+ case 0x34:
+ // rotw: rotate word
+ if (m_r[R1] > 0)
+ m_r[R2] = rotl32(m_r[R2], m_r[R1]);
+ else
+ m_r[R2] = rotr32(m_r[R2], -m_r[R1]);
+ // FLAGS: 00ZN
+ FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0);
+ break;
+ case 0x35:
+ // rotl: rotate longword
+ if (m_r[R1] > 0)
+ ((u64 *)m_r)[R2 >> 1] = rotl64(((u64 *)m_r)[R2 >> 1], m_r[R1]);
+ else
+ ((u64 *)m_r)[R2 >> 1] = rotr64(((u64 *)m_r)[R2 >> 1], -m_r[R1]);
+ // FLAGS: 00ZN
+ FLAGS(0, 0, ((s64 *)m_r)[R2 >> 1] == 0, ((s64 *)m_r)[R2 >> 1] < 0);
+ break;
+
+ case 0x38:
+ // shai: shift arithmetic immediate
+ if (m_info.imm > 0)
+ {
+ // save the bits that will be shifted out plus new sign bit
+ s32 v = m_r[R2] >> (31 - m_info.imm);
+
+ m_r[R2] <<= m_info.imm;
+
+ // overflow is set if sign changes during shift
+ FLAGS(0, v != 0 && v != -1, m_r[R2] == 0, m_r[R2] < 0)
+ }
+ else
+ {
+ m_r[R2] >>= -m_info.imm;
+ FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0)
+ }
+ // FLAGS: 0VZN
+ // TRAPS: I
+ break;
+ case 0x39:
+ // shali: shift arithmetic longword immediate
+ if (m_info.imm > 0)
+ {
+ // save the bits that will be shifted out plus new sign bit
+ s64 v = ((s64 *)m_r)[R2 >> 1] >> (63 - m_info.imm);
+
+ ((s64 *)m_r)[R2 >> 1] <<= m_info.imm;
+
+ // overflow is set if sign changes during shift
+ FLAGS(0, v != 0 && v != -1, ((s64 *)m_r)[R2 >> 1] == 0, ((s64 *)m_r)[R2 >> 1] < 0)
+ }
+ else
+ {
+ ((s64 *)m_r)[R2 >> 1] >>= -m_info.imm;
+ FLAGS(0, 0, ((s64 *)m_r)[R2 >> 1] == 0, ((s64 *)m_r)[R2 >> 1] < 0)
+ }
+ // FLAGS: 0VZN
+ // TRAPS: I
+ break;
+ case 0x3a:
+ // shli: shift logical immediate
+ if (m_info.imm > 0)
+ m_r[R2] <<= m_info.imm;
+ else
+ ((u32 *)m_r)[R2] >>= -m_info.imm;
+ FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0);
+ // FLAGS: 00ZN
+ // TRAPS: I
+ break;
+ case 0x3b:
+ // shlli: shift logical longword immediate
+ if (m_info.imm > 0)
+ ((u64 *)m_r)[R2 >> 1] <<= m_info.imm;
+ else
+ ((u64 *)m_r)[R2 >> 1] >>= -m_info.imm;
+ FLAGS(0, 0, ((s64 *)m_r)[R2 >> 1] == 0, ((s64 *)m_r)[R2 >> 1] < 0);
+ // FLAGS: 00ZN
+ // TRAPS: I
+ break;
+ case 0x3c:
+ // roti: rotate immediate
+ if (m_info.imm > 0)
+ m_r[R2] = rotl32(m_r[R2], m_info.imm);
+ else
+ m_r[R2] = rotr32(m_r[R2], -m_info.imm);
+ FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0);
+ // FLAGS: 00ZN
+ // TRAPS: I
+ break;
+ case 0x3d:
+ // rotli: rotate longword immediate
+ if (m_info.imm > 0)
+ ((u64 *)m_r)[R2 >> 1] = rotl64(((u64 *)m_r)[R2 >> 1], m_info.imm);
+ else
+ ((u64 *)m_r)[R2 >> 1] = rotr64(((u64 *)m_r)[R2 >> 1], -m_info.imm);
+ FLAGS(0, 0, ((s64 *)m_r)[R2 >> 1] == 0, ((s64 *)m_r)[R2 >> 1] < 0);
+ // FLAGS: 00ZN
+ // TRAPS: I
+ break;
+
+ case 0x44:
+ case 0x45:
+ // call: call subroutine
+ m_r[R2] -= 4;
+ m_data->write_dword(m_r[R2], next_pc);
+ next_pc = m_info.address;
+ // TRAPS: A,P,W
+ break;
+#ifdef UNIMPLEMENTED_C400
+ case 0x46:
+ case 0x47:
+ // loadd2:
+ break;
+#endif
+ case 0x48:
+ case 0x49:
+ // b*: branch on condition
+ if (evaluate_branch())
+ next_pc = m_info.address;
+ // TRAPS: A,I
+ break;
+#ifdef UNIMPLEMENTED_C400
+ case 0x4a:
+ case 0x4b:
+ // cdb:
+ break;
+ case 0x4c:
+ case 0x4d:
+ // cdbeq:
+ break;
+ case 0x4e:
+ case 0x4f:
+ // cdbne:
+ break;
+ case 0x50:
+ case 0x51:
+ // db*:
+ break;
+#endif
+#ifdef UNIMPLEMENTED
+ case 0x4c:
+ case 0x4d:
+ // bf*:
+ break;
+#endif
+
+ case 0x60:
+ case 0x61:
+ // loadw: load word
+ m_r[R2] = m_data->read_dword(m_info.address);
+ // TRAPS: C,U,A,P,R,I
+ break;
+ case 0x62:
+ case 0x63:
+ // loada: load address
+ m_r[R2] = m_info.address;
+ // TRAPS: I
+ break;
+ case 0x64:
+ case 0x65:
+ // loads: load single floating
+ ((u64 *)&m_f)[R2] = m_data->read_dword(m_info.address);
+ // TRAPS: C,U,A,P,R,I
+ break;
+ case 0x66:
+ case 0x67:
+ // loadd: load double floating
+ ((u64 *)&m_f)[R2] = m_data->read_qword(m_info.address);
+ // TRAPS: C,U,A,P,R,I
+ break;
+ case 0x68:
+ case 0x69:
+ // loadb: load byte
+ m_r[R2] = (s8)m_data->read_byte(m_info.address);
+ // TRAPS: C,U,A,P,R,I
+ break;
+ case 0x6a:
+ case 0x6b:
+ // loadbu: load byte unsigned
+ m_r[R2] = m_data->read_byte(m_info.address);
+ // TRAPS: C,U,A,P,R,I
+ break;
+ case 0x6c:
+ case 0x6d:
+ // loadh: load halfword
+ m_r[R2] = (s16)m_data->read_word(m_info.address);
+ // TRAPS: C,U,A,P,R,I
+ break;
+ case 0x6e:
+ case 0x6f:
+ // loadhu: load halfword unsigned
+ m_r[R2] = m_data->read_word(m_info.address);
+ // TRAPS: C,U,A,P,R,I
+ break;
+ case 0x70:
+ case 0x71:
+ // storw: store word
+ m_data->write_dword(m_info.address, m_r[R2]);
+ // TRAPS: A,P,W,I
+ break;
+ case 0x72:
+ case 0x73:
+ // tsts: test and set
+ m_r[R2] = m_data->read_dword(m_info.address);
+ m_data->write_dword(m_info.address, m_r[R2] | 0x80000000);
+ // TRAPS: C,U,A,P,R,W,I
+ break;
+ case 0x74:
+ case 0x75:
+ // stors: store single floating
+ m_data->write_dword(m_info.address, *((u32 *)&m_f[R2]));
+ // TRAPS: A,P,W,I
+ break;
+ case 0x76:
+ case 0x77:
+ // stord: store double floating
+ m_data->write_qword(m_info.address, *((u64 *)&m_f[R2]));
+ // TRAPS: A,P,W,I
+ break;
+ case 0x78:
+ case 0x79:
+ // storb: store byte
+ m_data->write_byte(m_info.address, (u8)m_r[R2]);
+ // TRAPS: A,P,W,I
+ break;
+
+ case 0x7c:
+ case 0x7d:
+ // storh: store halfword
+ m_data->write_word(m_info.address, (u16)m_r[R2]);
+ // TRAPS: A,P,W,I
+ break;
+
+ case 0x80:
+ // addw: add word
+ FLAGS_CV(C_ADD(m_r[R2], m_r[R1]), V_ADD(m_r[R2], m_r[R1]))
+ m_r[R2] += m_r[R1];
+ FLAGS_ZN(m_r[R2] == 0, m_r[R2] < 0)
+ // FLAGS: CVZN
+ break;
+
+ case 0x82:
+ // addq: add quick
+ FLAGS_CV(C_ADD(m_r[R2], R1), V_ADD(m_r[R2], R1))
+ m_r[R2] += R1;
+ FLAGS_ZN(m_r[R2] == 0, m_r[R2] < 0)
+ // FLAGS: CVZN
+ break;
+ case 0x83:
+ // addi: add immediate
+ FLAGS_CV(C_ADD(m_r[R2], m_info.imm), V_ADD(m_r[R2], m_info.imm))
+ m_r[R2] += m_info.imm;
+ FLAGS_ZN(m_r[R2] == 0, m_r[R2] < 0)
+ // FLAGS: CVZN
+ // TRAPS: I
+ break;
+ case 0x84:
+ // movw: move word
+ m_r[R2] = m_r[R1];
+ FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0)
+ // FLAGS: 00ZN
+ break;
+
+ case 0x86:
+ // loadq: load quick
+ m_r[R2] = R1;
+ FLAGS(0, 0, m_r[R2] == 0, 0)
+ // FLAGS: 00Z0
+ break;
+ case 0x87:
+ // loadi: load immediate
+ m_r[R2] = m_info.imm;
+ FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0)
+ // FLAGS: 00ZN
+ // TRAPS: I
+ break;
+ case 0x88:
+ // andw: and word
+ m_r[R2] &= m_r[R1];
+ FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0)
+ // FLAGS: 00ZN
+ break;
+
+ case 0x8b:
+ // andi: and immediate
+ m_r[R2] &= m_info.imm;
+ FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0)
+ // FLAGS: 00ZN
+ // TRAPS: I
+ break;
+ case 0x8c:
+ // orw: or word
+ m_r[R2] |= m_r[R1];
+ FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0)
+ // FLAGS: 00ZN
+ break;
+
+ case 0x8f:
+ // ori: or immediate
+ m_r[R2] |= m_info.imm;
+ FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0)
+ // FLAGS: 00ZN
+ // TRAPS: I
+ break;
+ case 0x90:
+ // addwc: add word with carry
+ FLAGS_CV(C_ADD(m_r[R2], (m_r[R1] + (PSW(C) ? 1 : 0))), V_ADD(m_r[R2], (m_r[R1] + (PSW(C) ? 1 : 0))))
+ m_r[R2] += m_r[R1] + (PSW(C) ? 1 : 0);
+ FLAGS_ZN(m_r[R2] == 0, m_r[R2] < 0)
+ // FLAGS: CVZN
+ break;
+ case 0x91:
+ // subwc: subtract word with carry
+ FLAGS_CV(C_SUB(m_r[R2], (m_r[R1] + (PSW(C) ? 1 : 0))), V_SUB(m_r[R2], (m_r[R1] + (PSW(C) ? 1 : 0))))
+ m_r[R2] -= m_r[R1] + (PSW(C) ? 1 : 0);
+ FLAGS_ZN(m_r[R2] == 0, m_r[R2] < 0)
+ // FLAGS: CVZN
+ break;
+
+ case 0x93:
+ // negw: negate word
+ FLAGS_CV(m_r[R1] != 0, m_r[R1] == INT32_MIN)
+ m_r[R2] = -m_r[R1];
+ FLAGS_ZN(m_r[R2] == 0, m_r[R2] < 0)
+ // FLAGS: CVZN
+ break;
+
+ case 0x98:
+ // mulw: multiply word
+ m_r[R2] = m_r[R2] * m_r[R1];
+ // FLAGS: 0V00
+ break;
+ case 0x99:
+ // mulwx: multiply word extended
+ ((s64 *)m_r)[R2 >> 1] = (s64)m_r[R2] * (s64)m_r[R1];
+ // FLAGS: 0V00
+ break;
+ case 0x9a:
+ // mulwu: multiply word unsigned
+ m_r[R2] = (u32)m_r[R2] * (u32)m_r[R1];
+ // FLAGS: 0V00
+ break;
+ case 0x9b:
+ // mulwux: multiply word unsigned extended
+ ((u64 *)m_r)[R2 >> 1] = (u64)m_r[R2] * (u64)m_r[R1];
+ // FLAGS: 0V00
+ break;
+ case 0x9c:
+ // divw: divide word
+ if (m_r[R1] != 0)
+ {
+ FLAGS(0, m_r[R2] == INT32_MIN && m_r[R1] == -1, 0, 0)
+ m_r[R2] = m_r[R2] / m_r[R1];
+ }
+ else
+ next_pc = intrap(EXCEPTION_INTEGER_DIVIDE_BY_ZERO, next_pc, CTS_DIVIDE_BY_ZERO);
+ // FLAGS: 0V00
+ // TRAPS: D
+ break;
+ case 0x9d:
+ // modw: modulus word
+ if (m_r[R1] != 0)
+ {
+ FLAGS(0, m_r[R2] == INT32_MIN && m_r[R1] == -1, 0, 0)
+ m_r[R2] = m_r[R2] % m_r[R1];
+ }
+ else
+ next_pc = intrap(EXCEPTION_INTEGER_DIVIDE_BY_ZERO, next_pc, CTS_DIVIDE_BY_ZERO);
+ // FLAGS: 0V00
+ // TRAPS: D
+ break;
+ case 0x9e:
+ // divwu: divide word unsigned
+ if ((u32)m_r[R1] != 0)
+ m_r[R2] = (u32)m_r[R2] / (u32)m_r[R1];
+ else
+ next_pc = intrap(EXCEPTION_INTEGER_DIVIDE_BY_ZERO, next_pc, CTS_DIVIDE_BY_ZERO);
+ FLAGS(0, 0, 0, 0)
+ // FLAGS: 0000
+ // TRAPS: D
+ break;
+ case 0x9f:
+ // modwu: modulus word unsigned
+ if ((u32)m_r[R1] != 0)
+ m_r[R2] = (u32)m_r[R2] % (u32)m_r[R1];
+ else
+ next_pc = intrap(EXCEPTION_INTEGER_DIVIDE_BY_ZERO, next_pc, CTS_DIVIDE_BY_ZERO);
+ FLAGS(0, 0, 0, 0)
+ // FLAGS: 0000
+ // TRAPS: D
+ break;
+ case 0xa0:
+ // subw: subtract word
+ FLAGS_CV(C_SUB(m_r[R2], m_r[R1]), V_SUB(m_r[R2], m_r[R1]))
+ m_r[R2] -= m_r[R1];
+ FLAGS_ZN(m_r[R2] == 0, m_r[R2] < 0)
+ // FLAGS: CVZN
+ break;
+
+ case 0xa2:
+ // subq: subtract quick
+ FLAGS_CV(C_SUB(m_r[R2], R1), V_SUB(m_r[R2], R1))
+ m_r[R2] -= R1;
+ FLAGS_ZN(m_r[R2] == 0, m_r[R2] < 0)
+ // FLAGS: CVZN
+ break;
+ case 0xa3:
+ // subi: subtract immediate
+ FLAGS_CV(C_SUB(m_r[R2], m_info.imm), V_SUB(m_r[R2], m_info.imm))
+ m_r[R2] -= m_info.imm;
+ FLAGS_ZN(m_r[R2] == 0, m_r[R2] < 0)
+ // FLAGS: CVZN
+ // TRAPS: I
+ break;
+ case 0xa4:
+ // cmpw: compare word
+ FLAGS(C_SUB(m_r[R2], m_r[R1]), V_SUB(m_r[R2], m_r[R1]), m_r[R2] == m_r[R1], m_r[R2] < m_r[R1])
+ // FLAGS: CVZN
+ break;
+
+ case 0xa6:
+ // cmpq: compare quick
+ FLAGS(C_SUB(m_r[R2], R1), V_SUB(m_r[R2], R1), m_r[R2] == (s32)R1, m_r[R2] < (s32)R1)
+ // FLAGS: CVZN
+ break;
+ case 0xa7:
+ // cmpi: compare immediate
+ FLAGS(C_SUB(m_r[R2], m_info.imm), V_SUB(m_r[R2], m_info.imm), m_r[R2] == m_info.imm, m_r[R2] < m_info.imm)
+ // FLAGS: CVZN
+ // TRAPS: I
+ break;
+ case 0xa8:
+ // xorw: exclusive or word
+ m_r[R2] ^= m_r[R1];
+ FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0)
+ // FLAGS: 00ZN
+ break;
+
+ case 0xab:
+ // xori: exclusive or immediate
+ m_r[R2] ^= m_info.imm;
+ FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0)
+ // FLAGS: 00ZN
+ // TRAPS: I
+ break;
+ case 0xac:
+ // notw: not word
+ m_r[R2] = ~m_r[R1];
+ FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0)
+ // FLAGS: 00ZN
+ break;
+
+ case 0xae:
+ // notq: not quick
+ m_r[R2] = ~R1;
+ FLAGS(0, 0, 0, 1)
+ // FLAGS: 0001
+ break;
+
+#ifdef UNIMPLEMENTED_C400
+ case 0xb0:
+ // abss: absolute value single floating?
+ break;
+
+ case 0xb2:
+ // absd: absolute value double floating?
+ break;
+#endif
+
+ case 0xb4:
+ // unprivileged macro instructions
+ switch (m_info.subopcode)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ case 0x04: case 0x05: case 0x06: case 0x07:
+ case 0x08: case 0x09: case 0x0a: case 0x0b:
+ case 0x0c:
+ // savew0..savew12: push registers rN:r14
+
+ // store ri at sp - 4 * (15 - i)
+ for (int i = R2; i < 15; i++)
+ m_data->write_dword(m_r[15] - 4 * (15 - i), m_r[i]);
+
+ // decrement sp after push to allow restart on exceptions
+ m_r[15] -= 4 * (15 - R2);
+ // TRAPS: A,P,W
+ break;
+ // NOTE: the movc, initc and cmpc macro instructions are implemented in a very basic way because
+ // at some point they will need to be improved to deal with possible exceptions (e.g. page faults)
+ // that may occur during execution. The implementation here is intended to allow the instructions
+ // to be "continued" after such exceptions.
+ case 0x0d:
+ // movc: copy r0 bytes from r1 to r2
+
+ while (m_r[0])
+ {
+ m_data->write_byte(m_r[2], m_data->read_byte(m_r[1]));
+
+ m_r[0]--;
+ m_r[1]++;
+ m_r[2]++;
+ }
+ // TRAPS: C,U,P,R,W
+ break;
+ case 0x0e:
+ // initc: initialise r0 bytes at r1 with value in r2
+ while (m_r[0])
+ {
+ m_data->write_byte(m_r[1], m_r[2] & 0xff);
+
+ m_r[0]--;
+ m_r[1]++;
+ m_r[2] = rotr32(m_r[2], 8);
+ }
+ // TRAPS: P,W
+ break;
+ case 0x0f:
+ // cmpc: compare r0 bytes at r1 with r2
+
+ // set condition codes assuming strings match
+ FLAGS(0, 0, 1, 0);
+
+ while (m_r[0])
+ {
+ // set condition codes and abort the loop if the current byte does not match
+ s32 byte1 = (s8)m_data->read_byte(m_r[1]);
+ s32 byte2 = (s8)m_data->read_byte(m_r[2]);
+ if (byte1 != byte2)
+ {
+ FLAGS(C_SUB(byte2, byte1), V_SUB(byte2, byte1), byte2 == byte1, byte2 < byte1)
+ break;
+ }
+
+ m_r[0]--;
+ m_r[1]++;
+ m_r[2]++;
+ }
+ // TRAPS: C,U,P,R
+ break;
+ case 0x10: case 0x11: case 0x12: case 0x13:
+ case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x18: case 0x19: case 0x1a: case 0x1b:
+ case 0x1c:
+ // restwN..restw12: pop registers rN:r14
+
+ // load ri from sp + 4 * (i - N)
+ for (int i = R2; i < 15; i++)
+ m_r[i] = m_data->read_dword(m_r[15] + 4 * (i - R2));
+
+ // increment sp after pop to allow restart on exceptions
+ m_r[15] += 4 * (15 - R2);
+ // TRAPS: C,U,A,P,R
+ break;
+
+ case 0x20: case 0x21: case 0x22: case 0x23:
+ case 0x24: case 0x25: case 0x26: case 0x27:
+ // saved0..saved7: push registers fN:f7
+
+ // store fi at sp - 8 * (8 - i)
+ for (int i = R2; i < 8; i++)
+ m_data->write_qword(m_r[15] - 8 * (8 - i), m_f[i]);
+
+ // decrement sp after push to allow restart on exceptions
+ m_r[15] -= 8 * (8 - R2);
+ // TRAPS: A,P,W
+ break;
+ case 0x28: case 0x29: case 0x2a: case 0x2b:
+ case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ // restd0..restd7: pop registers fN:f7
+
+ // load fi from sp + 8 * (i - N)
+ for (int i = R2; i < 8; i++)
+ m_f[i] = m_data->read_qword(m_r[15] + 8 * (i - R2));
+
+ // increment sp after pop to allow restart on exceptions
+ m_r[15] += 8 * (8 - R2);
+ // TRAPS: C,U,A,P,R
+ break;
+#ifdef UNIMPLEMENTED
+ case 0x30:
+ // cnvsw
+ case 0x31:
+ // cnvrsw
+ // TRAPS: F_IX
+ case 0x32:
+ // cnvtsw
+ // TRAPS: F_IX
+ case 0x33:
+ // cnvws
+ // TRAPS: F_X
+ case 0x34:
+ // cnvdw
+ // TRAPS: F_IX
+ case 0x35:
+ // cnvrdw
+ // TRAPS: F_IX
+ break;
+#endif
+ case 0x36: // cnvtdw
+ m_r[m_info.macro & 0xf] = (s32)m_f[(m_info.macro >> 4) & 0xf];
+ // TRAPS: F_IX
+ break;
+ case 0x37: // cnvwd
+ m_f[m_info.macro & 0xf] = (double)m_r[(m_info.macro >> 4) & 0xf];
+ break;
+#ifdef UNIMPLEMENTED
+ case 0x38:
+ // cnvsd
+ // TRAPS: F_I
+ case 0x39:
+ // cnvds
+ // TRAPS: F_IVUX
+ case 0x3a:
+ // negs
+ case 0x3b:
+ // negds
+ case 0x3c:
+ // scalbs
+ // TRAPS: F_IVUX
+ case 0x3d:
+ // scalbd
+ // FLAGS: N
+ // TRAPS: F_IVUX
+ case 0x3e:
+ // trapfn
+ // TRAPS: I
+ case 0x3f:
+ // loadfs
+ break;
+#endif
+ default:
+ logerror("illegal unprivileged macro opcode at 0x%08x\n", m_pc);
+ next_pc = intrap(EXCEPTION_ILLEGAL_OPERATION, next_pc, CTS_ILLEGAL_OPERATION);
+ machine().debug_break();
+ break;
+ }
+
+ break;
+
+ case 0xb6:
+ // privileged macro instructions
+ if (!SSW(U))
+ {
+ switch (m_info.subopcode)
+ {
+ case 0x00:
+ // movus: move user to supervisor
+ m_rs[m_info.macro & 0xf] = m_ru[(m_info.macro >> 4) & 0xf];
+ FLAGS(0, 0, m_rs[m_info.macro & 0xf] == 0, m_rs[m_info.macro & 0xf] < 0)
+ // FLAGS: 00ZN
+ // TRAPS: S
+ break;
+ case 0x01:
+ // movsu: move supervisor to user
+ m_ru[m_info.macro & 0xf] = m_rs[(m_info.macro >> 4) & 0xf];
+ FLAGS(0, 0, m_ru[m_info.macro & 0xf] == 0, m_ru[m_info.macro & 0xf] < 0)
+ // FLAGS: 00ZN
+ // TRAPS: S
+ break;
+ case 0x02:
+ // saveur: save user registers
+ for (int i = 0; i < 16; i++)
+ m_data->write_dword(m_rs[(m_info.macro >> 4) & 0xf] - 4 * (i + 1), m_ru[15 - i]);
+
+ m_rs[(m_info.macro >> 4) & 0xf] -= 64;
+ // TRAPS: A,P,W,S
+ break;
+ case 0x03:
+ // restur: restore user registers
+ for (int i = 0; i < 16; i++)
+ m_ru[i] = m_data->read_dword(m_rs[(m_info.macro >> 4) & 0xf] + 4 * i);
+
+ m_rs[(m_info.macro >> 4) & 0xf] += 64;
+ // TRAPS: C,U,A,P,R,S
+ break;
+ case 0x04:
+ // reti: restore psw, ssw and pc from supervisor stack
+ LOG_INTERRUPT("reti r%d, ssp = %08x, pc = %08x, next_pc = %08x\n",
+ (macro >> 4) & 0xf, m_rs[(m_info.macro >> 4) & 0xf], m_pc, m_program->read_dword(m_rs[(m_info.macro >> 4) & 0xf] + 8));
+
+ m_psw = m_data->read_dword(m_rs[(m_info.macro >> 4) & 0xf] + 0);
+ m_ssw = m_data->read_dword(m_rs[(m_info.macro >> 4) & 0xf] + 4);
+ next_pc = m_data->read_dword(m_rs[(m_info.macro >> 4) & 0xf] + 8);
+
+ m_rs[(m_info.macro >> 4) & 0xf] += 12;
+
+ m_r = SSW(U) ? m_ru : m_rs;
+ // TRAPS: S
+ break;
+ case 0x05:
+ // wait: wait for interrupt
+ next_pc = m_pc;
+ // TRAPS: S
+ break;
+#ifdef UNIMPLEMENTED_C400
+ case 0x07:
+ // loadts: unknown?
+ break;
+#endif
+
+ default:
+ // illegal operation
+ logerror("illegal privileged macro opcode at 0x%08x\n", m_pc);
+ next_pc = intrap(EXCEPTION_ILLEGAL_OPERATION, next_pc, CTS_ILLEGAL_OPERATION);
+ machine().debug_break();
+ break;
+ }
+ }
+ else
+ next_pc = intrap(EXCEPTION_PRIVILEGED_INSTRUCTION, next_pc, CTS_PRIVILEGED_INSTRUCTION);
+ break;
+
+#ifdef UNIMPLEMENTED_C400
+ case 0xbc:
+ // waitd:
+ break;
+
+ case 0xc0:
+ // s*:
+ break;
+#endif
+
+ default:
+ logerror("illegal opcode at 0x%08x\n", m_pc);
+ next_pc = intrap(EXCEPTION_ILLEGAL_OPERATION, next_pc, CTS_ILLEGAL_OPERATION);
+ break;
+ }
+
+ return next_pc;
+}
+
+/*
+* Common entry point for transferring control in the event of an interrupt or exception.
+*/
+u32 clipper_device::intrap(u32 vector, u32 pc, u32 cts, u32 mts)
+{
+ LOG_INTERRUPT("intrap - vector %x, pc = 0x%08x, next_pc = 0x%08x, ssp = 0x%08x\n", vector, pc, m_program->read_dword(vector + 4), m_rs[15]);
+
+ // set cts and mts to indicate source of exception
+ m_psw = (m_psw & ~(PSW_CTS | PSW_MTS)) | mts | cts;
+
+ // push pc, psw and ssw onto supervisor stack
+ m_data->write_dword(m_rs[15] - 4, pc);
+ m_data->write_dword(m_rs[15] - 12, m_psw);
+ m_data->write_dword(m_rs[15] - 8, m_ssw);
+
+ // decrement supervisor stack pointer
+
+ // NOTE: while not explicitly stated anywhere, it seems the InterPro boot code has been
+ // developed with the assumption that the SSP is decremented by 24 bytes during an exception,
+ // rather than the 12 bytes that might otherwise be expected. This means the exception handler
+ // code must explicitly increment the SSP by 12 prior to executing the RETI instruction,
+ // as otherwise the SSP will not be pointing at a valid return frame. It's possible this
+ // behaviour might vary with some other version of the CPU, but this is all we know for now.
+ m_rs[15] -= 24;
+
+ // load ssw from trap vector and set previous mode
+ m_ssw = (m_data->read_dword(vector + 0) & ~SSW_P) | (SSW(U) << 1);
+
+ // clear psw
+ m_psw = 0;
+
+ m_r = SSW(U) ? m_ru : m_rs;
+
+ // return new pc from trap vector
+ return m_data->read_dword(vector + 4);
+}
+
+bool clipper_device::evaluate_branch ()
+{
+ switch (m_info.r2)
+ {
+ case BRANCH_T:
+ return true;
+
+ case BRANCH_LT:
+ return (!PSW(V) && !PSW(Z) && !PSW(N))
+ || (PSW(V) && !PSW(Z) && PSW(N));
+
+ case BRANCH_LE:
+ return (!PSW(V) && !PSW(N))
+ || (PSW(V) && !PSW(Z) && PSW(N));
+
+ case BRANCH_EQ:
+ return PSW(Z) && !PSW(N);
+
+ case BRANCH_GT:
+ return (!PSW(V) && !PSW(Z) && PSW(N))
+ || (PSW(V) && !PSW(N));
+
+ case BRANCH_GE:
+ return (PSW(V) && !PSW(N))
+ || (!PSW(V) && !PSW(Z) && PSW(N))
+ || (PSW(Z) && !PSW(N));
+
+ case BRANCH_NE:
+ return (!PSW(Z))
+ || (PSW(Z) && PSW(N));
+
+ case BRANCH_LTU:
+ return (!PSW(C) && !PSW(Z));
+
+ case BRANCH_LEU:
+ return !PSW(C);
+
+ case BRANCH_GTU:
+ return PSW(C);
+
+ case BRANCH_GEU:
+ return PSW(C) || PSW(Z);
+
+ case BRANCH_V:
+ return PSW(V);
+ case BRANCH_NV:
+ return !PSW(V);
+
+ case BRANCH_N:
+ return !PSW(Z) && PSW(N);
+ case BRANCH_NN:
+ return !PSW(N);
+
+ case BRANCH_FN:
+ return PSW(Z) && PSW(N);
+ }
+
+ return false;
+}
+
+offs_t clipper_device::disasm_disassemble(std::ostream &stream, offs_t pc, const u8 *oprom, const u8 *opram, u32 options)
+{
+ return CPU_DISASSEMBLE_NAME(clipper)(this, stream, pc, oprom, opram, options);
+}
diff --git a/src/devices/cpu/clipper/clipper.h b/src/devices/cpu/clipper/clipper.h
new file mode 100644
index 00000000000..ff872891bbd
--- /dev/null
+++ b/src/devices/cpu/clipper/clipper.h
@@ -0,0 +1,296 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+#pragma once
+
+#ifndef __CLIPPER_H__
+#define __CLIPPER_H__
+
+#include <limits.h>
+
+enum clipper_registers
+{
+ CLIPPER_R0, CLIPPER_R1, CLIPPER_R2, CLIPPER_R3, CLIPPER_R4, CLIPPER_R5, CLIPPER_R6, CLIPPER_R7,
+ CLIPPER_R8, CLIPPER_R9, CLIPPER_R10, CLIPPER_R11, CLIPPER_R12, CLIPPER_R13, CLIPPER_R14, CLIPPER_R15,
+
+ CLIPPER_F0, CLIPPER_F1, CLIPPER_F2, CLIPPER_F3, CLIPPER_F4, CLIPPER_F5, CLIPPER_F6, CLIPPER_F7,
+ CLIPPER_F8, CLIPPER_F9, CLIPPER_F10, CLIPPER_F11, CLIPPER_F12, CLIPPER_F13, CLIPPER_F14, CLIPPER_F15,
+
+ CLIPPER_PSW,
+ CLIPPER_SSW,
+ CLIPPER_PC,
+};
+
+enum clipper_addressing_modes
+{
+ ADDR_MODE_PC32 = 0x10,
+ ADDR_MODE_ABS32 = 0x30,
+ ADDR_MODE_REL32 = 0x60,
+ ADDR_MODE_PC16 = 0x90,
+ ADDR_MODE_REL12 = 0xa0,
+ ADDR_MODE_ABS16 = 0xb0,
+ ADDR_MODE_PCX = 0xd0,
+ ADDR_MODE_RELX = 0xe0,
+};
+
+// branch conditions
+enum clipper_branch_conditions
+{
+ BRANCH_T = 0x0,
+ BRANCH_LT = 0x1,
+ BRANCH_LE = 0x2,
+ BRANCH_EQ = 0x3,
+ BRANCH_GT = 0x4,
+ BRANCH_GE = 0x5,
+ BRANCH_NE = 0x6,
+ BRANCH_LTU = 0x7,
+ BRANCH_LEU = 0x8,
+ BRANCH_GTU = 0x9,
+ BRANCH_GEU = 0xa,
+ BRANCH_V = 0xb,
+ BRANCH_NV = 0xc,
+ BRANCH_N = 0xd,
+ BRANCH_NN = 0xe,
+ BRANCH_FN = 0xf,
+};
+
+enum clipper_psw
+{
+ PSW_N = 0x00000001, // negative
+ PSW_Z = 0x00000002, // zero
+ PSW_V = 0x00000004, // overflow
+ PSW_C = 0x00000008, // carry out or borrow in
+ PSW_FX = 0x00000010, // floating inexact
+ PSW_FU = 0x00000020, // floating underflow
+ PSW_FD = 0x00000040, // floating divide by zero
+ PSW_FV = 0x00000080, // floating overflow
+ PSW_FI = 0x00000100, // floating invalid operation
+ PSW_EFX = 0x00000200, // enable floating inexact trap
+ PSW_EFU = 0x00000400, // enable floating underflow trap
+ PSW_EFD = 0x00000800, // enable floating divide by zero trap
+ PSW_EFV = 0x00001000, // enable floating overflow trap
+ PSW_EFI = 0x00002000, // enable floating invalid operation trap
+ PSW_EFT = 0x00004000, // enable floating trap
+ PSW_FR = 0x00018000, // floating rounding mode (2 bits)
+ // unused (3 bits)
+ PSW_DSP = 0x00300000, // c400 - delay slot pointer (2 bits)
+ PSW_BIG = 0x00400000, // c400 - big endian (hardware)
+ PSW_T = 0x00800000, // trace trap
+ PSW_CTS = 0x0f000000, // cpu trap status (4 bits)
+ PSW_MTS = 0xf0000000, // memory trap status (4 bits)
+};
+
+enum clipper_ssw
+{
+ SSW_IN = 0x0000000f, // interrupt number (4 bits)
+ SSW_IL = 0x000000f0, // interrupt level (4 bits)
+ SSW_EI = 0x00000100, // enable interrupts
+ SSW_ID = 0x0001fe00, // cpu rev # and type (8 bits)
+ // unused (5 bits)
+ SSW_FRD = 0x00400000, // floating registers dirty
+ SSW_TP = 0x00800000, // trace trap pending
+ SSW_ECM = 0x01000000, // enabled corrected memory error
+ SSW_DF = 0x02000000, // fpu disabled
+ SSW_M = 0x04000000, // mapped mode
+ SSW_KU = 0x08000000, // user protect key
+ SSW_UU = 0x10000000, // user data mode
+ SSW_K = 0x20000000, // protect key
+ SSW_U = 0x40000000, // user mode
+ SSW_P = 0x80000000, // previous mode
+};
+
+enum clipper_exception_vectors
+{
+ // data memory trap group
+ EXCEPTION_D_CORRECTED_MEMORY_ERROR = 0x108,
+ EXCEPTION_D_UNCORRECTABLE_MEMORY_ERROR = 0x110,
+ EXCEPTION_D_ALIGNMENT_FAULT = 0x120,
+ EXCEPTION_D_PAGE_FAULT = 0x128,
+ EXCEPTION_D_READ_PROTECT_FAULT = 0x130,
+ EXCEPTION_D_WRITE_PROTECT_FAULT = 0x138,
+
+ // floating-point arithmetic trap group
+ EXCEPTION_FLOATING_INEXACT = 0x180,
+ EXCEPTION_FLOATING_UNDERFLOW = 0x188,
+ EXCEPTION_FLOATING_DIVIDE_BY_ZERO = 0x190,
+ EXCEPTION_FLOATING_OVERFLOW = 0x1a0,
+ EXCEPTION_FLOATING_INVALID_OPERATION = 0x1c0,
+
+ // integer arithmetic trap group
+ EXCEPTION_INTEGER_DIVIDE_BY_ZERO = 0x208,
+
+ // instruction memory trap group
+ EXCEPTION_I_CORRECTED_MEMORY_ERROR = 0x288,
+ EXCEPTION_I_UNCORRECTABLE_MEMORY_ERROR = 0x290,
+ EXCEPTION_I_ALIGNMENT_FAULT = 0x2a0,
+ EXCEPTION_I_PAGE_FAULT = 0x2a8,
+ EXCEPTION_I_EXECUTE_PROTECT_FAULT = 0x2b0,
+
+ // illegal operation trap group
+ EXCEPTION_ILLEGAL_OPERATION = 0x300,
+ EXCEPTION_PRIVILEGED_INSTRUCTION = 0x308,
+
+ // diagnostic trap group
+ EXCEPTION_TRACE = 0x380,
+
+ // supervisor calls (0x400-0x7f8)
+ EXCEPTION_SUPERVISOR_CALL_BASE = 0x400,
+
+ // prioritized interrupts (0x800-0xff8)
+ EXCEPTION_INTERRUPT_BASE = 0x800,
+};
+
+// trap source values are shifted into the correct field in the psw
+enum clipper_cpu_trap_sources
+{
+ CTS_NO_CPU_TRAP = 0 << 24,
+ CTS_DIVIDE_BY_ZERO = 2 << 24,
+ CTS_ILLEGAL_OPERATION = 4 << 24,
+ CTS_PRIVILEGED_INSTRUCTION = 5 << 24,
+ CTS_TRACE_TRAP = 7 << 24,
+};
+
+enum clipper_memory_trap_sources
+{
+ MTS_NO_MEMORY_TRAP = 0 << 28,
+ MTS_CORRECTED_MEMORY_ERROR = 1 << 28,
+ MTS_UNCORRECTABLE_MEMORY_ERROR = 2 << 28,
+ MTS_ALIGNMENT_FAULT = 4 << 28,
+ MTS_PAGE_FAULT = 5 << 28,
+ MTS_READ_OR_EXECUTE_PROTECT_FAULT = 6 << 28,
+ MTS_WRITE_PROTECT_FAULT = 7 << 28,
+};
+
+// convenience macros for frequently used instruction fields
+#define R1 (m_info.r1)
+#define R2 (m_info.r2)
+
+// convenience macros for dealing with the psw
+#define PSW(mask) (m_psw & PSW_##mask)
+#define SSW(mask) (m_ssw & SSW_##mask)
+
+// macros for setting psw condition codes
+#define FLAGS(C,V,Z,N) \
+ m_psw = (m_psw & ~(PSW_C | PSW_V | PSW_Z | PSW_N)) | (((C) << 3) | ((V) << 2) | ((Z) << 1) | ((N) << 0));
+#define FLAGS_CV(C,V) \
+ m_psw = (m_psw & ~(PSW_C | PSW_V)) | (((C) << 3) | ((V) << 2));
+#define FLAGS_ZN(Z,N) \
+ m_psw = (m_psw & ~(PSW_Z | PSW_N)) | (((Z) << 1) | ((N) << 0));
+
+// over/underflow for addition/subtraction from here: http://stackoverflow.com/questions/199333/how-to-detect-integer-overflow-in-c-c
+#define OF_ADD(a, b) ((b > 0) && (a > INT_MAX - b))
+#define UF_ADD(a, b) ((b < 0) && (a < INT_MIN - b))
+#define OF_SUB(a, b) ((b < 0) && (a > INT_MAX + b))
+#define UF_SUB(a, b) ((b > 0) && (a < INT_MIN + b))
+
+// CLIPPER logic for carry and overflow flags
+#define C_ADD(a, b) ((u32)a + (u32)b < (u32)a)
+#define V_ADD(a, b) (OF_ADD((s32)a, (s32)b) || UF_ADD((s32)a, (s32)b))
+#define C_SUB(a, b) ((u32)a < (u32)b)
+#define V_SUB(a, b) (OF_SUB((s32)a, (s32)b) || UF_SUB((s32)a, (s32)b))
+
+class clipper_device : public cpu_device
+{
+public:
+ clipper_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, const char *shortname, const char *source);
+
+ DECLARE_READ_LINE_MEMBER(ssw) { return m_ssw; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // device_execute_interface overrides
+ virtual u32 execute_min_cycles() const override { return 1; };
+ virtual u32 execute_max_cycles() const override { return 1; }; // FIXME: don't know, especially macro instructions
+ virtual u32 execute_input_lines() const override { return 2; }; // number of input/interrupt lines (irq/nmi)
+ virtual void execute_run() override;
+ virtual void execute_set_input(int inputnum, int state) override;
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const override;
+
+ // device_state_interface overrides
+#if 0
+ virtual void state_import(const device_state_entry &entry) override;
+ virtual void state_export(const device_state_entry &entry) override;
+#endif
+ virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
+
+ // device_disasm_interface overrides
+ virtual uint32_t disasm_min_opcode_bytes() const override { return 2; } // smallest instruction
+ virtual uint32_t disasm_max_opcode_bytes() const override { return 8; } // largest instruction
+ virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const u8 *oprom, const u8 *opram, u32 options) override;
+
+ // core registers
+ u32 m_pc;
+ u32 m_psw;
+ u32 m_ssw;
+
+ // integer registers
+ s32 *m_r; // active registers
+ s32 m_ru[16]; // user registers
+ s32 m_rs[16]; // supervisor registers
+
+ // floating registers
+ double m_f[16];
+
+private:
+ address_space_config m_insn_config;
+ address_space_config m_data_config;
+
+ address_space *m_insn;
+ address_space *m_data;
+
+ int m_icount;
+
+ int m_irq;
+ int m_nmi;
+
+ // decoded instruction information
+ struct
+ {
+ u8 opcode, subopcode;
+ u8 r1, r2;
+
+ s32 imm;
+ u16 macro;
+
+ // total size of instruction in bytes
+ u32 size;
+
+ // computed effective address
+ u32 address;
+ } m_info;
+
+ void decode_instruction(u16 insn);
+ int execute_instruction();
+ bool evaluate_branch();
+
+ uint32_t intrap(u32 vector, u32 pc, u32 cts = CTS_NO_CPU_TRAP, u32 mts = MTS_NO_MEMORY_TRAP);
+};
+
+class clipper_c100_device : public clipper_device
+{
+public:
+ clipper_c100_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+class clipper_c300_device : public clipper_device
+{
+public:
+ clipper_c300_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+class clipper_c400_device : public clipper_device
+{
+public:
+ clipper_c400_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+extern const device_type CLIPPER_C100;
+extern const device_type CLIPPER_C300;
+extern const device_type CLIPPER_C400;
+
+extern CPU_DISASSEMBLE(clipper);
+#endif /* __CLIPPER_H__ */
diff --git a/src/devices/cpu/clipper/clipperd.cpp b/src/devices/cpu/clipper/clipperd.cpp
new file mode 100644
index 00000000000..735804b2742
--- /dev/null
+++ b/src/devices/cpu/clipper/clipperd.cpp
@@ -0,0 +1,351 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#include "emu.h"
+
+/*
+ * TODO
+ * - dynamically switch between C400 and C100/C300 instruction sets
+ * - handle failures of addressing mode decoding more elegantly
+ * - improve address decoding to use streams
+ * - detect various cases of illegal instruction encoding
+ */
+
+// enable C400 instruction decoding
+#define C400_INSTRUCTIONS 1
+
+// the CLIPPER addressing modes (unshifted)
+enum
+{
+ ADDR_MODE_PC32 = 0x10,
+ ADDR_MODE_ABS32 = 0x30,
+ ADDR_MODE_REL32 = 0x60,
+ ADDR_MODE_PC16 = 0x90,
+ ADDR_MODE_REL12 = 0xa0,
+ ADDR_MODE_ABS16 = 0xb0,
+ ADDR_MODE_PCX = 0xd0,
+ ADDR_MODE_RELX = 0xe0
+};
+
+// macros for decoding various operand fields
+#define R1 ((insn[0] & 0x00f0) >> 4)
+#define R2 (insn[0] & 0x000f)
+
+#define I16 ((int16_t)insn[1])
+#define I32 (*(int32_t *)&insn[1])
+#define IMM_VALUE (insn[0] & 0x0080 ? I16 : I32)
+#define IMM_SIZE (insn[0] & 0x0080 ? 2 : 4)
+
+#define ADDR_MODE (insn[0] & 0x00f0)
+#define ADDR_R2 ((insn[0] & 0x0050) == 0x0010 ? (insn[0] & 0x000f) : (insn[1] & 0x000f))
+#define ADDR_SIZE (ADDR_MODE > ADDR_MODE_REL32 ? 2 : ADDR_MODE == ADDR_MODE_REL32 ? 6 : 4)
+#define ADDR_RX ((insn[1] & 0xf0) >> 4)
+#define ADDR_I12 (((int16_t)insn[1]) >> 4)
+
+/*
+ * Branch condition code mnemonics - the forms beginning with 'c' are
+ * supposed to be used for branches following comparison instructions,
+ * while those beginning with 'r' are for use after move or logical
+ * instructions. We use the first form because we can't know which type
+ * should be used without some kind of dynamic information.
+ */
+static const char *const cc[] =
+{
+ "",
+ "clt", // rgt
+ "cle", // rge
+ "ceq", // req
+ "cgt", // rlt
+ "cge", // rle
+ "cne", // rne
+ "cltu", // rgtu
+ "cleu", // rgeu, nc
+ "cgtu", // rltu, c
+ "cgeu", // rleu
+ "v",
+ "nv",
+ "n",
+ "nn",
+ "fn"
+};
+
+/*
+ * Decode an addressing mode into a string.
+ */
+char *address (offs_t pc, u16 *insn)
+{
+ static char buffer[32];
+
+ switch (ADDR_MODE)
+ {
+ case ADDR_MODE_PC32: sprintf(buffer, "0x%x", pc + I32); break;
+ case ADDR_MODE_ABS32: sprintf(buffer, "0x%x", I32); break;
+ case ADDR_MODE_REL32: sprintf(buffer, "%d(r%d)", *(int32_t *)&insn[2], R2); break;
+ case ADDR_MODE_PC16: sprintf(buffer, "0x%x", pc + I16); break;
+ case ADDR_MODE_REL12: sprintf(buffer, "%d(r%d)", ADDR_I12, R2); break;
+ case ADDR_MODE_ABS16: sprintf(buffer, "0x%x", I16); break;
+ case ADDR_MODE_PCX: sprintf(buffer, "[r%d](pc)", ADDR_RX); break;
+ case ADDR_MODE_RELX: sprintf(buffer, "[r%d](r%d)", ADDR_RX, R2); break;
+ default: sprintf(buffer, "ERROR"); break;
+ }
+
+ return buffer;
+}
+
+/*
+ * CLIPPER instructions are composed of 1, 2, 3 or 4 16-bit "parcels". The first parcel contains
+ * the opcode and enough information to work out how many additional parcels might be required. The
+ * instruction set is fairly typically RISC-ish, except for these variable length instructions, the
+ * 8 addressing modes, and the "macro instructions", which are actually "subroutines" embedded in
+ * an on-CPU macro instruction ROM. It appears at least some of these macro instructions were removed
+ * from the C400 and generate traps which can be used to implement them in software instead.
+ */
+CPU_DISASSEMBLE(clipper)
+{
+ u16 *insn = (u16 *)oprom;
+ u32 flags = DASMFLAG_SUPPORTED;
+ offs_t bytes;
+
+ switch (insn[0] >> 8)
+ {
+ case 0x00:
+ if (oprom[0] == 0)
+ util::stream_format(stream, "noop");
+ else
+ util::stream_format(stream, "noop $%d", oprom[0]);
+ bytes = 2;
+ break;
+
+ case 0x10: util::stream_format(stream, "movwp r%d,%s", R2, R1 == 0 ? "psw" : R1 == 1 ? "ssw" : "sswf"); bytes = 2; break;
+ case 0x11: util::stream_format(stream, "movpw %s,r%d", R1 == 0 ? "psw" : "ssw", R2); bytes = 2; break;
+ case 0x12: util::stream_format(stream, "calls $%d", insn[0] & 0x7F); bytes = 2; flags |= DASMFLAG_STEP_OVER; break;
+ case 0x13: util::stream_format(stream, "ret r%d", R2); bytes = 2; flags |= DASMFLAG_STEP_OUT; break;
+ case 0x14: util::stream_format(stream, "pushw r%d,r%d", R2, R1); bytes = 2; break;
+
+ case 0x16: util::stream_format(stream, "popw r%d,r%d", R1, R2); bytes = 2; break;
+
+ case 0x20: util::stream_format(stream, "adds f%d,f%d", R1, R2); bytes = 2; break;
+ case 0x21: util::stream_format(stream, "subs f%d,f%d", R1, R2); bytes = 2; break;
+ case 0x22: util::stream_format(stream, "addd f%d,f%d", R1, R2); bytes = 2; break;
+ case 0x23: util::stream_format(stream, "subd f%d,f%d", R1, R2); bytes = 2; break;
+ case 0x24: util::stream_format(stream, "movs f%d,f%d", R1, R2); bytes = 2; break;
+ case 0x25: util::stream_format(stream, "cmps f%d,f%d", R1, R2); bytes = 2; break;
+ case 0x26: util::stream_format(stream, "movd f%d,f%d", R1, R2); bytes = 2; break;
+ case 0x27: util::stream_format(stream, "cmpd f%d,f%d", R1, R2); bytes = 2; break;
+ case 0x28: util::stream_format(stream, "muls f%d,f%d", R1, R2); bytes = 2; break;
+ case 0x29: util::stream_format(stream, "divs f%d,f%d", R1, R2); bytes = 2; break;
+ case 0x2a: util::stream_format(stream, "muld f%d,f%d", R1, R2); bytes = 2; break;
+ case 0x2b: util::stream_format(stream, "divd f%d,f%d", R1, R2); bytes = 2; break;
+ case 0x2c: util::stream_format(stream, "movsw f%d,r%d", R1, R2); bytes = 2; break;
+ case 0x2d: util::stream_format(stream, "movws r%d,f%d", R1, R2); bytes = 2; break;
+ case 0x2e: util::stream_format(stream, "movdl f%d,r%d:%d", R1, R2 + 0, R2 + 1); bytes = 2; break;
+ case 0x2f: util::stream_format(stream, "movld r%d:r%d,f%d", R1 + 0, R1 + 1, R2); bytes = 2; break;
+
+ case 0x30: util::stream_format(stream, "shaw r%d,r%d", R1, R2); bytes = 2; break;
+ case 0x31: util::stream_format(stream, "shal r%d,r%d:r%d", R1, R2 + 0, R2 + 1); bytes = 2; break;
+ case 0x32: util::stream_format(stream, "shlw r%d,r%d", R1, R2); bytes = 2; break;
+ case 0x33: util::stream_format(stream, "shll r%d,r%d:r%d", R1, R2 + 0, R2 + 1); bytes = 2; break;
+ case 0x34: util::stream_format(stream, "rotw r%d,r%d", R1, R2); bytes = 2; break;
+ case 0x35: util::stream_format(stream, "rotl r%d,r%d:r%d", R1, R2 + 0, R2 + 1); bytes = 2; break;
+
+ case 0x38: util::stream_format(stream, "shai $%d,r%d", I16, R2); bytes = 4; break;
+ case 0x39: util::stream_format(stream, "shali $%d,r%d:r%d", I16, R2 + 0, R2 + 1); bytes = 4; break;
+ case 0x3a: util::stream_format(stream, "shli $%d,r%d", I16, R2); bytes = 4; break;
+ case 0x3b: util::stream_format(stream, "shlli $%d,r%d:r%d", I16, R2 + 0, R2 + 1); bytes = 4; break;
+ case 0x3c: util::stream_format(stream, "roti $%d,r%d", I16, R2); bytes = 4; break;
+ case 0x3d: util::stream_format(stream, "rotli $%d,r%d:r%d", I16, R2 + 0, R2 + 1); bytes = 4; break;
+
+ case 0x44: util::stream_format(stream, "call r%d,(r%d)", R2, R1); bytes = 2; flags |= DASMFLAG_STEP_OVER; break;
+ case 0x45: util::stream_format(stream, "call r%d,%s", ADDR_R2, address(pc, insn)); bytes = 2 + ADDR_SIZE; flags |= DASMFLAG_STEP_OVER; break;
+#if C400_INSTRUCTIONS
+ case 0x46: util::stream_format(stream, "loadd2 (r%d),f%d", R1, R2); bytes = 2; break;
+ case 0x47: util::stream_format(stream, "loadd2 %s,f%d", address(pc, insn), ADDR_R2); bytes = 2 + ADDR_SIZE; break;
+#endif
+ case 0x48: util::stream_format(stream, "b%-4s (r%d)", cc[R2], R1); bytes = 2; break;
+ case 0x49: util::stream_format(stream, "b%-4s %s", cc[ADDR_R2], address(pc, insn)); bytes = 2 + ADDR_SIZE; break;
+#if C400_INSTRUCTIONS
+ // delayed branches
+ case 0x4a: util::stream_format(stream, "cdb r%d,(r%d)", R2, R1); bytes = 2; break;
+ case 0x4b: util::stream_format(stream, "cdb r%d,%s", ADDR_R2, address(pc, insn)); bytes = 2 + ADDR_SIZE; break;
+ case 0x4c: util::stream_format(stream, "cdbeq r%d,(r%d)", R2, R1); bytes = 2; break;
+ case 0x4d: util::stream_format(stream, "cdbeq r%d,%s", ADDR_R2, address(pc, insn)); bytes = 2 + ADDR_SIZE; break;
+ case 0x4e: util::stream_format(stream, "cdbne r%d,(r%d)", R2, R1); bytes = 2; break;
+ case 0x4f: util::stream_format(stream, "cdbne r%d,%s", ADDR_R2, address(pc, insn)); bytes = 2 + ADDR_SIZE; break;
+ case 0x50: util::stream_format(stream, "db%-4s (r%d)", cc[R2], R1); bytes = 2; break;
+ case 0x51: util::stream_format(stream, "db%-4s %s", cc[ADDR_R2], address(pc, insn)); bytes = 2 + ADDR_SIZE; break;
+#else
+ // these instructions are in the C300 documentation, but appear to be replaced in the C400
+ case 0x4c: util::stream_format(stream, "bf%s (r%d)", R2 == 0 ? "any" : "bad", R1); bytes = 2; break;
+ case 0x4d: util::stream_format(stream, "bf%s %s", ADDR_R2 == 0 ? "any" : "bad", address(pc, insn)); bytes = 2 + ADDR_SIZE; break;
+#endif
+
+ case 0x60: util::stream_format(stream, "loadw (r%d),r%d", R1, R2); bytes = 2; break;
+ case 0x61: util::stream_format(stream, "loadw %s,r%d", address(pc, insn), ADDR_R2); bytes = 2 + ADDR_SIZE; break;
+ case 0x62: util::stream_format(stream, "loada (r%d),r%d", R1, R2); bytes = 2; break;
+ case 0x63: util::stream_format(stream, "loada %s,r%d", address(pc, insn), ADDR_R2); bytes = 2 + ADDR_SIZE; break;
+ case 0x64: util::stream_format(stream, "loads (r%d),f%d", R1, R2); bytes = 2; break;
+ case 0x65: util::stream_format(stream, "loads %s,f%d", address(pc, insn), ADDR_R2); bytes = 2 + ADDR_SIZE; break;
+ case 0x66: util::stream_format(stream, "loadd (r%d),f%d", R1, R2); bytes = 2; break;
+ case 0x67: util::stream_format(stream, "loadd %s,f%d", address(pc, insn), ADDR_R2); bytes = 2 + ADDR_SIZE; break;
+ case 0x68: util::stream_format(stream, "loadb (r%d),r%d", R1, R2); bytes = 2; break;
+ case 0x69: util::stream_format(stream, "loadb %s,r%d", address(pc, insn), ADDR_R2); bytes = 2 + ADDR_SIZE; break;
+ case 0x6a: util::stream_format(stream, "loadbu (r%d),r%d", R1, R2); bytes = 2; break;
+ case 0x6b: util::stream_format(stream, "loadbu %s,r%d", address(pc, insn), ADDR_R2); bytes = 2 + ADDR_SIZE; break;
+ case 0x6c: util::stream_format(stream, "loadh (r%d),r%d", R1, R2); bytes = 2; break;
+ case 0x6d: util::stream_format(stream, "loadh %s,r%d", address(pc, insn), ADDR_R2); bytes = 2 + ADDR_SIZE; break;
+ case 0x6e: util::stream_format(stream, "loadhu (r%d),r%d", R1, R2); bytes = 2; break;
+ case 0x6f: util::stream_format(stream, "loadhu %s,r%d", address(pc, insn), ADDR_R2); bytes = 2 + ADDR_SIZE; break;
+
+ case 0x70: util::stream_format(stream, "storw r%d,(r%d)", R2, R1); bytes = 2; break;
+ case 0x71: util::stream_format(stream, "storw r%d,%s", ADDR_R2, address(pc, insn)); bytes = 2 + ADDR_SIZE; break;
+ case 0x72: util::stream_format(stream, "tsts (r%d),r%d", R1, R2); bytes = 2; break;
+ case 0x73: util::stream_format(stream, "tsts %s,r%d", address(pc, insn), ADDR_R2); bytes = 2 + ADDR_SIZE; break;
+ case 0x74: util::stream_format(stream, "stors f%d,(r%d)", R2, R1); bytes = 2; break;
+ case 0x75: util::stream_format(stream, "stors f%d,%s", ADDR_R2, address(pc, insn)); bytes = 2 + ADDR_SIZE; break;
+ case 0x76: util::stream_format(stream, "stord f%d,(r%d)", R2, R1); bytes = 2; break;
+ case 0x77: util::stream_format(stream, "stord f%d,%s", ADDR_R2, address(pc, insn)); bytes = 2 + ADDR_SIZE; break;
+ case 0x78: util::stream_format(stream, "storb r%d,(r%d)", R2, R1); bytes = 2; break;
+ case 0x79: util::stream_format(stream, "storb r%d,%s", ADDR_R2, address(pc, insn)); bytes = 2 + ADDR_SIZE; break;
+
+ case 0x7c: util::stream_format(stream, "storh r%d,(r%d)", R2, R1); bytes = 2; break;
+ case 0x7d: util::stream_format(stream, "storh r%d,%s", ADDR_R2, address(pc, insn)); bytes = 2 + ADDR_SIZE; break;
+
+ case 0x80: util::stream_format(stream, "addw r%d,r%d", R1, R2); bytes = 2; break;
+
+ case 0x82: util::stream_format(stream, "addq $%d,r%d", R1, R2); bytes = 2; break;
+ case 0x83: util::stream_format(stream, "addi $%d,r%d", IMM_VALUE, R2); bytes = 2 + IMM_SIZE; break;
+ case 0x84: util::stream_format(stream, "movw r%d,r%d", R1, R2); bytes = 2; break;
+
+ case 0x86: util::stream_format(stream, "loadq $%d,r%d", R1, R2); bytes = 2; break;
+ case 0x87: util::stream_format(stream, "loadi $%d,r%d", IMM_VALUE, R2); bytes = 2 + IMM_SIZE; break;
+ case 0x88: util::stream_format(stream, "andw r%d,r%d", R1, R2); bytes = 2; break;
+
+ case 0x8b: util::stream_format(stream, "andi $%d,r%d", IMM_VALUE, R2); bytes = 2 + IMM_SIZE; break;
+ case 0x8c: util::stream_format(stream, "orw r%d,r%d", R1, R2); bytes = 2; break;
+
+ case 0x8f: util::stream_format(stream, "ori $%d,r%d", IMM_VALUE, R2); bytes = 2 + IMM_SIZE; break;
+
+ case 0x90: util::stream_format(stream, "addwc r%d,r%d", R1, R2); bytes = 2; break;
+ case 0x91: util::stream_format(stream, "subwc r%d,r%d", R1, R2); bytes = 2; break;
+
+ case 0x93: util::stream_format(stream, "negw r%d,r%d", R1, R2); bytes = 2; break;
+
+ case 0x98: util::stream_format(stream, "mulw r%d,r%d", R1, R2); bytes = 2; break;
+ case 0x99: util::stream_format(stream, "mulwx r%d,r%d:r%d", R1, R2 + 0, R2 + 1); bytes = 2; break;
+ case 0x9a: util::stream_format(stream, "mulwu r%d,r%d", R1, R2); bytes = 2; break;
+ case 0x9b: util::stream_format(stream, "mulwux r%d,r%d:r%d", R1, R2 + 0, R2 + 1); bytes = 2; break;
+ case 0x9c: util::stream_format(stream, "divw r%d,r%d", R1, R2); bytes = 2; break;
+ case 0x9d: util::stream_format(stream, "modw r%d,r%d", R1, R2); bytes = 2; break;
+ case 0x9e: util::stream_format(stream, "divwu r%d,r%d", R1, R2); bytes = 2; break;
+ case 0x9f: util::stream_format(stream, "modwu r%d,r%d", R1, R2); bytes = 2; break;
+
+ case 0xa0: util::stream_format(stream, "subw r%d,r%d", R1, R2); bytes = 2; break;
+
+ case 0xa2: util::stream_format(stream, "subq $%d,r%d", R1, R2); bytes = 2; break;
+ case 0xa3: util::stream_format(stream, "subi $%d,r%d", IMM_VALUE, R2); bytes = 2 + IMM_SIZE; break;
+ case 0xa4: util::stream_format(stream, "cmpw r%d,r%d", R1, R2); bytes = 2; break;
+
+ case 0xa6: util::stream_format(stream, "cmpq $%d,r%d", R1, R2); bytes = 2; break;
+ case 0xa7: util::stream_format(stream, "cmpi $%d,r%d", IMM_VALUE, R2); bytes = 2 + IMM_SIZE; break;
+ case 0xa8: util::stream_format(stream, "xorw r%d,r%d", R1, R2); bytes = 2; break;
+
+ case 0xab: util::stream_format(stream, "xori $%d,r%d", IMM_VALUE, R2); bytes = 2 + IMM_SIZE; break;
+ case 0xac: util::stream_format(stream, "notw r%d,r%d", R1, R2); bytes = 2; break;
+
+ case 0xae: util::stream_format(stream, "notq $%d,r%d", R1, R2); bytes = 2; break;
+
+#if C400_INSTRUCTIONS
+ case 0xb0: util::stream_format(stream, "abss f%d,f%d", R1, R2); bytes = 2; break;
+ case 0xb2: util::stream_format(stream, "absd f%d,f%d", R1, R2); bytes = 2; break;
+#endif
+
+ case 0xb4:
+ case 0xb5:
+ // unprivileged macro instructions
+ switch (insn[0] & 0xff)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ case 0x04: case 0x05: case 0x06: case 0x07:
+ case 0x08: case 0x09: case 0x0a: case 0x0b:
+ case 0x0c:
+ util::stream_format(stream, "savew%d", R2);
+ break;
+
+ case 0x0d: util::stream_format(stream, "movc"); break;
+ case 0x0e: util::stream_format(stream, "initc"); break;
+ case 0x0f: util::stream_format(stream, "cmpc"); break;
+
+ case 0x10: case 0x11: case 0x12: case 0x13:
+ case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x18: case 0x19: case 0x1a: case 0x1b:
+ case 0x1c:
+ util::stream_format(stream, "restw%d", R2);
+ break;
+
+ case 0x20: case 0x21: case 0x22: case 0x23:
+ case 0x24: case 0x25: case 0x26: case 0x27:
+ util::stream_format(stream, "saved%d", R2);
+ break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b:
+ case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ util::stream_format(stream, "restd%d", R2);
+ break;
+
+ case 0x30: util::stream_format(stream, "cnvsw f%d,r%d", (insn[1] & 0xf0) >> 4, insn[1] & 0xf); break;
+ case 0x31: util::stream_format(stream, "cnvrsw f%d,r%d", (insn[1] & 0xf0) >> 4, insn[1] & 0xf); break;
+ case 0x32: util::stream_format(stream, "cnvtsw f%d,r%d", (insn[1] & 0xf0) >> 4, insn[1] & 0xf); break;
+ case 0x33: util::stream_format(stream, "cnvws r%d,f%d", (insn[1] & 0xf0) >> 4, insn[1] & 0xf); break;
+ case 0x34: util::stream_format(stream, "cnvdw f%d,r%d", (insn[1] & 0xf0) >> 4, insn[1] & 0xf); break;
+ case 0x35: util::stream_format(stream, "cnvrdw f%d,r%d", (insn[1] & 0xf0) >> 4, insn[1] & 0xf); break;
+ case 0x36: util::stream_format(stream, "cnvtdw f%d,r%d", (insn[1] & 0xf0) >> 4, insn[1] & 0xf); break;
+ case 0x37: util::stream_format(stream, "cnvwd r%d,f%d", (insn[1] & 0xf0) >> 4, insn[1] & 0xf); break;
+ case 0x38: util::stream_format(stream, "cnvsd f%d,f%d", (insn[1] & 0xf0) >> 4, insn[1] & 0xf); break;
+ case 0x39: util::stream_format(stream, "cnvds f%d,f%d", (insn[1] & 0xf0) >> 4, insn[1] & 0xf); break;
+ case 0x3a: util::stream_format(stream, "negs f%d,f%d", (insn[1] & 0xf0) >> 4, insn[1] & 0xf); break;
+ case 0x3b: util::stream_format(stream, "negd f%d,f%d", (insn[1] & 0xf0) >> 4, insn[1] & 0xf); break;
+ case 0x3c: util::stream_format(stream, "scalbs r%d,f%d", (insn[1] & 0xf0) >> 4, insn[1] & 0xf); break;
+ case 0x3d: util::stream_format(stream, "scalbd r%d,f%d", (insn[1] & 0xf0) >> 4, insn[1] & 0xf); break;
+ case 0x3e: util::stream_format(stream, "trapfn"); break;
+ case 0x3f: util::stream_format(stream, "loadfs r%d,f%d", (insn[1] & 0xf0) >> 4, insn[1] & 0xf); break;
+
+ default:
+ util::stream_format(stream, "macro 0x%04x 0x%04x", insn[0], insn[1]);
+ break;
+ }
+ bytes = 4;
+ break;
+ case 0xb6:
+ case 0xb7:
+ // privileged macro instructions
+ switch (insn[0] & 0xff)
+ {
+ case 0x00: util::stream_format(stream, "movus r%d,r%d", (insn[1] & 0xf0) >> 4, insn[1] & 0xf); break;
+ case 0x01: util::stream_format(stream, "movsu r%d,r%d", (insn[1] & 0xf0) >> 4, insn[1] & 0xf); break;
+ case 0x02: util::stream_format(stream, "saveur r%d", (insn[1] & 0xf0) >> 4); break;
+ case 0x03: util::stream_format(stream, "restur r%d", (insn[1] & 0xf0) >> 4); break;
+ case 0x04: util::stream_format(stream, "reti r%d", (insn[1] & 0xf0) >> 4); flags |= DASMFLAG_STEP_OUT; break;
+ case 0x05: util::stream_format(stream, "wait"); break;
+#if C400_INSTRUCTIONS
+ case 0x07: util::stream_format(stream, "loadts r%d,f%d", (insn[1] & 0xf0) >> 4, insn[1] & 0xf); break;
+#endif
+ default:
+ util::stream_format(stream, "macro 0x%04x 0x%04x", insn[0], insn[1]);
+ break;
+ }
+ bytes = 4;
+ break;
+
+#if C400_INSTRUCTIONS
+ case 0xbc: util::stream_format(stream, "waitd"); bytes = 2; break;
+ case 0xc0: util::stream_format(stream, "s%-4s r%d", cc[R2], R1); bytes = 2; break;
+#endif
+
+ default:
+ util::stream_format(stream, ".word 0x%04x", insn[0]);
+ bytes = 2;
+ break;
+ }
+
+ return bytes | flags;
+} \ No newline at end of file
diff --git a/src/devices/cpu/drcbec.cpp b/src/devices/cpu/drcbec.cpp
index 28a4abdd9be..ea0a3f08f5a 100644
--- a/src/devices/cpu/drcbec.cpp
+++ b/src/devices/cpu/drcbec.cpp
@@ -1747,7 +1747,7 @@ int drcbe_c::execute(code_handle &entry)
break;
case MAKE_OPCODE_SHORT(OP_ROL, 8, 0): // DROL dst,src,count[,f]
- shift = DPARAM2 & 31;
+ shift = DPARAM2 & 63;
DPARAM0 = (DPARAM1 << shift) | (DPARAM1 >> ((64 - shift) & 63));
break;
diff --git a/src/devices/cpu/sh4/sh4.cpp b/src/devices/cpu/sh4/sh4.cpp
index 72ceae2c0a2..17c8b0a7459 100644
--- a/src/devices/cpu/sh4/sh4.cpp
+++ b/src/devices/cpu/sh4/sh4.cpp
@@ -2556,21 +2556,7 @@ inline void sh34_base_device::PREFM(const uint16_t opcode)
* OPCODE DISPATCHERS
*****************************************************************************/
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+// TODO: current SZ=1(64bit) FMOVs correct for SH4 in LE mode only
/* FMOV.S @Rm+,FRn PR=0 SZ=0 1111nnnnmmmm1001 */
/* FMOV @Rm+,DRn PR=0 SZ=1 1111nnn0mmmm1001 */
@@ -2580,33 +2566,34 @@ inline void sh34_base_device::FMOVMRIFR(const uint16_t opcode)
{
uint32_t m = Rm; uint32_t n = Rn;
- if (m_fpu_pr) { /* PR = 1 */
- n = n & 14;
- m_ea = m_r[m];
- m_r[m] += 8;
- m_xf[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(m_ea );
- m_xf[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(m_ea+4 );
- } else { /* PR = 0 */
- if (m_fpu_sz) { /* SZ = 1 */
- if (n & 1) {
- n = n & 14;
- m_ea = m_r[m];
- m_xf[n] = RL(m_ea );
- m_r[m] += 4;
- m_xf[n+1] = RL(m_ea+4 );
- m_r[m] += 4;
- } else {
- m_ea = m_r[m];
- m_fr[n] = RL(m_ea );
- m_r[m] += 4;
- m_fr[n+1] = RL(m_ea+4 );
- m_r[m] += 4;
- }
- } else { /* SZ = 0 */
+ if (m_fpu_sz) { /* SZ = 1 */
+ if (n & 1) {
+ n &= 14;
+#ifdef LSB_FIRST
+ n ^= m_fpu_pr;
+#endif
+ m_ea = m_r[m];
+ m_xf[n] = RL(m_ea );
+ m_r[m] += 4;
+ m_xf[n^1] = RL(m_ea+4 );
+ m_r[m] += 4;
+ } else {
+#ifdef LSB_FIRST
+ n ^= m_fpu_pr;
+#endif
m_ea = m_r[m];
m_fr[n] = RL(m_ea );
m_r[m] += 4;
+ m_fr[n^1] = RL(m_ea+4 );
+ m_r[m] += 4;
}
+ } else { /* SZ = 0 */
+ m_ea = m_r[m];
+#ifdef LSB_FIRST
+ n ^= m_fpu_pr;
+#endif
+ m_fr[n] = RL(m_ea );
+ m_r[m] += 4;
}
}
@@ -2618,27 +2605,29 @@ inline void sh34_base_device::FMOVFRMR(const uint16_t opcode)
{
uint32_t m = Rm; uint32_t n = Rn;
- if (m_fpu_pr) { /* PR = 1 */
- m= m & 14;
- m_ea = m_r[n];
- WL(m_ea,m_xf[m+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] );
- WL(m_ea+4,m_xf[m+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] );
- } else { /* PR = 0 */
- if (m_fpu_sz) { /* SZ = 1 */
- if (m & 1) {
- m= m & 14;
- m_ea = m_r[n];
- WL(m_ea,m_xf[m] );
- WL(m_ea+4,m_xf[m+1] );
- } else {
- m_ea = m_r[n];
- WL(m_ea,m_fr[m] );
- WL(m_ea+4,m_fr[m+1] );
- }
- } else { /* SZ = 0 */
+ if (m_fpu_sz) { /* SZ = 1 */
+ if (m & 1) {
+ m &= 14;
+#ifdef LSB_FIRST
+ m ^= m_fpu_pr;
+#endif
+ m_ea = m_r[n];
+ WL(m_ea,m_xf[m] );
+ WL(m_ea+4,m_xf[m^1] );
+ } else {
+#ifdef LSB_FIRST
+ m ^= m_fpu_pr;
+#endif
m_ea = m_r[n];
WL(m_ea,m_fr[m] );
+ WL(m_ea+4,m_fr[m^1] );
}
+ } else { /* SZ = 0 */
+ m_ea = m_r[n];
+#ifdef LSB_FIRST
+ m ^= m_fpu_pr;
+#endif
+ WL(m_ea,m_fr[m] );
}
}
@@ -2650,31 +2639,32 @@ inline void sh34_base_device::FMOVFRMDR(const uint16_t opcode)
{
uint32_t m = Rm; uint32_t n = Rn;
- if (m_fpu_pr) { /* PR = 1 */
- m= m & 14;
- m_r[n] -= 8;
- m_ea = m_r[n];
- WL(m_ea,m_xf[m+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] );
- WL(m_ea+4,m_xf[m+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] );
- } else { /* PR = 0 */
- if (m_fpu_sz) { /* SZ = 1 */
- if (m & 1) {
- m= m & 14;
- m_r[n] -= 8;
- m_ea = m_r[n];
- WL(m_ea,m_xf[m] );
- WL(m_ea+4,m_xf[m+1] );
- } else {
- m_r[n] -= 8;
- m_ea = m_r[n];
- WL(m_ea,m_fr[m] );
- WL(m_ea+4,m_fr[m+1] );
- }
- } else { /* SZ = 0 */
- m_r[n] -= 4;
+ if (m_fpu_sz) { /* SZ = 1 */
+ if (m & 1) {
+ m &= 14;
+#ifdef LSB_FIRST
+ m ^= m_fpu_pr;
+#endif
+ m_r[n] -= 8;
+ m_ea = m_r[n];
+ WL(m_ea,m_xf[m] );
+ WL(m_ea+4,m_xf[m^1] );
+ } else {
+#ifdef LSB_FIRST
+ m ^= m_fpu_pr;
+#endif
+ m_r[n] -= 8;
m_ea = m_r[n];
WL(m_ea,m_fr[m] );
+ WL(m_ea+4,m_fr[m^1] );
}
+ } else { /* SZ = 0 */
+ m_r[n] -= 4;
+ m_ea = m_r[n];
+#ifdef LSB_FIRST
+ m ^= m_fpu_pr;
+#endif
+ WL(m_ea,m_fr[m] );
}
}
@@ -2686,27 +2676,29 @@ inline void sh34_base_device::FMOVFRS0(const uint16_t opcode)
{
uint32_t m = Rm; uint32_t n = Rn;
- if (m_fpu_pr) { /* PR = 1 */
- m= m & 14;
- m_ea = m_r[0] + m_r[n];
- WL(m_ea,m_xf[m+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] );
- WL(m_ea+4,m_xf[m+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] );
- } else { /* PR = 0 */
- if (m_fpu_sz) { /* SZ = 1 */
- if (m & 1) {
- m= m & 14;
- m_ea = m_r[0] + m_r[n];
- WL(m_ea,m_xf[m] );
- WL(m_ea+4,m_xf[m+1] );
- } else {
- m_ea = m_r[0] + m_r[n];
- WL(m_ea,m_fr[m] );
- WL(m_ea+4,m_fr[m+1] );
- }
- } else { /* SZ = 0 */
+ if (m_fpu_sz) { /* SZ = 1 */
+ if (m & 1) {
+ m &= 14;
+#ifdef LSB_FIRST
+ m ^= m_fpu_pr;
+#endif
+ m_ea = m_r[0] + m_r[n];
+ WL(m_ea,m_xf[m] );
+ WL(m_ea+4,m_xf[m^1] );
+ } else {
+#ifdef LSB_FIRST
+ m ^= m_fpu_pr;
+#endif
m_ea = m_r[0] + m_r[n];
WL(m_ea,m_fr[m] );
+ WL(m_ea+4,m_fr[m^1] );
}
+ } else { /* SZ = 0 */
+ m_ea = m_r[0] + m_r[n];
+#ifdef LSB_FIRST
+ m ^= m_fpu_pr;
+#endif
+ WL(m_ea,m_fr[m] );
}
}
@@ -2718,27 +2710,29 @@ inline void sh34_base_device::FMOVS0FR(const uint16_t opcode)
{
uint32_t m = Rm; uint32_t n = Rn;
- if (m_fpu_pr) { /* PR = 1 */
- n= n & 14;
- m_ea = m_r[0] + m_r[m];
- m_xf[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(m_ea );
- m_xf[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(m_ea+4 );
- } else { /* PR = 0 */
- if (m_fpu_sz) { /* SZ = 1 */
- if (n & 1) {
- n= n & 14;
- m_ea = m_r[0] + m_r[m];
- m_xf[n] = RL(m_ea );
- m_xf[n+1] = RL(m_ea+4 );
- } else {
- m_ea = m_r[0] + m_r[m];
- m_fr[n] = RL(m_ea );
- m_fr[n+1] = RL(m_ea+4 );
- }
- } else { /* SZ = 0 */
+ if (m_fpu_sz) { /* SZ = 1 */
+ if (n & 1) {
+ n &= 14;
+#ifdef LSB_FIRST
+ n ^= m_fpu_pr;
+#endif
+ m_ea = m_r[0] + m_r[m];
+ m_xf[n] = RL(m_ea );
+ m_xf[n^1] = RL(m_ea+4 );
+ } else {
+#ifdef LSB_FIRST
+ n ^= m_fpu_pr;
+#endif
m_ea = m_r[0] + m_r[m];
m_fr[n] = RL(m_ea );
+ m_fr[n^1] = RL(m_ea+4 );
}
+ } else { /* SZ = 0 */
+ m_ea = m_r[0] + m_r[m];
+#ifdef LSB_FIRST
+ n ^= m_fpu_pr;
+#endif
+ m_fr[n] = RL(m_ea );
}
}
@@ -2751,35 +2745,29 @@ inline void sh34_base_device::FMOVMRFR(const uint16_t opcode)
{
uint32_t m = Rm; uint32_t n = Rn;
- if (m_fpu_pr) { /* PR = 1 */
+ if (m_fpu_sz) { /* SZ = 1 */
if (n & 1) {
- n= n & 14;
+ n &= 14;
+#ifdef LSB_FIRST
+ n ^= m_fpu_pr;
+#endif
m_ea = m_r[m];
- m_xf[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(m_ea );
- m_xf[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(m_ea+4 );
+ m_xf[n] = RL(m_ea );
+ m_xf[n^1] = RL(m_ea+4 );
} else {
- n= n & 14;
- m_ea = m_r[m];
- m_fr[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(m_ea );
- m_fr[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(m_ea+4 );
- }
- } else { /* PR = 0 */
- if (m_fpu_sz) { /* SZ = 1 */
- if (n & 1) {
- n= n & 14;
- m_ea = m_r[m];
- m_xf[n] = RL(m_ea );
- m_xf[n+1] = RL(m_ea+4 );
- } else {
- n= n & 14;
- m_ea = m_r[m];
- m_fr[n] = RL(m_ea );
- m_fr[n+1] = RL(m_ea+4 );
- }
- } else { /* SZ = 0 */
+#ifdef LSB_FIRST
+ n ^= m_fpu_pr;
+#endif
m_ea = m_r[m];
m_fr[n] = RL(m_ea );
+ m_fr[n^1] = RL(m_ea+4 );
}
+ } else { /* SZ = 0 */
+ m_ea = m_r[m];
+#ifdef LSB_FIRST
+ n ^= m_fpu_pr;
+#endif
+ m_fr[n] = RL(m_ea );
}
}
@@ -2792,9 +2780,14 @@ inline void sh34_base_device::FMOVFR(const uint16_t opcode)
{
uint32_t m = Rm; uint32_t n = Rn;
- if ((m_fpu_sz == 0) && (m_fpu_pr == 0)) /* SZ = 0 */
+ if (m_fpu_sz == 0) { /* SZ = 0 */
+#ifdef LSB_FIRST
+ n ^= m_fpu_pr;
+ m ^= m_fpu_pr;
+#endif
m_fr[n] = m_fr[m];
- else { /* SZ = 1 or PR = 1 */
+ }
+ else { /* SZ = 1 */
if (m & 1) {
if (n & 1) {
m_xf[n & 14] = m_xf[m & 14];
@@ -2818,25 +2811,41 @@ inline void sh34_base_device::FMOVFR(const uint16_t opcode)
/* FLDI1 FRn 1111nnnn10011101 */
inline void sh34_base_device::FLDI1(const uint16_t opcode)
{
+#ifdef LSB_FIRST
+ m_fr[Rn ^ m_fpu_pr] = 0x3F800000;
+#else
m_fr[Rn] = 0x3F800000;
+#endif
}
/* FLDI0 FRn 1111nnnn10001101 */
inline void sh34_base_device::FLDI0(const uint16_t opcode)
{
+#ifdef LSB_FIRST
+ m_fr[Rn ^ m_fpu_pr] = 0;
+#else
m_fr[Rn] = 0;
+#endif
}
/* FLDS FRm,FPUL 1111mmmm00011101 */
inline void sh34_base_device:: FLDS(const uint16_t opcode)
{
+#ifdef LSB_FIRST
+ m_fpul = m_fr[Rn ^ m_fpu_pr];
+#else
m_fpul = m_fr[Rn];
+#endif
}
/* FSTS FPUL,FRn 1111nnnn00001101 */
inline void sh34_base_device:: FSTS(const uint16_t opcode)
{
+#ifdef LSB_FIRST
+ m_fr[Rn ^ m_fpu_pr] = m_fpul;
+#else
m_fr[Rn] = m_fpul;
+#endif
}
/* FRCHG 1111101111111101 */
diff --git a/src/devices/cpu/tms1000/tms1k_base.cpp b/src/devices/cpu/tms1000/tms1k_base.cpp
index 43d86a49fae..8caa62493c7 100644
--- a/src/devices/cpu/tms1000/tms1k_base.cpp
+++ b/src/devices/cpu/tms1000/tms1k_base.cpp
@@ -220,6 +220,8 @@ void tms1k_base_device::device_reset()
m_eac = 0;
m_bl = 0;
m_add = 0;
+ m_status = 0;
+ m_clatch = 0;
m_opcode = 0;
m_micro = 0;
diff --git a/src/devices/machine/netlist.cpp b/src/devices/machine/netlist.cpp
index 10bc304eb98..75ba0615896 100644
--- a/src/devices/machine/netlist.cpp
+++ b/src/devices/machine/netlist.cpp
@@ -619,11 +619,11 @@ void netlist_mame_cpu_device_t::device_start()
netlist::detail::net_t *n = netlist().m_nets[i].get();
if (n->is_logic())
{
- state_add(i*2, n->name().c_str(), downcast<netlist::logic_net_t *>(n)->Q_state_ptr());
+ state_add(i*2, n->name().c_str(), *downcast<netlist::logic_net_t *>(n)->Q_state_ptr());
}
else
{
- state_add(i*2+1, n->name().c_str(), downcast<netlist::analog_net_t *>(n)->Q_Analog_state_ptr()).formatstr("%20s");
+ state_add(i*2+1, n->name().c_str(), *downcast<netlist::analog_net_t *>(n)->Q_Analog_state_ptr()).formatstr("%20s");
}
}
diff --git a/src/devices/sound/saa1099.cpp b/src/devices/sound/saa1099.cpp
index 4ea28c6adcf..b43103ca73c 100644
--- a/src/devices/sound/saa1099.cpp
+++ b/src/devices/sound/saa1099.cpp
@@ -221,7 +221,7 @@ void saa1099_device::sound_stream_update(sound_stream &stream, stream_sample_t *
case 0: m_noise[ch].freq = m_master_clock/256.0 * 2; break;
case 1: m_noise[ch].freq = m_master_clock/512.0 * 2; break;
case 2: m_noise[ch].freq = m_master_clock/1024.0 * 2; break;
- case 3: m_noise[ch].freq = m_channels[ch * 3].freq; break;
+ case 3: m_noise[ch].freq = m_channels[ch * 3].freq; break; // todo: this case will be m_master_clock/[ch*3's octave divisor, 0 is = 256*2, higher numbers are higher] * 2 if the tone generator phase reset bit (0x1c bit 1) is set.
}
}
@@ -280,12 +280,14 @@ void saa1099_device::sound_stream_update(sound_stream &stream, stream_sample_t *
for (ch = 0; ch < 2; ch++)
{
- /* check the actual position in noise generator */
+ /* update the state of the noise generator
+ * polynomial is x^18 + x^11 + x (i.e. 0x20400) and is a plain XOR, initial state is probably all 1s
+ * see http://www.vogons.org/viewtopic.php?f=9&t=51695 */
m_noise[ch].counter -= m_noise[ch].freq;
while (m_noise[ch].counter < 0)
{
m_noise[ch].counter += m_sample_rate;
- if( ((m_noise[ch].level & 0x4000) == 0) == ((m_noise[ch].level & 0x0040) == 0) )
+ if( ((m_noise[ch].level & 0x20000) == 0) != ((m_noise[ch].level & 0x0400) == 0) )
m_noise[ch].level = (m_noise[ch].level << 1) | 1;
else
m_noise[ch].level <<= 1;
diff --git a/src/devices/sound/saa1099.h b/src/devices/sound/saa1099.h
index 58b29c58989..6863bd73e76 100644
--- a/src/devices/sound/saa1099.h
+++ b/src/devices/sound/saa1099.h
@@ -56,12 +56,12 @@ struct saa1099_noise
saa1099_noise() :
counter(0.0),
freq(0.0),
- level(0) {}
+ level(0xFFFFFFFF) {}
/* vars to simulate the noise generator output */
double counter;
double freq;
- int level; /* noise polynomial shifter */
+ uint32_t level; /* noise polynomial shifter */
};
diff --git a/src/devices/video/hlcd0515.cpp b/src/devices/video/hlcd0515.cpp
index 052c3ba4933..eb9f6271c07 100644
--- a/src/devices/video/hlcd0515.cpp
+++ b/src/devices/video/hlcd0515.cpp
@@ -3,10 +3,12 @@
/*
Hughes HLCD 0515/0569 LCD Driver
+
+ 0515: 25 columns(also size of buffer/ram)
+ 0569: 24 columns, no DATA OUT pin, display blank has no effect
TODO:
- - What's the difference between 0515 and 0569? For now assume 0569 is a cost-reduced chip,
- lacking the data out pin.
+ - read mode is untested
- MAME bitmap update callback when needed
*/
@@ -21,20 +23,19 @@ const device_type HLCD0569 = &device_creator<hlcd0569_device>;
// constructor
//-------------------------------------------------
-hlcd0515_device::hlcd0515_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : device_t(mconfig, HLCD0515, "HLCD 0515 LCD Driver", tag, owner, clock, "hlcd0515", __FILE__),
- m_write_cols(*this), m_write_data(*this)
+hlcd0515_device::hlcd0515_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, u8 colmax, const char *shortname, const char *source)
+ : device_t(mconfig, type, name, tag, owner, clock, shortname, source),
+ m_colmax(colmax), m_write_cols(*this), m_write_data(*this)
{
}
-hlcd0515_device::hlcd0515_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, const char *shortname, const char *source)
- : device_t(mconfig, type, name, tag, owner, clock, shortname, source),
- m_write_cols(*this), m_write_data(*this)
+hlcd0515_device::hlcd0515_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : hlcd0515_device(mconfig, HLCD0515, "HLCD 0515 LCD Driver", tag, owner, clock, 25, "hlcd0515", __FILE__)
{
}
hlcd0569_device::hlcd0569_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : hlcd0515_device(mconfig, HLCD0569, "HLCD 0569 LCD Driver", tag, owner, clock, "hlcd0569", __FILE__)
+ : hlcd0515_device(mconfig, HLCD0569, "HLCD 0569 LCD Driver", tag, owner, clock, 24, "hlcd0569", __FILE__)
{
}
@@ -64,6 +65,7 @@ void hlcd0515_device::device_start()
m_rowmax = 0;
m_rowout = 0;
m_rowsel = 0;
+ m_buffer = 0;
memset(m_ram, 0, sizeof(m_ram));
// register for savestates
@@ -76,6 +78,7 @@ void hlcd0515_device::device_start()
save_item(NAME(m_rowmax));
save_item(NAME(m_rowout));
save_item(NAME(m_rowsel));
+ save_item(NAME(m_buffer));
save_item(NAME(m_ram));
}
@@ -101,7 +104,7 @@ void hlcd0515_device::device_timer(emu_timer &timer, device_timer_id id, int par
m_rowout = 0;
// write to COL/ROW pins
- m_write_cols(m_rowout, m_blank ? m_ram[m_rowout] : 0, 0xffffffff);
+ m_write_cols(m_rowout, m_blank ? 0 : m_ram[m_rowout], 0xffffffff);
m_rowout++;
}
@@ -111,68 +114,90 @@ void hlcd0515_device::device_timer(emu_timer &timer, device_timer_id id, int par
// handlers
//-------------------------------------------------
-WRITE_LINE_MEMBER(hlcd0515_device::write_cs)
+void hlcd0515_device::set_control()
{
- state = (state) ? 1 : 0;
+ // clock 0,1,2: row select
+ m_rowsel = m_control >> 2 & 7;
- // start serial sequence on falling edge
- if (!state && m_cs)
+ // clock 3(,4): initialize
+ if (m_control & 2)
{
- m_count = 0;
- m_control = 0;
+ m_rowmax = m_rowsel;
+ m_blank = bool(~m_control & 1);
}
- m_cs = state;
+ // clock 4: read/write mode
+ m_buffer = (m_control & 1) ? m_ram[m_rowsel] : 0;
}
+void hlcd0569_device::set_control()
+{
+ hlcd0515_device::set_control();
+ m_blank = false; // 0569 doesn't support display blanking
+}
+
+
+void hlcd0515_device::clock_data(int col)
+{
+ if (m_control & 1)
+ {
+ if (col < m_colmax)
+ m_buffer <<= 1;
+
+ m_write_data(m_buffer >> m_colmax & 1);
+ }
+ else
+ {
+ if (col < m_colmax)
+ m_buffer >>= 1;
+
+ // always write last column
+ u32 mask = 1 << (m_colmax - 1);
+ m_buffer = (m_buffer & ~mask) | (m_data ? mask : 0);
+ }
+}
+
+
WRITE_LINE_MEMBER(hlcd0515_device::write_clock)
{
state = (state) ? 1 : 0;
// clock/shift data on falling edge
- if (!m_cs && m_count < 30 && !state && m_clock)
+ if (!m_cs && !state && m_clock)
{
if (m_count < 5)
{
// 5-bit mode/control
m_control = m_control << 1 | m_data;
-
if (m_count == 4)
- {
- // clock 0,1,2: row select
- // clock 3: initialize
- // clock 4: read/write
- m_rowsel = m_control >> 2 & 7;
- if (m_control & 2)
- {
- m_rowmax = m_rowsel;
- m_blank = bool(m_control & 1);
- }
- }
+ set_control();
}
else
- {
- if (m_control & 1)
- {
- // read data, output
- m_write_data(m_ram[m_rowsel] >> (m_count - 5) & 1);
- }
- else
- {
- // write data
- u32 mask = 1 << (m_count - 5);
- m_ram[m_rowsel] = (m_ram[m_rowsel] & ~mask) | (m_data ? mask : 0);
- }
- }
-
- m_count++;
+ clock_data(m_count - 5);
+
+ if (m_count < (m_colmax + 5))
+ m_count++;
}
m_clock = state;
}
-WRITE_LINE_MEMBER(hlcd0515_device::write_data)
+
+WRITE_LINE_MEMBER(hlcd0515_device::write_cs)
{
- m_data = (state) ? 1 : 0;
+ state = (state) ? 1 : 0;
+
+ // finish serial sequence on rising edge
+ if (state && !m_cs)
+ {
+ // transfer to ram
+ if (~m_control & 1)
+ m_ram[m_rowsel] = m_buffer;
+
+ m_count = 0;
+ m_control = 0;
+ }
+
+ m_cs = state;
}
diff --git a/src/devices/video/hlcd0515.h b/src/devices/video/hlcd0515.h
index 622a68e7126..a09af404b55 100644
--- a/src/devices/video/hlcd0515.h
+++ b/src/devices/video/hlcd0515.h
@@ -16,7 +16,7 @@
#define MCFG_HLCD0515_WRITE_COLS_CB(_devcb) \
hlcd0515_device::set_write_cols_callback(*device, DEVCB_##_devcb);
-// DATA OUT pin
+// DATA OUT pin, don't use on HLCD0569
#define MCFG_HLCD0515_WRITE_DATA_CB(_devcb) \
hlcd0515_device::set_write_data_callback(*device, DEVCB_##_devcb);
@@ -46,6 +46,8 @@
COL11 19 | | 22 COL13
GND 20 |___________| 21 COL12
+ HLCD 0569 doesn't have DATA OUT, instead it has what seems like OSC OUT on pin 34.
+
OSC is tied to a capacitor, the result frequency is 50000 * cap(in uF), eg. 0.01uF cap = 500Hz.
Internally, this is divided by 2, and by number of rows to get display refresh frequency.
*/
@@ -54,15 +56,15 @@ class hlcd0515_device : public device_t
{
public:
hlcd0515_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- hlcd0515_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, const char *shortname, const char *source);
+ hlcd0515_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, u8 colmax, const char *shortname, const char *source);
// static configuration helpers
template<class _Object> static devcb_base &set_write_cols_callback(device_t &device, _Object object) { return downcast<hlcd0515_device &>(device).m_write_cols.set_callback(object); }
template<class _Object> static devcb_base &set_write_data_callback(device_t &device, _Object object) { return downcast<hlcd0515_device &>(device).m_write_data.set_callback(object); }
- DECLARE_WRITE_LINE_MEMBER(write_cs);
DECLARE_WRITE_LINE_MEMBER(write_clock);
- DECLARE_WRITE_LINE_MEMBER(write_data);
+ DECLARE_WRITE_LINE_MEMBER(write_cs);
+ DECLARE_WRITE_LINE_MEMBER(write_data) { m_data = (state) ? 1 : 0; }
protected:
// device-level overrides
@@ -70,6 +72,11 @@ protected:
virtual void device_reset() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void set_control();
+ void clock_data(int col);
+
+ u8 m_colmax; // number of column pins
+
int m_cs; // input pin state
int m_clock; // "
int m_data; // "
@@ -79,7 +86,8 @@ protected:
u8 m_rowmax; // number of rows output by lcd (max 8)
u8 m_rowout; // current row for lcd output
u8 m_rowsel; // current row for data in/out
- u32 m_ram[8]; // 8x25bit ram
+ u32 m_buffer; // data in/out shift register
+ u32 m_ram[8]; // internal lcd ram, 8 rows
emu_timer *m_lcd_timer;
@@ -93,6 +101,9 @@ class hlcd0569_device : public hlcd0515_device
{
public:
hlcd0569_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void set_control() override;
};
diff --git a/src/devices/video/huc6261.cpp b/src/devices/video/huc6261.cpp
index ddd11783131..08f234acbff 100644
--- a/src/devices/video/huc6261.cpp
+++ b/src/devices/video/huc6261.cpp
@@ -27,7 +27,7 @@ const device_type HUC6261 = &device_creator<huc6261_device>;
huc6261_device::huc6261_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, HUC6261, "HuC6261", tag, owner, clock, "huc6261", __FILE__),
- device_video_interface(mconfig, *this), m_huc6270_a_tag(nullptr), m_huc6270_b_tag(nullptr), m_huc6270_a(nullptr), m_huc6270_b(nullptr), m_last_h(0), m_last_v(0), m_height(0), m_address(0), m_palette_latch(0), m_register(0), m_control(0), m_pixels_per_clock(0), m_pixel_data(0), m_pixel_clock(0), m_timer(nullptr), m_bmp(nullptr)
+ device_video_interface(mconfig, *this), m_huc6270_a_tag(nullptr), m_huc6270_b_tag(nullptr), m_huc6270_a(nullptr), m_huc6270_b(nullptr), m_last_h(0), m_last_v(0), m_height(0), m_address(0), m_palette_latch(0), m_register(0), m_control(0), m_pixels_per_clock(0), m_pixel_data_a(0), m_pixel_data_b(0), m_pixel_clock(0), m_timer(nullptr), m_bmp(nullptr)
{
// Set up UV lookup table
for ( int ur = 0; ur < 256; ur++ )
@@ -38,10 +38,10 @@ huc6261_device::huc6261_device(const machine_config &mconfig, const char *tag, d
int32_t u = ur - 128;
int32_t v = vr - 128;
- r = - 1.13983 * v;
+ r = + 1.13983 * v;
g = -0.35465 * u - 0.58060 * v;
b = 2.03211 * u;
-
+
m_uv_lookup[ ( ur << 8 ) | vr ][0] = r;
m_uv_lookup[ ( ur << 8 ) | vr ][1] = g;
m_uv_lookup[ ( ur << 8 ) | vr ][2] = b;
@@ -53,8 +53,8 @@ huc6261_device::huc6261_device(const machine_config &mconfig, const char *tag, d
inline uint32_t huc6261_device::yuv2rgb(uint32_t yuv)
{
int32_t r, g, b;
- uint8_t y = yuv >> 16;
- uint16_t uv = yuv & 0xffff;
+ uint8_t y = yuv >> 8;
+ uint16_t uv = ((yuv & 0xf0) << 8) | ((yuv & 0xf) << 4);
r = y + m_uv_lookup[uv][0];
g = y + m_uv_lookup[uv][1];
@@ -70,6 +70,20 @@ inline uint32_t huc6261_device::yuv2rgb(uint32_t yuv)
return ( r << 16 ) | ( g << 8 ) | b;
}
+void huc6261_device::apply_pal_offs(uint16_t *pix_data)
+{
+ // sprite
+ if(*pix_data & 0x100)
+ {
+ *pix_data &= 0xff;
+ *pix_data += ((m_palette_offset[0] & 0x7f00) >> 8) << 1;
+ }
+ else // background
+ *pix_data += (m_palette_offset[0] & 0x7f) << 1;
+
+ *pix_data &= 0x1ff;
+}
+
void huc6261_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
int vpos = m_screen->vpos();
@@ -77,18 +91,26 @@ void huc6261_device::device_timer(emu_timer &timer, device_timer_id id, int para
int h = m_last_h;
int v = m_last_v;
uint32_t *bitmap_line = &m_bmp->pix32(v);
-
+
while ( h != hpos || v != vpos )
{
if ( m_pixel_clock == 0 )
{
g_profiler.start( PROFILER_VIDEO );
/* Get next pixel information */
- m_pixel_data = m_huc6270_b->next_pixel( machine().dummy_space(), 0, 0xffff );
+ m_pixel_data_a = m_huc6270_a->next_pixel( machine().dummy_space(), 0, 0xffff );
+ m_pixel_data_b = m_huc6270_b->next_pixel( machine().dummy_space(), 0, 0xffff );
+ apply_pal_offs(&m_pixel_data_a);
+ apply_pal_offs(&m_pixel_data_b);
+
g_profiler.stop();
}
- bitmap_line[ h ] = yuv2rgb( ( ( m_palette[m_pixel_data] & 0xff00 ) << 8 ) | ( ( m_palette[m_pixel_data] & 0xf0 ) << 8 ) | ( ( m_palette[m_pixel_data] & 0x0f ) << 4 ) );
+ bitmap_line[ h ] = yuv2rgb( m_palette[m_pixel_data_a] );
+ // TODO: is mixing correct?
+ if((m_pixel_data_b & 0xff) != 0)
+ bitmap_line[ h ] = yuv2rgb( m_palette[m_pixel_data_b] );
+
m_pixel_clock = ( m_pixel_clock + 1 ) % m_pixels_per_clock;
h = ( h + 1 ) % HUC6261_WPF;
@@ -297,20 +319,12 @@ WRITE16_MEMBER( huc6261_device::write )
m_address = ( m_address + 1 ) & 0x1FF;
break;
- // Palette offset 0
+ // Palette offset 0-3
case 0x04:
- break;
-
- // Palette offset 1
case 0x05:
- break;
-
- // Palette offset 2
case 0x06:
- break;
-
- // Palette offset 3
case 0x07:
+ m_palette_offset[m_register & 3] = data;
break;
// Priority 0
@@ -414,7 +428,8 @@ void huc6261_device::device_start()
save_item(NAME(m_control));
save_item(NAME(m_priority));
save_item(NAME(m_pixels_per_clock));
- save_item(NAME(m_pixel_data));
+ save_item(NAME(m_pixel_data_a));
+ save_item(NAME(m_pixel_data_b));
save_item(NAME(m_pixel_clock));
}
diff --git a/src/devices/video/huc6261.h b/src/devices/video/huc6261.h
index a6f5b0f55a2..c62e5a1a296 100644
--- a/src/devices/video/huc6261.h
+++ b/src/devices/video/huc6261.h
@@ -40,8 +40,6 @@ public:
DECLARE_READ16_MEMBER( read );
DECLARE_WRITE16_MEMBER( write );
- inline uint32_t yuv2rgb(uint32_t yuv);
-
protected:
// device-level overrides
virtual void device_start() override;
@@ -66,12 +64,16 @@ private:
uint8_t m_priority[7];
uint8_t m_pixels_per_clock; /* Number of pixels to output per colour clock */
- uint16_t m_pixel_data;
+ uint16_t m_pixel_data_a;
+ uint16_t m_pixel_data_b;
+ uint16_t m_palette_offset[4];
uint8_t m_pixel_clock;
emu_timer *m_timer;
std::unique_ptr<bitmap_rgb32> m_bmp;
int32_t m_uv_lookup[65536][3];
+ inline uint32_t yuv2rgb(uint32_t yuv);
+ inline void apply_pal_offs(uint16_t *pix_data);
};
diff --git a/src/devices/video/huc6271.cpp b/src/devices/video/huc6271.cpp
new file mode 100644
index 00000000000..e75b8ccae13
--- /dev/null
+++ b/src/devices/video/huc6271.cpp
@@ -0,0 +1,65 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/***************************************************************************
+
+ Hudson/NEC HuC6271 "Rainbow" device
+
+***************************************************************************/
+
+#include "emu.h"
+#include "huc6271.h"
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+const device_type huc6271 = &device_creator<huc6271_device>;
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// huc6271_device - constructor
+//-------------------------------------------------
+
+huc6271_device::huc6271_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, huc6271, "HuC6271 \"Rainbow\"", tag, owner, clock, "huc6271", __FILE__)
+{
+}
+
+DEVICE_ADDRESS_MAP_START( regs, 16, huc6271_device )
+ AM_RANGE(0x00, 0x01) AM_WRITENOP // hscroll
+ AM_RANGE(0x02, 0x03) AM_WRITENOP // control
+ AM_RANGE(0x04, 0x05) AM_WRITENOP // hsync
+ AM_RANGE(0x06, 0x07) AM_WRITENOP // base Y
+ AM_RANGE(0x08, 0x09) AM_WRITENOP // base U
+ AM_RANGE(0x0a, 0x0b) AM_WRITENOP // base V
+ADDRESS_MAP_END
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void huc6271_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void huc6271_device::device_reset()
+{
+}
+
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
diff --git a/src/devices/video/huc6271.h b/src/devices/video/huc6271.h
new file mode 100644
index 00000000000..155b964b395
--- /dev/null
+++ b/src/devices/video/huc6271.h
@@ -0,0 +1,57 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/***************************************************************************
+
+ Hudson/NEC HuC6271 "Rainbow" device
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __HUC6271DEV_H__
+#define __HUC6271DEV_H__
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_HUC6271_ADD(_tag,_freq) \
+ MCFG_DEVICE_ADD(_tag, huc6271, _freq)
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> huc6271_device
+
+class huc6271_device : public device_t
+{
+public:
+ // construction/destruction
+ huc6271_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // I/O operations
+ DECLARE_ADDRESS_MAP(regs, 16);
+
+protected:
+ // device-level overrides
+// virtual void device_validity_check(validity_checker &valid) const;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+};
+
+
+// device type definition
+extern const device_type huc6271;
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+
+
+#endif
diff --git a/src/devices/video/huc6272.cpp b/src/devices/video/huc6272.cpp
index dce9cb7fe5c..2e4be104527 100644
--- a/src/devices/video/huc6272.cpp
+++ b/src/devices/video/huc6272.cpp
@@ -18,88 +18,103 @@
// device type definition
const device_type huc6272 = &device_creator<huc6272_device>;
-static ADDRESS_MAP_START( huc6272_vram, AS_0, 32, huc6272_device )
+static ADDRESS_MAP_START( microprg_map, AS_PROGRAM, 16, huc6272_device )
+ AM_RANGE(0x00, 0x0f) AM_RAM AM_SHARE("microprg_ram")
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( kram_map, AS_DATA, 32, huc6272_device )
AM_RANGE(0x000000, 0x0fffff) AM_RAM
AM_RANGE(0x100000, 0x1fffff) AM_RAM
ADDRESS_MAP_END
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
//-------------------------------------------------
-// memory_space_config - return a description of
-// any address spaces owned by this device
+// huc6272_device - constructor
//-------------------------------------------------
-const address_space_config *huc6272_device::memory_space_config(address_spacenum spacenum) const
+huc6272_device::huc6272_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, huc6272, "HuC6272 \"King\"", tag, owner, clock, "huc6272", __FILE__),
+ device_memory_interface(mconfig, *this),
+ m_program_space_config("microprg", ENDIANNESS_LITTLE, 16, 4, 0, nullptr, *ADDRESS_MAP_NAME(microprg_map)),
+ m_data_space_config("kram", ENDIANNESS_LITTLE, 32, 32, 0, nullptr, *ADDRESS_MAP_NAME(kram_map)),
+ m_microprg_ram(*this, "microprg_ram")
{
- return (spacenum == AS_0) ? &m_space_config : nullptr;
}
-//**************************************************************************
-// INLINE HELPERS
-//**************************************************************************
//-------------------------------------------------
-// read_dword - read a dword at the given address
+// device_validity_check - perform validity checks
+// on this device
//-------------------------------------------------
-inline uint32_t huc6272_device::read_dword(offs_t address)
+void huc6272_device::device_validity_check(validity_checker &valid) const
{
- return space().read_dword(address << 2);
}
//-------------------------------------------------
-// write_dword - write a dword at the given address
+// device_start - device-specific startup
//-------------------------------------------------
-inline void huc6272_device::write_dword(offs_t address, uint32_t data)
+void huc6272_device::device_start()
{
- space().write_dword(address << 2, data);
}
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
//-------------------------------------------------
-// huc6272_device - constructor
+// device_reset - device-specific reset
//-------------------------------------------------
-huc6272_device::huc6272_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, huc6272, "huc6272", tag, owner, clock, "huc6272", __FILE__),
- device_memory_interface(mconfig, *this),
- m_space_config("videoram", ENDIANNESS_LITTLE, 32, 32, 0, nullptr, *ADDRESS_MAP_NAME(huc6272_vram))
+void huc6272_device::device_reset()
{
}
-
//-------------------------------------------------
-// device_validity_check - perform validity checks
-// on this device
+// memory_space_config - return a description of
+// any address spaces owned by this device
//-------------------------------------------------
-void huc6272_device::device_validity_check(validity_checker &valid) const
+const address_space_config *huc6272_device::memory_space_config(address_spacenum spacenum) const
{
+ switch(spacenum)
+ {
+ case AS_PROGRAM: return &m_program_space_config;
+ case AS_DATA: return &m_data_space_config;
+ default: return nullptr;
+ }
}
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
//-------------------------------------------------
-// device_start - device-specific startup
+// read_dword - read a dword at the given address
//-------------------------------------------------
-void huc6272_device::device_start()
+inline uint32_t huc6272_device::read_dword(offs_t address)
{
+ return space(AS_DATA).read_dword(address << 2);
}
//-------------------------------------------------
-// device_reset - device-specific reset
+// write_dword - write a dword at the given address
//-------------------------------------------------
-void huc6272_device::device_reset()
+inline void huc6272_device::write_dword(offs_t address, uint32_t data)
{
+ space(AS_DATA).write_dword(address << 2, data);
}
+void huc6272_device::write_microprg_data(offs_t address, uint16_t data)
+{
+ space(AS_PROGRAM).write_word(address << 1, data);
+}
//**************************************************************************
// READ/WRITE HANDLERS
@@ -168,14 +183,17 @@ WRITE32_MEMBER( huc6272_device::write )
{
switch(m_register)
{
- case 0x09: // DMA addr
- //printf("%08x DMA ADDR\n",data);
- break;
- case 0x0a: // DMA size
- //printf("%08x DMA SIZE\n",data);
- break;
- case 0x0b: // DMA status
- //printf("%08x DMA STATUS\n",data);
+ case 0x00: // SCSI data
+ case 0x01: // SCSI command
+ case 0x02: // SCSI mode
+ case 0x03: // SCSI target command
+ case 0x05: // SCSI bus status
+ case 0x06: // SCSI input data
+ case 0x07: // SCSI DMA trigger
+ case 0x08: // SCSI subcode
+ case 0x09: // SCSI DMA start address
+ case 0x0a: // SCSI DMA size
+ case 0x0b: // SCSI DMA control
break;
/*
---- ---- ---- ---- ----
@@ -230,13 +248,13 @@ WRITE32_MEMBER( huc6272_device::write )
break;
case 0x13:
- m_micro_prg.addr = data & 0xf;
+ m_micro_prg.index = data & 0xf;
break;
case 0x14:
- m_micro_prg.data[m_micro_prg.addr] = data & 0xffff;
- m_micro_prg.addr++;
- m_micro_prg.addr &= 0xf;
+ write_microprg_data(m_micro_prg.index,data & 0xffff);
+ m_micro_prg.index ++;
+ m_micro_prg.index &= 0xf;
break;
case 0x15:
diff --git a/src/devices/video/huc6272.h b/src/devices/video/huc6272.h
index 9a2e173f919..5fcbdaf1901 100644
--- a/src/devices/video/huc6272.h
+++ b/src/devices/video/huc6272.h
@@ -2,7 +2,7 @@
// copyright-holders:Wilbert Pol
/***************************************************************************
-Template for skeleton device
+ Hudson/NEC HuC6272 "King" device
***************************************************************************/
@@ -44,11 +44,9 @@ protected:
virtual void device_validity_check(validity_checker &valid) const override;
virtual void device_start() override;
virtual void device_reset() override;
- virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const override;
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_PROGRAM) const override;
private:
- inline uint32_t read_dword(offs_t address);
- inline void write_dword(offs_t address, uint32_t data);
uint8_t m_register;
uint32_t m_kram_addr_r, m_kram_addr_w;
uint16_t m_kram_inc_r,m_kram_inc_w;
@@ -57,12 +55,17 @@ private:
uint8_t m_bgmode[4];
struct{
- uint8_t addr;
+ uint8_t index;
uint8_t ctrl;
- uint16_t data[16];
}m_micro_prg;
- const address_space_config m_space_config;
+ const address_space_config m_program_space_config;
+ const address_space_config m_data_space_config;
+ required_shared_ptr<uint16_t> m_microprg_ram;
+
+ uint32_t read_dword(offs_t address);
+ void write_dword(offs_t address, uint32_t data);
+ void write_microprg_data(offs_t address, uint16_t data);
};
diff --git a/src/lib/netlist/analog/nld_twoterm.cpp b/src/lib/netlist/analog/nld_twoterm.cpp
index 0e53d77f1f5..f676fe928ac 100644
--- a/src/lib/netlist/analog/nld_twoterm.cpp
+++ b/src/lib/netlist/analog/nld_twoterm.cpp
@@ -5,9 +5,10 @@
*
*/
-#include <solver/nld_solver.h>
#include <algorithm>
+#include "solver/nld_solver.h"
+
#include "nld_twoterm.h"
namespace netlist
@@ -23,6 +24,7 @@ generic_diode::generic_diode(device_t &dev, pstring name)
, m_Id(dev, name + ".m_Id", 0.0)
, m_G(dev, name + ".m_G", 1e-15)
, m_Vt(0.0)
+ , m_Vmin(0.0)
, m_Is(0.0)
, m_n(0.0)
, m_gmin(1e-15)
@@ -40,6 +42,7 @@ void generic_diode::set_param(const nl_double Is, const nl_double n, nl_double g
m_gmin = gmin;
m_Vt = 0.0258 * m_n;
+ m_Vmin = -5.0 * m_Vt;
m_Vcrit = m_Vt * std::log(m_Vt / m_Is / csqrt2);
m_VtInv = 1.0 / m_Vt;
@@ -47,8 +50,7 @@ void generic_diode::set_param(const nl_double Is, const nl_double n, nl_double g
void generic_diode::update_diode(const nl_double nVd)
{
-#if 1
- if (nVd < NL_FCONST(-5.0) * m_Vt)
+ if (nVd < m_Vmin)
{
m_Vd = nVd;
m_G = m_gmin;
@@ -58,29 +60,19 @@ void generic_diode::update_diode(const nl_double nVd)
{
m_Vd = nVd;
//m_Vd = m_Vd + 10.0 * m_Vt * std::tanh((nVd - m_Vd) / 10.0 / m_Vt);
- const nl_double eVDVt = std::exp(m_Vd * m_VtInv);
- m_Id = m_Is * (eVDVt - NL_FCONST(1.0));
- m_G = m_Is * m_VtInv * eVDVt + m_gmin;
+ //const double IseVDVt = m_Is * std::exp(m_Vd * m_VtInv);
+ const double IseVDVt = m_Is * std::exp(m_Vd * m_VtInv);
+ m_Id = IseVDVt - m_Is;
+ m_G = IseVDVt * m_VtInv + m_gmin;
}
else
{
-#if 1
- const nl_double a = std::max((nVd - m_Vd) * m_VtInv, NL_FCONST(-0.99));
+ const double a = std::max((nVd - m_Vd) * m_VtInv, NL_FCONST(-0.99));
m_Vd = m_Vd + std::log1p(a) * m_Vt;
-#else
- m_Vd = m_Vd + 10.0 * m_Vt * std::tanh((nVd - m_Vd) / 10.0 / m_Vt);
-#endif
- const nl_double eVDVt = std::exp(m_Vd * m_VtInv);
- m_Id = m_Is * (eVDVt - NL_FCONST(1.0));
-
- m_G = m_Is * m_VtInv * eVDVt + m_gmin;
+ const double IseVDVt = m_Is * std::exp(m_Vd * m_VtInv);
+ m_Id = IseVDVt - m_Is;
+ m_G = IseVDVt * m_VtInv + m_gmin;
}
-#else
- m_Vd = m_Vd + 20.0 * m_Vt * std::tanh((nVd - m_Vd) / 20.0 / m_Vt);
- const nl_double eVDVt = std::exp(m_Vd * m_VtInv);
- m_Id = m_Is * (eVDVt - NL_FCONST(1.0));
- m_G = m_Is * m_VtInv * eVDVt + m_gmin;
-#endif
}
// ----------------------------------------------------------------------------------------
diff --git a/src/lib/netlist/analog/nld_twoterm.h b/src/lib/netlist/analog/nld_twoterm.h
index 9494ad26520..44b3d29c16e 100644
--- a/src/lib/netlist/analog/nld_twoterm.h
+++ b/src/lib/netlist/analog/nld_twoterm.h
@@ -338,29 +338,30 @@ class generic_diode
public:
generic_diode(device_t &dev, pstring name);
- void update_diode(const nl_double nVd);
+ void update_diode(const double nVd);
- void set_param(const nl_double Is, const nl_double n, nl_double gmin);
+ void set_param(const double Is, const double n, double gmin);
- inline nl_double I() const { return m_Id; }
- inline nl_double G() const { return m_G; }
- inline nl_double Ieq() const { return (m_Id - m_Vd * m_G); }
- inline nl_double Vd() const { return m_Vd; }
+ inline double I() const { return m_Id; }
+ inline double G() const { return m_G; }
+ inline double Ieq() const { return (m_Id - m_Vd * m_G); }
+ inline double Vd() const { return m_Vd; }
/* owning object must save those ... */
private:
- state_var<nl_double> m_Vd;
- state_var<nl_double> m_Id;
- state_var<nl_double> m_G;
-
- nl_double m_Vt;
- nl_double m_Is;
- nl_double m_n;
- nl_double m_gmin;
-
- nl_double m_VtInv;
- nl_double m_Vcrit;
+ state_var<double> m_Vd;
+ state_var<double> m_Id;
+ state_var<double> m_G;
+
+ double m_Vt;
+ double m_Vmin;
+ double m_Is;
+ double m_n;
+ double m_gmin;
+
+ double m_VtInv;
+ double m_Vcrit;
};
/*! Class representing the diode model paramers.
diff --git a/src/lib/netlist/devices/nld_4020.cpp b/src/lib/netlist/devices/nld_4020.cpp
index a147cf3f58f..14459fb3b62 100644
--- a/src/lib/netlist/devices/nld_4020.cpp
+++ b/src/lib/netlist/devices/nld_4020.cpp
@@ -5,7 +5,7 @@
*
*/
-#include <devices/nlid_cmos.h>
+#include "devices/nlid_cmos.h"
#include "nld_4020.h"
namespace netlist
diff --git a/src/lib/netlist/devices/nld_4066.cpp b/src/lib/netlist/devices/nld_4066.cpp
index f33688b73b7..f93bad59143 100644
--- a/src/lib/netlist/devices/nld_4066.cpp
+++ b/src/lib/netlist/devices/nld_4066.cpp
@@ -5,7 +5,7 @@
*
*/
-#include <devices/nlid_cmos.h>
+#include "devices/nlid_cmos.h"
#include "analog/nld_twoterm.h"
#include "nld_4066.h"
diff --git a/src/lib/netlist/devices/nld_4316.cpp b/src/lib/netlist/devices/nld_4316.cpp
index 8b9cb0d46ad..1a3b5c77144 100644
--- a/src/lib/netlist/devices/nld_4316.cpp
+++ b/src/lib/netlist/devices/nld_4316.cpp
@@ -5,7 +5,7 @@
*
*/
-#include <devices/nlid_cmos.h>
+#include "devices/nlid_cmos.h"
#include "analog/nld_twoterm.h"
#include "nld_4316.h"
diff --git a/src/lib/netlist/devices/nld_74166.cpp b/src/lib/netlist/devices/nld_74166.cpp
index 5cb7114ee0f..c9e935cb0d1 100644
--- a/src/lib/netlist/devices/nld_74166.cpp
+++ b/src/lib/netlist/devices/nld_74166.cpp
@@ -82,7 +82,7 @@ namespace netlist
netlist_time delay = NLTIME_FROM_NS(26);
if (m_CLRQ())
{
- bool clear_unset = !m_last_CLRQ();
+ bool clear_unset = !m_last_CLRQ;
if (clear_unset)
{
delay = NLTIME_FROM_NS(35);
diff --git a/src/lib/netlist/devices/nld_7493.cpp b/src/lib/netlist/devices/nld_7493.cpp
index 557d7fa42b6..151e407a210 100644
--- a/src/lib/netlist/devices/nld_7493.cpp
+++ b/src/lib/netlist/devices/nld_7493.cpp
@@ -29,8 +29,8 @@ namespace netlist
logic_input_t m_I;
logic_output_t m_Q;
- state_var_u8 m_reset;
- state_var_u8 m_state;
+ state_var<netlist_sig_t> m_reset;
+ state_var<netlist_sig_t> m_state;
};
NETLIB_OBJECT(7493)
@@ -99,7 +99,7 @@ namespace netlist
NETLIB_UPDATE(7493ff)
{
- constexpr netlist_time out_delay = NLTIME_FROM_NS(18);
+ static constexpr netlist_time out_delay = NLTIME_FROM_NS(18);
if (m_reset)
{
m_state ^= 1;
diff --git a/src/lib/netlist/devices/nld_9310.cpp b/src/lib/netlist/devices/nld_9310.cpp
index 4ddb62af519..c45f3bb1ed2 100644
--- a/src/lib/netlist/devices/nld_9310.cpp
+++ b/src/lib/netlist/devices/nld_9310.cpp
@@ -158,21 +158,22 @@ namespace netlist
{
if (m_loadq)
{
- switch (m_cnt())
+ if (m_cnt < MAXCNT - 1)
{
- case MAXCNT - 1:
- m_cnt = MAXCNT;
- m_RC.push(m_ent, NLTIME_FROM_NS(20));
- m_QA.push(1, NLTIME_FROM_NS(20));
- break;
- case MAXCNT:
- m_RC.push(0, NLTIME_FROM_NS(20));
- m_cnt = 0;
- update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
- break;
- default:
- m_cnt++;
- update_outputs(m_cnt);
+ m_cnt++;
+ update_outputs(m_cnt);
+ }
+ else if (m_cnt == MAXCNT - 1)
+ {
+ m_cnt = MAXCNT;
+ m_RC.push(m_ent, NLTIME_FROM_NS(20));
+ m_QA.push(1, NLTIME_FROM_NS(20));
+ }
+ else // MAXCNT
+ {
+ m_RC.push(0, NLTIME_FROM_NS(20));
+ m_cnt = 0;
+ update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
}
}
else
diff --git a/src/lib/netlist/devices/nld_9316.cpp b/src/lib/netlist/devices/nld_9316.cpp
index ea7ca9fc45c..d1a4ae7334b 100644
--- a/src/lib/netlist/devices/nld_9316.cpp
+++ b/src/lib/netlist/devices/nld_9316.cpp
@@ -161,22 +161,22 @@ namespace netlist
{
if (m_loadq)
{
- switch (m_cnt())
+ if (m_cnt < MAXCNT - 1)
{
- case MAXCNT - 1:
- m_cnt = MAXCNT;
- m_RC.push(m_ent, NLTIME_FROM_NS(27));
- m_QA.push(1, NLTIME_FROM_NS(20));
- break;
- case MAXCNT:
- m_RC.push(0, NLTIME_FROM_NS(27));
- m_cnt = 0;
- update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
- break;
- default:
- m_cnt++;
- update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
- break;
+ m_cnt++;
+ update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
+ }
+ else if (m_cnt == MAXCNT - 1)
+ {
+ m_cnt = MAXCNT;
+ m_RC.push(m_ent, NLTIME_FROM_NS(27));
+ m_QA.push(1, NLTIME_FROM_NS(20));
+ }
+ else // MAXCNT
+ {
+ m_RC.push(0, NLTIME_FROM_NS(27));
+ m_cnt = 0;
+ update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
}
}
else
diff --git a/src/lib/netlist/devices/nld_mm5837.cpp b/src/lib/netlist/devices/nld_mm5837.cpp
index 256ced2d2a7..6be7d717221 100644
--- a/src/lib/netlist/devices/nld_mm5837.cpp
+++ b/src/lib/netlist/devices/nld_mm5837.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_mm5837.h"
-#include <solver/nld_matrix_solver.h>
+#include "solver/nld_matrix_solver.h"
#include "analog/nld_twoterm.h"
#define R_LOW (1000.0)
diff --git a/src/lib/netlist/devices/nld_ne555.cpp b/src/lib/netlist/devices/nld_ne555.cpp
index 3cfd120be30..67b13fd32b3 100644
--- a/src/lib/netlist/devices/nld_ne555.cpp
+++ b/src/lib/netlist/devices/nld_ne555.cpp
@@ -7,7 +7,7 @@
#include "nld_ne555.h"
#include "analog/nld_twoterm.h"
-#include <solver/nld_solver.h>
+#include "solver/nld_solver.h"
#define R_OFF (1E20)
#define R_ON (25) // Datasheet states a maximum discharge of 200mA, R = 5V / 0.2
diff --git a/src/lib/netlist/devices/nld_system.cpp b/src/lib/netlist/devices/nld_system.cpp
index 2a403c070a3..e3585271696 100644
--- a/src/lib/netlist/devices/nld_system.cpp
+++ b/src/lib/netlist/devices/nld_system.cpp
@@ -5,8 +5,8 @@
*
*/
-#include <solver/nld_solver.h>
-#include <solver/nld_matrix_solver.h>
+#include "solver/nld_solver.h"
+#include "solver/nld_matrix_solver.h"
#include "nlid_system.h"
namespace netlist
diff --git a/src/lib/netlist/devices/nld_truthtable.cpp b/src/lib/netlist/devices/nld_truthtable.cpp
index 1e786805eda..e7cedfba13f 100644
--- a/src/lib/netlist/devices/nld_truthtable.cpp
+++ b/src/lib/netlist/devices/nld_truthtable.cpp
@@ -8,6 +8,7 @@
#include "nld_truthtable.h"
#include "plib/plists.h"
#include "nl_setup.h"
+#include "plib/palloc.h"
namespace netlist
{
@@ -272,7 +273,7 @@ netlist_base_factory_truthtable_t::~netlist_base_factory_truthtable_t()
#define ENTRYY(n, m, s) case (n * 100 + m): \
{ using xtype = netlist_factory_truthtable_t<n, m>; \
- ret = new xtype(desc.name, desc.classname, desc.def_param, s); } break
+ ret = plib::palloc<xtype>(desc.name, desc.classname, desc.def_param, s); } break
#define ENTRY(n, s) ENTRYY(n, 1, s); ENTRYY(n, 2, s); ENTRYY(n, 3, s); \
ENTRYY(n, 4, s); ENTRYY(n, 5, s); ENTRYY(n, 6, s)
diff --git a/src/lib/netlist/devices/nlid_proxy.cpp b/src/lib/netlist/devices/nlid_proxy.cpp
index 3edb25f73e2..59f6f39420b 100644
--- a/src/lib/netlist/devices/nlid_proxy.cpp
+++ b/src/lib/netlist/devices/nlid_proxy.cpp
@@ -113,9 +113,9 @@ namespace netlist
{
pstring devname = out_proxied->device().name();
auto tp = netlist().setup().find_terminal(devname + "." + power_syms[i][0],
- detail::device_object_t::type_t::INPUT, false);
+ detail::core_terminal_t::type_t::INPUT, false);
auto tn = netlist().setup().find_terminal(devname + "." + power_syms[i][1],
- detail::device_object_t::type_t::INPUT, false);
+ detail::core_terminal_t::type_t::INPUT, false);
if (tp != nullptr && tn != nullptr)
{
/* alternative logic */
diff --git a/src/lib/netlist/devices/nlid_system.h b/src/lib/netlist/devices/nlid_system.h
index f2d893c7d28..5c29d40fd94 100644
--- a/src/lib/netlist/devices/nlid_system.h
+++ b/src/lib/netlist/devices/nlid_system.h
@@ -323,7 +323,7 @@ namespace netlist
inps.push_back(n);
m_vals.push_back(0.0);
}
- m_precompiled.compile_postfix(inps, m_func());
+ m_precompiled.compile(inps, m_func());
}
protected:
diff --git a/src/lib/netlist/documentation/mainpage.dox.h b/src/lib/netlist/documentation/mainpage.dox.h
index 75df1a18065..744abe642e6 100644
--- a/src/lib/netlist/documentation/mainpage.dox.h
+++ b/src/lib/netlist/documentation/mainpage.dox.h
@@ -161,5 +161,4 @@ equation solver.
The formal representation of the circuit will stay the same, thus scales.
-
*/
diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp
index 6128200fe9a..90149f44e8e 100644
--- a/src/lib/netlist/nl_base.cpp
+++ b/src/lib/netlist/nl_base.cpp
@@ -25,7 +25,7 @@ namespace netlist
namespace detail
{
#if (USE_MEMPOOL)
-static plib::mempool pool(65536, 8);
+static plib::mempool pool(6553600, 64);
void * object_t::operator new (size_t size)
{
@@ -184,7 +184,7 @@ void detail::queue_t::on_post_load()
detail::net_t *n = netlist().find_net(pstring(m_names[i].m_buf, pstring::UTF8));
//log().debug("Got {1} ==> {2}\n", qtemp[i].m_name, n));
//log().debug("schedule time {1} ({2})\n", n->time().as_double(), netlist_time::from_raw(m_times[i]).as_double()));
- this->push(n, netlist_time::from_raw(m_times[i]));
+ this->push(queue_t::entry_t(netlist_time::from_raw(m_times[i]),n));
}
}
@@ -216,20 +216,18 @@ detail::device_object_t::device_object_t(core_device_t &dev, const pstring &anam
{
}
-detail::device_object_t::type_t detail::device_object_t::type() const
+detail::core_terminal_t::type_t detail::core_terminal_t::type() const
{
if (dynamic_cast<const terminal_t *>(this) != nullptr)
return type_t::TERMINAL;
- else if (dynamic_cast<const param_t *>(this) != nullptr)
- return param_t::PARAM;
else if (dynamic_cast<const logic_input_t *>(this) != nullptr)
- return param_t::INPUT;
+ return type_t::INPUT;
else if (dynamic_cast<const logic_output_t *>(this) != nullptr)
- return param_t::OUTPUT;
+ return type_t::OUTPUT;
else if (dynamic_cast<const analog_input_t *>(this) != nullptr)
- return param_t::INPUT;
+ return type_t::INPUT;
else if (dynamic_cast<const analog_output_t *>(this) != nullptr)
- return param_t::OUTPUT;
+ return type_t::OUTPUT;
else
{
netlist().log().fatal(MF_1_UNKNOWN_TYPE_FOR_OBJECT, name());
@@ -254,19 +252,16 @@ netlist_t::netlist_t(const pstring &aname)
{
state().save_item(this, static_cast<plib::state_manager_t::callback_t &>(m_queue), "m_queue");
state().save_item(this, m_time, "m_time");
- m_setup = new setup_t(*this);
+ m_setup = plib::make_unique<setup_t>(*this);
/* FIXME: doesn't really belong here */
NETLIST_NAME(base)(*m_setup);
}
netlist_t::~netlist_t()
{
- if (m_setup != nullptr)
- delete m_setup;
m_nets.clear();
m_devices.clear();
- pfree(m_lib);
pstring::resetmem();
}
@@ -356,7 +351,7 @@ void netlist_t::start()
}
pstring libpath = plib::util::environment("NL_BOOSTLIB", plib::util::buildpath({".", "nlboost.so"}));
- m_lib = plib::palloc<plib::dynlib>(libpath);
+ m_lib = plib::make_unique<plib::dynlib>(libpath);
/* resolve inputs */
setup().resolve_inputs();
@@ -448,7 +443,7 @@ void netlist_t::process_queue(const netlist_time &delta)
{
netlist_time stop(m_time + delta);
- m_queue.push(nullptr, stop);
+ m_queue.push(detail::queue_t::entry_t(stop, nullptr));
m_stat_mainloop.start();
@@ -475,17 +470,20 @@ void netlist_t::process_queue(const netlist_time &delta)
while (m_queue.top().m_exec_time > mc_time)
{
m_time = mc_time;
- mc_time += inc;
mc_net.toggle_new_Q();
mc_net.update_devs();
+ mc_time += inc;
}
const detail::queue_t::entry_t e(m_queue.pop());
m_time = e.m_exec_time;
- if (e.m_object == nullptr)
+ if (e.m_object != nullptr)
+ {
+ e.m_object->update_devs();
+ m_perf_out_processed.inc();
+ }
+ else
break;
- e.m_object->update_devs();
- m_perf_out_processed.inc();
}
mc_net.set_time(mc_time);
}
@@ -578,7 +576,7 @@ core_device_t::core_device_t(netlist_t &owner, const pstring &name)
, logic_family_t()
, netlist_ref(owner)
, m_hint_deactivate(false)
-#if (NL_PMF_TYPE > NL_PMF_TYPE_VIRTUAL)
+#if (!NL_USE_PMF_VIRTUAL)
, m_static_update()
#endif
{
@@ -591,7 +589,7 @@ core_device_t::core_device_t(core_device_t &owner, const pstring &name)
, logic_family_t()
, netlist_ref(owner.netlist())
, m_hint_deactivate(false)
-#if (NL_PMF_TYPE > NL_PMF_TYPE_VIRTUAL)
+#if (!NL_USE_PMF_VIRTUAL)
, m_static_update()
#endif
{
@@ -607,14 +605,8 @@ core_device_t::~core_device_t()
void core_device_t::set_delegate_pointer()
{
-#if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF)
- void (core_device_t::* pFunc)() = &core_device_t::update;
- m_static_update = pFunc;
-#elif (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV)
- void (core_device_t::* pFunc)() = &core_device_t::update;
- m_static_update = reinterpret_cast<net_update_delegate>((this->*pFunc));
-#elif (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL)
- m_static_update = plib::mfp::get_mfp<net_update_delegate>(&core_device_t::update, this);
+#if (!NL_USE_PMF_VIRTUAL)
+ m_static_update.set_base(&core_device_t::update, this);
#endif
}
@@ -692,13 +684,6 @@ detail::family_setter_t::family_setter_t(core_device_t &dev, const logic_family_
// net_t
// ----------------------------------------------------------------------------------------
-// FIXME: move somewhere central
-
-struct do_nothing_deleter{
- template<typename T> void operator()(T*){}
-};
-
-
detail::net_t::net_t(netlist_t &nl, const pstring &aname, core_terminal_t *mr)
: object_t(aname)
, netlist_ref(nl)
@@ -731,7 +716,7 @@ void detail::net_t::inc_active(core_terminal_t &term) NL_NOEXCEPT
if (m_time > netlist().time())
{
m_in_queue = 1; /* pending */
- netlist().queue().push(this, m_time);
+ netlist().queue().push(queue_t::entry_t(m_time, this));
}
else
{
@@ -1106,11 +1091,11 @@ param_double_t::param_double_t(device_t &device, const pstring name, const doubl
m_param = device.setup().get_initial_param_val(this->name(),val);
netlist().save(*this, m_param, "m_param");
}
-
+#if 0
param_double_t::~param_double_t()
{
}
-
+#endif
param_int_t::param_int_t(device_t &device, const pstring name, const int val)
: param_t(device, name)
{
@@ -1118,9 +1103,11 @@ param_int_t::param_int_t(device_t &device, const pstring name, const int val)
netlist().save(*this, m_param, "m_param");
}
+#if 0
param_int_t::~param_int_t()
{
}
+#endif
param_logic_t::param_logic_t(device_t &device, const pstring name, const bool val)
: param_t(device, name)
@@ -1129,9 +1116,11 @@ param_logic_t::param_logic_t(device_t &device, const pstring name, const bool va
netlist().save(*this, m_param, "m_param");
}
+#if 0
param_logic_t::~param_logic_t()
{
}
+#endif
param_ptr_t::param_ptr_t(device_t &device, const pstring name, uint8_t * val)
: param_t(device, name)
@@ -1140,9 +1129,11 @@ param_ptr_t::param_ptr_t(device_t &device, const pstring name, uint8_t * val)
//netlist().save(*this, m_param, "m_param");
}
+#if 0
param_ptr_t::~param_ptr_t()
{
}
+#endif
void param_model_t::changed()
{
diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h
index 57d1e197378..b1b4dac9341 100644
--- a/src/lib/netlist/nl_base.h
+++ b/src/lib/netlist/nl_base.h
@@ -29,7 +29,7 @@
// ----------------------------------------------------------------------------------------
/*! netlist_sig_t is the type used for logic signals. */
-using netlist_sig_t = std::uint_least32_t;
+using netlist_sig_t = std::uint32_t;
//============================================================
// MACROS / New Syntax
@@ -281,12 +281,12 @@ namespace netlist
public:
logic_family_t() : m_logic_family(nullptr) {}
- ~logic_family_t() { }
const logic_family_desc_t *logic_family() const { return m_logic_family; }
void set_logic_family(const logic_family_desc_t *fam) { m_logic_family = fam; }
protected:
+ ~logic_family_t() { } // prohibit polymorphic destruction
const logic_family_desc_t *m_logic_family;
};
@@ -321,19 +321,15 @@ namespace netlist
//! Move Constructor.
state_var(state_var &&rhs) NL_NOEXCEPT = default;
//! Assignment operator to assign value of a state var.
- state_var &operator=(state_var rhs) { std::swap(rhs.m_value, this->m_value); return *this; }
+ state_var &operator=(const state_var &rhs) { m_value = rhs; return *this; }
//! Assignment operator to assign value of type T.
- state_var &operator=(const T rhs) { m_value = rhs; return *this; }
+ state_var &operator=(const T &rhs) { m_value = rhs; return *this; }
//! Return value of state variable.
operator T & () { return m_value; }
- //! Return value of state variable.
- T & operator()() { return m_value; }
- //! Return const value of state variable.
- operator const T & () const { return m_value; }
//! Return const value of state variable.
- const T & operator()() const { return m_value; }
+ constexpr operator const T & () const { return m_value; }
T * ptr() { return &m_value; }
- const T * ptr() const { return &m_value; }
+ constexpr T * ptr() const { return &m_value; }
private:
T m_value;
};
@@ -346,13 +342,20 @@ namespace netlist
struct state_var<T[N]>
{
public:
- state_var(device_t &dev, const pstring name, const T & value);
+ //! Constructor.
+ template <typename O>
+ state_var(O &owner, //!< owner must have a netlist() method.
+ const pstring name, //!< identifier/name for this state variable
+ const T &value //!< Initial value after construction
+ );
+ //! Copy Constructor.
state_var(const state_var &rhs) NL_NOEXCEPT = default;
+ //! Move Constructor.
state_var(state_var &&rhs) NL_NOEXCEPT = default;
- state_var &operator=(const state_var rhs) { m_value = rhs.m_value; return *this; }
- state_var &operator=(const T rhs) { m_value = rhs; return *this; }
+ state_var &operator=(const state_var &rhs) { m_value = rhs.m_value; return *this; }
+ state_var &operator=(const T &rhs) { m_value = rhs; return *this; }
T & operator[](const std::size_t i) { return m_value[i]; }
- const T & operator[](const std::size_t i) const { return m_value[i]; }
+ constexpr T & operator[](const std::size_t i) const { return m_value[i]; }
private:
T m_value[N];
};
@@ -392,7 +395,6 @@ namespace netlist
* Every class derived from the object_t class must have a name.
*/
object_t(const pstring &aname /*!< string containing name of the object */);
- virtual ~object_t();
/*! return name of the object
*
@@ -404,6 +406,8 @@ namespace netlist
void operator delete (void *ptr, void *) { }
void * operator new (size_t size);
void operator delete (void * mem);
+ protected:
+ ~object_t(); // only childs should be destructible
private:
pstring m_name;
@@ -412,11 +416,13 @@ namespace netlist
struct detail::netlist_ref
{
netlist_ref(netlist_t &nl) : m_netlist(nl) { }
- ~netlist_ref() {}
netlist_t & netlist() { return m_netlist; }
const netlist_t & netlist() const { return m_netlist; }
+ protected:
+ ~netlist_ref() {} // prohibit polymorphic destruction
+
private:
netlist_t & m_netlist;
@@ -435,14 +441,6 @@ namespace netlist
{
P_PREVENT_COPYING(device_object_t)
public:
- /*! Enum specifying the type of object */
- enum type_t {
- TERMINAL = 0, /*!< object is an analog terminal */
- INPUT = 1, /*!< object is an input */
- OUTPUT = 2, /*!< object is an output */
- PARAM = 3, /*!< object is a parameter */
- };
-
/*! Constructor.
*
* \param dev device owning the object.
@@ -454,16 +452,6 @@ namespace netlist
*/
core_device_t &device() const { return m_device; }
- /*! The object type.
- * \returns type of the object
- */
- type_t type() const;
- /*! Checks if object is of specified type.
- * \param atype type to check object against.
- * \returns true if object is of specified type else false.
- */
- bool is_type(const type_t atype) const { return (type() == atype); }
-
/*! The netlist owning the owner of this object.
* \returns reference to netlist object.
*/
@@ -500,9 +488,26 @@ namespace netlist
STATE_BIDIR = 256
};
+ /*! Enum specifying the type of object */
+ enum type_t {
+ TERMINAL = 0, /*!< object is an analog terminal */
+ INPUT = 1, /*!< object is an input */
+ OUTPUT = 2, /*!< object is an output */
+ };
+
core_terminal_t(core_device_t &dev, const pstring &aname, const state_e state);
virtual ~core_terminal_t();
+ /*! The object type.
+ * \returns type of the object
+ */
+ type_t type() const;
+ /*! Checks if object is of specified type.
+ * \param atype type to check object against.
+ * \returns true if object is of specified type else false.
+ */
+ bool is_type(const type_t atype) const { return (type() == atype); }
+
void set_net(net_t *anet);
void clear_net();
bool has_net() const { return (m_net != nullptr); }
@@ -706,12 +711,6 @@ namespace netlist
void reset();
- void add_terminal(core_terminal_t &terminal);
- void remove_terminal(core_terminal_t &terminal);
-
- bool is_logic() const NL_NOEXCEPT;
- bool is_analog() const NL_NOEXCEPT;
-
void toggle_new_Q() { m_new_Q ^= 1; }
void force_queue_execution() { m_new_Q = (m_cur_Q ^ 1); }
@@ -732,6 +731,14 @@ namespace netlist
void inc_active(core_terminal_t &term) NL_NOEXCEPT;
void dec_active(core_terminal_t &term) NL_NOEXCEPT;
+ /* setup stuff */
+
+ void add_terminal(core_terminal_t &terminal);
+ void remove_terminal(core_terminal_t &terminal);
+
+ bool is_logic() const NL_NOEXCEPT;
+ bool is_analog() const NL_NOEXCEPT;
+
void rebuild_list(); /* rebuild m_list after a load */
void move_connections(net_t &dest_net);
@@ -764,7 +771,7 @@ namespace netlist
virtual ~logic_net_t();
netlist_sig_t Q() const { return m_cur_Q; }
- netlist_sig_t new_Q() const { return m_new_Q; }
+ netlist_sig_t new_Q() const { return m_new_Q; }
void initial(const netlist_sig_t val) { m_cur_Q = m_new_Q = val; }
void set_Q(const netlist_sig_t newQ, const netlist_time delay) NL_NOEXCEPT
@@ -789,7 +796,7 @@ namespace netlist
/* internal state support
* FIXME: get rid of this and implement export/import in MAME
*/
- netlist_sig_t &Q_state_ptr() { return m_cur_Q; }
+ netlist_sig_t *Q_state_ptr() { return m_cur_Q.ptr(); }
protected:
private:
@@ -808,7 +815,7 @@ namespace netlist
virtual ~analog_net_t();
nl_double Q_Analog() const { return m_cur_Analog; }
- nl_double &Q_Analog_state_ptr() { return m_cur_Analog; }
+ nl_double *Q_Analog_state_ptr() { return m_cur_Analog.ptr(); }
//FIXME: needed by current solver code
devices::matrix_solver_t *solver() const { return m_solver; }
@@ -874,11 +881,12 @@ namespace netlist
};
param_t(device_t &device, const pstring &name);
- virtual ~param_t();
param_type_t param_type() const;
protected:
+ virtual ~param_t(); /* not intended to be destroyed */
+
void update_param();
template<typename C>
@@ -897,7 +905,6 @@ namespace netlist
{
public:
param_ptr_t(device_t &device, const pstring name, std::uint8_t* val);
- virtual ~param_ptr_t();
std::uint8_t * operator()() const { return m_param; }
void setTo(std::uint8_t *param) { set(m_param, param); }
private:
@@ -908,7 +915,6 @@ namespace netlist
{
public:
param_logic_t(device_t &device, const pstring name, const bool val);
- virtual ~param_logic_t();
bool operator()() const { return m_param; }
void setTo(const bool &param) { set(m_param, param); }
private:
@@ -919,7 +925,6 @@ namespace netlist
{
public:
param_int_t(device_t &device, const pstring name, const int val);
- virtual ~param_int_t();
int operator()() const { return m_param; }
void setTo(const int &param) { set(m_param, param); }
private:
@@ -930,7 +935,6 @@ namespace netlist
{
public:
param_double_t(device_t &device, const pstring name, const double val);
- virtual ~param_double_t();
double operator()() const { return m_param; }
void setTo(const double &param) { set(m_param, param); }
private:
@@ -942,6 +946,7 @@ namespace netlist
public:
param_str_t(device_t &device, const pstring name, const pstring val);
virtual ~param_str_t();
+
const pstring operator()() const { return Value(); }
void setTo(const pstring &param)
{
@@ -1082,12 +1087,10 @@ namespace netlist
void do_update() NL_NOEXCEPT
{
- #if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF)
- (this->*m_static_update)();
- #elif ((NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV) || (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL))
- m_static_update(this);
+ #if (NL_USE_PMF_VIRTUAL)
+ update();
#else
- update();
+ m_static_update.call(this);
#endif
}
@@ -1104,14 +1107,9 @@ namespace netlist
private:
bool m_hint_deactivate;
- #if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF)
- typedef void (core_device_t::*net_update_delegate)();
- #elif ((NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV) || (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL))
- using net_update_delegate = MEMBER_ABI void (*)(core_device_t *);
- #endif
- #if (NL_PMF_TYPE > NL_PMF_TYPE_VIRTUAL)
- net_update_delegate m_static_update;
+ #if (!NL_USE_PMF_VIRTUAL)
+ plib::pmfp_base<void> m_static_update;
#endif
};
@@ -1135,7 +1133,7 @@ namespace netlist
template<class C, typename... Args>
void register_sub(const pstring &name, std::unique_ptr<C> &dev, const Args&... args)
{
- dev.reset(new C(*this, name, args...));
+ dev.reset(plib::palloc<C>(*this, name, args...));
}
void register_subalias(const pstring &name, detail::core_terminal_t &term);
@@ -1277,11 +1275,11 @@ namespace netlist
template<typename O, typename C> void save(O &owner, C &state, const pstring &stname)
{
- this->state().save_item(static_cast<void *>(&owner), state, pstring::from_utf8(owner.name()) + pstring(".") + stname);
+ this->state().save_item(static_cast<void *>(&owner), state, from_utf8(owner.name()) + pstring(".") + stname);
}
template<typename O, typename C> void save(O &owner, C *state, const pstring &stname, const std::size_t count)
{
- this->state().save_state_ptr(static_cast<void *>(&owner), pstring::from_utf8(owner.name()) + pstring(".") + stname, plib::state_manager_t::datatype_f<C>::f(), count, state);
+ this->state().save_state_ptr(static_cast<void *>(&owner), from_utf8(owner.name()) + pstring(".") + stname, plib::state_manager_t::datatype_f<C>::f(), count, state);
}
void rebuild_lists(); /* must be called after post_load ! */
@@ -1299,6 +1297,10 @@ namespace netlist
private:
+ /* helper for save above */
+ static pstring from_utf8(const char *c) { return pstring(c, pstring::UTF8); }
+ static pstring from_utf8(const pstring &c) { return c; }
+
core_device_t *pget_single_device(const pstring classname, bool (*cc)(core_device_t *));
/* mostly rw */
@@ -1312,9 +1314,9 @@ namespace netlist
devices::NETLIB_NAME(netlistparams) *m_params;
pstring m_name;
- setup_t * m_setup;
+ std::unique_ptr<setup_t> m_setup;
plib::plog_base<NL_DEBUG> m_log;
- plib::dynlib * m_lib; // external lib needs to be loaded as long as netlist exists
+ std::unique_ptr<plib::dynlib> m_lib; // external lib needs to be loaded as long as netlist exists
plib::state_manager_t m_state;
@@ -1424,7 +1426,7 @@ namespace netlist
m_time = netlist().time() + delay;
m_in_queue = (m_active > 0); /* queued ? */
if (m_in_queue)
- netlist().queue().push(this, m_time);
+ netlist().queue().push(queue_t::entry_t(m_time, this));
}
}
@@ -1436,7 +1438,7 @@ namespace netlist
m_time = netlist().time() + delay;
m_in_queue = (m_active > 0); /* queued ? */
if (m_in_queue)
- netlist().queue().push(this, m_time);
+ netlist().queue().push(queue_t::entry_t(m_time, this));
}
inline const analog_net_t & analog_t::net() const NL_NOEXCEPT
@@ -1453,7 +1455,7 @@ namespace netlist
inline logic_net_t & logic_t::net() NL_NOEXCEPT
{
- return *static_cast<logic_net_t *>(&core_terminal_t::net());
+ return static_cast<logic_net_t &>(core_terminal_t::net());
}
inline const logic_net_t & logic_t::net() const NL_NOEXCEPT
@@ -1490,9 +1492,10 @@ namespace netlist
}
template <typename T, std::size_t N>
- state_var<T[N]>::state_var(device_t &dev, const pstring name, const T & value)
+ template <typename O>
+ state_var<T[N]>::state_var(O &owner, const pstring name, const T & value)
{
- dev.netlist().save(dev, m_value, name);
+ owner.netlist().save(owner, m_value, name);
for (std::size_t i=0; i<N; i++)
m_value[i] = value;
}
@@ -1509,5 +1512,14 @@ namespace netlist
}
+namespace plib
+{
+ template<typename X>
+ struct ptype_traits<netlist::state_var<X>> : ptype_traits<X>
+ {
+ };
+}
+
+
#endif /* NLBASE_H_ */
diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h
index 88f240394be..174549410d6 100644
--- a/src/lib/netlist/nl_config.h
+++ b/src/lib/netlist/nl_config.h
@@ -18,59 +18,6 @@
// SETUP
//============================================================
-/*
- * The following options determine how object::update is called.
- * NL_PMF_TYPE_VIRTUAL
- * Use stock virtual call
- *
- * NL_PMF_TYPE_GNUC_PMF
- * Use standard pointer to member function syntax
- *
- * NL_PMF_TYPE_GNUC_PMF_CONV
- * Use gnu extension and convert the pmf to a function pointer.
- * This is not standard compliant and needs
- * -Wno-pmf-conversions to compile.
- *
- * NL_PMF_TYPE_INTERNAL
- * Use the same approach as MAME for deriving the function pointer.
- * This is compiler-dependant as well
- *
- * Benchmarks for ./nltool -c run -f src/mame/drivers/nl_pong.c -t 10 -n pong_fast
- *
- * NL_PMF_TYPE_INTERNAL: 215%
- * NL_PMF_TYPE_GNUC_PMF: 163%
- * NL_PMF_TYPE_GNUC_PMF_CONV: 215%
- * NL_PMF_TYPE_VIRTUAL: 213%
- *
- * The whole exercise was done to avoid virtual calls. In prior versions of
- * netlist, the INTERNAL and GNUC_PMF_CONV approach provided significant improvement.
- * Since than, was removed from functions declared as virtual.
- * This may explain that the recent benchmarks show no difference at all.
- *
- * Disappointing is the GNUC_PMF performance.
- */
-
-// This will be autodetected
-// #define NL_PMF_TYPE 0
-
-#define NL_PMF_TYPE_VIRTUAL 0
-#define NL_PMF_TYPE_GNUC_PMF 1
-#define NL_PMF_TYPE_GNUC_PMF_CONV 2
-#define NL_PMF_TYPE_INTERNAL 3
-
-#ifndef NL_PMF_TYPE
- #if PHAS_PMF_INTERNAL
- #define NL_PMF_TYPE NL_PMF_TYPE_INTERNAL
- #else
- #define NL_PMF_TYPE NL_PMF_TYPE_VIRTUAL
- #endif
-#endif
-
-#if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV)
-#pragma GCC diagnostic ignored "-Wpmf-conversions"
-#endif
-
-
//============================================================
// GENERAL
@@ -156,6 +103,20 @@ using nperfcount_t = plib::chrono::counter<false>;
#define NL_FCONST(x) x
using nl_double = double;
+/* The following option determines how object::update is called.
+ * If set to 1, a virtual call is used. If it is left undefined, the best
+ * approach will be automatically selected.
+ */
+
+//#define NL_USE_PMF_VIRTUAL 1
+
+#ifndef NL_USE_PMF_VIRTUAL
+ #if PPMF_TYPE == PPMF_TYPE_PMF
+ #define NL_USE_PMF_VIRTUAL 1
+ #else
+ #define NL_USE_PMF_VIRTUAL 0
+ #endif
+#endif
//============================================================
// WARNINGS
diff --git a/src/lib/netlist/nl_factory.h b/src/lib/netlist/nl_factory.h
index 8c911e2a0bd..f5a38d416da 100644
--- a/src/lib/netlist/nl_factory.h
+++ b/src/lib/netlist/nl_factory.h
@@ -17,12 +17,11 @@
#include "plib/putil.h"
#include "nl_base.h"
-#if 1
#define NETLIB_DEVICE_IMPL(chip) \
static std::unique_ptr<factory::element_t> NETLIB_NAME(chip ## _c)( \
const pstring &name, const pstring &classname, const pstring &def_param) \
{ \
- return std::unique_ptr<factory::element_t>(new factory::device_element_t<NETLIB_NAME(chip)>(name, classname, def_param, pstring(__FILE__))); \
+ return std::unique_ptr<factory::element_t>(plib::palloc<factory::device_element_t<NETLIB_NAME(chip)>>(name, classname, def_param, pstring(__FILE__))); \
} \
factory::constructor_ptr_t decl_ ## chip = NETLIB_NAME(chip ## _c);
@@ -30,16 +29,10 @@
static std::unique_ptr<factory::element_t> NETLIB_NAME(chip ## _c)( \
const pstring &name, const pstring &classname, const pstring &def_param) \
{ \
- return std::unique_ptr<factory::element_t>(new factory::device_element_t<ns :: NETLIB_NAME(chip)>(name, classname, def_param, pstring(__FILE__))); \
+ return std::unique_ptr<factory::element_t>(plib::palloc<factory::device_element_t<ns :: NETLIB_NAME(chip)>>(name, classname, def_param, pstring(__FILE__))); \
} \
factory::constructor_ptr_t decl_ ## chip = NETLIB_NAME(chip ## _c);
-#else
-#define NETLIB_DEVICE_IMPL(chip) factory::constructor_ptr_t decl_ ## chip = factory::constructor_t< NETLIB_NAME(chip) >;
-#define NETLIB_DEVICE_IMPL_NS(ns, chip) factory::constructor_ptr_t decl_ ## chip = factory::constructor_t< ns :: NETLIB_NAME(chip) >;
-#endif
-
-
namespace netlist { namespace factory
{
// -----------------------------------------------------------------------------
@@ -99,7 +92,7 @@ namespace netlist { namespace factory
void register_device(const pstring &name, const pstring &classname,
const pstring &def_param)
{
- register_device(std::unique_ptr<element_t>(new device_element_t<device_class>(name, classname, def_param)));
+ register_device(std::unique_ptr<element_t>(plib::palloc<device_element_t<device_class>>(name, classname, def_param)));
}
void register_device(std::unique_ptr<element_t> factory);
@@ -127,7 +120,7 @@ namespace netlist { namespace factory
std::unique_ptr<element_t> constructor_t(const pstring &name, const pstring &classname,
const pstring &def_param)
{
- return std::unique_ptr<element_t>(new device_element_t<T>(name, classname, def_param));
+ return std::unique_ptr<element_t>(plib::palloc<device_element_t<T>>(name, classname, def_param));
}
// -----------------------------------------------------------------------------
diff --git a/src/lib/netlist/nl_lists.h b/src/lib/netlist/nl_lists.h
index 2b378dadf71..9d35adf20ef 100644
--- a/src/lib/netlist/nl_lists.h
+++ b/src/lib/netlist/nl_lists.h
@@ -11,6 +11,8 @@
#define NLLISTS_H_
#include <atomic>
+#include <thread>
+#include <mutex>
#include "nl_config.h"
#include "plib/plists.h"
@@ -26,30 +28,24 @@ namespace netlist
//FIXME: move to an appropriate place
template<bool enabled_ = true>
- class pspin_lock
+ class pspin_mutex
{
public:
- pspin_lock() { }
- void acquire() noexcept{ while (m_lock.test_and_set(std::memory_order_acquire)) { } }
- void release() noexcept { m_lock.clear(std::memory_order_release); }
+ pspin_mutex() noexcept { }
+ void lock() noexcept{ while (m_lock.test_and_set(std::memory_order_acquire)) { } }
+ void unlock() noexcept { m_lock.clear(std::memory_order_release); }
private:
std::atomic_flag m_lock = ATOMIC_FLAG_INIT;
};
template<>
- class pspin_lock<false>
+ class pspin_mutex<false>
{
public:
- void acquire() const noexcept { }
- void release() const noexcept { }
+ void lock() const noexcept { }
+ void unlock() const noexcept { }
};
- #if HAS_OPENMP && USE_OPENMP
- using tqlock = pspin_lock<true>;
- #else
- using tqlock = pspin_lock<false>;
- #endif
-
template <class Element, class Time>
class timed_queue
{
@@ -58,6 +54,18 @@ namespace netlist
struct entry_t
{
+ entry_t() { }
+ entry_t(const Time &t, const Element &o) : m_exec_time(t), m_object(o) { }
+ entry_t(const entry_t &e) : m_exec_time(e.m_exec_time), m_object(e.m_object) { }
+ entry_t(entry_t &&e) : m_exec_time(e.m_exec_time), m_object(e.m_object) { }
+
+ entry_t& operator=(entry_t && other)
+ {
+ m_exec_time = other.m_exec_time;
+ m_object = other.m_object;
+ return *this;
+ }
+
Time m_exec_time;
Element m_object;
};
@@ -65,37 +73,35 @@ namespace netlist
timed_queue(unsigned list_size)
: m_list(list_size)
{
- m_lock.acquire();
clear();
- m_lock.release();
}
std::size_t capacity() const { return m_list.size(); }
bool empty() const { return (m_end == &m_list[1]); }
- void push(Element o, const Time t) noexcept
+ void push(entry_t &&e) noexcept
{
/* Lock */
- m_lock.acquire();
+ tqlock lck(m_lock);
entry_t * i = m_end;
- for (; t > (i - 1)->m_exec_time; --i)
+ while (e.m_exec_time > (i - 1)->m_exec_time)
{
- *(i) = *(i-1);
+ *(i) = std::move(*(i-1));
+ --i;
m_prof_sortmove.inc();
}
- *i = { t, o };
+ *i = std::move(e);
++m_end;
m_prof_call.inc();
- m_lock.release();
}
- entry_t pop() noexcept { return *(--m_end); }
- const entry_t &top() const noexcept { return *(m_end-1); }
+ entry_t pop() noexcept { return std::move(*(--m_end)); }
+ const entry_t &top() const noexcept { return std::move(*(m_end-1)); }
void remove(const Element &elem) noexcept
{
/* Lock */
- m_lock.acquire();
+ tqlock lck(m_lock);
for (entry_t * i = m_end - 1; i > &m_list[0]; i--)
{
if (i->m_object == elem)
@@ -103,24 +109,23 @@ namespace netlist
m_end--;
while (i < m_end)
{
- *i = *(i+1);
+ *i = std::move(*(i+1));
++i;
}
- m_lock.release();
return;
}
}
- m_lock.release();
}
void retime(const Element &elem, const Time t) noexcept
{
remove(elem);
- push(elem, t);
+ push(entry_t(t, elem));
}
void clear()
{
+ tqlock lck(m_lock);
m_end = &m_list[0];
/* put an empty element with maximum time into the queue.
* the insert algo above will run into this element and doesn't
@@ -137,8 +142,14 @@ namespace netlist
const entry_t & operator[](const std::size_t index) const { return m_list[ 1 + index]; }
private:
+ #if HAS_OPENMP && USE_OPENMP
+ using tqmutex = pspin_mutex<true>;
+ #else
+ using tqmutex = pspin_mutex<false>;
+ #endif
+ using tqlock = std::lock_guard<tqmutex>;
- tqlock m_lock;
+ tqmutex m_lock;
entry_t * m_end;
std::vector<entry_t> m_list;
diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp
index 46f6a92aed1..2fbc4d5f6f5 100644
--- a/src/lib/netlist/nl_setup.cpp
+++ b/src/lib/netlist/nl_setup.cpp
@@ -135,7 +135,7 @@ void setup_t::register_dippins_arr(const pstring &terms)
}
}
-pstring setup_t::objtype_as_str(detail::device_object_t &in) const
+pstring setup_t::termtype_as_str(detail::core_terminal_t &in) const
{
switch (in.type())
{
@@ -145,8 +145,6 @@ pstring setup_t::objtype_as_str(detail::device_object_t &in) const
return pstring("INPUT");
case terminal_t::OUTPUT:
return pstring("OUTPUT");
- case terminal_t::PARAM:
- return pstring("PARAM");
}
// FIXME: noreturn
log().fatal(MF_1_UNKNOWN_OBJECT_TYPE_1, static_cast<unsigned>(in.type()));
@@ -199,9 +197,9 @@ void setup_t::register_param(pstring name, param_t &param)
void setup_t::register_term(detail::core_terminal_t &term)
{
if (!m_terminals.insert({term.name(), &term}).second)
- log().fatal(MF_2_ADDING_1_2_TO_TERMINAL_LIST, objtype_as_str(term),
+ log().fatal(MF_2_ADDING_1_2_TO_TERMINAL_LIST, termtype_as_str(term),
term.name());
- log().debug("{1} {2}\n", objtype_as_str(term), term.name());
+ log().debug("{1} {2}\n", termtype_as_str(term), term.name());
}
void setup_t::register_link_arr(const pstring &terms)
@@ -340,12 +338,12 @@ detail::core_terminal_t *setup_t::find_terminal(const pstring &terminal_in, bool
}
detail::core_terminal_t *setup_t::find_terminal(const pstring &terminal_in,
- detail::device_object_t::type_t atype, bool required)
+ detail::core_terminal_t::type_t atype, bool required)
{
const pstring &tname = resolve_alias(terminal_in);
auto ret = m_terminals.find(tname);
/* look for default */
- if (ret == m_terminals.end() && atype == detail::device_object_t::OUTPUT)
+ if (ret == m_terminals.end() && atype == detail::core_terminal_t::OUTPUT)
{
/* look for ".Q" std output */
ret = m_terminals.find(tname + ".Q");
@@ -440,7 +438,6 @@ devices::nld_base_proxy *setup_t::get_a_d_proxy(detail::core_terminal_t &inp)
auto ret = new_proxy.get();
-#if 1
/* connect all existing terminals to new net */
if (inp.has_net())
@@ -455,13 +452,6 @@ devices::nld_base_proxy *setup_t::get_a_d_proxy(detail::core_terminal_t &inp)
inp.net().m_core_terms.clear(); // clear the list
}
ret->out().net().add_terminal(inp);
-#else
- if (inp.has_net())
- //fatalerror("logic inputs can only belong to one net!\n");
- merge_nets(ret->out().net(), inp.net());
- else
- ret->out().net().add_terminal(inp);
-#endif
netlist().register_dev(std::move(new_proxy));
return ret;
}
diff --git a/src/lib/netlist/nl_setup.h b/src/lib/netlist/nl_setup.h
index 06f70623ada..79a21a6815b 100644
--- a/src/lib/netlist/nl_setup.h
+++ b/src/lib/netlist/nl_setup.h
@@ -285,7 +285,7 @@ namespace netlist
std::unordered_map<pstring, detail::core_terminal_t *> m_terminals;
/* needed by proxy */
- detail::core_terminal_t *find_terminal(const pstring &outname_in, detail::device_object_t::type_t atype, bool required = true);
+ detail::core_terminal_t *find_terminal(const pstring &outname_in, detail::core_terminal_t::type_t atype, bool required = true);
private:
@@ -300,7 +300,7 @@ namespace netlist
bool connect_input_input(detail::core_terminal_t &t1, detail::core_terminal_t &t2);
// helpers
- pstring objtype_as_str(detail::device_object_t &in) const;
+ pstring termtype_as_str(detail::core_terminal_t &in) const;
devices::nld_base_proxy *get_d_a_proxy(detail::core_terminal_t &out);
devices::nld_base_proxy *get_a_d_proxy(detail::core_terminal_t &inp);
diff --git a/src/lib/netlist/nl_time.h b/src/lib/netlist/nl_time.h
index 4edc9524a43..6235c195172 100644
--- a/src/lib/netlist/nl_time.h
+++ b/src/lib/netlist/nl_time.h
@@ -45,82 +45,83 @@ namespace netlist
constexpr explicit ptime(const internal_type nom, const internal_type den) noexcept
: m_time(nom * (resolution / den)) { }
- ptime &operator=(const ptime rhs) { m_time = rhs.m_time; return *this; }
+ ptime &operator=(const ptime rhs) noexcept { m_time = rhs.m_time; return *this; }
- ptime &operator+=(const ptime &rhs) { m_time += rhs.m_time; return *this; }
- ptime &operator-=(const ptime &rhs) { m_time -= rhs.m_time; return *this; }
+ ptime &operator+=(const ptime &rhs) noexcept { m_time += rhs.m_time; return *this; }
+ ptime &operator-=(const ptime &rhs) noexcept { m_time -= rhs.m_time; return *this; }
- friend ptime operator-(ptime lhs, const ptime &rhs)
+ friend constexpr ptime operator-(const ptime &lhs, const ptime &rhs) noexcept
{
- lhs -= rhs;
- return lhs;
+ return ptime(lhs.m_time - rhs.m_time);
}
- friend ptime operator+(ptime lhs, const ptime &rhs)
+ friend constexpr ptime operator+(const ptime &lhs, const ptime &rhs) noexcept
{
- lhs += rhs;
- return lhs;
+ return ptime(lhs.m_time + rhs.m_time);
}
- friend ptime operator*(ptime lhs, const mult_type factor)
+ friend constexpr ptime operator*(const ptime &lhs, const mult_type factor) noexcept
{
- lhs.m_time *= static_cast<internal_type>(factor);
- return lhs;
+ return ptime(lhs.m_time * static_cast<internal_type>(factor));
}
- friend mult_type operator/(const ptime &lhs, const ptime &rhs)
+ friend constexpr mult_type operator/(const ptime &lhs, const ptime &rhs) noexcept
{
return static_cast<mult_type>(lhs.m_time / rhs.m_time);
}
- friend bool operator<(const ptime &lhs, const ptime &rhs)
+ friend constexpr bool operator<(const ptime &lhs, const ptime &rhs) noexcept
{
return (lhs.m_time < rhs.m_time);
}
- friend bool operator>(const ptime &lhs, const ptime &rhs)
+ friend constexpr bool operator>(const ptime &lhs, const ptime &rhs) noexcept
{
return (rhs < lhs);
}
- friend bool operator<=(const ptime &lhs, const ptime &rhs)
+ friend constexpr bool operator<=(const ptime &lhs, const ptime &rhs) noexcept
{
return !(lhs > rhs);
}
- friend bool operator>=(const ptime &lhs, const ptime &rhs)
+ friend constexpr bool operator>=(const ptime &lhs, const ptime &rhs) noexcept
{
return !(lhs < rhs);
}
- friend bool operator==(const ptime &lhs, const ptime &rhs)
+ friend constexpr bool operator==(const ptime &lhs, const ptime &rhs) noexcept
{
return lhs.m_time == rhs.m_time;
}
- friend bool operator!=(const ptime &lhs, const ptime &rhs)
+ friend constexpr bool operator!=(const ptime &lhs, const ptime &rhs) noexcept
{
return !(lhs == rhs);
}
- constexpr internal_type as_raw() const { return m_time; }
- constexpr double as_double() const { return static_cast<double>(m_time)
- / static_cast<double>(resolution); }
+ constexpr internal_type as_raw() const noexcept { return m_time; }
+ constexpr double as_double() const noexcept
+ {
+ return static_cast<double>(m_time)
+ / static_cast<double>(resolution);
+ }
// for save states ....
- internal_type *get_internaltype_ptr() { return &m_time; }
-
- static constexpr ptime from_nsec(const internal_type ns) { return ptime(ns, UINT64_C(1000000000)); }
- static constexpr ptime from_usec(const internal_type us) { return ptime(us, UINT64_C(1000000)); }
- static constexpr ptime from_msec(const internal_type ms) { return ptime(ms, UINT64_C(1000)); }
- static constexpr ptime from_hz(const internal_type hz) { return ptime(1 , hz); }
- static constexpr ptime from_raw(const internal_type raw) { return ptime(raw, resolution); }
- static constexpr ptime from_double(const double t) { return ptime(static_cast<internal_type>( t * static_cast<double>(resolution)), resolution); }
-
- static constexpr ptime zero() { return ptime(0, resolution); }
- static constexpr ptime quantum() { return ptime(1, resolution); }
- static constexpr ptime never() { return ptime(plib::numeric_limits<internal_type>::max(), resolution); }
+ internal_type *get_internaltype_ptr() noexcept { return &m_time; }
+
+ static constexpr ptime from_nsec(const internal_type ns) noexcept { return ptime(ns, UINT64_C(1000000000)); }
+ static constexpr ptime from_usec(const internal_type us) noexcept { return ptime(us, UINT64_C(1000000)); }
+ static constexpr ptime from_msec(const internal_type ms) noexcept { return ptime(ms, UINT64_C(1000)); }
+ static constexpr ptime from_hz(const internal_type hz) noexcept { return ptime(1 , hz); }
+ static constexpr ptime from_raw(const internal_type raw) noexcept { return ptime(raw); }
+ static constexpr ptime from_double(const double t) noexcept { return ptime(static_cast<internal_type>( t * static_cast<double>(resolution)), resolution); }
+
+ static constexpr ptime zero() noexcept { return ptime(0, resolution); }
+ static constexpr ptime quantum() noexcept { return ptime(1, resolution); }
+ static constexpr ptime never() noexcept { return ptime(plib::numeric_limits<internal_type>::max(), resolution); }
private:
+ constexpr explicit ptime(const internal_type time) : m_time(time) {}
internal_type m_time;
};
diff --git a/src/lib/netlist/plib/pconfig.h b/src/lib/netlist/plib/pconfig.h
index 9cd917ceb28..756130dd190 100644
--- a/src/lib/netlist/plib/pconfig.h
+++ b/src/lib/netlist/plib/pconfig.h
@@ -41,6 +41,9 @@ typedef __int128_t INT128;
#endif
#if defined(__GNUC__)
+#ifdef RESTRICT
+#undef RESTRICT
+#endif
#define RESTRICT __restrict__
#define ATTR_UNUSED __attribute__((__unused__))
#else
@@ -63,6 +66,42 @@ typedef __int128_t INT128;
// cut down delegate implementation
//============================================================
+/*
+ *
+ * NL_PMF_TYPE_GNUC_PMF
+ * Use standard pointer to member function syntax C++11
+ *
+ * NL_PMF_TYPE_GNUC_PMF_CONV
+ * Use gnu extension and convert the pmf to a function pointer.
+ * This is not standard compliant and needs
+ * -Wno-pmf-conversions to compile.
+ *
+ * NL_PMF_TYPE_INTERNAL
+ * Use the same approach as MAME for deriving the function pointer.
+ * This is compiler-dependent as well
+ *
+ * Benchmarks for ./nltool -c run -f src/mame/machine/nl_pong.cpp -t 10 -n pong_fast
+ *
+ * NL_PMF_TYPE_INTERNAL: 215% 215%
+ * NL_PMF_TYPE_GNUC_PMF: 163% 196%
+ * NL_PMF_TYPE_GNUC_PMF_CONV: 215% 215%
+ * NL_PMF_TYPE_VIRTUAL: 213% 209%
+ *
+ * The whole exercise was done to avoid virtual calls. In prior versions of
+ * netlist, the INTERNAL and GNUC_PMF_CONV approach provided significant improvement.
+ * Since than, "hot" was removed from functions declared as virtual.
+ * This may explain that the recent benchmarks show no difference at all.
+ *
+ */
+
+// This will be autodetected
+// #define PPMF_TYPE 1
+
+#define PPMF_TYPE_PMF 0
+#define PPMF_TYPE_GNUC_PMF_CONV 1
+#define PPMF_TYPE_INTERNAL 2
+
+
#if defined(__GNUC__)
/* does not work in versions over 4.7.x of 32bit MINGW */
#if defined(__MINGW32__) && !defined(__x86_64) && defined(__i386__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)))
@@ -87,6 +126,18 @@ typedef __int128_t INT128;
#define MEMBER_ABI
#endif
+#ifndef PPMF_TYPE
+ #if PHAS_PMF_INTERNAL
+ #define PPMF_TYPE PPMF_TYPE_INTERNAL
+ #else
+ #define PPMF_TYPE PPMF_TYPE_PMF
+ #endif
+#endif
+
+#if (PPMF_TYPE == PPMF_TYPE_GNUC_PMF_CONV)
+#pragma GCC diagnostic ignored "-Wpmf-conversions"
+#endif
+
namespace plib {
/*
* The following class was derived from the MAME delegate.h code.
@@ -108,18 +159,13 @@ namespace plib {
*reinterpret_cast<MemberFunctionType *>(this) = mftp;
}
- // binding helper
- template<typename FunctionType, typename ObjectType>
- FunctionType update_after_bind(ObjectType *object)
- {
- return reinterpret_cast<FunctionType>(
- convert_to_generic(reinterpret_cast<generic_class *>(object)));
- }
template<typename FunctionType, typename MemberFunctionType, typename ObjectType>
static FunctionType get_mfp(MemberFunctionType mftp, ObjectType *object)
{
mfp mfpo(mftp);
- return mfpo.update_after_bind<FunctionType>(object);
+ //return mfpo.update_after_bind<FunctionType>(object);
+ return reinterpret_cast<FunctionType>(
+ mfpo.convert_to_generic(reinterpret_cast<generic_class *>(object)));
}
private:
@@ -144,9 +190,89 @@ namespace plib {
// if odd, it's the byte offset into the vtable
int m_this_delta; // delta to apply to the 'this' pointer
};
+#endif
+#if (PPMF_TYPE == PPMF_TYPE_PMF)
+ template<typename R, typename... Targs>
+ class pmfp_base
+ {
+ public:
+ class generic_class;
+ using generic_function = R (generic_class::*)(Targs...);
+ pmfp_base() : m_func(nullptr) {}
+
+ template<typename MemberFunctionType, typename O>
+ void set_base(MemberFunctionType mftp, O *object)
+ {
+ using function_ptr = R (O::*)(Targs...);
+ function_ptr t = mftp;
+ m_func = reinterpret_cast<generic_function>(t);
+ }
+ template<typename O>
+ inline R call(O *obj, Targs... args) const
+ {
+ using function_ptr = R (O::*)(Targs...);
+ function_ptr t = reinterpret_cast<function_ptr>(m_func);
+ return (obj->*t)(std::forward<Targs>(args)...);
+ }
+ private:
+ generic_function m_func;
+ };
+
+#elif ((PPMF_TYPE == PPMF_TYPE_GNUC_PMF_CONV) || (PPMF_TYPE == PPMF_TYPE_INTERNAL))
+ template<typename R, typename... Targs>
+ class pmfp_base
+ {
+ public:
+ using generic_function = void (*)();
+
+ pmfp_base() : m_func(nullptr) {}
+
+ template<typename MemberFunctionType, typename O>
+ void set_base(MemberFunctionType mftp, O *object)
+ {
+ #if (PPMF_TYPE == PPMF_TYPE_INTERNAL)
+ using function_ptr = MEMBER_ABI R (*)(O *obj, Targs... args);
+ m_func = reinterpret_cast<generic_function>(plib::mfp::get_mfp<function_ptr>(mftp, object));
+ #elif (PPMF_TYPE == PPMF_TYPE_GNUC_PMF_CONV)
+ R (O::* pFunc)(Targs...) = mftp;
+ m_func = reinterpret_cast<generic_function>((object->*pFunc));
+ #endif
+ }
+ template<typename O>
+ inline R call(O *obj, Targs... args) const
+ {
+ using function_ptr = MEMBER_ABI R (*)(O *obj, Targs... args);
+ return (reinterpret_cast<function_ptr>(m_func))(obj, std::forward<Targs>(args)...);
+ }
+ private:
+ generic_function m_func;
+ };
#endif
+ template<typename R, typename... Targs>
+ class pmfp : public pmfp_base<R, Targs...>
+ {
+ public:
+ class generic_class;
+ pmfp() : pmfp_base<R, Targs...>(), m_obj(nullptr) {}
+
+ template<typename MemberFunctionType, typename O>
+ void set(MemberFunctionType mftp, O *object)
+ {
+ this->set_base(mftp, object);
+ m_obj = reinterpret_cast<generic_class *>(object);
+ }
+
+ inline R operator()(Targs... args) const
+ {
+ return this->call(m_obj, std::forward<Targs>(args)...);
+ }
+ private:
+ generic_class *m_obj;
+ };
+
+
}
#endif /* PCONFIG_H_ */
diff --git a/src/lib/netlist/plib/pfunction.cpp b/src/lib/netlist/plib/pfunction.cpp
index c0f3e18a4f2..4736d047bbd 100644
--- a/src/lib/netlist/plib/pfunction.cpp
+++ b/src/lib/netlist/plib/pfunction.cpp
@@ -6,6 +6,7 @@
*/
#include <cmath>
+#include <stack>
#include "pfunction.h"
#include "pfmtlog.h"
#include "putil.h"
@@ -13,13 +14,27 @@
namespace plib {
+void pfunction::compile(const std::vector<pstring> &inputs, const pstring expr)
+{
+ if (expr.startsWith("rpn:"))
+ compile_postfix(inputs, expr.substr(4));
+ else
+ compile_infix(inputs, expr);
+}
+
void pfunction::compile_postfix(const std::vector<pstring> &inputs, const pstring expr)
{
plib::pstring_vector_t cmds(expr, " ");
+ compile_postfix(inputs, cmds, expr);
+}
+
+void pfunction::compile_postfix(const std::vector<pstring> &inputs,
+ const std::vector<pstring> &cmds, const pstring expr)
+{
m_precompiled.clear();
int stk = 0;
- for (pstring &cmd : cmds)
+ for (const pstring &cmd : cmds)
{
rpn_inst rc;
if (cmd == "+")
@@ -66,6 +81,99 @@ void pfunction::compile_postfix(const std::vector<pstring> &inputs, const pstrin
throw plib::pexception(plib::pfmt("nld_function: stack count different to one on <{2}>")(expr));
}
+static int get_prio(pstring v)
+{
+ if (v == "(" || v == ")")
+ return 1;
+ else if (v.left(v.begin()+1) >= "a" && v.left(v.begin()+1) <= "z")
+ return 0;
+ else if (v == "*" || v == "/")
+ return 20;
+ else if (v == "+" || v == "-")
+ return 10;
+ else if (v == "^")
+ return 30;
+ else
+ return -1;
+}
+
+static pstring pop_check(std::stack<pstring> &stk, const pstring &expr)
+{
+ if (stk.size() == 0)
+ throw plib::pexception(plib::pfmt("nld_function: stack underflow during infix parsing of: <{1}>")(expr));
+ pstring res = stk.top();
+ stk.pop();
+ return res;
+}
+
+void pfunction::compile_infix(const std::vector<pstring> &inputs, const pstring expr)
+{
+ // Shunting-yard infix parsing
+ std::vector<pstring> sep = {"(", ")", ",", "*", "/", "+", "-", "^"};
+ plib::pstring_vector_t sexpr(expr.replace(" ",""), sep);
+ std::stack<pstring> opstk;
+ plib::pstring_vector_t postfix;
+
+ //printf("dbg: %s\n", expr.c_str());
+ for (unsigned i = 0; i < sexpr.size(); i++)
+ {
+ pstring &s = sexpr[i];
+ if (s=="(")
+ opstk.push(s);
+ else if (s==")")
+ {
+ pstring x = pop_check(opstk, expr);
+ while (x != "(")
+ {
+ postfix.push_back(x);
+ x = pop_check(opstk, expr);
+ }
+ if (opstk.size() > 0 && get_prio(opstk.top()) == 0)
+ postfix.push_back(pop_check(opstk, expr));
+ }
+ else if (s==",")
+ {
+ pstring x = pop_check(opstk, expr);
+ while (x != "(")
+ {
+ postfix.push_back(x);
+ x = pop_check(opstk, expr);
+ }
+ opstk.push(x);
+ }
+ else {
+ int p = get_prio(s);
+ if (p>0)
+ {
+ if (opstk.size() == 0)
+ opstk.push(s);
+ else
+ {
+ if (get_prio(opstk.top()) >= get_prio(s))
+ postfix.push_back(pop_check(opstk, expr));
+ opstk.push(s);
+ }
+ }
+ else if (p == 0) // Function or variable
+ {
+ if (sexpr[i+1] == "(")
+ opstk.push(s);
+ else
+ postfix.push_back(s);
+ }
+ else
+ postfix.push_back(s);
+ }
+ }
+ while (opstk.size() > 0)
+ {
+ postfix.push_back(opstk.top());
+ opstk.pop();
+ }
+ compile_postfix(inputs, postfix, expr);
+}
+
+
#define ST1 stack[ptr]
#define ST2 stack[ptr-1]
diff --git a/src/lib/netlist/plib/pfunction.h b/src/lib/netlist/plib/pfunction.h
index 2ad32106569..0f4960d4e1c 100644
--- a/src/lib/netlist/plib/pfunction.h
+++ b/src/lib/netlist/plib/pfunction.h
@@ -16,10 +16,10 @@
namespace plib {
//============================================================
- // function evaluation - reverse polish notation
+ // function evaluation
//============================================================
- /*! Class providing support for precompiled rpn expressions
+ /*! Class providing support for evaluating expressions
*
*/
class pfunction
@@ -47,12 +47,26 @@ namespace plib {
{
}
+ /*! Compile an expression
+ *
+ * @param inputs Vector of input variables, e.g. {"A","B"}
+ * @param expr infix or postfix expression. default is infix, postrix
+ * to be prefixed with rpn, e.g. "rpn:A B + 1.3 /"
+ */
+ void compile(const std::vector<pstring> &inputs, const pstring expr);
+
/*! Compile a rpn expression
*
* @param inputs Vector of input variables, e.g. {"A","B"}
* @param expr Reverse polish notation expression, e.g. "A B + 1.3 /"
*/
void compile_postfix(const std::vector<pstring> &inputs, const pstring expr);
+ /*! Compile an infix expression
+ *
+ * @param inputs Vector of input variables, e.g. {"A","B"}
+ * @param expr Infix expression, e.g. "(A+B)/1.3"
+ */
+ void compile_infix(const std::vector<pstring> &inputs, const pstring expr);
/*! Evaluate the expression
*
* @param values for input variables, e.g. {1.1, 2.2}
@@ -61,6 +75,10 @@ namespace plib {
double evaluate(const std::vector<double> &values);
private:
+
+ void compile_postfix(const std::vector<pstring> &inputs,
+ const std::vector<pstring> &cmds, const pstring expr);
+
std::vector<rpn_inst> m_precompiled; //!< precompiled expression
};
diff --git a/src/lib/netlist/plib/plists.h b/src/lib/netlist/plib/plists.h
index 37f4e2a1391..fd9aaa5e176 100644
--- a/src/lib/netlist/plib/plists.h
+++ b/src/lib/netlist/plib/plists.h
@@ -56,6 +56,7 @@ public:
template<typename... Args>
void emplace(const std::size_t index, Args&&... args)
{
+ // allocate on buffer
new (&m_buf[index]) C(std::forward<Args>(args)...);
}
diff --git a/src/lib/netlist/plib/pstring.cpp b/src/lib/netlist/plib/pstring.cpp
index 7d676f34c0d..baeace1edb9 100644
--- a/src/lib/netlist/plib/pstring.cpp
+++ b/src/lib/netlist/plib/pstring.cpp
@@ -6,17 +6,16 @@
*/
#include <cstring>
-//FIXME:: pstring should be locale free
-#include <cctype>
-#include <cstdlib>
-#include <cstdio>
#include <algorithm>
#include <stack>
+#include <cstdlib>
#include "pstring.h"
#include "palloc.h"
#include "plists.h"
+template <typename F> pstr_t pstring_t<F>::m_zero(0);
+
template<typename F>
pstring_t<F>::~pstring_t()
{
@@ -240,7 +239,7 @@ double pstring_t<F>::as_double(bool *error) const
if (error != nullptr)
*error = false;
- ret = strtod(c_str(), &e);
+ ret = std::strtod(c_str(), &e);
if (*e != 0)
if (error != nullptr)
*error = true;
@@ -256,9 +255,9 @@ long pstring_t<F>::as_long(bool *error) const
if (error != nullptr)
*error = false;
if (startsWith("0x"))
- ret = strtol(substr(2).c_str(), &e, 16);
+ ret = std::strtol(substr(2).c_str(), &e, 16);
else
- ret = strtol(c_str(), &e, 10);
+ ret = std::strtol(c_str(), &e, 10);
if (*e != 0)
if (error != nullptr)
*error = true;
@@ -416,8 +415,8 @@ static inline std::size_t countleadbits(std::size_t x)
template<typename F>
void pstring_t<F>::sfree(pstr_t *s)
{
- s->m_ref_count--;
- if (s->m_ref_count == 0 && s != &m_zero)
+ bool b = s->dec_and_check();
+ if ( b && s != &m_zero)
{
if (stk != nullptr)
{
@@ -472,8 +471,8 @@ void pstring_t<F>::resetmem()
template<typename F>
void pstring_t<F>::sfree(pstr_t *s)
{
- s->m_ref_count--;
- if (s->m_ref_count == 0 && s != &m_zero)
+ bool b = s->dec_and_check();
+ if ( b && s != &m_zero)
{
plib::pfree_array(((char *)s));
}
diff --git a/src/lib/netlist/plib/pstring.h b/src/lib/netlist/plib/pstring.h
index 999bd10ce6b..e3dd475175e 100644
--- a/src/lib/netlist/plib/pstring.h
+++ b/src/lib/netlist/plib/pstring.h
@@ -10,6 +10,7 @@
#include <cstdarg>
#include <cstddef>
#include <iterator>
+#include <exception>
#include "pconfig.h"
@@ -22,27 +23,24 @@
struct pstr_t
{
- //str_t() : m_ref_count(1), m_len(0) { m_str[0] = 0; }
- pstr_t(const std::size_t alen)
- {
- init(alen);
- }
+ pstr_t(const std::size_t alen) { init(alen); }
void init(const std::size_t alen)
{
- m_ref_count = 1;
- m_len = alen;
- m_str[0] = 0;
+ m_ref_count = 1;
+ m_len = alen;
+ m_str[0] = 0;
}
char *str() { return &m_str[0]; }
unsigned char *ustr() { return reinterpret_cast<unsigned char *>(&m_str[0]); }
std::size_t len() const { return m_len; }
- int m_ref_count;
+ void inc() { m_ref_count++; }
+ bool dec_and_check() { --m_ref_count; return m_ref_count == 0; }
private:
+ int m_ref_count;
std::size_t m_len;
char m_str[1];
};
-
template <typename F>
struct pstring_t
{
@@ -75,7 +73,8 @@ public:
pstring_t(C (&string)[N]) : m_ptr(&m_zero) {
static_assert(std::is_same<C, const mem_t>::value, "pstring constructor only accepts const mem_t");
static_assert(N>0,"pstring from array of length 0");
- //static_assert(string[N-1] == 0, "pstring constructor parameter not a string literal");
+ if (string[N-1] != 0)
+ throw std::exception();
init(string);
}
@@ -170,13 +169,6 @@ public:
const pstring_t ucase() const;
- // FIXME: do something with encoding
- // FIXME: belongs into derived class
- // This is only used in state saving to support "owners" whose name() function
- // returns char*.
- static pstring_t from_utf8(const mem_t *c) { return pstring_t(c, UTF8); }
- static pstring_t from_utf8(const pstring_t &c) { return c; }
-
static void resetmem();
protected:
@@ -185,13 +177,13 @@ protected:
private:
void init(const mem_t *string)
{
- m_ptr->m_ref_count++;
+ m_ptr->inc();
if (string != nullptr && *string != 0)
pcopy(string);
}
void init(const pstring_t &string)
{
- m_ptr->m_ref_count++;
+ m_ptr->inc();
pcopy(string);
}
@@ -206,7 +198,7 @@ private:
{
sfree(m_ptr);
m_ptr = from.m_ptr;
- m_ptr->m_ref_count++;
+ m_ptr->inc();
}
void pcat(const mem_t *s);
void pcat(const pstring_t &s);
@@ -217,8 +209,6 @@ private:
static pstr_t m_zero;
};
-template <typename F> pstr_t pstring_t<F>::m_zero(0);
-
struct pu8_traits
{
static const unsigned MAXCODELEN = 1; /* in memory units */
diff --git a/src/lib/netlist/plib/putil.cpp b/src/lib/netlist/plib/putil.cpp
index b21f945662c..7007c818384 100644
--- a/src/lib/netlist/plib/putil.cpp
+++ b/src/lib/netlist/plib/putil.cpp
@@ -62,7 +62,7 @@ namespace plib
}
}
- pstring_vector_t::pstring_vector_t(const pstring &str, const pstring_vector_t &onstrl)
+ pstring_vector_t::pstring_vector_t(const pstring &str, const std::vector<pstring> &onstrl)
: std::vector<pstring>()
{
pstring col = "";
diff --git a/src/lib/netlist/plib/putil.h b/src/lib/netlist/plib/putil.h
index 728a475dd28..e340acbd8ec 100644
--- a/src/lib/netlist/plib/putil.h
+++ b/src/lib/netlist/plib/putil.h
@@ -71,7 +71,7 @@ namespace plib
public:
pstring_vector_t() : std::vector<pstring>() { }
pstring_vector_t(const pstring &str, const pstring &onstr, bool ignore_empty = false);
- pstring_vector_t(const pstring &str, const pstring_vector_t &onstrl);
+ pstring_vector_t(const pstring &str, const std::vector<pstring> &onstrl);
};
}
diff --git a/src/lib/netlist/prg/nltool.cpp b/src/lib/netlist/prg/nltool.cpp
index a6513f260b9..f63369839ef 100644
--- a/src/lib/netlist/prg/nltool.cpp
+++ b/src/lib/netlist/prg/nltool.cpp
@@ -320,7 +320,15 @@ static void static_compile(tool_options_t &opts)
opts.opt_logs(),
opts.opt_defines(), opts.opt_rfolders());
- nt.solver()->create_solver_code(pout_strm);
+ plib::putf8_writer w(pout_strm);
+ std::map<pstring, pstring> mp;
+
+ nt.solver()->create_solver_code(mp);
+
+ for (auto &e : mp)
+ {
+ w.write(e.second);
+ }
nt.stop();
@@ -531,7 +539,7 @@ int main(int argc, char *argv[])
{
pout(
"nltool (netlist) 0.1\n"
- "Copyright (C) 2016 Couriersud\n"
+ "Copyright (C) 2017 Couriersud\n"
"License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>.\n"
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.\n\n"
diff --git a/src/lib/netlist/prg/nlwav.cpp b/src/lib/netlist/prg/nlwav.cpp
index 5a3fdbbfad0..8612469431e 100644
--- a/src/lib/netlist/prg/nlwav.cpp
+++ b/src/lib/netlist/prg/nlwav.cpp
@@ -1,13 +1,12 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
-#include <plib/poptions.h>
#include <cstdio>
#include <cstring>
#include "plib/pstring.h"
#include "plib/plists.h"
#include "plib/pstream.h"
+#include "plib/poptions.h"
#include "nl_setup.h"
-#include <memory>
class nlwav_options_t : public plib::options
{
@@ -143,10 +142,10 @@ private:
static void convert()
{
- plib::postream *fo = (opts.opt_out() == "-" ? &pout_strm : new plib::pofilestream(opts.opt_out()));
- plib::pistream *fin = (opts.opt_inp() == "-" ? &pin_strm : new plib::pifilestream(opts.opt_inp()));
+ plib::postream *fo = (opts.opt_out() == "-" ? &pout_strm : plib::palloc<plib::pofilestream>(opts.opt_out()));
+ plib::pistream *fin = (opts.opt_inp() == "-" ? &pin_strm : plib::palloc<plib::pifilestream>(opts.opt_inp()));
plib::putf8_reader reader(*fin);
- wav_t *wo = new wav_t(*fo, 48000);
+ wav_t *wo = plib::palloc<wav_t>(*fo, 48000U);
double dt = 1.0 / static_cast<double>(wo->sample_rate());
double ct = dt;
@@ -213,11 +212,11 @@ static void convert()
//printf("%f %f\n", t, v);
#endif
}
- delete wo;
+ plib::pfree(wo);
if (opts.opt_inp() != "-")
- delete fin;
+ plib::pfree(fin);
if (opts.opt_out() != "-")
- delete fo;
+ plib::pfree(fo);
if (!opts.opt_quiet())
{
@@ -256,7 +255,7 @@ int main(int argc, char *argv[])
{
pout(
"nlwav (netlist) 0.1\n"
- "Copyright (C) 2016 Couriersud\n"
+ "Copyright (C) 2017 Couriersud\n"
"License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>.\n"
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.\n\n"
diff --git a/src/lib/netlist/solver/nld_matrix_solver.cpp b/src/lib/netlist/solver/nld_matrix_solver.cpp
index 051fa10a253..71950174a5a 100644
--- a/src/lib/netlist/solver/nld_matrix_solver.cpp
+++ b/src/lib/netlist/solver/nld_matrix_solver.cpp
@@ -91,11 +91,6 @@ matrix_solver_t::matrix_solver_t(netlist_t &anetlist, const pstring &name,
matrix_solver_t::~matrix_solver_t()
{
- for (unsigned k = 0; k < m_terms.size(); k++)
- {
- plib::pfree(m_terms[k]);
- }
-
}
void matrix_solver_t::setup_base(analog_net_t::list_t &nets)
@@ -109,7 +104,7 @@ void matrix_solver_t::setup_base(analog_net_t::list_t &nets)
for (auto & net : nets)
{
m_nets.push_back(net);
- m_terms.push_back(plib::palloc<terms_for_net_t>());
+ m_terms.push_back(plib::make_unique<terms_for_net_t>());
m_rails_temp.push_back(plib::palloc<terms_for_net_t>());
}
@@ -164,7 +159,6 @@ void matrix_solver_t::setup_base(analog_net_t::list_t &nets)
}
break;
case terminal_t::OUTPUT:
- case terminal_t::PARAM:
log().fatal(MF_1_UNHANDLED_ELEMENT_1_FOUND,
p->name());
break;
@@ -242,7 +236,7 @@ void matrix_solver_t::setup_matrix()
/* create a list of non zero elements. */
for (unsigned k = 0; k < iN; k++)
{
- terms_for_net_t * t = m_terms[k];
+ terms_for_net_t * t = m_terms[k].get();
/* pretty brutal */
int *other = t->connected_net_idx();
@@ -264,7 +258,7 @@ void matrix_solver_t::setup_matrix()
*/
for (unsigned k = 0; k < iN; k++)
{
- terms_for_net_t * t = m_terms[k];
+ terms_for_net_t * t = m_terms[k].get();
/* pretty brutal */
int *other = t->connected_net_idx();
@@ -294,9 +288,9 @@ void matrix_solver_t::setup_matrix()
* This should reduce cache misses ...
*/
- bool **touched = new bool*[iN];
+ bool **touched = plib::palloc_array<bool *>(iN);
for (unsigned k=0; k<iN; k++)
- touched[k] = new bool[iN];
+ touched[k] = plib::palloc_array<bool>(iN);
for (unsigned k = 0; k < iN; k++)
{
@@ -354,8 +348,8 @@ void matrix_solver_t::setup_matrix()
}
for (unsigned k=0; k<iN; k++)
- delete [] touched[k];
- delete [] touched;
+ plib::pfree_array(touched[k]);
+ plib::pfree_array(touched);
}
void matrix_solver_t::update_inputs()
@@ -499,7 +493,7 @@ netlist_time matrix_solver_t::compute_next_timestep(const double cur_ts)
for (std::size_t k = 0, iN=m_terms.size(); k < iN; k++)
{
analog_net_t *n = m_nets[k];
- terms_for_net_t *t = m_terms[k];
+ terms_for_net_t *t = m_terms[k].get();
const nl_double DD_n = (n->Q_Analog() - t->m_last_V);
const nl_double hn = cur_ts;
@@ -548,12 +542,12 @@ void matrix_solver_t::log_stats()
log().verbose(" {1:6.3} average newton raphson loops",
static_cast<double>(this->m_stat_newton_raphson) / static_cast<double>(this->m_stat_vsolver_calls));
log().verbose(" {1:10} invocations ({2:6.0} Hz) {3:10} gs fails ({4:6.2} %) {5:6.3} average",
- this->m_stat_calculations(),
- static_cast<double>(this->m_stat_calculations()) / this->netlist().time().as_double(),
- this->m_iterative_fail(),
- 100.0 * static_cast<double>(this->m_iterative_fail())
- / static_cast<double>(this->m_stat_calculations()),
- static_cast<double>(this->m_iterative_total()) / static_cast<double>(this->m_stat_calculations()));
+ this->m_stat_calculations,
+ static_cast<double>(this->m_stat_calculations) / this->netlist().time().as_double(),
+ this->m_iterative_fail,
+ 100.0 * static_cast<double>(this->m_iterative_fail)
+ / static_cast<double>(this->m_stat_calculations),
+ static_cast<double>(this->m_iterative_total) / static_cast<double>(this->m_stat_calculations));
}
}
diff --git a/src/lib/netlist/solver/nld_matrix_solver.h b/src/lib/netlist/solver/nld_matrix_solver.h
index fc7ab7fcbdb..e5f7bcf38b1 100644
--- a/src/lib/netlist/solver/nld_matrix_solver.h
+++ b/src/lib/netlist/solver/nld_matrix_solver.h
@@ -44,14 +44,14 @@ public:
void add(terminal_t *term, int net_other, bool sorted);
- inline std::size_t count() { return m_terms.size(); }
+ inline std::size_t count() const { return m_terms.size(); }
inline terminal_t **terms() { return m_terms.data(); }
inline int *connected_net_idx() { return m_connected_net_idx.data(); }
inline nl_double *gt() { return m_gt.data(); }
inline nl_double *go() { return m_go.data(); }
inline nl_double *Idr() { return m_Idr.data(); }
- inline nl_double **connected_net_V() { return m_connected_net_V.data(); }
+ inline nl_double * const *connected_net_V() const { return m_connected_net_V.data(); }
void set_pointers();
@@ -135,9 +135,9 @@ public:
virtual void log_stats();
- virtual void create_solver_code(plib::putf8_fmt_writer &strm)
+ virtual std::pair<pstring, pstring> create_solver_code()
{
- strm.writeline(plib::pfmt("/* {1} doesn't support static compile */"));
+ return std::pair<pstring, pstring>("", plib::pfmt("/* {1} doesn't support static compile */"));
}
protected:
@@ -161,7 +161,7 @@ protected:
template <typename T>
void build_LE_RHS();
- std::vector<terms_for_net_t *> m_terms;
+ std::vector<std::unique_ptr<terms_for_net_t>> m_terms;
std::vector<analog_net_t *> m_nets;
std::vector<std::unique_ptr<proxied_analog_output_t>> m_inps;
@@ -226,12 +226,14 @@ void matrix_solver_t::build_LE_A()
const unsigned iN = child.N();
for (unsigned k = 0; k < iN; k++)
{
+ terms_for_net_t *terms = m_terms[k].get();
+
for (unsigned i=0; i < iN; i++)
child.A(k,i) = 0.0;
- const std::size_t terms_count = m_terms[k]->count();
- const std::size_t railstart = m_terms[k]->m_railstart;
- const nl_double * RESTRICT gt = m_terms[k]->gt();
+ const std::size_t terms_count = terms->count();
+ const std::size_t railstart = terms->m_railstart;
+ const nl_double * const RESTRICT gt = terms->gt();
{
nl_double akk = 0.0;
@@ -241,8 +243,8 @@ void matrix_solver_t::build_LE_A()
child.A(k,k) = akk;
}
- const nl_double * RESTRICT go = m_terms[k]->go();
- const int * RESTRICT net_other = m_terms[k]->connected_net_idx();
+ const nl_double * const RESTRICT go = terms->go();
+ int * RESTRICT net_other = terms->connected_net_idx();
for (std::size_t i = 0; i < railstart; i++)
child.A(k,net_other[i]) -= go[i];
@@ -262,8 +264,8 @@ void matrix_solver_t::build_LE_RHS()
nl_double rhsk_b = 0.0;
const std::size_t terms_count = m_terms[k]->count();
- const nl_double * RESTRICT go = m_terms[k]->go();
- const nl_double * RESTRICT Idr = m_terms[k]->Idr();
+ const nl_double * const RESTRICT go = m_terms[k]->go();
+ const nl_double * const RESTRICT Idr = m_terms[k]->Idr();
const nl_double * const * RESTRICT other_cur_analog = m_terms[k]->connected_net_V();
for (std::size_t i = 0; i < terms_count; i++)
diff --git a/src/lib/netlist/solver/nld_ms_direct.h b/src/lib/netlist/solver/nld_ms_direct.h
index a5ee5bbf8c1..e7f89a57e67 100644
--- a/src/lib/netlist/solver/nld_ms_direct.h
+++ b/src/lib/netlist/solver/nld_ms_direct.h
@@ -200,7 +200,7 @@ void matrix_solver_direct_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
/* add RHS element */
for (unsigned k = 0; k < N(); k++)
{
- terms_for_net_t * t = m_terms[k];
+ terms_for_net_t * t = m_terms[k].get();
if (!plib::container::contains(t->m_nzrd, N()))
t->m_nzrd.push_back(N());
diff --git a/src/lib/netlist/solver/nld_ms_gcr.h b/src/lib/netlist/solver/nld_ms_gcr.h
index 853cc34d39c..11d71c531fa 100644
--- a/src/lib/netlist/solver/nld_ms_gcr.h
+++ b/src/lib/netlist/solver/nld_ms_gcr.h
@@ -52,7 +52,7 @@ public:
virtual void vsetup(analog_net_t::list_t &nets) override;
virtual unsigned vsolve_non_dynamic(const bool newton_raphson) override;
- virtual void create_solver_code(plib::putf8_fmt_writer &strm) override;
+ virtual std::pair<pstring, pstring> create_solver_code() override;
private:
@@ -60,15 +60,7 @@ private:
using extsolver = void (*)(double * RESTRICT m_A, double * RESTRICT RHS);
- pstring static_compile_name()
- {
- plib::postringstream t;
- plib::putf8_fmt_writer w(t);
- csc_private(w);
- std::hash<pstring> h;
-
- return plib::pfmt("nl_gcr_{1:x}_{2}")(h( t.str() ))(mat.nz_num);
- }
+ pstring static_compile_name();
unsigned m_dim;
std::vector<unsigned> m_term_cr[storage_N];
@@ -96,7 +88,7 @@ void matrix_solver_GCR_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
bool touched[storage_N][storage_N] = { { false } };
for (unsigned k = 0; k < iN; k++)
{
- for (auto & j : this->m_terms[k]->m_nz)
+ for (auto &j : this->m_terms[k]->m_nz)
touched[k][j] = true;
}
@@ -104,32 +96,21 @@ void matrix_solver_GCR_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
unsigned ops = 0;
- const bool static_compile = false;
for (unsigned k = 0; k < iN; k++)
{
ops++; // 1/A(k,k)
- if (static_compile) printf("const double fd%d = 1.0 / A(%d,%d); \n", k, k, k);
for (unsigned row = k + 1; row < iN; row++)
{
if (touched[row][k])
{
ops++;
fc++;
- if (static_compile) printf(" const double f%d = -fd%d * A(%d,%d); \n", fc, k, row, k);
for (unsigned col = k + 1; col < iN; col++)
if (touched[k][col])
{
- if (touched[row][col])
- {
- if (static_compile) printf(" A(%d,%d) += f%d * A(%d,%d); \n", row, col, fc, k, col);
- } else
- {
- if (static_compile) printf(" A(%d,%d) = f%d * A(%d,%d); \n", row, col, fc, k, col);
- }
touched[row][col] = true;
ops += 2;
}
- if (static_compile) printf(" RHS(%d) += f%d * RHS(%d); \n", row, fc, k);
}
}
}
@@ -180,7 +161,7 @@ void matrix_solver_GCR_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
if (m_proc != nullptr)
this->log().verbose("External static solver {1} found ...", symname);
else
- this->log().verbose("External static solver {1} not found ...", symname);
+ this->log().warning("External static solver {1} not found ...", symname);
}
}
@@ -198,7 +179,7 @@ void matrix_solver_GCR_t<m_N, storage_N>::csc_private(plib::putf8_fmt_writer &st
unsigned pi = mat.diag[i];
//const nl_double f = 1.0 / m_A[pi++];
- strm("const double f{1} = 1.0 / m_A[{2}];", i,pi);
+ strm("const double f{1} = 1.0 / m_A[{2}];\n", i, pi);
pi++;
const unsigned piie = mat.ia[i+1];
@@ -211,7 +192,7 @@ void matrix_solver_GCR_t<m_N, storage_N>::csc_private(plib::putf8_fmt_writer &st
pj++;
//const nl_double f1 = - m_A[pj++] * f;
- strm("\tconst double f{1}_{2} = -f{3} * m_A[{4}];", i, j, i, pj);
+ strm("\tconst double f{1}_{2} = -f{3} * m_A[{4}];\n", i, j, i, pj);
pj++;
// subtract row i from j */
@@ -220,25 +201,40 @@ void matrix_solver_GCR_t<m_N, storage_N>::csc_private(plib::putf8_fmt_writer &st
while (mat.ja[pj] < mat.ja[pii])
pj++;
//m_A[pj++] += m_A[pii++] * f1;
- strm("\tm_A[{1}] += m_A[{2}] * f{3}_{4};", pj, pii, i, j);
+ strm("\tm_A[{1}] += m_A[{2}] * f{3}_{4};\n", pj, pii, i, j);
pj++; pii++;
}
//RHS[j] += f1 * RHS[i];
- strm("\tRHS[{1}] += f{2}_{3} * RHS[{4}];", j, i, j, i);
+ strm("\tRHS[{1}] += f{2}_{3} * RHS[{4}];\n", j, i, j, i);
}
}
}
}
+
+template <unsigned m_N, unsigned storage_N>
+pstring matrix_solver_GCR_t<m_N, storage_N>::static_compile_name()
+{
+ plib::postringstream t;
+ plib::putf8_fmt_writer w(t);
+ csc_private(w);
+ std::hash<pstring> h;
+
+ return plib::pfmt("nl_gcr_{1:x}_{2}")(h( t.str() ))(mat.nz_num);
+}
+
template <unsigned m_N, unsigned storage_N>
-void matrix_solver_GCR_t<m_N, storage_N>::create_solver_code(plib::putf8_fmt_writer &strm)
+std::pair<pstring, pstring> matrix_solver_GCR_t<m_N, storage_N>::create_solver_code()
{
- //const unsigned iN = N();
+ plib::postringstream t;
+ plib::putf8_fmt_writer strm(t);
+ pstring name = static_compile_name();
- strm.writeline(plib::pfmt("extern \"C\" void {1}(double * _restrict m_A, double * _restrict RHS)")(static_compile_name()));
- strm.writeline("{");
+ strm.writeline(plib::pfmt("extern \"C\" void {1}(double * __restrict m_A, double * __restrict RHS)\n")(name));
+ strm.writeline("{\n");
csc_private(strm);
- strm.writeline("}");
+ strm.writeline("}\n");
+ return std::pair<pstring, pstring>(name, t.str());
}
@@ -255,7 +251,7 @@ unsigned matrix_solver_GCR_t<m_N, storage_N>::vsolve_non_dynamic(const bool newt
for (unsigned k = 0; k < iN; k++)
{
- terms_for_net_t *t = this->m_terms[k];
+ terms_for_net_t *t = this->m_terms[k].get();
nl_double gtot_t = 0.0;
nl_double RHS_t = 0.0;
@@ -265,7 +261,9 @@ unsigned matrix_solver_GCR_t<m_N, storage_N>::vsolve_non_dynamic(const bool newt
const nl_double * const RESTRICT go = t->go();
const nl_double * const RESTRICT Idr = t->Idr();
const nl_double * const * RESTRICT other_cur_analog = t->connected_net_V();
+ const unsigned * const RESTRICT tcr = m_term_cr[k].data();
+#if 1
#if (0 ||NL_USE_SSE)
__m128d mg = _mm_set_pd(0.0, 0.0);
__m128d mr = _mm_set_pd(0.0, 0.0);
@@ -298,11 +296,26 @@ unsigned matrix_solver_GCR_t<m_N, storage_N>::vsolve_non_dynamic(const bool newt
m_A[mat.diag[k]] = gtot_t;
for (unsigned i = 0; i < railstart; i++)
+ m_A[tcr[i]] -= go[i];
+ }
+#else
+ for (std::size_t i = 0; i < railstart; i++)
{
- const unsigned pi = m_term_cr[k][i];
- m_A[pi] -= go[i];
+ m_A[tcr[i]] -= go[i];
+ gtot_t = gtot_t + gt[i];
+ RHS_t = RHS_t + Idr[i];
}
+
+ for (std::size_t i = railstart; i < term_count; i++)
+ {
+ RHS_t += (Idr[i] + go[i] * *other_cur_analog[i]);
+ gtot_t += gt[i];
+ }
+
+ RHS[k] = RHS_t;
+ m_A[mat.diag[k]] += gtot_t;
}
+#endif
mat.ia[iN] = mat.nz_num;
/* now solve it */
diff --git a/src/lib/netlist/solver/nld_ms_gmres.h b/src/lib/netlist/solver/nld_ms_gmres.h
index 0c5a5e6228f..baa61723cf9 100644
--- a/src/lib/netlist/solver/nld_ms_gmres.h
+++ b/src/lib/netlist/solver/nld_ms_gmres.h
@@ -81,7 +81,7 @@ void matrix_solver_GMRES_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
for (unsigned k=0; k<iN; k++)
{
- terms_for_net_t * RESTRICT row = this->m_terms[k];
+ terms_for_net_t * RESTRICT row = this->m_terms[k].get();
mat.ia[k] = nz;
for (unsigned j=0; j<row->m_nz.size(); j++)
diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp
index 629c7c0173e..cfdf411c553 100644
--- a/src/lib/netlist/solver/nld_solver.cpp
+++ b/src/lib/netlist/solver/nld_solver.cpp
@@ -10,23 +10,24 @@
*/
#if 0
-#pragma GCC optimize "-ffast-math"
-#pragma GCC optimize "-fstrict-aliasing"
-#pragma GCC optimize "-ftree-vectorizer-verbose=2"
-#pragma GCC optimize "-fopt-info-vec"
-#pragma GCC optimize "-fopt-info-vec-missed"
-//#pragma GCC optimize "-ftree-parallelize-loops=4"
-#pragma GCC optimize "-funroll-loops"
-#pragma GCC optimize "-funswitch-loops"
-#pragma GCC optimize "-fvariable-expansion-in-unroller"
-#pragma GCC optimize "-funsafe-loop-optimizations"
-#pragma GCC optimize "-fvect-cost-model"
-#pragma GCC optimize "-fvariable-expansion-in-unroller"
-#pragma GCC optimize "-ftree-loop-if-convert-stores"
-#pragma GCC optimize "-ftree-loop-distribution"
-#pragma GCC optimize "-ftree-loop-im"
-#pragma GCC optimize "-ftree-loop-ivcanon"
-#pragma GCC optimize "-fivopts"
+#pragma GCC optimize "fast-math"
+#pragma GCC optimize "strict-aliasing"
+#pragma GCC optimize "tree-vectorize"
+#pragma GCC optimize "tree-vectorizer-verbose=7"
+#pragma GCC optimize "opt-info-vec"
+#pragma GCC optimize "opt-info-vec-missed"
+//#pragma GCC optimize "tree-parallelize-loops=4"
+#pragma GCC optimize "unroll-loops"
+#pragma GCC optimize "unswitch-loops"
+#pragma GCC optimize "variable-expansion-in-unroller"
+#pragma GCC optimize "unsafe-loop-optimizations"
+#pragma GCC optimize "vect-cost-model"
+#pragma GCC optimize "variable-expansion-in-unroller"
+#pragma GCC optimize "tree-loop-if-convert-stores"
+#pragma GCC optimize "tree-loop-distribution"
+#pragma GCC optimize "tree-loop-im"
+#pragma GCC optimize "tree-loop-ivcanon"
+#pragma GCC optimize "ivopts"
#endif
#include <iostream>
@@ -297,12 +298,12 @@ void NETLIB_NAME(solver)::post_start()
switch (net_count)
{
-#if 1
+#if 0
case 1:
- ms = create_solver<1,1>(1, use_specific);
+ ms = create_solver<1,1>(1, false);
break;
case 2:
- ms = create_solver<2,2>(2, use_specific);
+ ms = create_solver<2,2>(2, false);
break;
case 3:
ms = create_solver<3,3>(3, use_specific);
@@ -322,6 +323,9 @@ void NETLIB_NAME(solver)::post_start()
case 8:
ms = create_solver<8,8>(8, use_specific);
break;
+ case 9:
+ ms = create_solver<9,9>(9, use_specific);
+ break;
case 10:
ms = create_solver<10,10>(10, use_specific);
break;
@@ -396,11 +400,13 @@ void NETLIB_NAME(solver)::post_start()
}
}
-void NETLIB_NAME(solver)::create_solver_code(plib::postream &strm)
+void NETLIB_NAME(solver)::create_solver_code(std::map<pstring, pstring> &mp)
{
- plib::putf8_fmt_writer w(strm);
for (auto & s : m_mat_solvers)
- s->create_solver_code(w);
+ {
+ auto r = s->create_solver_code();
+ mp[r.first] = r.second; // automatically overwrites identical names
+ }
}
NETLIB_DEVICE_IMPL(solver)
diff --git a/src/lib/netlist/solver/nld_solver.h b/src/lib/netlist/solver/nld_solver.h
index 5430fc4ce28..d982b81ec0c 100644
--- a/src/lib/netlist/solver/nld_solver.h
+++ b/src/lib/netlist/solver/nld_solver.h
@@ -8,6 +8,8 @@
#ifndef NLD_SOLVER_H_
#define NLD_SOLVER_H_
+#include <map>
+
#include "nl_setup.h"
#include "nl_base.h"
#include "plib/pstream.h"
@@ -79,7 +81,7 @@ NETLIB_OBJECT(solver)
inline nl_double gmin() { return m_gmin(); }
- void create_solver_code(plib::postream &strm);
+ void create_solver_code(std::map<pstring, pstring> &mp);
NETLIB_UPDATEI();
NETLIB_RESETI();
diff --git a/src/lib/util/unicode.cpp b/src/lib/util/unicode.cpp
index 8f5295de4af..b48cef44c79 100644
--- a/src/lib/util/unicode.cpp
+++ b/src/lib/util/unicode.cpp
@@ -15,7 +15,7 @@
#define UTF8PROC_DLLEXPORT
#endif
-#include "utf8proc/utf8proc.h"
+#include <utf8proc.h>
#include <codecvt>
#include <locale>
diff --git a/src/mame/drivers/aristmk5.cpp b/src/mame/drivers/aristmk5.cpp
index 98bbd6727d6..29617a3f2f5 100644
--- a/src/mame/drivers/aristmk5.cpp
+++ b/src/mame/drivers/aristmk5.cpp
@@ -249,7 +249,6 @@ private:
emu_timer * m_mk5_2KHz_timer;
emu_timer * m_mk5_VSYNC_timer;
emu_timer * m_spi_timer;
- uint8_t m_ext_latch;
uint8_t m_sram_bank;
uint8_t m_ldor_shift_reg;
uint8_t m_hopper_test;
@@ -273,32 +272,32 @@ WRITE8_MEMBER(aristmk5_state::spi_mux_w)
switch (m_spi_mux)
{
- case 0: // Test
- case 3: // not used
+ case 0: // Test
+ case 3: // not used
break;
- case 1: // Top box lamps
+ case 1: // Top box lamps
break;
- case 2: // Mechanical meters
+ case 2: // Mechanical meters
for(int i=0; i<4; i++)
- output().set_lamp_value(32 + i, BIT(m_spi_data[m_spi_mux], 1 + i)); // Tower Lamps
+ output().set_lamp_value(32 + i, BIT(m_spi_data[m_spi_mux], 1 + i)); // Tower Lamps
break;
- case 4: // Door inputs
+ case 4: // Door inputs
m_spi_data[m_spi_mux] = m_p1->read();
break;
- case 5: // Door outputs
+ case 5: // Door outputs
for(int i=0; i<32; i++)
output().set_lamp_value(i, BIT(m_spi_data[m_spi_mux], i));
break;
-
- case 6: // Main board slow I/O
+
+ case 6: // Main board slow I/O
m_spi_data[m_spi_mux] = m_p2->read() & ~((data & 0x80) ? 0 : 0x100);
break;
- case 7: // Main board security registers
+ case 7: // Main board security registers
break;
}
}
@@ -314,7 +313,7 @@ WRITE8_MEMBER(aristmk5_state::spi_data_w)
READ8_MEMBER(aristmk5_state::spi_data_r)
{
- return m_spi_latch;
+ return m_spi_latch;
}
READ8_MEMBER(aristmk5_state::spi_int_ack_r)
@@ -628,7 +627,7 @@ static ADDRESS_MAP_START( aristmk5_map, AS_PROGRAM, 32, aristmk5_state )
AM_RANGE(0x03010580, 0x03010583) AM_READ_PORT("P3")
AM_RANGE(0x03010600, 0x0301061f) AM_DEVREADWRITE8("uart_1a", ins8250_uart_device, ins8250_r, ins8250_w, 0x000000ff)
AM_RANGE(0x03010680, 0x0301069f) AM_DEVREADWRITE8("uart_1b", ins8250_uart_device, ins8250_r, ins8250_w, 0x000000ff)
-
+
AM_RANGE(0x03010700, 0x03010703) AM_READ_PORT("P6")
AM_RANGE(0x03010800, 0x03010803) AM_READ8(eeprom_r, 0x000000ff)
AM_RANGE(0x03010810, 0x03010813) AM_DEVREADWRITE("watchdog", watchdog_timer_device, reset32_r, reset32_w) //MK-5 specific, watchdog
@@ -693,7 +692,7 @@ static ADDRESS_MAP_START( aristmk5_drame_map, AS_PROGRAM, 32, aristmk5_state )
AM_RANGE(0x03014000, 0x0301401f) AM_DEVREADWRITE8("uart_2a", ins8250_uart_device, ins8250_r, ins8250_w, 0x000000ff)
AM_RANGE(0x03014020, 0x0301403f) AM_DEVREADWRITE8("uart_2b", ins8250_uart_device, ins8250_r, ins8250_w, 0x000000ff)
-
+
AM_IMPORT_FROM(aristmk5_map)
ADDRESS_MAP_END
@@ -846,46 +845,46 @@ static INPUT_PORTS_START( aristmk5 )
PORT_CONFSETTING( 0x03, "Game Mode" )
PORT_START("P1")
- PORT_BIT(0x00000001, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_Q)
- PORT_BIT(0x00000002, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_W)
- PORT_BIT(0x00000004, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_E)
- PORT_BIT(0x00000008, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_R)
- PORT_BIT(0x00000010, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_T)
- PORT_BIT(0x00000020, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_Y)
- PORT_BIT(0x00000040, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_U)
- PORT_BIT(0x00000080, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_I)
- PORT_BIT(0x00000100, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_A)
- PORT_BIT(0x00000200, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_S)
- PORT_BIT(0x00000400, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_D)
- PORT_BIT(0x00000800, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_F)
- PORT_BIT(0x00001000, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_G)
- PORT_BIT(0x00002000, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_H)
- PORT_BIT(0x00004000, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_J)
- PORT_BIT(0x00008000, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_K)
+ PORT_BIT(0x00000001, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_Q)
+ PORT_BIT(0x00000002, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_W)
+ PORT_BIT(0x00000004, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_E)
+ PORT_BIT(0x00000008, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_R)
+ PORT_BIT(0x00000010, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_T)
+ PORT_BIT(0x00000020, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_Y)
+ PORT_BIT(0x00000040, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_U)
+ PORT_BIT(0x00000080, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_I)
+ PORT_BIT(0x00000100, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_A)
+ PORT_BIT(0x00000200, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_S)
+ PORT_BIT(0x00000400, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_D)
+ PORT_BIT(0x00000800, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_F)
+ PORT_BIT(0x00001000, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_G)
+ PORT_BIT(0x00002000, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_H)
+ PORT_BIT(0x00004000, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_J)
+ PORT_BIT(0x00008000, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_K)
PORT_BIT(0x00ff0000, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_START("P2")
- PORT_BIT(0x00000001, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_V) PORT_NAME("Reset Key")
+ PORT_BIT(0x00000001, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_V) PORT_NAME("Reset Key")
PORT_BIT(0x00000002, IP_ACTIVE_HIGH, IPT_SERVICE)
PORT_BIT(0x00000004, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_BIT(0x00000008, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_BIT(0x00000010, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_BIT(0x00000020, IP_ACTIVE_HIGH, IPT_UNUSED)
- PORT_BIT(0x00000040, IP_ACTIVE_HIGH, IPT_OTHER) // Hopper full
- PORT_BIT(0x00000080, IP_ACTIVE_HIGH, IPT_OTHER) // Hopper empty
- PORT_BIT(0x00000100, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_M) PORT_TOGGLE PORT_NAME("Main door optical sensor")
- PORT_BIT(0x0000fe00, IP_ACTIVE_HIGH, IPT_UNUSED) // Unused optical security sensors
- PORT_BIT(0x00010000, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_L) PORT_TOGGLE PORT_NAME("Logic door")
- PORT_BIT(0x00020000, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_Z) PORT_TOGGLE PORT_NAME("Topbox door")
- PORT_BIT(0x00040000, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_X) PORT_TOGGLE PORT_NAME("Meter cage")
- PORT_BIT(0x00080000, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_C) PORT_TOGGLE PORT_NAME("Cashbox door")
- PORT_BIT(0x00100000, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_M) PORT_TOGGLE PORT_NAME("Main door")
- PORT_BIT(0x00200000, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_B) PORT_TOGGLE PORT_NAME("Bill acceptor door")
- PORT_BIT(0x00c00000, IP_ACTIVE_HIGH, IPT_UNUSED) // Unused mechanical security switch
+ PORT_BIT(0x00000040, IP_ACTIVE_HIGH, IPT_OTHER) // Hopper full
+ PORT_BIT(0x00000080, IP_ACTIVE_HIGH, IPT_OTHER) // Hopper empty
+ PORT_BIT(0x00000100, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_M) PORT_TOGGLE PORT_NAME("Main door optical sensor")
+ PORT_BIT(0x0000fe00, IP_ACTIVE_HIGH, IPT_UNUSED) // Unused optical security sensors
+ PORT_BIT(0x00010000, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_L) PORT_TOGGLE PORT_NAME("Logic door")
+ PORT_BIT(0x00020000, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_Z) PORT_TOGGLE PORT_NAME("Topbox door")
+ PORT_BIT(0x00040000, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_X) PORT_TOGGLE PORT_NAME("Meter cage")
+ PORT_BIT(0x00080000, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_C) PORT_TOGGLE PORT_NAME("Cashbox door")
+ PORT_BIT(0x00100000, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_M) PORT_TOGGLE PORT_NAME("Main door")
+ PORT_BIT(0x00200000, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_B) PORT_TOGGLE PORT_NAME("Bill acceptor door")
+ PORT_BIT(0x00c00000, IP_ACTIVE_HIGH, IPT_UNUSED) // Unused mechanical security switch
PORT_START("P3")
- PORT_BIT(0x00000002, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CUSTOM_MEMBER(DEVICE_SELF, aristmk5_state, hopper_r, nullptr)
- PORT_BIT(0x000000f8, IP_ACTIVE_HIGH, IPT_SPECIAL) PORT_CUSTOM_MEMBER(DEVICE_SELF, aristmk5_state, coin_r, nullptr)
+ PORT_BIT(0x00000002, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CUSTOM_MEMBER(DEVICE_SELF, aristmk5_state, hopper_r, nullptr)
+ PORT_BIT(0x000000f8, IP_ACTIVE_HIGH, IPT_SPECIAL) PORT_CUSTOM_MEMBER(DEVICE_SELF, aristmk5_state, coin_r, nullptr)
PORT_START("P6")
PORT_BIT(0x00000002, IP_ACTIVE_LOW, IPT_OTHER) // Battery
@@ -1659,7 +1658,7 @@ ROM_END
// 630 - 10 Credit Multiplier / 9 Line Multiline.
-// The Chariot Challenge - NSW/ACT - A - 10/08/98.
+// The Chariot Challenge - Venezuela - A - 10/08/98.
// 04J00714
ROM_START( chariotc )
ARISTOCRAT_MK5_BIOS
@@ -2022,6 +2021,24 @@ ROM_START( dolphntrb )
ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
ROM_END
+ROM_START( dolphntrce )
+ ARISTOCRAT_MK5_BIOS
+
+ ROM_REGION( 0x400000, "game_prg", ROMREGION_ERASEFF )
+ ROM_LOAD32_WORD("ahg1606.u7", 0x0000000, 0x0080000, CRC(d468edf7) SHA1(100672d09184e06130ce253749bd9e20ee0a06d4) )
+ ROM_LOAD32_WORD("ahg1606.u11", 0x0000002, 0x0080000, CRC(0fe64635) SHA1(b504216e59984951b46701019f87cad759ab60f2) )
+ ROM_LOAD32_WORD("ahg1606.u8", 0x0100000, 0x0080000, CRC(a53a2de4) SHA1(1741af795f88e867021f3c08d8990611d893a8e8) )
+ ROM_LOAD32_WORD("ahg1606.u12", 0x0100002, 0x0080000, CRC(c2e268a2) SHA1(6aeb27ae844dbf495c64be210bcac97f4c7a6969) )
+ ROM_LOAD32_WORD("ahg1606.u9", 0x0200000, 0x0080000, CRC(fe9146f7) SHA1(95bef8910d213d588d45ec2639828a31aab6603c) )
+ ROM_LOAD32_WORD("ahg1606.u13", 0x0200002, 0x0080000, CRC(d6aa89fe) SHA1(eccb49d49f533aeed9fefb14018bcc06d3fdaf23) )
+ ROM_LOAD32_WORD("ahg1606.u10", 0x0300000, 0x0080000, CRC(0be76189) SHA1(a458f620f48b9f4a73f59d31ba98864c5a64e1d7) )
+ ROM_LOAD32_WORD("ahg1606.u14", 0x0300002, 0x0080000, CRC(c6c59ed6) SHA1(0ce8e5824c5937ffe2eeb34320db9dc568bca7cb) )
+
+ ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 ) /* ARM Code */
+ ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
+ ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
+ROM_END
+
// 602/1 - 10 Credit Multiplier / 9 Line Multiline.
// Dolphin Treasure - Export B - 06/12/96.
@@ -2059,6 +2076,17 @@ ROM_START( dolphntru )
ROM_LOAD( "rtc", 0x000000, 0x00001f, CRC(6909acb0) SHA1(6a4589599cd1c477e916474e7b029e9a4e92019b) )
ROM_END
+ROM_START( drgneye )
+ ARISTOCRAT_MK5_BIOS
+
+ ROM_REGION( 0x400000, "game_prg", ROMREGION_ERASEFF )
+ ROM_LOAD32_WORD("0100521v.u7", 0x0000000, 0x0080000, CRC(db9c952d) SHA1(4cbe3ffe6cf0bb112cb9a2d7a4ff0b28154d32c1) )
+ ROM_LOAD32_WORD("0100521v.u11", 0x0000002, 0x0080000, CRC(2bb47749) SHA1(796f610e5202b5eb26a6e901d43ee5d9e3f95332) )
+
+ ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 ) /* ARM Code */
+ ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
+ ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
+ROM_END
ROM_START( dynajack )
ARISTOCRAT_MK5_BIOS
@@ -2310,6 +2338,24 @@ ROM_START( goldpyra )
ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
ROM_END
+ROM_START( goldpyrb )
+ ARISTOCRAT_MK5_BIOS
+
+ ROM_REGION( 0x400000, "game_prg", ROMREGION_ERASEFF )
+ // these are the 'bios' for Casino games (could be moved to a different base set)
+ ROM_LOAD32_WORD( "0700474v.u7", 0x000000, 0x80000, CRC(04b7dcbf) SHA1(eded1223336181bb08f9593247f1f79d96278b75) )
+ ROM_LOAD32_WORD( "0700474v.u11", 0x000002, 0x80000, CRC(a89ce1b5) SHA1(411b474a111f23ebd834bea5af0bf0cf3926d590) )
+
+ ROM_LOAD32_WORD( "0100878v.u8", 0x100000, 0x80000, CRC(c3184f1c) SHA1(3f808b465175108d48ca5b2560e4546b30a7fd72) )
+ ROM_LOAD32_WORD( "0100878v.u12", 0x100002, 0x80000, CRC(acb3de77) SHA1(e0e337d6efbd6ee8e0c0ec2653c3dc0bd5741ff4) )
+ ROM_LOAD32_WORD( "0100878v.u9", 0x200000, 0x80000, CRC(0a2f6903) SHA1(11fd913f8c3a677ae07c7ec50548a82c1eaf63ee) )
+ ROM_LOAD32_WORD( "0100878v.u13", 0x200002, 0x80000, CRC(0df660be) SHA1(73d370d90655dada34f2b5b2209652632c34a22e) )
+
+ ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 ) /* ARM Code */
+ ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
+ ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
+ROM_END
+
ROM_START( goldenra )
ARISTOCRAT_MK5_BIOS
@@ -2746,6 +2792,25 @@ ROM_START( marmagic )
ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
ROM_END
+ROM_START( marmagicua )
+ ARISTOCRAT_MK5_BIOS
+
+ ROM_REGION( 0x400000, "game_prg", ROMREGION_ERASEFF )
+ ROM_LOAD32_WORD( "ehg1558.u7", 0x000000, 0x80000, CRC(7c2602ae) SHA1(f5a13154448041575e4bea1399ed0a5a0888d493) )
+ ROM_LOAD32_WORD( "ehg1558.u11", 0x000002, 0x80000, CRC(4fe3b18a) SHA1(cc36eddd264de1a088c16e1b741168130d895bd7) )
+ ROM_LOAD32_WORD( "ehg1558.u8", 0x100000, 0x80000, CRC(c9ff4bd8) SHA1(5766d7c39e753fb2a2412a41338dcfd4e31b642b) )
+ ROM_LOAD32_WORD( "ehg1558.u12", 0x100002, 0x80000, CRC(d00cd217) SHA1(2be7c1ef6c0a39d1c7ed391feeaf0f42a6471bae) )
+ ROM_LOAD32_WORD( "ehg1558.u9", 0x200000, 0x80000, CRC(879e4b14) SHA1(52d9540dd3ed51d42a31d1a7effe75e995e95330) )
+ ROM_LOAD32_WORD( "ehg1558.u13", 0x200002, 0x80000, CRC(770872a1) SHA1(cd430385a3dfc080decfa2402d7dbad0db912e15) )
+ ROM_LOAD32_WORD( "ehg1558.u10", 0x300000, 0x80000, CRC(4301eb40) SHA1(1a32c61df2ab04c365135378d97d18bbb0b50179) )
+ ROM_LOAD32_WORD( "ehg1558.u14", 0x300002, 0x80000, CRC(a2096cb3) SHA1(c2bba35396f9c83b17d692a384b6406f3441c8f5) )
+
+ ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 ) /* ARM Code */
+ ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
+ ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
+ROM_END
+
+
// US003 - Multi credit / Multi line.
// Margarita Magic [Reel Game] - NSW/ACT - A - 07/07/2000.
@@ -3181,6 +3246,51 @@ ROM_START( petshop )
ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
ROM_END
+ROM_START( petshopa )
+ ARISTOCRAT_MK5_BIOS
+
+ ROM_REGION( 0x400000, "game_prg", ROMREGION_ERASEFF )
+ ROM_LOAD32_WORD("0100731v.u7", 0x0000000, 0x0080000, CRC(01cffccc) SHA1(a39d943e700fff34d82bcff8c61f2586ee65e673) )
+ ROM_LOAD32_WORD("0100731v.u11", 0x0000002, 0x0080000, CRC(a8e906c5) SHA1(f6dd7bcf5fa90933c9741699f0c1e07b685ccb40) )
+ ROM_LOAD32_WORD("0100731v.u8", 0x0100000, 0x0080000, CRC(757e1296) SHA1(e14508bbaa3439a93c8b716267a2198ed3c54728) )
+ ROM_LOAD32_WORD("0100731v.u12", 0x0100002, 0x0080000, CRC(6e74cd57) SHA1(9092e656cbd8627b208b81ca0d737483a779bce1) )
+
+ ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 ) /* ARM Code */
+ ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
+ ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
+ROM_END
+
+ROM_START( phantpay )
+ ARISTOCRAT_MK5_BIOS
+
+ ROM_REGION( 0x400000, "game_prg", ROMREGION_ERASEFF )
+ ROM_LOAD32_WORD("0500005v.u7", 0x0000000, 0x0080000, CRC(2cfc44a7) SHA1(a2a93047311d7a1f45e2915478ba2a11d5179194) )
+ ROM_LOAD32_WORD("0500005v.u11", 0x0000002, 0x0080000, CRC(3e91ed2a) SHA1(92d49bd78d329ad53cb2063af2d324eada3f53d1) )
+ ROM_LOAD32_WORD("0500005v.u8", 0x0100000, 0x0080000, CRC(ab1e77e9) SHA1(5a8da1210214ccc89dfde2e28f5142036a743172) )
+ ROM_LOAD32_WORD("0500005v.u12", 0x0100002, 0x0080000, CRC(d43a092a) SHA1(5f851bd179b14ef3983b460ed932810f3713d3e5) )
+
+ ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 ) /* ARM Code */
+ ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
+ ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
+ROM_END
+
+ROM_START( penpir2 )
+ ARISTOCRAT_MK5_BIOS
+
+ ROM_REGION( 0x400000, "game_prg", ROMREGION_ERASEFF )
+ // these are the 'bios' for Casino games (could be moved to a different base set)
+ ROM_LOAD32_WORD( "0700474v.u7", 0x000000, 0x80000, CRC(04b7dcbf) SHA1(eded1223336181bb08f9593247f1f79d96278b75) )
+ ROM_LOAD32_WORD( "0700474v.u11", 0x000002, 0x80000, CRC(a89ce1b5) SHA1(411b474a111f23ebd834bea5af0bf0cf3926d590) )
+
+ ROM_LOAD32_WORD( "0100869v.u8", 0x100000, 0x80000, CRC(5a87f637) SHA1(0fee8140637e9f923727e8c358c9f59b8319855d) )
+ ROM_LOAD32_WORD( "0100869v.u12", 0x100002, 0x80000, CRC(2aef04c1) SHA1(7415f436960c7b4a43634161ca317b2ae34ee745) )
+ ROM_LOAD32_WORD( "0100869v.u9", 0x200000, 0x80000, CRC(05de2653) SHA1(7d3f9d50013d8137cef285940b04209cfdae4a1d) )
+ ROM_LOAD32_WORD( "0100869v.u13", 0x200002, 0x80000, CRC(e1dbfd58) SHA1(687b7254279734e1835e1713d032b5aa2cf70812) )
+
+ ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 ) /* ARM Code */
+ ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
+ ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
+ROM_END
ROM_START( przfight )
ARISTOCRAT_MK5_BIOS
@@ -3380,6 +3490,20 @@ ROM_START( qnilemax )
ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
ROM_END
+ROM_START( qtbird )
+ ARISTOCRAT_MK5_BIOS
+
+ ROM_REGION( 0x400000, "game_prg", ROMREGION_ERASEFF )
+ ROM_LOAD32_WORD("0500009v.u7", 0x0000000, 0x0080000, CRC(f294fc0a) SHA1(f3d60ca6008445f535fce027f5ec3fe82ae552c3) )
+ ROM_LOAD32_WORD("0500009v.u11", 0x0000002, 0x0080000, CRC(328b7e04) SHA1(5c49f60b7c88d6e94e7ab464fad4eee6806f327a) )
+ ROM_LOAD32_WORD("0500009v.u8", 0x0100000, 0x0080000, CRC(764b5568) SHA1(a097992499044b7ca017a8c85387dc1ea94ff27a) )
+ ROM_LOAD32_WORD("0500009v.u12", 0x0100002, 0x0080000, CRC(bb8344a9) SHA1(8b0e904b937c7f34470ad946076240b0c54bf434) )
+
+ ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 ) /* ARM Code */
+ ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
+ ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
+ROM_END
+
ROM_START( rainwrce )
ARISTOCRAT_MK5_BIOS
@@ -3781,7 +3905,7 @@ ROM_START( wamazon )
ROM_LOAD32_WORD("0200285v.u7", 0x0000000, 0x0080000, CRC(bfa21358) SHA1(6b76656401b3dbbace8d4335951468b9885fc7f0) )
ROM_LOAD32_WORD("0200285v.u11", 0x0000002, 0x0080000, CRC(54b2a375) SHA1(635fde5c678b908fa58c0e04ba9b7a84fac1f7fe) )
ROM_LOAD32_WORD("0200285v.u8", 0x0100000, 0x0080000, CRC(4e39f128) SHA1(91d3c6a9e5c30275c3f8967dde55214df097f2ba) )
- ROM_LOAD32_WORD("0200285v.u12", 0x0100002, 0x0080000, CRC(2cd12986) SHA1(b6b0bd6dd8c964498edc3763cb5c450795042a8d) )
+ ROM_LOAD32_WORD("0200285v.u12", 0x0100002, 0x0080000, BAD_DUMP CRC(2cd12986) SHA1(b6b0bd6dd8c964498edc3763cb5c450795042a8d) ) // actually a bad dump of u7 from oscara5!
ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 ) /* ARM Code */
ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
@@ -3907,6 +4031,33 @@ ROM_START( wcougaru )
ROM_LOAD( "rtc", 0x000000, 0x00001f, CRC(6909acb0) SHA1(6a4589599cd1c477e916474e7b029e9a4e92019b) )
ROM_END
+ROM_START( wizways )
+ ARISTOCRAT_MK5_BIOS
+
+ ROM_REGION( 0x400000, "game_prg", ROMREGION_ERASEFF )
+ ROM_LOAD32_WORD("0200396v.u7", 0x0000000, 0x0080000, CRC(85fca945) SHA1(ca48a907b4f6c1b665ae053e2992681f02166cb1) )
+ ROM_LOAD32_WORD("0200396v.u11", 0x0000002, 0x0080000, CRC(677c855f) SHA1(a4ec8e6151271af292379ead28214ef9163bfdc3) )
+ ROM_LOAD32_WORD("0200396v.u8", 0x0100000, 0x0080000, CRC(4b1192ae) SHA1(2537249ccfc8c507762ac2c46d05ef13fa3d0bf9) )
+ ROM_LOAD32_WORD("0200396v.u12", 0x0100002, 0x0080000, CRC(934d7286) SHA1(205f72b62d83667e9068141346bda3bcb9742a83) )
+
+ ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 ) /* ARM Code */
+ ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
+ ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
+ROM_END
+
+ROM_START( wnpost )
+ ARISTOCRAT_MK5_BIOS
+
+ ROM_REGION( 0x400000, "game_prg", ROMREGION_ERASEFF )
+ ROM_LOAD32_WORD("rhg041804.u7", 0x0000000, 0x0080000, CRC(73274802) SHA1(9838a63d5f4e1bf31675ac15c34a17e709f2f647) )
+ ROM_LOAD32_WORD("rhg041804.u11", 0x0000002, 0x0080000, CRC(4f076a94) SHA1(2962429c930ffc17e2f37a006215ee6f1c649953) )
+ ROM_LOAD32_WORD("rhg041804.u8", 0x0100000, 0x0080000, CRC(b1830ffa) SHA1(c23a97bfdfe9e408f0ec8053646d6c8c8e06a263) )
+ ROM_LOAD32_WORD("rhg041804.u12", 0x0100002, 0x0080000, CRC(ff70b305) SHA1(3c832ed20b1d00318fd3d2428bb469735f68965b) )
+
+ ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 ) /* ARM Code */
+ ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
+ ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
+ROM_END
ROM_START( wthing )
ARISTOCRAT_MK5_BIOS
@@ -3966,7 +4117,7 @@ GAMEL( 1998, adonisa, adonis, aristmk5, aristmk5, aristmk5_state, aristm
GAMEL( 2001, adonisu, adonis, aristmk5_usa, aristmk5_usa, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Adonis (BHG1508, US)", MACHINE_FLAGS, layout_aristmk5_us ) // MV4124/1, B - 31/07/01 - BAD DUMP
GAMEL( 1999, adonisce, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Adonis - Cash Express (0201005V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 602/9, C - 06/07/99
GAMEL( 1996, baddog, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Bad Dog Poker (0200428V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 386/56, A - 17/12/96
-GAMEL( 1996, blackpnt, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Black Panther (0200818V, Victoria)", MACHINE_FLAGS, layout_aristmk5 ) // 594/1, A - 30/07/96
+GAMEL( 1996, blackpnt, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Black Panther (0200818V, Victoria)", MACHINE_FLAGS, layout_aristmk5 ) // 594/1, A - 30/07/96 - doesn't boot, 'needs VLC comms instead of QCOM' (or bad?)
GAMEL( 1998, bootsctn, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Boot Scootin' (0100812V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 616/1, B - 11/12/98
GAMEL( 1999, bootsctnu, bootsctn, aristmk5_usa, aristmk5_usa, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Boot Scootin' (GHG1012-02, US)", MACHINE_FLAGS, layout_aristmk5_us ) // MV4098, A - 25/08/99 - BAD DUMP
GAMEL( 1996, bumblbug, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Bumble Bugs (0200510V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 593, D - 5/07/96
@@ -3979,11 +4130,11 @@ GAMEL( 1996, cashchamu, cashcham, aristmk5_usa, aristmk5_usa, aristmk5_state, ar
GAMEL( 1998, cashchama, cashcham, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Cash Chameleon (0200437V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 603(a), D - 18/02/98
GAMEL( 1998, cashchamnz,cashcham, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Cash Chameleon (0300781V, New Zealand)", MACHINE_FLAGS, layout_aristmk5 ) // MV4067, A - 31/08/98
GAMEL( 1997, cashcra5, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Cash Crop (0300467V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 607, C - 14/07/97
-GAMEL( 1998, chariotc, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "The Chariot Challenge (04J00714, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 630, A - 10/08/98, Rev 12
+GAMEL( 1998, chariotc, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "The Chariot Challenge (04J00714, Venezuela)", MACHINE_FLAGS, layout_aristmk5 ) // 630, A - 10/08/98, Rev 12
GAMEL( 1998, chariotca, chariotc, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "The Chariot Challenge (0100787V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 630/1, A - 10/08/98
GAMEL( 2001, checkma5, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Checkmate (01J00681, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // JB011, B - 06/07/01
GAMEL( 1996, chickna5, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Chicken (0100351V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 596, A - 27/08/96
-GAMEL( 1998, chickna5u, chickna5, aristmk5_usa, aristmk5_usa, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Chicken (RHG0730-03, US)", MACHINE_FLAGS, layout_aristmk5_us ) // 596, C - 23/02/98 - BAD DUMP
+GAMEL( 1998, chickna5u, chickna5, aristmk5_usa, aristmk5_usa, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Chicken (RHG0730-03, US)", MACHINE_FLAGS, layout_aristmk5_us ) // 596, C - 23/02/98
GAMEL( 1998, chickna5qld,chickna5,aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Chicken (0200530V, Queensland)", MACHINE_FLAGS, layout_aristmk5 ) // 596, C - 23/02/98
GAMEL( 1998, coralrc2, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Coral Riches II (0100919V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 577/7, A - 29/12/98
GAMEL( 1998, cuckoo, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Cuckoo (0200753V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 615/1, D - 03/07/98
@@ -3996,6 +4147,8 @@ GAMEL( 1996, dolphntr, aristmk5, aristmk5, aristmk5, aristmk5_state, aristm
GAMEL( 1996, dolphntra, dolphntr, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Dolphin Treasure (0100424V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 602/1, B - 06/12/96, Rev 1.24.4.0
GAMEL( 1996, dolphntrb, dolphntr, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Dolphin Treasure (0100388V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 602, B - 10/12/96
GAMEL( 1996, dolphntru, dolphntr, aristmk5_usa, aristmk5_usa, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Dolphin Treasure (FHG4077-02, US)", MACHINE_FLAGS, layout_aristmk5_us ) // 602/1, B - 06/12/96
+GAMEL( 1999, dolphntrce,dolphntr, aristmk5_usa, aristmk5_usa, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Dolphin Treasure - Cash Express (AHG1606, US)",MACHINE_FLAGS, layout_aristmk5_us ) // (MV4090, D - 22/12/99)
+GAMEL( 1997, drgneye, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Dragon's Eye (0100521V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // (610, A - 09/05/97)
GAMEL( 2000, dynajack, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Dynamite Jack (01J00081, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // JB004, A - 12/07/2000
GAMEL( 1998, eldorda5, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "El Dorado (0100652V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 623, B - 24/03/98
GAMEL( 1995, eforsta5, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Enchanted Forest (0400122V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 570/3, E - 23/06/95
@@ -4007,6 +4160,7 @@ GAMEL( 1999, genmagi, aristmk5, aristmk5_touch, aristmk5, aristmk5_state,
GAMEL( 1998, gnomeatw, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Gnome Around The World (0100767V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 625, C - 18/12/98
GAMEL( 1997, goldpyr, aristmk5, aristmk5_usa, aristmk5_usa, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Golden Pyramids (AHG1205-03, US)", MACHINE_FLAGS, layout_aristmk5_us ) // MV4091, B - 13/05/97
GAMEL( 1997, goldpyra, goldpyr, aristmk5_usa, aristmk5_usa, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Golden Pyramids (AHG1206-99, US)", MACHINE_FLAGS, layout_aristmk5_us ) // 602/2, B - 13/05/97 - BAD DUMP
+GAMEL( 1998, goldpyrb, goldpyr, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Golden Pyramids (0100878V, Victoria)", MACHINE_FLAGS, layout_aristmk5 ) // (602/5, C - 19/06/98)
GAMEL( 2000, goldenra, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Golden Ra (0101164V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 661, A - 10/04/00
GAMEL( 1999, incasun, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Inca Sun (0100872V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 631/3 B, B - 03/05/99
GAMEL( 1999, incasunsp, incasun, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Inca Sun (0100872V, NSW/ACT, Show Program)", MACHINE_FLAGS, layout_aristmk5 ) // 631/3 B, B - 03/05/99
@@ -4026,6 +4180,7 @@ GAMEL( 2000, magimaska, magimask, aristmk5_usa_touch, aristmk5_usa, aristmk5_sta
GAMEL( 1997, magtcha5, aristmk5, aristmk5_touch, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Magic Touch (0200455V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 606, A - 06/03/97
GAMEL( 2000, marmagic, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Margarita Magic (01J00101, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // JB005, A - 07/07/00
GAMEL( 2000, marmagicu, marmagic, aristmk5_usa, aristmk5_usa, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Margarita Magic (EHG1559, US)", MACHINE_FLAGS, layout_aristmk5_us ) // US003, A - 07/07/00 - BAD DUMP
+GAMEL( 2000, marmagicua,marmagic, aristmk5_usa, aristmk5_usa, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Margarita Magic (EHG1558, US)", MACHINE_FLAGS, layout_aristmk5_us ) // (US003, 07/07/2000)
GAMEL( 1996, minemine, aristmk5, aristmk5_usa, aristmk5_usa, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Mine, Mine, Mine (VHG0416-99, US)", MACHINE_FLAGS, layout_aristmk5_us ) // 559/2, E - 14/02/96
GAMEL( 1997, monmouse, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Money Mouse (0400469V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 607/1, B - 08/04/97
GAMEL( 2001, montree, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Money Tree (0201397V, New Zealand)", MACHINE_FLAGS, layout_aristmk5 ) // MV4126, C - 12/04/01
@@ -4043,6 +4198,9 @@ GAMEL( 1996, pengpaya, pengpay, aristmk5, aristmk5, aristmk5_state, aristm
GAMEL( 1997, pengpayb, pengpay, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Penguin Pays (0200359V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 586/3(a), D - 03/06/97
GAMEL( 1997, pengpayu, pengpay, aristmk5_usa, aristmk5_usa, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Penguin Pays (BHI0417-03, US)", MACHINE_FLAGS, layout_aristmk5_us ) // 586/7(b) B - 14/07/97
GAMEL( 1998, petshop, aristmk5, aristmk5_usa, aristmk5_usa, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Pet Shop (0100679V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5_us ) // 618, A - 09/03/98 - BAD DUMP
+GAMEL( 1998, petshopa, petshop, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Pet Shop (0100731V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // (618/1, A - 17/04/98)
+GAMEL( 1995, phantpay, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Phantom Pays (0500005V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // (570/1, E - 12/09/95)
+GAMEL( 1998, penpir2, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Penguin Pirate II (0100869V, Victoria)", MACHINE_FLAGS, layout_aristmk5 ) // (619/3, A - 17/12/98)
GAMEL( 1996, przfight, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Prize Fight (0100299V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 578/4, B - 08/08/96
GAMEL( 1998, qcash, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Queens of Cash (0100706V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 603/6, C - 23/07/98
GAMEL( 1997, qnile, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Queen of the Nile (0100439V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 602/4, B - 13/05/97
@@ -4051,30 +4209,33 @@ GAMEL( 1997, qnileb, qnile, aristmk5, aristmk5, aristmk5_state, aristm
GAMEL( 1997, qnilec, qnile, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Queen of the Nile (0300439V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 602/4, B - 13/05/97
GAMEL( 1997, qnileu, qnile, aristmk5_usa, aristmk5_usa, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Queen of the Nile (GHG4091-02, US)", MACHINE_FLAGS, layout_aristmk5_us ) // MV4091, B - 13/05/97
GAMEL( 1999, qnilemax, aristmk5, aristmk5_touch, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Queen of the Nile - Maximillions (0401072V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 602/4, D - 18/06/99
+GAMEL( 1994, qtbird, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Q.T. Bird (0500009V, NSW/ACT) ", MACHINE_FLAGS, layout_aristmk5 ) // (581, A - 27/10/94)
GAMEL( 2000, rainwrce, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Rainbow Warriors - Cash Express (0101332V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 655, B - 02/03/00
GAMEL( 1998, reelrock, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Reelin-n-Rockin (0100779V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 628, A - 13/07/98
GAMEL( 1997, retrsam, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Return of the Samurai (0400549V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 608, A - 17/04/97
GAMEL( 1997, retrsama, retrsam, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Return of the Samurai (0200506V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 608, A - 17/04/97
GAMEL( 1997, retrsamb, retrsam, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Return of the Samurai (0200549V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 608, A - 17/04/97
GAMEL( 1997, sumospin, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Sumo Spins (0200606V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 622, A - 08/12/97
-GAMEL( 1999, sbuk2, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Super Bucks II (0400501V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 578, G - 26/07/99
+GAMEL( 1999, sbuk2, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Super Bucks II (0400501V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 578, G - 26/07/99 - doesn't boot (maybe bad?)
GAMEL( 1998, sbuk3, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Super Bucks III (0200711V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 626, A - 22/04/98
GAMEL( 1995, swhr2, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Sweethearts II (0200004V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 577/1, C - 07/09/95
GAMEL( 1998, swhr2u, swhr2, aristmk5_usa, aristmk5_usa, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Sweethearts II (PHG0742-02, US)", MACHINE_FLAGS, layout_aristmk5_us ) // MV4061, A - 29/06/98 - BAD DUMP
GAMEL( 1995, swhr2v, swhr2, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Sweet Hearts II (01J01986, Venezuela)", MACHINE_FLAGS, layout_aristmk5 ) // 577/1, C - 07/09/95
-GAMEL( 199?, topbana, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Top Banana (0100550V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // BAD DUMP
+GAMEL( 199?, topbana, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Top Banana (0100550V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) //
GAMEL( 2000, trstrove, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Treasure Trove (01J00161, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // JB001/3, A - 5/10/00
GAMEL( 2002, tritreat, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Triple Treat (0201692V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 692, A - 17/05/02
GAMEL( 2001, trojhors, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Trojan Horse (01J00851, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // JB001/5, A - 30/10/01
GAMEL( 1997, trpdlght, aristmk5, aristmk5_usa, aristmk5_usa, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Tropical Delight (PHG0625-02, US)", MACHINE_FLAGS, layout_aristmk5_us ) // 577/3, D - 24/09/97 - BAD DUMP
GAMEL( 1998, unicornd, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Unicorn Dreaming (0100791V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 631/1, A - 31/08/98
GAMEL( 2000, unicorndnz,unicornd, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Unicorn Dreaming (0101228V, New Zealand)", MACHINE_FLAGS, layout_aristmk5 ) // MV4113/1, A - 05/04/2000
-GAMEL( 1996, wamazon, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Wild Amazon (0200285V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 506/6, A - 7/5/96
+GAMEL( 1996, wamazon, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Wild Amazon (0200285V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 506/6, A - 7/5/96 - BAD DUMP
GAMEL( 1996, wamazona, wamazon, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Wild Amazon (0200507V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 506/8, A - 10/10/96
GAMEL( 1996, wamazonv, wamazon, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Wild Amazon (01J01996, Venezuela)", MACHINE_FLAGS, layout_aristmk5 ) // 506/8, A - 10/10/96
GAMEL( 1996, wildbill, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Wild Bill (0100297V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 543/8, C - 15/08/96
GAMEL( 1996, wcougar, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Wild Cougar (0100167V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 569/9, B - 27/2/96
GAMEL( 1997, wcougaru, wcougar, aristmk5_usa, aristmk5_usa, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Wild Cougar (NHG0296-04, US)", MACHINE_FLAGS, layout_aristmk5_us ) // 569/8, D - 19/05/97
+GAMEL( 1996, wizways, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Wizard Ways (0200396V, NSW/ACT) ", MACHINE_FLAGS, layout_aristmk5 ) // (598/3, A - 04/11/96)
+GAMEL( 1997, wnpost, aristmk5, aristmk5_usa, aristmk5_usa, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Winning Post (RHG0418-04, US)", MACHINE_FLAGS, layout_aristmk5_us ) // (541/2, G - 11/02/97)
GAMEL( 1999, wthing, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Wild Thing (0101158V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 608/4, B - 14/12/99
GAMEL( 1999, wtiger, aristmk5, aristmk5, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "White Tiger Classic (0200954V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 ) // 638/1, B - 08/07/99
diff --git a/src/mame/drivers/fccpu20.cpp b/src/mame/drivers/fccpu20.cpp
index f5bc2668247..8ed782b2ea4 100644
--- a/src/mame/drivers/fccpu20.cpp
+++ b/src/mame/drivers/fccpu20.cpp
@@ -86,9 +86,9 @@ MACHINE_CONFIG_START (cpu20, cpu20_state)
MACHINE_CONFIG_END
/* ROM configuration */
-ROM_START(fccpu20)
+ROM_START(fccpu20sbc)
ROM_END
/* Driver */
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
-COMP (1986, fccpu20, 0, 0, cpu20, cpu20, driver_device, 0, "Force Computers Gmbh", "SYS68K/CPU-20", MACHINE_NO_SOUND_HW | MACHINE_TYPE_COMPUTER )
+COMP (1986, fccpu20sbc, 0, 0, cpu20, cpu20, driver_device, 0, "Force Computers Gmbh", "SYS68K/CPU-20", MACHINE_NO_SOUND_HW | MACHINE_TYPE_COMPUTER )
diff --git a/src/mame/drivers/hh_cop400.cpp b/src/mame/drivers/hh_cop400.cpp
index e9a2610a6f0..458c1dfee61 100644
--- a/src/mame/drivers/hh_cop400.cpp
+++ b/src/mame/drivers/hh_cop400.cpp
@@ -770,7 +770,6 @@ INPUT_CHANGED_MEMBER(funrlgl_state::reset_button)
m_maincpu->set_input_line(INPUT_LINE_RESET, newval ? ASSERT_LINE : CLEAR_LINE);
}
-
static MACHINE_CONFIG_START( funrlgl, funrlgl_state )
/* basic machine hardware */
diff --git a/src/mame/drivers/hh_hmcs40.cpp b/src/mame/drivers/hh_hmcs40.cpp
index 4f6f357d1f3..ea66da14cdf 100644
--- a/src/mame/drivers/hh_hmcs40.cpp
+++ b/src/mame/drivers/hh_hmcs40.cpp
@@ -698,7 +698,6 @@ INPUT_CHANGED_MEMBER(bfriskyt_state::input_changed)
update_int1();
}
-
static MACHINE_CONFIG_START( bfriskyt, bfriskyt_state )
/* basic machine hardware */
@@ -944,7 +943,6 @@ INPUT_CHANGED_MEMBER(msthawk_state::input_changed)
update_int0();
}
-
static MACHINE_CONFIG_START( msthawk, msthawk_state )
/* basic machine hardware */
@@ -1066,7 +1064,6 @@ INPUT_CHANGED_MEMBER(bzaxxon_state::input_changed)
update_int1();
}
-
static MACHINE_CONFIG_START( bzaxxon, bzaxxon_state )
/* basic machine hardware */
@@ -1183,7 +1180,6 @@ INPUT_CHANGED_MEMBER(zackman_state::input_changed)
update_int0();
}
-
static MACHINE_CONFIG_START( zackman, zackman_state )
/* basic machine hardware */
@@ -1311,7 +1307,6 @@ INPUT_CHANGED_MEMBER(bpengo_state::input_changed)
update_int0();
}
-
static MACHINE_CONFIG_START( bpengo, bpengo_state )
/* basic machine hardware */
@@ -1437,7 +1432,6 @@ INPUT_CHANGED_MEMBER(bbtime_state::input_changed)
update_int0();
}
-
static MACHINE_CONFIG_START( bbtime, bbtime_state )
/* basic machine hardware */
@@ -2248,7 +2242,6 @@ INPUT_CHANGED_MEMBER(cgalaxn_state::player_switch)
prepare_display();
}
-
static MACHINE_CONFIG_START( cgalaxn, cgalaxn_state )
/* basic machine hardware */
@@ -2988,7 +2981,6 @@ INPUT_CHANGED_MEMBER(eturtles_state::input_changed)
update_int();
}
-
void eturtles_state::machine_start()
{
hh_hmcs40_state::machine_start();
@@ -3360,7 +3352,6 @@ INPUT_CHANGED_MEMBER(gckong_state::input_changed)
update_int1();
}
-
static MACHINE_CONFIG_START( gckong, gckong_state )
/* basic machine hardware */
@@ -3480,7 +3471,6 @@ INPUT_CHANGED_MEMBER(gdigdug_state::input_changed)
update_int1();
}
-
static MACHINE_CONFIG_START( gdigdug, gdigdug_state )
/* basic machine hardware */
@@ -3856,7 +3846,6 @@ INPUT_CHANGED_MEMBER(kingman_state::input_changed)
update_int0();
}
-
static MACHINE_CONFIG_START( kingman, kingman_state )
/* basic machine hardware */
@@ -3978,7 +3967,6 @@ INPUT_CHANGED_MEMBER(tmtron_state::input_changed)
update_int1();
}
-
static MACHINE_CONFIG_START( tmtron, tmtron_state )
/* basic machine hardware */
diff --git a/src/mame/drivers/hh_tms1k.cpp b/src/mame/drivers/hh_tms1k.cpp
index bd4d6191b61..6a202910716 100644
--- a/src/mame/drivers/hh_tms1k.cpp
+++ b/src/mame/drivers/hh_tms1k.cpp
@@ -19,6 +19,7 @@
@CP0904A TMS0970 1977, Milton Bradley Comp IV
@MP0905B TMS0970 1977, Parker Brothers Codename Sector
*MP0057 TMS1000 1978, APH Student Speech+ (same ROM contents as TSI Speech+?)
+ @MP0154 TMS1000 1979, Fonas 2 Player Baseball
@MP0158 TMS1000 1979, Entex Soccer (6003)
@MP0163 TMS1000 1979, A-One LSI Match Number/LJN Electronic Concentration
@MP0168 TMS1000 1979, Conic Multisport/Tandy Sports Arena (model 60-2158)
@@ -166,6 +167,7 @@
#include "elecdet.lh"
#include "esbattle.lh"
#include "esoccer.lh"
+//#include "f2pbball.lh"
#include "fxmcr165.lh" // clickable
#include "gjackpot.lh"
#include "gpoker.lh"
@@ -1466,7 +1468,6 @@ INPUT_CHANGED_MEMBER(h2hbaseb_state::skill_switch)
set_clock();
}
-
void h2hbaseb_state::set_clock()
{
// MCU clock is from an RC circuit with C=47pF, and R value is depending on
@@ -2748,7 +2749,6 @@ INPUT_CHANGED_MEMBER(ebball3_state::skill_switch)
set_clock();
}
-
void ebball3_state::set_clock()
{
// MCU clock is from an RC circuit(R=47K, C=33pF) oscillating by default at ~340kHz,
@@ -2969,7 +2969,6 @@ INPUT_CHANGED_MEMBER(einvader_state::skill_switch)
set_clock();
}
-
void einvader_state::set_clock()
{
// MCU clock is from an RC circuit(R=47K, C=56pF) oscillating by default at ~320kHz,
@@ -3347,7 +3346,6 @@ INPUT_CHANGED_MEMBER(raisedvl_state::skill_switch)
set_clock();
}
-
void raisedvl_state::set_clock()
{
// MCU clock is from an RC circuit with C=47pF, R=47K by default. Skills
@@ -3388,6 +3386,125 @@ MACHINE_CONFIG_END
/***************************************************************************
+ Fonas 2 Player Baseball
+ * TMS1000NLL MP0154 (die label 1000B, MP0154)
+ * 4 7seg LEDs, 37 other LEDs, 1-bit sound
+
+ known releases:
+ - World: 2 Player Baseball
+ - USA: 2 Player Baseball, distributed by Sears
+ - Canada: 2 Player Baseball, distributed by Talbot Electronics
+
+***************************************************************************/
+
+class f2pbball_state : public hh_tms1k_state
+{
+public:
+ f2pbball_state(const machine_config &mconfig, device_type type, const char *tag)
+ : hh_tms1k_state(mconfig, type, tag)
+ { }
+
+ void prepare_display();
+ DECLARE_WRITE16_MEMBER(write_r);
+ DECLARE_WRITE16_MEMBER(write_o);
+ DECLARE_READ8_MEMBER(read_k);
+
+ DECLARE_INPUT_CHANGED_MEMBER(reset_button);
+};
+
+// handlers
+
+void f2pbball_state::prepare_display()
+{
+ // R5-R8 are 7segs
+ set_display_segmask(0x1e0, 0xff);
+ display_matrix(8, 9, m_o, m_r);
+}
+
+WRITE16_MEMBER(f2pbball_state::write_r)
+{
+ // R4,R9,R10: input mux
+ m_inp_mux = (data >> 4 & 1) | (data >> 8 & 6);
+
+ // R9,R10(ANDed together): speaker out
+ m_speaker->level_w(data >> 10 & data >> 9 & 1);
+
+ // R0-R8: led select
+ m_r = data;
+ prepare_display();
+}
+
+WRITE16_MEMBER(f2pbball_state::write_o)
+{
+ // O0-O7: led state
+ m_o = BITSWAP8(data,0,7,2,6,5,4,3,1);
+ prepare_display();
+}
+
+READ8_MEMBER(f2pbball_state::read_k)
+{
+ // K: multiplexed inputs
+ return read_inputs(3);
+}
+
+
+// config
+
+static INPUT_PORTS_START( f2pbball )
+ PORT_START("IN.0") // R4
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_COCKTAIL PORT_NAME("Pick Off")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_CONFNAME( 0x0c, 0x04, "Players" )
+ PORT_CONFSETTING( 0x04, "1" )
+ PORT_CONFSETTING( 0x00, "Practice" )
+ PORT_CONFSETTING( 0x08, "2" )
+
+ PORT_START("IN.1") // R9
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("Score")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Steal")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Pitch")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Swing")
+
+ PORT_START("IN.2") // R10
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_COCKTAIL PORT_NAME("Curve Left")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_COCKTAIL PORT_NAME("Slow")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_COCKTAIL PORT_NAME("Curve Right")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_COCKTAIL PORT_NAME("Fast")
+
+ PORT_START("RESET")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("Reset") PORT_CHANGED_MEMBER(DEVICE_SELF, f2pbball_state, reset_button, 0)
+INPUT_PORTS_END
+
+INPUT_CHANGED_MEMBER(f2pbball_state::reset_button)
+{
+ // reset button is directly wired to TMS1000 INIT pin
+ m_maincpu->set_input_line(INPUT_LINE_RESET, newval ? ASSERT_LINE : CLEAR_LINE);
+}
+
+static MACHINE_CONFIG_START( f2pbball, f2pbball_state )
+
+ /* basic machine hardware */
+ MCFG_CPU_ADD("maincpu", TMS1000, 325000) // approximation - RC osc. R=51K, C=39pF
+ MCFG_TMS1XXX_READ_K_CB(READ8(f2pbball_state, read_k))
+ MCFG_TMS1XXX_WRITE_R_CB(WRITE16(f2pbball_state, write_r))
+ MCFG_TMS1XXX_WRITE_O_CB(WRITE16(f2pbball_state, write_o))
+
+ MCFG_TIMER_DRIVER_ADD_PERIODIC("display_decay", hh_tms1k_state, display_decay_tick, attotime::from_msec(1))
+ MCFG_DEFAULT_LAYOUT(layout_hh_tms1k_test)
+ //MCFG_DEFAULT_LAYOUT(layout_f2pbball)
+
+ /* sound hardware */
+ MCFG_SPEAKER_STANDARD_MONO("mono")
+ MCFG_SOUND_ADD("speaker", SPEAKER_SOUND, 0)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
+MACHINE_CONFIG_END
+
+
+
+
+
+/***************************************************************************
+
Gakken Poker
* PCB label POKER. gakken
* TMS1370 MP2105 (die label same)
@@ -4823,7 +4940,6 @@ WRITE16_MEMBER(comp4_state::write_o)
// O0: leds common
// other bits: N/C
m_o = data;
- display_matrix(11, 1, m_r, m_o);
}
READ8_MEMBER(comp4_state::read_k)
@@ -5350,7 +5466,6 @@ INPUT_CHANGED_MEMBER(ssimon_state::speed_switch)
set_clock();
}
-
void ssimon_state::set_clock()
{
// MCU clock is from an RC circuit with C=100pF, R=x depending on speed switch:
@@ -5875,28 +5990,28 @@ static INPUT_PORTS_START( cnsector )
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_Z) PORT_NAME("Range")
PORT_START("IN.1") // O1
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_X) PORT_NAME("Aim")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_S) PORT_NAME("Right")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_X) PORT_NAME("Aim")
PORT_START("IN.2") // O2
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_C) PORT_NAME("Fire")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_E) PORT_NAME("Recall")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_J) PORT_NAME("Evasive Sub") // expert button
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_E) PORT_NAME("Recall")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_C) PORT_NAME("Fire")
PORT_START("IN.3") // O3
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_M) PORT_NAME("Sub Finder") // expert button
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_F) PORT_NAME("Slower")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_M) PORT_NAME("Sub Finder") // expert button
PORT_START("IN.4") // O4
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_B) PORT_NAME("Teach Mode")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_T) PORT_NAME("Move Ship")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_G) PORT_NAME("Faster")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_T) PORT_NAME("Move Ship")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_B) PORT_NAME("Teach Mode")
INPUT_PORTS_END
static MACHINE_CONFIG_START( cnsector, cnsector_state )
@@ -7664,7 +7779,6 @@ INPUT_CHANGED_MEMBER(tbreakup_state::skill_switch)
set_clock();
}
-
void tbreakup_state::set_clock()
{
// MCU clock is from an analog circuit with resistor of 73K, PRO2 adds 100K
@@ -7817,7 +7931,6 @@ INPUT_CHANGED_MEMBER(phpball_state::flipper_button)
output().set_lamp_value(90 + (int)(uintptr_t)param, newval);
}
-
static MACHINE_CONFIG_START( phpball, phpball_state )
/* basic machine hardware */
@@ -8237,6 +8350,17 @@ ROM_START( raisedvl )
ROM_END
+ROM_START( f2pbball )
+ ROM_REGION( 0x0400, "maincpu", 0 )
+ ROM_LOAD( "mp0154", 0x0000, 0x0400, CRC(c5b45ace) SHA1(b2de32e83ab447b22d6828f0081843f364040b01) )
+
+ ROM_REGION( 867, "maincpu:mpla", 0 )
+ ROM_LOAD( "tms1000_common2_micro.pla", 0, 867, CRC(d33da3cf) SHA1(13c4ebbca227818db75e6db0d45b66ba5e207776) )
+ ROM_REGION( 365, "maincpu:opla", 0 )
+ ROM_LOAD( "tms1000_f2pbball_output.pla", 0, 365, CRC(30c2f28f) SHA1(db969b22475f37f083c3594f5e4f5759048377b8) )
+ROM_END
+
+
ROM_START( gpoker )
ROM_REGION( 0x0800, "maincpu", 0 )
ROM_LOAD( "mp2105", 0x0000, 0x0800, CRC(95a8f5b4) SHA1(d14f00ba9f57e437264d972baa14a14a28ff8719) )
@@ -8707,6 +8831,8 @@ CONS( 1980, efootb4 , 0, 0, efootb4, efootb4, driver_device, 0, "Ent
CONS( 1980, ebaskb2 , 0, 0, ebaskb2, ebaskb2, driver_device, 0, "Entex", "Electronic Basketball 2 (Entex)", MACHINE_SUPPORTS_SAVE )
CONS( 1980, raisedvl, 0, 0, raisedvl, raisedvl, driver_device, 0, "Entex", "Raise The Devil", MACHINE_SUPPORTS_SAVE | MACHINE_REQUIRES_ARTWORK )
+CONS( 1979, f2pbball, 0, 0, f2pbball, f2pbball, driver_device, 0, "Fonas", "2 Player Baseball (Fonas)", MACHINE_SUPPORTS_SAVE )
+
CONS( 1979, gpoker, 0, 0, gpoker, gpoker, driver_device, 0, "Gakken", "Poker (Gakken, 1979 version)", MACHINE_SUPPORTS_SAVE )
CONS( 1980, gjackpot, 0, 0, gjackpot, gjackpot, driver_device, 0, "Gakken", "Jackpot: Gin Rummy & Black Jack", MACHINE_SUPPORTS_SAVE )
CONS( 1982, ginv1000, 0, 0, ginv1000, ginv1000, driver_device, 0, "Gakken", "Galaxy Invader 1000", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/hh_ucom4.cpp b/src/mame/drivers/hh_ucom4.cpp
index c3486fb191e..160bbde1f72 100644
--- a/src/mame/drivers/hh_ucom4.cpp
+++ b/src/mame/drivers/hh_ucom4.cpp
@@ -2167,7 +2167,6 @@ INPUT_CHANGED_MEMBER(tmtennis_state::difficulty_switch)
set_clock();
}
-
void tmtennis_state::set_clock()
{
// MCU clock is from an LC circuit oscillating by default at ~360kHz,
diff --git a/src/mame/drivers/interpro.cpp b/src/mame/drivers/interpro.cpp
new file mode 100644
index 00000000000..9cc9264f608
--- /dev/null
+++ b/src/mame/drivers/interpro.cpp
@@ -0,0 +1,348 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#include "includes/interpro.h"
+#include "debugger.h"
+
+#define VERBOSE 0
+#if VERBOSE
+#define LOG_SYSTEM(...) logerror(__VA_ARGS__)
+#define LOG_IDPROM(...) logerror(__VA_ARGS__)
+#else
+#define LOG_SYSTEM(...) {}
+#define LOG_IDPROM(...) {}
+#endif
+
+// machine start
+void interpro_state::machine_start()
+{
+ m_system_reg[SREG_CTRL2] = CTRL2_COLDSTART | CTRL2_PWRENA | CTRL2_PWRUP;
+}
+
+void interpro_state::machine_reset()
+{
+ // flash rom requires the following values
+ m_system_reg[SREG_ERROR] = 0x00;
+ m_system_reg[SREG_STATUS] = 0x400;
+ m_system_reg[SREG_CTRL1] = CTRL1_FLOPRDY;
+}
+
+WRITE16_MEMBER(interpro_state::system_w)
+{
+ switch (offset)
+ {
+ case SREG_LED:
+ LOG_SYSTEM("LED value %d at pc 0x%08x\n", data, space.device().safe_pc());
+ break;
+
+ case SREG_STATUS: // not sure if writable?
+ break;
+
+ case SREG_CTRL1:
+ LOG_SYSTEM("system control register 1 write data 0x%x pc 0x%08x\n", data, space.device().safe_pc());
+
+ if ((data ^ m_system_reg[offset]) & CTRL1_LEDDP)
+ LOG_SYSTEM("LED decimal point %s\n", data & CTRL1_LEDDP ? "on" : "off");
+
+ m_system_reg[offset] = data;
+ break;
+
+ case SREG_CTRL2:
+ LOG_SYSTEM("system control register 2 write data 0x%x pc 0x%08x\n", data, space.device().safe_pc());
+ if (data & CTRL2_RESET)
+ {
+ m_system_reg[SREG_CTRL2] &= ~CTRL2_COLDSTART;
+
+ machine().schedule_soft_reset();
+ }
+ else
+ m_system_reg[offset] = data & 0x0f; // top four bits are not persistent
+ break;
+ }
+}
+
+READ16_MEMBER(interpro_state::system_r)
+{
+ LOG_SYSTEM("system register read offset %d pc 0x%08x\n", offset, space.device().safe_pc());
+ switch (offset)
+ {
+ case SREG_ERROR:
+ case SREG_STATUS:
+ case SREG_CTRL1:
+ case SREG_CTRL2:
+ default:
+ return m_system_reg[offset];
+ break;
+ }
+}
+
+READ32_MEMBER(interpro_state::idprom_r)
+{
+ LOG_IDPROM("idprom read offset 0x%x mask 0x%08x at 0x%08x\n", offset, mem_mask, space.device().safe_pc());
+
+ // abitrary fake number for now, not working properly
+ u32 speed = 70000000;
+ u32 speed1 = speed >> 24;
+ u32 speed2 = speed >> 16;
+ u32 speed3 = speed >> 8;
+
+ static uint8_t idprom[] = {
+ // module type id
+ 'M', 'P', 'C', 'B',
+ '*', '*', '*', '*',
+
+ // ECO bytes
+ 0x87, 0x65, 0x43, 0x21,
+ 0xbb, 0xcc, 0xdd, 0xee,
+
+ // the following 8 bytes are "feature bytes"
+ // the feature bytes contain a 32 bit word which is divided by 40000
+ // if they're empty, a default value of 50 000 000 is used
+ // perhaps this is a system speed (50MHz)?
+ 0x2, 0x34, 0x56, 0x78,
+ (u8)speed1, (u8)speed2, (u8)speed3, (u8)speed,
+
+ // reserved bytes
+ 0xff, 0xff,
+
+ // family
+ // boot rom tests for family == 0x41 or 0x42
+ // if so, speed read from feature bytes 2 & 3
+ // if not, read speed from feature bytes 4-7
+ //0x41, 0x00, // 2800-series CPU
+ 0x24, 0x00, // 2000-series system board
+
+ // footprint and checksum
+ 0x55, 0xaa, 0x55, 0x00
+ };
+
+ switch (offset)
+ {
+ case 0x1f:
+ {
+ uint8_t sum = 0;
+
+ // compute the checksum (sum of all bytes must be == 0x00)
+ for (int i = 0; i < 0x20; i++)
+ sum += idprom[i];
+
+ return 0x100 - (sum & 0xff);
+ }
+
+ default:
+ return idprom[offset];
+ }
+}
+
+READ32_MEMBER(interpro_state::slot0_r)
+{
+ // a known graphics board idprom
+ static uint8_t slot0[] = {
+ 0x00, 0x00, 0x00, 0x00, '9', '6', '3', 'A', // board
+ 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // eco
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // features
+ 0xff, 0xff, // reserved
+ 0x22, 0x00, // family
+ 0x55, 0xaa, 0x55, 0x00
+ };
+
+ return ((uint8_t *)&slot0)[offset % 32];
+}
+
+WRITE8_MEMBER(interpro_state::rtc_w)
+{
+ switch (offset)
+ {
+ case 0x00:
+ // write to RTC register
+ m_rtc->write(space, 1, data);
+ break;
+
+ case 0x40:
+ // set RTC read/write address
+ m_rtc->write(space, 0, data);
+ break;
+
+ default:
+ logerror("rtc: write to unknown offset 0x%02x data 0x%02x at pc 0x%08x\n", offset, data, space.device().safe_pc());
+ break;
+ }
+}
+
+READ8_MEMBER(interpro_state::rtc_r)
+{
+ switch (offset)
+ {
+ case 0x00:
+ // read from RTC register
+ return m_rtc->read(space, 1);
+
+ // read from InterPro system ID PROM (contains MAC address)
+ case 0x40: return 0x12;
+ case 0x41: return 0x34;
+ case 0x42: return 0x56;
+
+ default:
+ logerror("rtc: read from unknown offset 0x%02x at pc 0x%08x\n", offset, space.device().safe_pc());
+ return 0xff;
+ }
+}
+
+READ8_MEMBER(interpro_state::scsi_r)
+{
+ return m_scsi->read(space, offset >> 6, mem_mask);
+}
+
+WRITE8_MEMBER(interpro_state::scsi_w)
+{
+ m_scsi->write(space, offset >> 6, data, mem_mask);
+}
+
+// driver init
+DRIVER_INIT_MEMBER(interpro_state, ip2800)
+{
+ //address_space &as = m_mmu->space(AS_1);
+}
+
+// these maps point the cpu virtual addresses to the mmu
+static ADDRESS_MAP_START(clipper_insn_map, AS_PROGRAM, 32, interpro_state)
+ AM_RANGE(0x00000000, 0xffffffff) AM_DEVREAD32(INTERPRO_MMU_TAG, cammu_device, mmu_r, 0xffffffff)
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START(clipper_data_map, AS_DATA, 32, interpro_state)
+AM_RANGE(0x00000000, 0xffffffff) AM_DEVREADWRITE32(INTERPRO_MMU_TAG, cammu_device, mmu_r, mmu_w, 0xffffffff)
+ADDRESS_MAP_END
+
+// these maps represent the real main, i/o and boot spaces of the system
+static ADDRESS_MAP_START(interpro_main_map, AS_0, 32, interpro_state)
+ AM_RANGE(0x00000000, 0x00ffffff) AM_RAM // 16M RAM
+
+ AM_RANGE(0x7f100000, 0x7f11ffff) AM_ROM AM_REGION(INTERPRO_ROM_TAG, 0)
+ AM_RANGE(0x7f180000, 0x7f1bffff) AM_ROM AM_REGION(INTERPRO_EEPROM_TAG, 0)
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START(interpro_io_map, AS_1, 32, interpro_state)
+ AM_RANGE(0x00000000, 0x00000fff) AM_DEVICE(INTERPRO_MMU_TAG, cammu_device, map)
+ AM_RANGE(0x00001000, 0x00001fff) AM_RAM
+
+ AM_RANGE(0x40000000, 0x4000003f) AM_DEVICE16(INTERPRO_MCGA_TAG, interpro_mcga_device, map, 0xffff)
+ AM_RANGE(0x4f007e00, 0x4f007eff) AM_DEVICE(INTERPRO_SGA_TAG, interpro_sga_device, map)
+
+ AM_RANGE(0x7f000100, 0x7f00011f) AM_DEVICE8(INTERPRO_FDC_TAG, n82077aa_device, map, 0xff)
+ // this is probably the srx arbiter ga
+ AM_RANGE(0x7f000200, 0x7f0002ff) AM_RAM
+ AM_RANGE(0x7f000300, 0x7f00030f) AM_READWRITE16(system_r, system_w, 0xffff)
+ AM_RANGE(0x7f000400, 0x7f00040f) AM_DEVREADWRITE8(INTERPRO_SCC1_TAG, scc85C30_device, ba_cd_inv_r, ba_cd_inv_w, 0xff)
+ AM_RANGE(0x7f000410, 0x7f00041f) AM_DEVREADWRITE8(INTERPRO_SCC2_TAG, scc85230_device, ba_cd_inv_r, ba_cd_inv_w, 0xff)
+ AM_RANGE(0x7f000500, 0x7f0006ff) AM_READWRITE8(rtc_r, rtc_w, 0xff)
+ AM_RANGE(0x7f000700, 0x7f00077f) AM_READ(idprom_r)
+ AM_RANGE(0x7f001000, 0x7f001fff) AM_READWRITE8(scsi_r, scsi_w, 0x0000ff00)
+
+ AM_RANGE(0x7f0fff00, 0x7f0fffff) AM_DEVICE(INTERPRO_IOGA_TAG, interpro_ioga_device, map)
+
+ AM_RANGE(0x08000000, 0x08000fff) AM_NOP // bogus
+ AM_RANGE(0x8f000000, 0x8f0fffff) AM_READ(slot0_r)
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START(interpro_boot_map, AS_2, 32, interpro_state)
+ AM_RANGE(0x00000000, 0x00001fff) AM_RAM
+ADDRESS_MAP_END
+
+FLOPPY_FORMATS_MEMBER(interpro_state::floppy_formats)
+ FLOPPY_PC_FORMAT
+FLOPPY_FORMATS_END
+
+static SLOT_INTERFACE_START(interpro_floppies)
+ SLOT_INTERFACE("525dd", FLOPPY_525_DD)
+ SLOT_INTERFACE("35hd", FLOPPY_35_HD)
+SLOT_INTERFACE_END
+
+// input ports
+static INPUT_PORTS_START(ip2800)
+INPUT_PORTS_END
+
+static MACHINE_CONFIG_START(ip2800, interpro_state)
+ MCFG_CPU_ADD(INTERPRO_CPU_TAG, CLIPPER_C400, XTAL_10MHz)
+ MCFG_CPU_PROGRAM_MAP(clipper_insn_map)
+ MCFG_CPU_DATA_MAP(clipper_data_map)
+ MCFG_CPU_IRQ_ACKNOWLEDGE_DEVICE(INTERPRO_IOGA_TAG, interpro_ioga_device, inta_cb)
+
+ MCFG_DEVICE_ADD(INTERPRO_MMU_TAG, CAMMU_C4T, 0)
+ MCFG_DEVICE_ADDRESS_MAP(AS_0, interpro_main_map)
+ MCFG_DEVICE_ADDRESS_MAP(AS_1, interpro_io_map)
+ MCFG_DEVICE_ADDRESS_MAP(AS_2, interpro_boot_map)
+ MCFG_CAMMU_SSW_CB(DEVREADLINE(INTERPRO_CPU_TAG, clipper_device, ssw))
+
+ // serial controllers and rs232 bus
+ MCFG_SCC85C30_ADD(INTERPRO_SCC1_TAG, XTAL_4_9152MHz, 0, 0, 0, 0)
+
+ MCFG_Z80SCC_OUT_TXDA_CB(DEVWRITELINE("rs232a", rs232_port_device, write_txd))
+ MCFG_Z80SCC_OUT_TXDB_CB(DEVWRITELINE("rs232b", rs232_port_device, write_txd))
+ MCFG_Z80SCC_OUT_INT_CB(DEVWRITELINE(INTERPRO_IOGA_TAG, interpro_ioga_device, ir11_w))
+
+ MCFG_RS232_PORT_ADD("rs232a", default_rs232_devices, nullptr)
+ MCFG_RS232_RXD_HANDLER(DEVWRITELINE(INTERPRO_SCC1_TAG, z80scc_device, rxa_w))
+ MCFG_RS232_DCD_HANDLER(DEVWRITELINE(INTERPRO_SCC1_TAG, z80scc_device, dcda_w))
+ MCFG_RS232_CTS_HANDLER(DEVWRITELINE(INTERPRO_SCC1_TAG, z80scc_device, ctsa_w))
+
+ // the following port is known as "port 2"
+ MCFG_RS232_PORT_ADD("rs232b", default_rs232_devices, "terminal")
+ MCFG_RS232_RXD_HANDLER(DEVWRITELINE(INTERPRO_SCC1_TAG, z80scc_device, rxb_w))
+ MCFG_RS232_DCD_HANDLER(DEVWRITELINE(INTERPRO_SCC1_TAG, z80scc_device, dcdb_w))
+ MCFG_RS232_CTS_HANDLER(DEVWRITELINE(INTERPRO_SCC1_TAG, z80scc_device, ctsb_w))
+
+ MCFG_SCC85230_ADD(INTERPRO_SCC2_TAG, XTAL_4_9152MHz, 0, 0, 0, 0)
+
+ // real-time clock/non-volatile memory
+ MCFG_MC146818_ADD(INTERPRO_RTC_TAG, XTAL_32_768kHz)
+ MCFG_MC146818_UTC(true)
+ MCFG_MC146818_IRQ_HANDLER(DEVWRITELINE(INTERPRO_IOGA_TAG, interpro_ioga_device, ir9_w))
+
+ // floppy
+ MCFG_N82077AA_ADD(INTERPRO_FDC_TAG, n82077aa_device::MODE_PS2)
+ MCFG_UPD765_INTRQ_CALLBACK(DEVWRITELINE(INTERPRO_IOGA_TAG, interpro_ioga_device, ir1_w))
+ MCFG_UPD765_DRQ_CALLBACK(DEVWRITELINE(INTERPRO_IOGA_TAG, interpro_ioga_device, drq_floppy))
+ MCFG_FLOPPY_DRIVE_ADD("fdc:0", interpro_floppies, "525dd", interpro_state::floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD("fdc:1", interpro_floppies, "35hd", interpro_state::floppy_formats)
+ MCFG_FLOPPY_DRIVE_SOUND(false)
+
+ // scsi
+ MCFG_DEVICE_ADD(INTERPRO_SCSI_TAG, SCSI_PORT, 0)
+ MCFG_SCSIDEV_ADD(INTERPRO_SCSI_TAG ":" SCSI_PORT_DEVICE1, "harddisk", SCSIHD, SCSI_ID_0)
+ MCFG_SCSIDEV_ADD(INTERPRO_SCSI_TAG ":" SCSI_PORT_DEVICE2, "cdrom", SCSICD, SCSI_ID_3)
+
+ MCFG_DEVICE_ADD(INTERPRO_SCSI_ADAPTER_TAG, NCR539X, XTAL_12_5MHz)
+ MCFG_LEGACY_SCSI_PORT(INTERPRO_SCSI_TAG)
+ MCFG_NCR539X_OUT_IRQ_CB(DEVWRITELINE(INTERPRO_IOGA_TAG, interpro_ioga_device, ir0_w))
+ MCFG_NCR539X_OUT_DRQ_CB(DEVWRITELINE(INTERPRO_IOGA_TAG, interpro_ioga_device, drq_scsi))
+
+ // i/o gate array
+ MCFG_INTERPRO_IOGA_ADD(INTERPRO_IOGA_TAG)
+ MCFG_INTERPRO_IOGA_NMI_CB(INPUTLINE(INTERPRO_CPU_TAG, INPUT_LINE_NMI))
+ MCFG_INTERPRO_IOGA_IRQ_CB(INPUTLINE(INTERPRO_CPU_TAG, INPUT_LINE_IRQ0))
+ //MCFG_INTERPRO_IOGA_DMA_CB(IOGA_DMA_CHANNEL_PLOTTER, unknown)
+ //MCFG_INTERPRO_IOGA_DMA_CB(IOGA_DMA_SCSI, DEVREAD8(INTERPRO_SCSI_TAG, ncr539x_device, dma_read_data), DEVWRITE8(INTERPRO_SCSI_TAG, ncr539x_device, dma_write_data))
+ MCFG_INTERPRO_IOGA_DMA_CB(IOGA_DMA_FLOPPY, DEVREAD8(INTERPRO_FDC_TAG, n82077aa_device, mdma_r), DEVWRITE8(INTERPRO_FDC_TAG, n82077aa_device, mdma_w))
+ MCFG_INTERPRO_IOGA_DMA_CB(IOGA_DMA_SERIAL, DEVREAD8(INTERPRO_SCC1_TAG, z80scc_device, da_r), DEVWRITE8(INTERPRO_SCC1_TAG, z80scc_device, da_w))
+ MCFG_INTERPRO_IOGA_FDCTC_CB(DEVWRITELINE(INTERPRO_FDC_TAG, n82077aa_device, tc_line_w))
+ MCFG_INTERPRO_IOGA_DMA_BUS(INTERPRO_CAMMU_TAG, AS_0)
+
+ // memory control gate array
+ MCFG_DEVICE_ADD(INTERPRO_MCGA_TAG, INTERPRO_MCGA, 0)
+
+ // srx gate array
+ MCFG_DEVICE_ADD(INTERPRO_SGA_TAG, INTERPRO_SGA, 0)
+
+MACHINE_CONFIG_END
+
+ROM_START(ip2800)
+ ROM_REGION(0x0020000, INTERPRO_ROM_TAG, 0)
+ ROM_SYSTEM_BIOS(0, "IP2830", "IP2830")
+ ROMX_LOAD("ip2830_rom.bin", 0x00000, 0x20000, CRC(467ce7bd) SHA1(53faee40d5df311f53b24c930e434cbf94a5c4aa), ROM_BIOS(1))
+
+ ROM_REGION(0x0040000, INTERPRO_EEPROM_TAG, 0)
+ ROM_LOAD_OPTIONAL("ip2830_eeprom.bin", 0x00000, 0x40000, CRC(a0c0899f) SHA1(dda6fbca81f9885a1a76ca3c25e80463a83a0ef7))
+ROM_END
+
+/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
+COMP( 1990, ip2800, 0, 0, ip2800, ip2800, interpro_state, ip2800, "Intergraph", "InterPro 2800", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
diff --git a/src/mame/drivers/naomi.cpp b/src/mame/drivers/naomi.cpp
index f4d995c3907..493626a3926 100644
--- a/src/mame/drivers/naomi.cpp
+++ b/src/mame/drivers/naomi.cpp
@@ -61,9 +61,9 @@ TODO (game-specific):
- Giant Gram 2: no VMU emulation;
- Gun Survivor 2: crashes during game loading;
- Lupin the Shooting: "com. error between Naomi BD and i/o BD" after some secs. of gameplay;
- - marstv: locks up during anchor talking (does same in Demul);
+ - marstv: temporary lock ups during anchor talking (does same in Demul);
- marstv: missing graphics at stage select, renderer fault or something else?
- - Monkey Ball: asserts when attempts to load a stage;
+ - monkeyba: CPU jumps to la la land when attempts to load a stage (bp c09e950, uses FPU opcodes for calculating the return address?);
- Oinori-Daimyoujin Matsuri: reports "B. RAM error" in test mode, inputs doesn't seem to work after that point;
- OutTrigger: crashes on naomibd_r();
- puyofev: hangs after pressing start (bp 0C03F490, similar if not same snippet as Tetris 4d on DC).
@@ -1731,6 +1731,13 @@ ADDRESS_MAP_END
* Naomi 2 address map
*/
+// example hookup for accessing both PVRs, to be extended to everything else.
+WRITE32_MEMBER(naomi2_state::both_pvr2_ta_w)
+{
+ space.write_dword(0x005f8000|offset*4,data,mem_mask);
+ space.write_dword(0x025f8000|offset*4,data,mem_mask);
+}
+
static ADDRESS_MAP_START( naomi2_map, AS_PROGRAM, 64, naomi2_state )
/* Area 0 */
AM_RANGE(0x00000000, 0x001fffff) AM_MIRROR(0xa2000000) AM_ROM AM_REGION("maincpu", 0) // BIOS
@@ -1741,8 +1748,8 @@ static ADDRESS_MAP_START( naomi2_map, AS_PROGRAM, 64, naomi2_state )
AM_RANGE(0x005f7000, 0x005f70ff) AM_MIRROR(0x02000000) AM_DEVICE16( "rom_board", naomi_board, submap, 0x0000ffff0000ffffU )
AM_RANGE(0x005f7400, 0x005f74ff) AM_MIRROR(0x02000000) AM_DEVICE32( "rom_board", naomi_g1_device, amap, 0xffffffffffffffffU )
AM_RANGE(0x005f7800, 0x005f78ff) AM_MIRROR(0x02000000) AM_READWRITE(dc_g2_ctrl_r, dc_g2_ctrl_w )
- AM_RANGE(0x005f7c00, 0x005f7cff) AM_MIRROR(0x02000000) AM_DEVICE32("powervr2", powervr2_device, pd_dma_map, 0xffffffffffffffffU)
- AM_RANGE(0x005f8000, 0x005f9fff) AM_MIRROR(0x02000000) AM_DEVICE32("powervr2", powervr2_device, ta_map, 0xffffffffffffffffU)
+ AM_RANGE(0x005f7c00, 0x005f7cff) AM_DEVICE32("powervr2", powervr2_device, pd_dma_map, 0xffffffffffffffffU)
+ AM_RANGE(0x005f8000, 0x005f9fff) AM_DEVICE32("powervr2", powervr2_device, ta_map, 0xffffffffffffffffU)
AM_RANGE(0x00600000, 0x006007ff) AM_MIRROR(0x02000000) AM_READWRITE(dc_modem_r, dc_modem_w )
AM_RANGE(0x00700000, 0x00707fff) AM_MIRROR(0x02000000) AM_READWRITE32(dc_aica_reg_r, dc_aica_reg_w, 0xffffffffffffffffU)
AM_RANGE(0x00710000, 0x0071000f) AM_MIRROR(0x02000000) AM_DEVREADWRITE16("aicartc", aicartc_device, read, write, 0x0000ffff0000ffffU )
@@ -1752,9 +1759,11 @@ static ADDRESS_MAP_START( naomi2_map, AS_PROGRAM, 64, naomi2_state )
AM_RANGE(0x01010098, 0x0101009f) AM_MIRROR(0x02000000) AM_RAM // Naomi 2 BIOS tests this, needs to read back as written
AM_RANGE(0x0103ff00, 0x0103ffff) AM_MIRROR(0x02000000) AM_READWRITE(naomi_unknown1_r, naomi_unknown1_w ) // bios uses it, actual start and end addresses not known
+ AM_RANGE(0x025f7c00, 0x025f7cff) AM_DEVICE32("powervr2_slave", powervr2_device, pd_dma_map, 0xffffffffffffffffU)
+ AM_RANGE(0x025f8000, 0x025f9fff) AM_DEVICE32("powervr2_slave", powervr2_device, ta_map, 0xffffffffffffffffU)
// AM_RANGE(0x025f6800, 0x025f69ff) AM_READWRITE(dc_sysctrl_r, dc_sysctrl_w ) // second PVR DMA!
// AM_RANGE(0x025f7c00, 0x025f7cff) AM_DEVREADWRITE32("powervr2", powervr2_device, pvr_ctrl_r, pvr_ctrl_w, 0xffffffffffffffffU)
- AM_RANGE(0x005f8000, 0x005f9fff) AM_MIRROR(0x02000000) AM_DEVICE32("powervr2", powervr2_device, ta_map, 0xffffffffffffffffU)
+// AM_RANGE(0x005f8000, 0x005f9fff) AM_MIRROR(0x02000000) AM_DEVICE32("powervr2", powervr2_device, ta_map, 0xffffffffffffffffU)
/* Area 1 */
AM_RANGE(0x04000000, 0x04ffffff) AM_RAM AM_SHARE("dc_texture_ram") // texture memory 64 bit access
@@ -1763,8 +1772,8 @@ static ADDRESS_MAP_START( naomi2_map, AS_PROGRAM, 64, naomi2_state )
AM_RANGE(0x07000000, 0x07ffffff) AM_RAM AM_SHARE("frameram2")// 32 bit access 2nd PVR RAM
/* Area 2*/
- AM_RANGE(0x085f6800, 0x085f69ff) AM_WRITE(dc_sysctrl_w ) // writes to BOTH PVRs
- AM_RANGE(0x085f8000, 0x805f9fff) AM_DEVICE32("powervr2", powervr2_device, ta_map, 0xffffffffffffffffU)
+ AM_RANGE(0x085f6800, 0x085f69ff) AM_WRITE(dc_sysctrl_w ) // TODO: writes to BOTH PVRs
+ AM_RANGE(0x085f8000, 0x085f9fff) AM_WRITE32(both_pvr2_ta_w, 0xffffffffffffffffU)
AM_RANGE(0x08800000, 0x088000ff) AM_DEVREADWRITE32("powervr2", powervr2_device, elan_regs_r, elan_regs_w, 0xffffffffffffffffU) // T&L chip registers
// AM_RANGE(0x09000000, 0x09??????) T&L command processing
AM_RANGE(0x0a000000, 0x0bffffff) AM_RAM AM_SHARE("elan_ram") // T&L chip RAM
@@ -2571,6 +2580,7 @@ static INPUT_PORTS_START( aw2c )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1)
+
PORT_START("P1.1")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_SERVICE_NO_TOGGLE( 0x40, IP_ACTIVE_LOW )
@@ -2590,6 +2600,7 @@ static INPUT_PORTS_START( aw2c )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2)
+
PORT_START("P2.1")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
@@ -2767,9 +2778,16 @@ MACHINE_CONFIG_END
* Naomi 2 GD-Rom
*/
+static MACHINE_CONFIG_START( naomi2_base, naomi2_state )
+ MCFG_POWERVR2_ADD("powervr2_slave", WRITE8(dc_state, pvr_irq))
+
+ // TODO: ELAN device
+MACHINE_CONFIG_END
+
static MACHINE_CONFIG_START( naomi2gd, naomi2_state )
MCFG_FRAGMENT_ADD( naomigd )
-
+ MCFG_FRAGMENT_ADD( naomi2_base )
+
MCFG_CPU_MODIFY("maincpu")
MCFG_CPU_PROGRAM_MAP(naomi2_map)
MACHINE_CONFIG_END
@@ -2780,6 +2798,7 @@ MACHINE_CONFIG_END
static MACHINE_CONFIG_START( naomi2m1, naomi2_state )
MCFG_FRAGMENT_ADD( naomim1 )
+ MCFG_FRAGMENT_ADD( naomi2_base )
MCFG_CPU_MODIFY("maincpu")
MCFG_CPU_PROGRAM_MAP(naomi2_map)
@@ -2791,6 +2810,7 @@ MACHINE_CONFIG_END
static MACHINE_CONFIG_START( naomi2m2, naomi2_state )
MCFG_FRAGMENT_ADD( naomim2 )
+ MCFG_FRAGMENT_ADD( naomi2_base )
MCFG_CPU_MODIFY("maincpu")
MCFG_CPU_PROGRAM_MAP(naomi2_map)
diff --git a/src/mame/drivers/neodriv.hxx b/src/mame/drivers/neodriv.hxx
index ec40fe14df4..3fddef2b430 100644
--- a/src/mame/drivers/neodriv.hxx
+++ b/src/mame/drivers/neodriv.hxx
@@ -5893,7 +5893,41 @@ ROM_START( kof99e ) /* Original Version - Encrypted Code & GFX */
ROM_LOAD16_BYTE( "251-c8.c8", 0x3000001, 0x800000, CRC(8d921c68) SHA1(42acf1d27d52a8e3b6262eb7df50693c0b135565) ) /* Plane 2,3 */ /* TC5364205 */
ROM_END
-ROM_START( kof99k ) /* Original Version - Encrypted GFX */ /* KOREAN VERSION */
+ROM_START( kof99k ) /* Original Version - Encrypted Code & GFX */ /* KOREAN VERSION */
+ ROM_REGION( 0x900000, "cslot1:maincpu", ROMREGION_BE|ROMREGION_16BIT )
+ ROM_LOAD16_WORD_SWAP( "kb.neo-sma", 0x0c0000, 0x040000, CRC(9fccc688) SHA1(1a24d0fe7cabe7b346f538e099f1357bbf77bc89) ) /* stored in the custom chip */
+ ROM_LOAD16_WORD_SWAP( "151-pg1k.p1", 0x100000, 0x400000, CRC(ef259292) SHA1(e02f2d0c71eac74424507e4845991fbc12821045) ) /* mask rom TC5332205 */
+ ROM_LOAD16_WORD_SWAP( "151-pg2k.p2", 0x500000, 0x400000, CRC(f3898ec2) SHA1(c7fd230fbb97a9b171aeae8ff1a5cd39ba7fa9eb) ) /* mask rom TC5332205 */
+
+ ROM_Y_ZOOM
+
+ /* The Encrypted Boards do not have an s1 rom, data for it comes from the Cx ROMs */
+ ROM_REGION( 0x20000, "cslot1:fixed", 0 )
+ ROM_FILL( 0x000000, 0x20000, 0x000000 )
+ ROM_REGION( 0x20000, "fixedbios", 0 )
+ ROM_LOAD( "sfix.sfix", 0x000000, 0x20000, CRC(c2ea0cfd) SHA1(fd4a618cdcdbf849374f0a50dd8efe9dbab706c3) )
+
+ NEO_BIOS_AUDIO_128K( "251-m1.m1", CRC(5e74539c) SHA1(6f49a9343cbd026b2c6720ff3fa2e5b1f85e80da) ) /* TC531001 */
+
+ ROM_REGION( 0x0e00000, "cslot1:ymsnd", 0 )
+ ROM_LOAD( "251-v1.v1", 0x000000, 0x400000, CRC(ef2eecc8) SHA1(8ed13b9db92dba3124bc5ba66e3e275885ece24a) ) /* TC5332204 */
+ ROM_LOAD( "251-v2.v2", 0x400000, 0x400000, CRC(73e211ca) SHA1(0e60fa64cab6255d9721e2b4bc22e3de64c874c5) ) /* TC5332204 */
+ ROM_LOAD( "251-v3.v3", 0x800000, 0x400000, CRC(821901da) SHA1(c6d4975bfaa19a62ed59126cadf2578c0a5c257f) ) /* TC5332204 */
+ ROM_LOAD( "251-v4.v4", 0xc00000, 0x200000, CRC(b49e6178) SHA1(dde6f76e958841e8c99b693e13ced9aa9ef316dc) ) /* TC5316200 */
+
+ ROM_REGION( 0x4000000, "cslot1:sprites", 0 )
+ /* Encrypted */
+ ROM_LOAD16_BYTE( "251-c1.c1", 0x0000000, 0x800000, CRC(0f9e93fe) SHA1(c7d77f0833c6f526f632e4f2dce59e302f6b9a15) ) /* Plane 0,1 */ /* TC5364205 */
+ ROM_LOAD16_BYTE( "251-c2.c2", 0x0000001, 0x800000, CRC(e71e2ea3) SHA1(39c7a326fddbcca3b29c68cdc96aad4d62295c0f) ) /* Plane 2,3 */ /* TC5364205 */
+ ROM_LOAD16_BYTE( "251-c3.c3", 0x1000000, 0x800000, CRC(238755d2) SHA1(01125b5c7a28e350f091280b041954fd1ac7c98f) ) /* Plane 0,1 */ /* TC5364205 */
+ ROM_LOAD16_BYTE( "251-c4.c4", 0x1000001, 0x800000, CRC(438c8b22) SHA1(ffbc643f5b27dd00f2f95d4ef4c5f29ee814722b) ) /* Plane 2,3 */ /* TC5364205 */
+ ROM_LOAD16_BYTE( "251-c5.c5", 0x2000000, 0x800000, CRC(0b0abd0a) SHA1(d5ad324fe523bdc6f09209d236cc4932524a48f1) ) /* Plane 0,1 */ /* TC5364205 */
+ ROM_LOAD16_BYTE( "251-c6.c6", 0x2000001, 0x800000, CRC(65bbf281) SHA1(79ae174667a23dabcfe865b6cd6133c86098452e) ) /* Plane 2,3 */ /* TC5364205 */
+ ROM_LOAD16_BYTE( "251-c7.c7", 0x3000000, 0x800000, CRC(ff65f62e) SHA1(7cd335fede05b56e15db90ce407c1183a78da4e9) ) /* Plane 0,1 */ /* TC5364205 */
+ ROM_LOAD16_BYTE( "251-c8.c8", 0x3000001, 0x800000, CRC(8d921c68) SHA1(42acf1d27d52a8e3b6262eb7df50693c0b135565) ) /* Plane 2,3 */ /* TC5364205 */
+ROM_END
+
+ROM_START( kof99ka ) /* Original Version - Encrypted GFX */ /* KOREAN VERSION */
ROM_REGION( 0x500000, "cslot1:maincpu", ROMREGION_BE|ROMREGION_16BIT )
ROM_LOAD16_WORD_SWAP( "152-p1.p1", 0x000000, 0x100000, CRC(f2c7ddfa) SHA1(d592eecc53d442c55c2f26a6a721fdf2924d2a5b) ) /* TC538200 */
ROM_LOAD16_WORD_SWAP( "152-p2.sp2", 0x100000, 0x400000, CRC(274ef47a) SHA1(98654b68cc85c19d4a90b46f3110f551fa2e5357) ) /* TC5332205 */
@@ -8832,8 +8866,8 @@ GAME( 1998, mslug2, neogeo, neobase, neogeo, neogeo_state, neogeo, R
GAME( 2015, mslug2t, mslug2, neobase, neogeo, neogeo_state, neogeo, ROT0, "hack (trap15)", "Metal Slug 2 Turbo (NGM-9410) (hack)", MACHINE_SUPPORTS_SAVE )
GAME( 1998, kof98, neogeo, kof98, neogeo, neogeo_state, neogeo, ROT0, "SNK", "The King of Fighters '98 - The Slugfest / King of Fighters '98 - Dream Match Never Ends (NGM-2420)", MACHINE_SUPPORTS_SAVE )
GAME( 1998, kof98a, kof98, kof98, neogeo, neogeo_state, neogeo, ROT0, "SNK", "The King of Fighters '98 - The Slugfest / King of Fighters '98 - Dream Match Never Ends (NGM-2420, alt board)", MACHINE_SUPPORTS_SAVE )
-GAME( 1998, kof98k, kof98, kof98, neogeo, neogeo_state, neogeo, ROT0, "SNK", "The King of Fighters '98 - The Slugfest / King of Fighters '98 - Dream Match Never Ends (Korean board)", MACHINE_SUPPORTS_SAVE )
-GAME( 1998, kof98ka, kof98, kof98, neogeo, neogeo_state, neogeo, ROT0, "SNK", "The King of Fighters '98 - The Slugfest / King of Fighters '98 - Dream Match Never Ends (Korean board 2)", MACHINE_SUPPORTS_SAVE )
+GAME( 1998, kof98k, kof98, kof98, neogeo, neogeo_state, neogeo, ROT0, "SNK", "The King of Fighters '98 - The Slugfest / King of Fighters '98 - Dream Match Never Ends (Korean board, set 1)", MACHINE_SUPPORTS_SAVE )
+GAME( 1998, kof98ka, kof98, kof98, neogeo, neogeo_state, neogeo, ROT0, "SNK", "The King of Fighters '98 - The Slugfest / King of Fighters '98 - Dream Match Never Ends (Korean board, set 2)", MACHINE_SUPPORTS_SAVE )
GAME( 1998, kof98h, kof98, neobase, neogeo, neogeo_state, neogeo, ROT0, "SNK", "The King of Fighters '98 - The Slugfest / King of Fighters '98 - Dream Match Never Ends (NGH-2420)", MACHINE_SUPPORTS_SAVE )
GAME( 1998, lastbld2, neogeo, neobase, neogeo, neogeo_state, neogeo, ROT0, "SNK", "The Last Blade 2 / Bakumatsu Roman - Dai Ni Maku Gekka no Kenshi (NGM-2430 ~ NGH-2430)", MACHINE_SUPPORTS_SAVE )
GAME( 1998, neocup98, neogeo, neobase, neogeo, neogeo_state, neogeo, ROT0, "SNK", "Neo-Geo Cup '98 - The Road to the Victory", MACHINE_SUPPORTS_SAVE )
@@ -8841,7 +8875,8 @@ GAME( 1999, mslugx, neogeo, mslugx, neogeo, neogeo_state, neogeo, R
GAME( 1999, kof99, neogeo, kof99, neogeo, neogeo_state, neogeo, ROT0, "SNK", "The King of Fighters '99 - Millennium Battle (NGM-2510)" , MACHINE_SUPPORTS_SAVE ) /* Encrypted Code & GFX */
GAME( 1999, kof99h, kof99, kof99, neogeo, neogeo_state, neogeo, ROT0, "SNK", "The King of Fighters '99 - Millennium Battle (NGH-2510)" , MACHINE_SUPPORTS_SAVE ) /* Encrypted Code & GFX, crashes going into attract demo */
GAME( 1999, kof99e, kof99, kof99, neogeo, neogeo_state, neogeo, ROT0, "SNK", "The King of Fighters '99 - Millennium Battle (earlier)" , MACHINE_SUPPORTS_SAVE ) /* Encrypted Code & GFX */
-GAME( 1999, kof99k, kof99, kof99k, neogeo, neogeo_state, neogeo, ROT0, "SNK", "The King of Fighters '99 - Millennium Battle (Korean release)" , MACHINE_SUPPORTS_SAVE ) /* Encrypted GFX */
+GAME( 1999, kof99k, kof99, kof99, neogeo, neogeo_state, neogeo, ROT0, "SNK", "The King of Fighters '99 - Millennium Battle (Korean release)" , MACHINE_SUPPORTS_SAVE ) /* Encrypted Code & GFX */
+GAME( 1999, kof99ka, kof99, kof99k, neogeo, neogeo_state, neogeo, ROT0, "SNK", "The King of Fighters '99 - Millennium Battle (Korean release, non-encrypted program)" , MACHINE_SUPPORTS_SAVE ) /* Encrypted GFX */
GAME( 1999, kof99p, kof99, neobase, neogeo, neogeo_state, neogeo, ROT0, "SNK", "The King of Fighters '99 - Millennium Battle (prototype)", MACHINE_SUPPORTS_SAVE )
GAME( 1999, garou, neogeo, garou, neogeo, neogeo_state, neogeo, ROT0, "SNK", "Garou - Mark of the Wolves (NGM-2530)" , MACHINE_SUPPORTS_SAVE ) /* Encrypted Code & GFX */
GAME( 1999, garouh, garou, garouh, neogeo, neogeo_state, neogeo, ROT0, "SNK", "Garou - Mark of the Wolves (NGM-2530 ~ NGH-2530)" , MACHINE_SUPPORTS_SAVE ) /* Encrypted Code & GFX */
diff --git a/src/mame/drivers/novag6502.cpp b/src/mame/drivers/novag6502.cpp
index 814ed0fae33..fb0597f4564 100644
--- a/src/mame/drivers/novag6502.cpp
+++ b/src/mame/drivers/novag6502.cpp
@@ -13,7 +13,6 @@
TODO:
- cforteb emulation (was initially sforteba romset)
- verify supercon IRQ and beeper frequency
- - why is sforte H and 1 leds always on?
- printer port
******************************************************************************
@@ -413,8 +412,9 @@ WRITE8_MEMBER(novag6502_state::sforte_lcd_data_w)
// if lcd is disabled, misc control
if (~m_lcd_control & 4)
{
- // d5,d6: led data
- display_matrix(2, 8, data >> 5 & 3, m_inp_mux);
+ // d5,d6: led data, but not both at same time?
+ if ((data & 0x60) != 0x60)
+ display_matrix(2, 8, data >> 5 & 3, m_inp_mux);
// d7: enable beeper
m_beeper->set_state(data >> 7 & 1);
diff --git a/src/mame/drivers/pcfx.cpp b/src/mame/drivers/pcfx.cpp
index 11a5e93e6e6..204cc34446e 100644
--- a/src/mame/drivers/pcfx.cpp
+++ b/src/mame/drivers/pcfx.cpp
@@ -13,6 +13,7 @@
#include "cpu/v810/v810.h"
#include "video/huc6261.h"
#include "video/huc6270.h"
+#include "video/huc6271.h"
#include "video/huc6272.h"
struct pcfx_pad_t
@@ -181,7 +182,7 @@ WRITE16_MEMBER( pcfx_state::pad_w )
static ADDRESS_MAP_START( pcfx_io, AS_IO, 32, pcfx_state )
AM_RANGE( 0x00000000, 0x000000FF ) AM_READWRITE16(pad_r, pad_w, 0xffffffff) /* PAD */
AM_RANGE( 0x00000100, 0x000001FF ) AM_NOP /* HuC6230 */
- AM_RANGE( 0x00000200, 0x000002FF ) AM_NOP /* HuC6271 */
+ AM_RANGE( 0x00000200, 0x000002FF ) AM_DEVICE16( "huc6271", huc6271_device, regs, 0xffff ) /* HuC6271 */
AM_RANGE( 0x00000300, 0x000003FF ) AM_DEVREADWRITE16( "huc6261", huc6261_device, read, write, 0xffff ) /* HuC6261 */
AM_RANGE( 0x00000400, 0x000004FF ) AM_DEVREADWRITE8( "huc6270_a", huc6270_device, read, write, 0xffff ) /* HuC6270-A */
AM_RANGE( 0x00000500, 0x000005FF ) AM_DEVREADWRITE8( "huc6270_b", huc6270_device, read, write, 0xffff ) /* HuC6270-B */
@@ -497,6 +498,8 @@ static MACHINE_CONFIG_START( pcfx, pcfx_state )
MCFG_HUC6261_VDC2("huc6270_b")
MCFG_HUC6272_ADD( "huc6272", XTAL_21_4772MHz )
+
+ MCFG_HUC6271_ADD( "huc6271", XTAL_21_4772MHz )
MACHINE_CONFIG_END
diff --git a/src/mame/drivers/suprnova.cpp b/src/mame/drivers/suprnova.cpp
index ba70e1ef641..ebd842b310f 100644
--- a/src/mame/drivers/suprnova.cpp
+++ b/src/mame/drivers/suprnova.cpp
@@ -1761,6 +1761,28 @@ ROM_START( ryourano )
ROM_END
ROM_START( vblokbrk )
+ SKNS_EUROPE
+
+ ROM_REGION32_BE( 0x200000, "user1", 0 ) /* SH-2 Code mapped at 0x04000000 */
+ ROM_LOAD16_BYTE( "sk000e2-e.u10", 0x000000, 0x080000, CRC(5a278f10) SHA1(6f1be0657da76144b0feeed672d92a85091289b6) ) /* labeled SK000e2/E */
+ ROM_LOAD16_BYTE( "sk000e-o.u8", 0x000001, 0x080000, CRC(aecf0647) SHA1(4752e5012bae8e7af3972b455b4346499ec2b49c) ) /* labeled SK000e/O */
+
+ ROM_REGION( 0x0400000, "gfx1", 0 )
+ ROM_LOAD( "sk-100-00.u24", 0x000000, 0x200000, CRC(151dd88a) SHA1(87bb1039a9883f721a315760eb2c4abe4a94046f) )
+ ROM_LOAD( "sk-101.u20", 0x200000, 0x100000, CRC(779cce23) SHA1(70147b36d982524ba9921823e481ce8fbb5daa26) )
+
+ ROM_REGION( 0x200000, "gfx2", 0 )
+ ROM_LOAD( "sk-200-00.u16", 0x000000, 0x200000, CRC(2e297c61) SHA1(4071b945a1294fbc3d18fab1f144bf09af4349e8) )
+
+ ROM_REGION( 0x400000, "gfx3", ROMREGION_ERASE00 ) /* Tiles Plane B */
+ /* First 0x040000 bytes (0x03ff Tiles) are RAM Based Tiles */
+ /* 0x040000 - 0x3fffff empty? */
+
+ ROM_REGION( 0x200000, "ymz", 0 ) /* Samples */
+ ROM_LOAD( "sk-300-00.u4", 0x000000, 0x200000, CRC(e6535c05) SHA1(8895b7c326e0261691cb184887ac1ca637302460) )
+ROM_END
+
+ROM_START( vblokbrka )
SKNS_ASIA
ROM_REGION32_BE( 0x200000, "user1", 0 ) /* SH-2 Code mapped at 0x04000000 */
@@ -1768,18 +1790,18 @@ ROM_START( vblokbrk )
ROM_LOAD16_BYTE( "sk01a.u8", 0x000001, 0x080000, CRC(461e0197) SHA1(003573a4abdbecc6dd234a13c61ef07a25d980e2) )
ROM_REGION( 0x0400000, "gfx1", 0 )
- ROM_LOAD( "sk100-00.u24", 0x000000, 0x200000, CRC(151dd88a) SHA1(87bb1039a9883f721a315760eb2c4abe4a94046f) )
- ROM_LOAD( "sk-101.u20", 0x200000, 0x100000, CRC(779cce23) SHA1(70147b36d982524ba9921823e481ce8fbb5daa26) )
+ ROM_LOAD( "sk-100-00.u24", 0x000000, 0x200000, CRC(151dd88a) SHA1(87bb1039a9883f721a315760eb2c4abe4a94046f) )
+ ROM_LOAD( "sk-101.u20", 0x200000, 0x100000, CRC(779cce23) SHA1(70147b36d982524ba9921823e481ce8fbb5daa26) )
ROM_REGION( 0x200000, "gfx2", 0 )
- ROM_LOAD( "sk200-00.u16", 0x000000, 0x200000, CRC(2e297c61) SHA1(4071b945a1294fbc3d18fab1f144bf09af4349e8) )
+ ROM_LOAD( "sk-200-00.u16", 0x000000, 0x200000, CRC(2e297c61) SHA1(4071b945a1294fbc3d18fab1f144bf09af4349e8) )
ROM_REGION( 0x400000, "gfx3", ROMREGION_ERASE00 ) /* Tiles Plane B */
/* First 0x040000 bytes (0x03ff Tiles) are RAM Based Tiles */
/* 0x040000 - 0x3fffff empty? */
ROM_REGION( 0x200000, "ymz", 0 ) /* Samples */
- ROM_LOAD( "sk300-00.u4", 0x000000, 0x200000, CRC(e6535c05) SHA1(8895b7c326e0261691cb184887ac1ca637302460) )
+ ROM_LOAD( "sk-300-00.u4", 0x000000, 0x200000, CRC(e6535c05) SHA1(8895b7c326e0261691cb184887ac1ca637302460) )
ROM_END
ROM_START( sarukani )
@@ -1790,18 +1812,18 @@ ROM_START( sarukani )
ROM_LOAD16_BYTE( "sk1j1.u8", 0x000001, 0x080000, CRC(3b6aa343) SHA1(a969b20b1170d82351024cab9e37f2fbfd01ddeb) )
ROM_REGION( 0x0400000, "gfx1", 0 )
- ROM_LOAD( "sk100-00.u24", 0x000000, 0x200000, CRC(151dd88a) SHA1(87bb1039a9883f721a315760eb2c4abe4a94046f) )
- ROM_LOAD( "sk-101.u20", 0x200000, 0x100000, CRC(779cce23) SHA1(70147b36d982524ba9921823e481ce8fbb5daa26) )
+ ROM_LOAD( "sk-100-00.u24", 0x000000, 0x200000, CRC(151dd88a) SHA1(87bb1039a9883f721a315760eb2c4abe4a94046f) )
+ ROM_LOAD( "sk-101.u20", 0x200000, 0x100000, CRC(779cce23) SHA1(70147b36d982524ba9921823e481ce8fbb5daa26) )
ROM_REGION( 0x200000, "gfx2", 0 )
- ROM_LOAD( "sk200-00.u16", 0x000000, 0x200000, CRC(2e297c61) SHA1(4071b945a1294fbc3d18fab1f144bf09af4349e8) )
+ ROM_LOAD( "sk-200-00.u16", 0x000000, 0x200000, CRC(2e297c61) SHA1(4071b945a1294fbc3d18fab1f144bf09af4349e8) )
ROM_REGION( 0x400000, "gfx3", ROMREGION_ERASE00 ) /* Tiles Plane B */
/* First 0x040000 bytes (0x03ff Tiles) are RAM Based Tiles */
/* 0x040000 - 0x3fffff empty? */
ROM_REGION( 0x200000, "ymz", 0 ) /* Samples */
- ROM_LOAD( "sk300-00.u4", 0x000000, 0x200000, CRC(e6535c05) SHA1(8895b7c326e0261691cb184887ac1ca637302460) )
+ ROM_LOAD( "sk-300-00.u4", 0x000000, 0x200000, CRC(e6535c05) SHA1(8895b7c326e0261691cb184887ac1ca637302460) )
ROM_END
@@ -1825,7 +1847,8 @@ GAME( 1997, jjparad2, skns, sknsj, skns_1p, skns_state, jjparad2, ROT0,
GAME( 1997, sengekis, skns, sknsa, skns, skns_state, sengekis, ROT90, "Kaneko / Warashi", "Sengeki Striker (Asia)", MACHINE_IMPERFECT_GRAPHICS )
GAME( 1997, sengekisj, sengekis, sknsj, skns, skns_state, sengekij, ROT90, "Kaneko / Warashi", "Sengeki Striker (Japan)", MACHINE_IMPERFECT_GRAPHICS )
-GAME( 1997, vblokbrk, skns, sknsa, vblokbrk, skns_state, sarukani, ROT0, "Kaneko / Mediaworks", "VS Block Breaker (Asia)", MACHINE_IMPERFECT_GRAPHICS )
+GAME( 1997, vblokbrk, skns, sknse, vblokbrk, skns_state, sarukani, ROT0, "Kaneko / Mediaworks", "VS Block Breaker (Europe)", MACHINE_IMPERFECT_GRAPHICS )
+GAME( 1997, vblokbrka, vblokbrk, sknsa, vblokbrk, skns_state, sarukani, ROT0, "Kaneko / Mediaworks", "VS Block Breaker (Asia)", MACHINE_IMPERFECT_GRAPHICS )
GAME( 1997, sarukani, vblokbrk, sknsj, vblokbrk, skns_state, sarukani, ROT0, "Kaneko / Mediaworks", "Saru-Kani-Hamu-Zou (Japan)", MACHINE_IMPERFECT_GRAPHICS )
GAME( 1998, cyvern, skns, sknsu, cyvern, skns_state, cyvern, ROT90, "Kaneko", "Cyvern (US)", MACHINE_IMPERFECT_GRAPHICS )
diff --git a/src/mame/includes/interpro.h b/src/mame/includes/interpro.h
new file mode 100644
index 00000000000..6ae135b552c
--- /dev/null
+++ b/src/mame/includes/interpro.h
@@ -0,0 +1,131 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#pragma once
+
+#ifndef INTERPRO_H_
+#define INTERPRO_H_
+
+#include "emu.h"
+
+#include "cpu/clipper/clipper.h"
+#include "machine/cammu.h"
+
+#include "machine/interpro_ioga.h"
+#include "machine/interpro_mcga.h"
+#include "machine/interpro_sga.h"
+
+#include "machine/z80scc.h"
+#include "machine/mc146818.h"
+#include "machine/upd765.h"
+#include "machine/ncr539x.h"
+
+#include "bus/scsi/scsi.h"
+#include "bus/scsi/scsicd.h"
+#include "bus/scsi/scsihd.h"
+#include "bus/rs232/rs232.h"
+
+#include "formats/pc_dsk.h"
+
+#define INTERPRO_CPU_TAG "cpu"
+#define INTERPRO_MMU_TAG "mmu"
+
+#define INTERPRO_RTC_TAG "rtc"
+#define INTERPRO_SCC1_TAG "scc1"
+#define INTERPRO_SCC2_TAG "scc2"
+#define INTERPRO_ROM_TAG "rom"
+#define INTERPRO_EEPROM_TAG "eeprom"
+#define INTERPRO_TERMINAL_TAG "terminal"
+#define INTERPRO_FDC_TAG "fdc"
+#define INTERPRO_SCSI_TAG "scsi"
+#define INTERPRO_IOGA_TAG "ioga"
+#define INTERPRO_MCGA_TAG "mcga"
+#define INTERPRO_SGA_TAG "sga"
+#define INTERPRO_SCSI_ADAPTER_TAG "adapter"
+
+// system board register offsets
+#define SREG_LED 0
+#define SREG_ERROR 0
+#define SREG_STATUS 1
+#define SREG_CTRL1 2
+#define SREG_CTRL2 3
+
+// control register 1
+#define CTRL1_FLOPLOW 0x0001
+#define CTRL1_FLOPRDY 0x0002
+#define CTRL1_LEDENA 0x0004
+#define CTRL1_LEDDP 0x0008
+#define CTRL1_ETHLOOP 0x0010
+#define CTRL1_ETHDTR 0x0020
+#define CTRL1_ETHRMOD 0x0040
+#define CTRL1_CLIPRESET 0x0040
+#define CTRL1_FIFOACTIVE 0x0080
+
+// control register 2
+#define CTRL2_PWRUP 0x0001
+#define CTRL2_PWRENA 0x0002
+#define CTRL2_HOLDOFF 0x0004
+#define CTRL2_EXTNMIENA 0x0008
+#define CTRL2_COLDSTART 0x0010
+#define CTRL2_RESET 0x0020
+#define CTRL2_BUSENA 0x0040
+#define CTRL2_FRCPARITY 0x0080
+#define CTRL2_FLASHEN 0x0080
+#define CTRL2_WMASK 0x000f
+
+class interpro_state : public driver_device
+{
+public:
+ interpro_state(const machine_config &mconfig, device_type type, const char *tag)
+ : driver_device(mconfig, type, tag),
+ m_maincpu(*this, INTERPRO_CPU_TAG),
+ m_mmu(*this, INTERPRO_MMU_TAG),
+ m_scc1(*this, INTERPRO_SCC1_TAG),
+ m_scc2(*this, INTERPRO_SCC2_TAG),
+ m_rtc(*this, INTERPRO_RTC_TAG),
+ m_fdc(*this, INTERPRO_FDC_TAG),
+ m_scsi(*this, INTERPRO_SCSI_ADAPTER_TAG),
+ m_ioga(*this, INTERPRO_IOGA_TAG),
+ m_mcga(*this, INTERPRO_MCGA_TAG),
+ m_sga(*this, INTERPRO_SGA_TAG)
+ { }
+
+ required_device<clipper_device> m_maincpu;
+ required_device<cammu_device> m_mmu;
+
+ // FIXME: not sure which one is the escc
+ required_device<z80scc_device> m_scc1;
+ required_device<z80scc_device> m_scc2;
+ required_device<mc146818_device> m_rtc;
+ required_device<n82077aa_device> m_fdc;
+ required_device<ncr539x_device> m_scsi;
+
+ required_device<interpro_ioga_device> m_ioga;
+ required_device<interpro_mcga_device> m_mcga;
+ required_device<interpro_sga_device> m_sga;
+
+ DECLARE_DRIVER_INIT(ip2800);
+
+ DECLARE_WRITE16_MEMBER(system_w);
+ DECLARE_READ16_MEMBER(system_r);
+
+ DECLARE_WRITE8_MEMBER(rtc_w);
+ DECLARE_READ8_MEMBER(rtc_r);
+
+ DECLARE_READ32_MEMBER(idprom_r);
+ DECLARE_READ32_MEMBER(slot0_r);
+
+ DECLARE_READ8_MEMBER(scsi_r);
+ DECLARE_WRITE8_MEMBER(scsi_w);
+
+ DECLARE_FLOPPY_FORMATS(floppy_formats);
+
+protected:
+ virtual void machine_start() override;
+ virtual void machine_reset() override;
+
+private:
+ uint16_t m_system_reg[4];
+};
+
+#endif \ No newline at end of file
diff --git a/src/mame/includes/naomi.h b/src/mame/includes/naomi.h
index bef91e413d7..5fa4de38c37 100644
--- a/src/mame/includes/naomi.h
+++ b/src/mame/includes/naomi.h
@@ -83,16 +83,18 @@ class naomi2_state : public naomi_state
public:
naomi2_state(const machine_config &mconfig, device_type type, const char *tag)
: naomi_state(mconfig, type, tag),
- pvr2_texture_ram(*this, "textureram2"),
- pvr2_framebuffer_ram(*this, "frameram2"),
- elan_ram(*this, "elan_ram") { }
+ m_pvr2_texture_ram(*this, "textureram2"),
+ m_pvr2_framebuffer_ram(*this, "frameram2"),
+ m_elan_ram(*this, "elan_ram"),
+ m_powervr2_slave(*this, "powervr2_slave") { }
- /* Naomi 2 specific (To be moved) */
- required_shared_ptr<uint64_t> pvr2_texture_ram;
- required_shared_ptr<uint64_t> pvr2_framebuffer_ram;
- required_shared_ptr<uint64_t> elan_ram;
+ required_shared_ptr<uint64_t> m_pvr2_texture_ram;
+ required_shared_ptr<uint64_t> m_pvr2_framebuffer_ram;
+ required_shared_ptr<uint64_t> m_elan_ram;
+ required_device<powervr2_device> m_powervr2_slave;
DECLARE_DRIVER_INIT(naomi2);
+ DECLARE_WRITE32_MEMBER(both_pvr2_ta_w);
};
class atomiswave_state : public dc_state
diff --git a/src/mame/layout/cnsector.lay b/src/mame/layout/cnsector.lay
index 8bca9c3ab7a..15ca5c92e40 100644
--- a/src/mame/layout/cnsector.lay
+++ b/src/mame/layout/cnsector.lay
@@ -242,8 +242,8 @@
<bezel element="static_red"><bounds x="199" y="98" width="24" height="31" /></bezel>
<bezel element="button" inputtag="IN.0" inputmask="0x01"><bounds x="107" y="33" width="16" height="8" /></bezel>
- <bezel element="button" inputtag="IN.2" inputmask="0x08"><bounds x="155" y="33" width="16" height="8" /></bezel>
- <bezel element="button" inputtag="IN.4" inputmask="0x08"><bounds x="203" y="33" width="16" height="8" /></bezel>
+ <bezel element="button" inputtag="IN.2" inputmask="0x01"><bounds x="155" y="33" width="16" height="8" /></bezel>
+ <bezel element="button" inputtag="IN.4" inputmask="0x01"><bounds x="203" y="33" width="16" height="8" /></bezel>
<bezel element="button" inputtag="IN.0" inputmask="0x02"><bounds x="107" y="55" width="16" height="8" /></bezel>
<bezel element="button" inputtag="IN.1" inputmask="0x02"><bounds x="131" y="55" width="16" height="8" /></bezel>
@@ -252,10 +252,10 @@
<bezel element="button" inputtag="IN.4" inputmask="0x02"><bounds x="203" y="55" width="16" height="8" /></bezel>
<bezel element="button" inputtag="IN.0" inputmask="0x08"><bounds x="107" y="102" width="16" height="8" /></bezel>
- <bezel element="button" inputtag="IN.1" inputmask="0x01"><bounds x="131" y="102" width="16" height="8" /></bezel>
- <bezel element="button" inputtag="IN.2" inputmask="0x01"><bounds x="155" y="102" width="16" height="8" /></bezel>
- <bezel element="buttond" inputtag="IN.3" inputmask="0x01"><bounds x="185" y="104" width="4" height="4" /></bezel>
- <bezel element="button" inputtag="IN.4" inputmask="0x01"><bounds x="207" y="102" width="8" height="8" /></bezel>
+ <bezel element="button" inputtag="IN.1" inputmask="0x08"><bounds x="131" y="102" width="16" height="8" /></bezel>
+ <bezel element="button" inputtag="IN.2" inputmask="0x08"><bounds x="155" y="102" width="16" height="8" /></bezel>
+ <bezel element="buttond" inputtag="IN.3" inputmask="0x08"><bounds x="185" y="104" width="4" height="4" /></bezel>
+ <bezel element="button" inputtag="IN.4" inputmask="0x08"><bounds x="207" y="102" width="8" height="8" /></bezel>
<bezel element="text_rnext"><bounds x="127" y="32" width="18" height="5" /></bezel>
<bezel element="text_rship"><bounds x="127" y="37" width="18" height="5" /></bezel>
diff --git a/src/mame/machine/cammu.cpp b/src/mame/machine/cammu.cpp
new file mode 100644
index 00000000000..1ee7cdab38a
--- /dev/null
+++ b/src/mame/machine/cammu.cpp
@@ -0,0 +1,181 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * An implementation of the Fairchild/Intergraph Cache and Memory Management Unit (CAMMU) designed for use with the CLIPPER CPU family.
+ *
+ * Primary reference: http://bitsavers.trailing-edge.com/pdf/fairchild/clipper/CLIPPER%20C300%2032-Bit%20Compute%20Engine.pdf
+ * Another reference: http://www.eecs.berkeley.edu/Pubs/TechRpts/1986/CSD-86-289.pdf
+ *
+ * This implementation is currently at a very early stage, and is only sufficient to handle the bare minimum of boot/diagnostic code.
+ *
+ * TODO
+ * - almost everything
+ * - map registers
+ * - refactor hardware tlb
+ * - address translation
+ * - faults
+ * - tlb
+ * - cache
+ * - bus errors
+ */
+
+#include "cammu.h"
+
+#define VERBOSE 0
+
+// each variant of the cammu has different registers and a different addressing map
+// TODO: decode the cammu registers properly
+DEVICE_ADDRESS_MAP_START(map, 32, cammu_c4t_device)
+ AM_RANGE(0x000, 0xfff) AM_READWRITE(cammu_r, cammu_w)
+ADDRESS_MAP_END
+
+DEVICE_ADDRESS_MAP_START(map, 32, cammu_c4i_device)
+ AM_RANGE(0x000, 0xfff) AM_READWRITE(cammu_r, cammu_w)
+ADDRESS_MAP_END
+
+DEVICE_ADDRESS_MAP_START(map, 32, cammu_c3_device)
+ AM_RANGE(0x000, 0xfff) AM_READWRITE(cammu_r, cammu_w)
+ADDRESS_MAP_END
+
+const device_type CAMMU_C4T = &device_creator<cammu_c4t_device>;
+const device_type CAMMU_C4I = &device_creator<cammu_c4i_device>;
+const device_type CAMMU_C3 = &device_creator<cammu_c3_device>;
+
+cammu_c4t_device::cammu_c4t_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : cammu_device(mconfig, CAMMU_C4T, "C4E/C4T CAMMU", tag, owner, clock, "C4T", __FILE__) { }
+
+cammu_c4i_device::cammu_c4i_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : cammu_device(mconfig, CAMMU_C4I, "C4I CAMMU", tag, owner, clock, "C4I", __FILE__) { }
+
+cammu_c3_device::cammu_c3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : cammu_device(mconfig, CAMMU_C4T, "C1/C3 CAMMU", tag, owner, clock, "C3", __FILE__) { }
+
+cammu_device::cammu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, const char *source)
+ : device_t(mconfig, type, name, tag, owner, clock, shortname, source)
+ , device_memory_interface(mconfig, *this),
+ m_main_space_config("main", ENDIANNESS_LITTLE, 32, 32, 0),
+ m_io_space_config("io", ENDIANNESS_LITTLE, 32, 32, 0),
+ m_boot_space_config("boot", ENDIANNESS_LITTLE, 32, 32, 0),
+ m_main_space(nullptr),
+ m_io_space(nullptr),
+ m_boot_space(nullptr),
+ m_ssw_func(*this)
+{ }
+
+void cammu_device::device_start()
+{
+ m_ssw_func.resolve_safe(0);
+
+ m_main_space = &space(AS_0);
+ m_io_space = &space(AS_1);
+ m_boot_space = &space(AS_2);
+}
+
+void cammu_device::device_reset()
+{
+}
+
+const address_space_config *cammu_device::memory_space_config (address_spacenum spacenum) const
+{
+ switch (spacenum)
+ {
+ case AS_0: return &m_main_space_config;
+ case AS_1: return &m_io_space_config;
+ case AS_2: return &m_boot_space_config;
+ default: break;
+ }
+
+ return nullptr;
+}
+
+READ32_MEMBER(cammu_device::mmu_r)
+{
+ u32 ssw = m_ssw_func();
+ u32 address = offset << 2;
+
+ // in supervisor mode, the first 8 pages are always mapped via the hard-wired tlb
+ if ((ssw & 0x40000000) == 0 && (address & ~0x7fff) == 0)
+ {
+ switch (address & 0xf000)
+ {
+ case 0x0000:
+ case 0x1000:
+ case 0x2000:
+ case 0x3000:
+ // pages 0-3: main space pages 0-3
+ return m_main_space->read_dword(address, mem_mask);
+
+ case 0x4000:
+ case 0x5000:
+ // pages 4-5: i/o space pages 0-1
+ return m_io_space->read_dword(address & 0x1fff, mem_mask);
+
+ case 0x6000:
+ case 0x7000:
+ // pages 6-7: boot space pages 0-1
+ return m_boot_space->read_dword(address & 0x1fff, mem_mask);
+ }
+ }
+
+ // FIXME: currently maps addresses with upper bits 0x00 or 0x7f1 to main memory and everything else to I/O
+ if ((address & 0xff000000) == 0x00000000 || (address & 0xfff00000) == 0x7f100000)
+ {
+#ifdef ICACHE_ENTRIES
+ // if this is an instruction fetch, check the cache first
+ if (space.spacenum() == AS_PROGRAM)
+ {
+ if (m_icache[offset & (ICACHE_ENTRIES-1)].offset != offset)
+ {
+ m_icache[offset & (ICACHE_ENTRIES - 1)].offset = offset;
+ m_icache[offset & (ICACHE_ENTRIES - 1)].data = m_main_space->read_dword(address, mem_mask);
+ }
+
+ return m_icache[offset & (ICACHE_ENTRIES - 1)].data;
+ }
+ else
+#endif
+ return m_main_space->read_dword(address, mem_mask);
+ }
+ else
+ return m_io_space->read_dword(address, mem_mask);
+}
+
+WRITE32_MEMBER(cammu_device::mmu_w)
+{
+ u32 ssw = m_ssw_func();
+ u32 address = offset << 2;
+
+ // in supervisor mode, the first 8 pages are always mapped via the hard-wired tlb
+ if ((ssw & 0x40000000) == 0 && (address & ~0x7fff) == 0)
+ {
+ switch (address & 0xf000)
+ {
+ case 0x0000:
+ case 0x1000:
+ case 0x2000:
+ case 0x3000:
+ // pages 0-3: main space pages 0-3
+ m_main_space->write_dword(address, data, mem_mask);
+ return;
+
+ case 0x4000:
+ case 0x5000:
+ // pages 4-5: i/o space pages 0-1
+ m_io_space->write_dword(address & 0x1fff, data, mem_mask);
+ return;
+
+ case 0x6000:
+ case 0x7000:
+ // pages 6-7: boot space pages 0-1
+ m_boot_space->write_dword(address & 0x1fff, data, mem_mask);
+ return;
+ }
+ }
+
+ // FIXME: currently maps addresses with upper bits 0x00 or 0x7f1 to main memory and everything else to I/O
+ if ((address & 0xff000000) == 0x00000000 || (address & 0xfff00000) == 0x7f100000)
+ m_main_space->write_dword(address, data, mem_mask);
+ else
+ m_io_space->write_dword(address, data, mem_mask);
+}
diff --git a/src/mame/machine/cammu.h b/src/mame/machine/cammu.h
new file mode 100644
index 00000000000..a00208efbb5
--- /dev/null
+++ b/src/mame/machine/cammu.h
@@ -0,0 +1,91 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#pragma once
+
+#ifndef CAMMU_H_
+#define CAMMU_H_
+
+#include "emu.h"
+
+// the following enables a very crude instruction cache - it has known (future)
+// problems, but speeds up cpu execution quite noticeably in the short term by
+// avoiding some of the delays in the mame memory subsystem
+#define ICACHE_ENTRIES 32768
+
+#define MCFG_CAMMU_SSW_CB(_sswcb) \
+ devcb = &cammu_device::static_set_ssw_callback(*device, DEVCB_##_sswcb);
+
+class cammu_device : public device_t, public device_memory_interface
+{
+public:
+ cammu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, const char *source);
+
+ template<class _Object> static devcb_base &static_set_ssw_callback(device_t &device, _Object object) { return downcast<cammu_device &>(device).m_ssw_func.set_callback(object); }
+
+ virtual DECLARE_ADDRESS_MAP(map, 32) = 0;
+
+ DECLARE_READ32_MEMBER(mmu_r);
+ DECLARE_WRITE32_MEMBER(mmu_w);
+
+ DECLARE_READ32_MEMBER(cammu_r) { return m_cammu[offset]; }
+ DECLARE_WRITE32_MEMBER(cammu_w) { m_cammu[offset] = data; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config (address_spacenum spacenum) const override;
+
+private:
+ address_space_config m_main_space_config;
+ address_space_config m_io_space_config;
+ address_space_config m_boot_space_config;
+ address_space *m_main_space;
+ address_space *m_io_space;
+ address_space *m_boot_space;
+ devcb_read32 m_ssw_func;
+
+ u32 m_cammu[1024];
+
+#ifdef ICACHE_ENTRIES
+ struct icache
+ {
+ u32 offset;
+ u32 data;
+ } m_icache[ICACHE_ENTRIES];
+#endif
+};
+
+class cammu_c4t_device : public cammu_device
+{
+public:
+ cammu_c4t_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual DECLARE_ADDRESS_MAP(map, 32) override;
+};
+
+class cammu_c4i_device : public cammu_device
+{
+public:
+ cammu_c4i_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual DECLARE_ADDRESS_MAP(map, 32) override;
+};
+
+class cammu_c3_device : public cammu_device
+{
+public:
+ cammu_c3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual DECLARE_ADDRESS_MAP(map, 32) override;
+};
+
+// device type definitions
+extern const device_type CAMMU_C4T;
+extern const device_type CAMMU_C4I;
+extern const device_type CAMMU_C3;
+
+#endif \ No newline at end of file
diff --git a/src/mame/machine/interpro_ioga.cpp b/src/mame/machine/interpro_ioga.cpp
new file mode 100644
index 00000000000..67a47f2cfd0
--- /dev/null
+++ b/src/mame/machine/interpro_ioga.cpp
@@ -0,0 +1,691 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * An implementation of the IOGA device found on Intergraph InterPro family workstations. There is no
+ * public documentation on this device, so the implementation is being built to follow the logic of the
+ * system boot ROM and its diagnostic tests.
+ *
+ * The device handles most of the I/O for the system, including timers, interrupts, DMA and target device
+ * interfacing. There remains a significant amount of work to be completed before the boot diagnostics will
+ * pass without errors, let alone successfully booting CLIX.
+ *
+ * Please be aware that code in here is not only broken, it's likely wrong in many cases.
+ *
+ * TODO
+ * - too long to list
+ */
+#include "interpro_ioga.h"
+
+#define VERBOSE 0
+#if VERBOSE
+#define LOG_TIMER_MASK 0xff
+#define LOG_TIMER(timer, ...) if (LOG_TIMER_MASK & (1 << timer)) logerror(__VA_ARGS__)
+#define LOG_INTERRUPT(...) logerror(__VA_ARGS__)
+#define LOG_IOGA(...) logerror(__VA_ARGS__)
+#define LOG_DMA(...) logerror(__VA_ARGS__)
+#else
+#define LOG_TIMER_MASK 0x00
+#define LOG_TIMER(timer, ...)
+#define LOG_INTERRUPT(...)
+#define LOG_IOGA(...)
+#define LOG_DMA(...)
+#endif
+
+DEVICE_ADDRESS_MAP_START(map, 32, interpro_ioga_device)
+ AM_RANGE(0x0c, 0x1b) AM_READWRITE(dma_plotter_r, dma_plotter_w)
+ AM_RANGE(0x1c, 0x1f) AM_READWRITE(dma_plotter_eosl_r, dma_plotter_eosl_w)
+ AM_RANGE(0x20, 0x2f) AM_READWRITE(dma_scsi_r, dma_scsi_w)
+ AM_RANGE(0x30, 0x3f) AM_READWRITE(dma_floppy_r, dma_floppy_w)
+
+ AM_RANGE(0x5c, 0x7f) AM_READWRITE16(icr_r, icr_w, 0xffffffff)
+ AM_RANGE(0x80, 0x83) AM_READWRITE16(icr18_r, icr18_w, 0x0000ffff)
+ AM_RANGE(0x80, 0x83) AM_READWRITE8(softint_r, softint_w, 0x00ff0000)
+ AM_RANGE(0x80, 0x83) AM_READWRITE8(nmictrl_r, nmictrl_w, 0xff000000)
+
+ AM_RANGE(0x88, 0x8b) AM_READWRITE(timer_prescaler_r, timer_prescaler_w)
+ AM_RANGE(0x8c, 0x8f) AM_READWRITE(timer0_r, timer0_w)
+ AM_RANGE(0x90, 0x93) AM_READWRITE(timer1_r, timer1_w)
+ AM_RANGE(0x94, 0x97) AM_READ(error_address_r)
+ AM_RANGE(0x98, 0x9b) AM_READ(error_businfo_r)
+ AM_RANGE(0x9c, 0x9f) AM_READWRITE16(arbctl_r, arbctl_w, 0x0000ffff)
+
+ AM_RANGE(0xa8, 0xab) AM_READWRITE(timer3_r, timer3_w)
+
+ AM_RANGE(0xb0, 0xbf) AM_READWRITE16(softint_vector_r, softint_vector_w, 0xffffffff)
+ADDRESS_MAP_END
+
+const device_type INTERPRO_IOGA = &device_creator<interpro_ioga_device>;
+
+interpro_ioga_device::interpro_ioga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, INTERPRO_IOGA, "InterPro IOGA", tag, owner, clock, "ioga", __FILE__),
+ m_out_nmi_func(*this),
+ m_out_int_func(*this),
+ m_memory_space(nullptr),
+ m_dma_channel{
+ { 0,0,0,0,false, 0, {*this}, {*this} },
+ { 0,0,0,0,false, 0, {*this}, {*this} },
+ { 0,0,0,0,false, 0, {*this}, {*this} },
+ { 0,0,0,0,false, 0, {*this}, {*this} } },
+ m_fdc_tc_func(*this)
+{
+}
+
+void interpro_ioga_device::device_start()
+{
+ // resolve callbacks
+ m_out_nmi_func.resolve();
+ m_out_int_func.resolve();
+
+ // TODO: parameterise the cammu name and space number
+ // grab the main memory space from the mmu so we can do DMA to/from it
+ device_memory_interface *mmu;
+ siblingdevice("mmu")->interface(mmu);
+ m_memory_space = &mmu->space(AS_0);
+
+ for (int i = 0; i < IOGA_DMA_CHANNELS; i++)
+ {
+ m_dma_channel[i].device_r.resolve_safe(0xff);
+ m_dma_channel[i].device_w.resolve();
+ }
+
+ m_fdc_tc_func.resolve();
+
+ // allocate ioga timers
+ m_timer[0] = timer_alloc(IOGA_TIMER_0);
+ m_timer[1] = timer_alloc(IOGA_TIMER_1);
+ m_timer[2] = timer_alloc(IOGA_TIMER_2);
+ m_timer[3] = timer_alloc(IOGA_TIMER_3);
+
+ for (auto & elem : m_timer)
+ elem->enable(false);
+
+ // allocate timer for DMA controller
+ m_dma_timer = timer_alloc(IOGA_TIMER_DMA);
+ m_dma_timer->adjust(attotime::never);
+}
+
+void interpro_ioga_device::device_reset()
+{
+ m_nmi_pending = false;
+
+ m_interrupt_active = 0;
+ m_irq_forced = 0;
+
+ // configure timer 0 at 60Hz
+ m_timer_reg[0] = 0;
+ m_timer[0]->adjust(attotime::zero, IOGA_TIMER_0, attotime::from_hz(60));
+}
+
+/******************************************************************************
+ Timers
+******************************************************************************/
+READ32_MEMBER(interpro_ioga_device::timer1_r)
+{
+ uint32_t result = m_timer1_count & IOGA_TIMER1_VMASK;
+
+ // set the start bit if the timer is currently enabled
+ if (m_timer[1]->enabled())
+ result |= IOGA_TIMER1_START;
+ else if (m_timer[1]->param())
+ result |= IOGA_TIMER1_EXPIRED;
+
+ return result;
+}
+
+READ32_MEMBER(interpro_ioga_device::timer3_r)
+{
+ uint32_t result = m_timer3_count & IOGA_TIMER3_VMASK;
+
+ if (m_timer[3]->enabled())
+ result |= IOGA_TIMER3_START;
+ else if (m_timer[3]->param())
+ result |= IOGA_TIMER3_EXPIRED;
+
+ return result;
+}
+
+void interpro_ioga_device::write_timer(int timer, uint32_t value, device_timer_id id)
+{
+ switch (id)
+ {
+ case IOGA_TIMER_1:
+ // disable the timer
+ m_timer[timer]->enable(false);
+
+ // store the timer count value
+ m_timer1_count = value;
+
+ // start the timer if necessary
+ if (value & IOGA_TIMER1_START)
+ {
+ LOG_TIMER(1, "timer 1: started prescaler %d value %d\n", m_prescaler & 0x7fff, value & IOGA_TIMER1_VMASK);
+
+ // FIXME: this division by 50 is sufficient to pass iogadiag timer 1 tests
+ m_timer[timer]->adjust(attotime::zero, false, attotime::from_usec((m_prescaler & 0x7fff) / 50));
+ }
+ break;
+
+ case IOGA_TIMER_3:
+ // stop the timer so it won't trigger while we're fiddling with it
+ m_timer[timer]->enable(false);
+
+ // write the new value to the timer register
+ m_timer3_count = value & IOGA_TIMER3_VMASK;
+
+ // start the timer if necessary
+ if (value & IOGA_TIMER3_START)
+ {
+ LOG_TIMER(3, "timer 3: started value %d\n", value & IOGA_TIMER3_VMASK);
+
+ m_timer[timer]->adjust(attotime::zero, false, attotime::from_hz(XTAL_25MHz));
+ }
+ break;
+
+ default:
+ // save the value
+ m_timer_reg[timer] = value;
+
+ // timer_set(attotime::from_usec(500), id);
+
+ LOG_TIMER(0xf, "timer %d: set to 0x%x (%d)\n", timer, m_timer_reg[timer], m_timer_reg[timer]);
+ break;
+ }
+}
+
+void interpro_ioga_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case IOGA_TIMER_0:
+ m_timer_reg[0]++;
+ set_irq_line(IOGA_TIMER0_IRQ, ASSERT_LINE);
+ break;
+
+ case IOGA_TIMER_1:
+ // decrement timer count value
+ m_timer1_count--;
+
+ // check if timer has expired
+ if (m_timer1_count == 0)
+ {
+ LOG_TIMER(1, "timer 1: stopped\n");
+
+ // disable timer and set the zero flag
+ timer.enable(false);
+ timer.set_param(true);
+
+ // throw an interrupt
+ set_irq_line(IOGA_TIMER1_IRQ, ASSERT_LINE);
+ }
+ break;
+
+ case IOGA_TIMER_3:
+ // decrement timer count value
+ m_timer3_count--;
+
+ // check for expiry
+ if (m_timer3_count == 0)
+ {
+ LOG_TIMER(3, "timer 3: stopped\n");
+
+ // disable timer and set the zero flag
+ timer.enable(false);
+ timer.set_param(true);
+
+ // throw an interrupt
+ set_irq_line(IOGA_TIMER3_IRQ, ASSERT_LINE);
+ }
+ break;
+
+ case IOGA_TIMER_DMA:
+ // transfer data between device and main memory
+
+ // TODO: figure out what indicates dma write (memory -> device)
+ // TODO: implement multiple dma channels
+ // TODO: virtual memory?
+
+ if (!m_dma_channel[param].dma_active)
+ {
+ LOG_DMA("dma: transfer started, channel = %d, control 0x%08x, real address 0x%08x count 0x%08x\n",
+ param, m_dma_channel[param].control, m_dma_channel[param].real_address, m_dma_channel[param].transfer_count);
+ m_dma_channel[param].dma_active = true;
+ }
+
+ // while the device is requesting a data transfer and the transfer count is not zero
+ while (m_dma_channel[param].drq_state && m_dma_channel[param].transfer_count)
+ {
+ // transfer a byte between device and memory
+ if (true)
+ m_memory_space->write_byte(m_dma_channel[param].real_address, m_dma_channel[param].device_r());
+ else
+ m_dma_channel[param].device_w(m_memory_space->read_byte(m_dma_channel[param].real_address));
+
+ // increment addresses and decrement count
+ m_dma_channel[param].real_address++;
+ m_dma_channel[param].virtual_address++;
+ m_dma_channel[param].transfer_count--;
+ }
+
+ // if there are no more bytes remaining, terminate the transfer
+ if (m_dma_channel[param].transfer_count == 0)
+ {
+ LOG_DMA("dma: transfer stopped, control 0x%08x, real address 0x%08x count 0x%08x\n",
+ m_dma_channel[param].control, m_dma_channel[param].fdc_real_address, m_dma_channel[param].transfer_count);
+
+ if (param == IOGA_DMA_FLOPPY)
+ {
+ LOG_DMA("dma: asserting fdc terminal count line\n");
+
+ m_fdc_tc_func(ASSERT_LINE);
+ m_fdc_tc_func(CLEAR_LINE);
+ }
+
+ m_dma_channel[param].dma_active = false;
+ }
+ break;
+ }
+}
+
+/******************************************************************************
+ Interrupts
+******************************************************************************/
+
+static const uint16_t irq_enable_mask[IOGA_INTERRUPT_COUNT] =
+{
+ IOGA_INTERRUPT_ENABLE_EXTERNAL,
+ IOGA_INTERRUPT_ENABLE_EXTERNAL,
+ IOGA_INTERRUPT_ENABLE_EXTERNAL | IOGA_INTERRUPT_ENABLE_INTERNAL, // external interrupt 0: SCSI
+ IOGA_INTERRUPT_ENABLE_EXTERNAL | IOGA_INTERRUPT_ENABLE_INTERNAL, // external interrupt 1: floppy
+ IOGA_INTERRUPT_ENABLE_EXTERNAL | IOGA_INTERRUPT_ENABLE_INTERNAL, // external interrupt 2: plotter
+ IOGA_INTERRUPT_ENABLE_EXTERNAL,
+ IOGA_INTERRUPT_ENABLE_EXTERNAL,
+ IOGA_INTERRUPT_ENABLE_EXTERNAL,
+
+ IOGA_INTERRUPT_ENABLE_EXTERNAL,
+ IOGA_INTERRUPT_ENABLE_EXTERNAL,
+ IOGA_INTERRUPT_ENABLE_EXTERNAL,
+ IOGA_INTERRUPT_ENABLE_EXTERNAL,
+ IOGA_INTERRUPT_ENABLE_EXTERNAL,
+ IOGA_INTERRUPT_ENABLE_EXTERNAL,
+ IOGA_INTERRUPT_ENABLE_EXTERNAL,
+ IOGA_INTERRUPT_ENABLE_EXTERNAL,
+
+ // internal interrupt 5: serial DMA - one interrupt enable per DMA channel
+ IOGA_INTERRUPT_ENABLE_EXTERNAL << 0 | IOGA_INTERRUPT_ENABLE_EXTERNAL << 1 | IOGA_INTERRUPT_ENABLE_EXTERNAL << 2,
+ IOGA_INTERRUPT_ENABLE_EXTERNAL,
+ IOGA_INTERRUPT_ENABLE_EXTERNAL | IOGA_INTERRUPT_ENABLE_INTERNAL // external interrupt 12: Ethernet
+};
+
+void interpro_ioga_device::set_nmi_line(int state)
+{
+ switch (state)
+ {
+ case ASSERT_LINE:
+
+ LOG_INTERRUPT("nmi: ctrl = 0x%02x\n", m_nmictrl);
+
+ if ((m_nmictrl & IOGA_NMI_ENABLE) == IOGA_NMI_ENABLE)
+ {
+ // if edge triggered mode, clear enable in
+ if (m_nmictrl & IOGA_NMI_EDGE)
+ m_nmictrl &= ~IOGA_NMI_ENABLE_IN;
+
+ m_nmi_pending = true;
+ update_interrupt(ASSERT_LINE);
+ }
+ break;
+
+ case CLEAR_LINE:
+ m_nmi_pending = false;
+ update_interrupt(ASSERT_LINE);
+ break;
+ }
+}
+
+void interpro_ioga_device::set_irq_line(int irq, int state)
+{
+ LOG_INTERRUPT("set_irq_line(%d, %d)\n", irq, state);
+ switch (state)
+ {
+ case ASSERT_LINE:
+ if (m_int_vector[irq] & irq_enable_mask[irq])
+ {
+ // set pending bit
+ m_int_vector[irq] |= IOGA_INTERRUPT_PENDING;
+
+ // update irq line state
+ update_interrupt(state);
+ }
+ else
+ LOG_INTERRUPT("received disabled interrupt irq %d vector 0x%04x\n", irq, m_int_vector[irq]);
+ break;
+
+ case CLEAR_LINE:
+ // clear pending bit
+ m_int_vector[irq] &= ~IOGA_INTERRUPT_PENDING;
+
+ // update irq line state
+ update_interrupt(state);
+ break;
+ }
+}
+
+void interpro_ioga_device::set_irq_soft(int irq, int state)
+{
+ LOG_INTERRUPT("set_irq_soft(%d, %d)\n", irq, state);
+ switch (state)
+ {
+ case ASSERT_LINE:
+ // set pending bit
+ if (irq < 8)
+ m_softint |= 1 << irq;
+ else
+ m_softint_vector[irq - 8] |= IOGA_INTERRUPT_PENDING;
+
+ update_interrupt(state);
+ break;
+
+ case CLEAR_LINE:
+ // clear pending bit
+ if (irq < 8)
+ m_softint &= ~(1 << irq);
+ else
+ m_softint_vector[irq - 8] &= ~IOGA_INTERRUPT_PENDING;
+
+ // update irq line state
+ update_interrupt(state);
+ break;
+ }
+}
+
+IRQ_CALLBACK_MEMBER(interpro_ioga_device::inta_cb)
+{
+ switch (irqline)
+ {
+ case INPUT_LINE_IRQ0:
+ // FIXME: clear pending bit - can't rely on device callbacks
+ switch (m_interrupt_active)
+ {
+ case IOGA_INTERRUPT_INTERNAL:
+ case IOGA_INTERRUPT_EXTERNAL:
+ m_int_vector[m_irq_current] &= ~IOGA_INTERRUPT_PENDING;
+ break;
+
+ case IOGA_INTERRUPT_SOFT_LO:
+ m_softint &= ~(1 << m_irq_current);
+ break;
+
+ case IOGA_INTERRUPT_SOFT_HI:
+ m_softint_vector[m_irq_current] &= ~IOGA_INTERRUPT_PENDING;
+ break;
+ }
+
+ // clear irq line
+ update_interrupt(CLEAR_LINE);
+
+ // fall through to return interrupt vector
+ case -1:
+ // return vector for current interrupt without clearing irq line
+ switch (m_interrupt_active)
+ {
+ case IOGA_INTERRUPT_EXTERNAL:
+ case IOGA_INTERRUPT_INTERNAL:
+ return m_int_vector[m_irq_current] & 0xff;
+
+ case IOGA_INTERRUPT_SOFT_LO:
+ return 0x8f + m_irq_current * 0x10;
+
+ case IOGA_INTERRUPT_SOFT_HI:
+ return m_softint_vector[m_irq_current] & 0xff;
+ }
+ break;
+
+ case INPUT_LINE_NMI:
+ // clear pending flag
+ m_nmi_pending = false;
+
+ // clear line
+ update_interrupt(CLEAR_LINE);
+
+ // return vector
+ return 0;
+ }
+
+ return 0;
+}
+
+void interpro_ioga_device::update_interrupt(int state)
+{
+ switch (state)
+ {
+ case CLEAR_LINE:
+ if (m_interrupt_active)
+ {
+ // the cpu has acknowledged the active interrupt, deassert the nmi/irq line
+ m_interrupt_active == IOGA_INTERRUPT_NMI ? m_out_nmi_func(CLEAR_LINE) : m_out_int_func(CLEAR_LINE);
+
+ // clear the active status
+ m_interrupt_active = 0;
+ }
+ // fall through to handle any pending interrupts
+
+ case ASSERT_LINE:
+ // if an interrupt is currently active, don't do anything
+ if (m_interrupt_active == 0)
+ {
+ // check for pending nmi
+ if (m_nmi_pending)
+ {
+ m_interrupt_active = IOGA_INTERRUPT_NMI;
+
+ m_out_nmi_func(ASSERT_LINE);
+ return;
+ }
+
+ // check for any pending irq
+ for (int i = 0; i < IOGA_INTERRUPT_COUNT; i++)
+ {
+ if (m_int_vector[i] & IOGA_INTERRUPT_PENDING)
+ {
+ m_interrupt_active = IOGA_INTERRUPT_INTERNAL; // TODO: flag internal/external
+ m_irq_current = i;
+
+ m_out_int_func(ASSERT_LINE);
+ return;
+ }
+ }
+
+ // check for any pending soft interrupts (low type)
+ for (int i = 0; i < 8; i++)
+ {
+ if (m_softint & (1 << i))
+ {
+ m_interrupt_active = IOGA_INTERRUPT_SOFT_LO;
+ m_irq_current = i;
+
+ m_out_int_func(ASSERT_LINE);
+ return;
+ }
+ }
+
+ // check for any pending soft interrupts (high type)
+ for (int i = 0; i < 8; i++)
+ {
+ if (m_softint_vector[i] & IOGA_INTERRUPT_PENDING)
+ {
+ m_interrupt_active = IOGA_INTERRUPT_SOFT_HI;
+ m_irq_current = i;
+
+ m_out_int_func(ASSERT_LINE);
+ return;
+ }
+ }
+ }
+ break;
+ }
+}
+
+WRITE16_MEMBER(interpro_ioga_device::icr_w)
+{
+ LOG_INTERRUPT("interrupt vector %d set to 0x%04x at pc 0x%08x\n", offset, data, space.device().safe_pc());
+
+ // FIXME: now that the interrupt handling only depends on IOGA_INTERRUPT_PENDING, we might be able
+ // to avoid this hack
+ if (data & IOGA_INTERRUPT_PENDING)
+ {
+ m_irq_forced |= 1 << offset;
+ m_int_vector[offset] = data & ~IOGA_INTERRUPT_PENDING;
+ }
+ else if (m_irq_forced & 1 << offset)
+ {
+ m_int_vector[offset] = data;
+
+ // clear forced flag
+ m_irq_forced &= ~(1 << offset);
+
+ // force an interrupt
+ set_irq_line(offset, ASSERT_LINE);
+ }
+ else
+ m_int_vector[offset] = data;
+}
+
+WRITE8_MEMBER(interpro_ioga_device::softint_w)
+{
+ // save the existing value
+ uint8_t previous = m_softint;
+
+ // store the written value
+ m_softint = data;
+
+ // force soft interrupt for any bit written from 1 to 0
+ for (int i = 0; i < 8; i++)
+ {
+ uint8_t mask = 1 << i;
+
+ // check for transition from 1 to 0 and force a soft interrupt
+ if (previous & mask && !(data & mask))
+ set_irq_soft(i, ASSERT_LINE);
+ }
+}
+
+WRITE8_MEMBER(interpro_ioga_device::nmictrl_w)
+{
+ // save the existing value
+ uint8_t previous = m_nmictrl;
+
+ // store the written value
+ m_nmictrl = data;
+
+ // force an nmi when pending bit is written low
+ if (previous & IOGA_NMI_PENDING && !(data & IOGA_NMI_PENDING))
+ set_nmi_line(ASSERT_LINE);
+}
+
+WRITE16_MEMBER(interpro_ioga_device::softint_vector_w)
+{
+ // save the existing value
+ uint16_t previous = m_softint_vector[offset];
+
+ // store the written value
+ m_softint_vector[offset] = data;
+
+ // check for transition from 1 to 0 and force a soft interrupt
+ if (previous & IOGA_INTERRUPT_PENDING && !(data & IOGA_INTERRUPT_PENDING))
+ set_irq_soft(offset + 8, ASSERT_LINE);
+}
+
+/******************************************************************************
+ DMA
+******************************************************************************/
+void interpro_ioga_device::drq(int state, int channel)
+{
+ // this member is called when the device has data ready for reading via dma
+ m_dma_channel[channel].drq_state = state;
+
+ if (state)
+ {
+ // TODO: check if dma is enabled
+ m_dma_timer->adjust(attotime::zero, channel);
+ }
+}
+/*
+0x94: error address reg: expect 0x7f200000 after bus error (from dma virtual address)
+0x98: error cycle type: expect 0x52f0 (after failed dma?)
+ 0x5331 - forced berr with nmi/interrupts disabled?
+ 0xc2f0
+ 0x62f0
+*/
+// TODO: 7.0266 - forced BERR not working
+
+uint32_t interpro_ioga_device::dma_r(address_space &space, offs_t offset, uint32_t mem_mask, int channel)
+{
+ switch (offset)
+ {
+ case 0:
+ return m_dma_channel[channel].real_address;
+
+ case 1:
+ return m_dma_channel[channel].virtual_address;
+
+ case 2:
+ return m_dma_channel[channel].transfer_count;
+
+ case 3:
+ return m_dma_channel[channel].control;
+ }
+
+ logerror("dma_r: unknown channel %d\n", channel);
+ return 0;
+}
+
+void interpro_ioga_device::dma_w(address_space &space, offs_t offset, uint32_t data, uint32_t mem_mask, int channel)
+{
+ switch (offset)
+ {
+ case 0:
+ m_dma_channel[channel].real_address = data;
+ break;
+
+ case 1:
+ m_dma_channel[channel].virtual_address = data & ~0x3;
+ break;
+
+ case 2:
+ m_dma_channel[channel].transfer_count = data;
+ break;
+
+ case 3:
+ m_dma_channel[channel].control = data & IOGA_DMA_CTRL_WMASK;
+
+ logerror("dma: channel = %d, control = 0x%08x, ra = 0x%08x, va = 0x%08x, tc = 0x%08x\n",
+ channel, data, m_dma_channel[channel].real_address, m_dma_channel[channel].virtual_address, m_dma_channel[channel].transfer_count);
+
+ // iogadiag test 7.0265
+ if (data == IOGA_DMA_CTRL_START)
+ {
+ uint32_t mask = 0;
+
+ switch (channel)
+ {
+ case IOGA_DMA_PLOTTER:
+ mask = IOGA_ARBCTL_BGR_PLOT;
+ break;
+
+ case IOGA_DMA_SCSI:
+ mask = IOGA_ARBCTL_BGR_SCSI;
+ break;
+
+ case IOGA_DMA_FLOPPY:
+ mask = IOGA_ARBCTL_BGR_FDC;
+ break;
+ }
+
+ // if bus grant is not enabled, set the busy flag
+ if (!(m_arbctl & mask))
+ m_dma_channel[channel].control |= IOGA_DMA_CTRL_BUSY;
+ }
+ break;
+ }
+}
diff --git a/src/mame/machine/interpro_ioga.h b/src/mame/machine/interpro_ioga.h
new file mode 100644
index 00000000000..2809601d98e
--- /dev/null
+++ b/src/mame/machine/interpro_ioga.h
@@ -0,0 +1,255 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#pragma once
+
+#ifndef INTERPRO_IOGA_H_
+#define INTERPRO_IOGA_H_
+
+#include "emu.h"
+
+#define MCFG_INTERPRO_IOGA_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, INTERPRO_IOGA, 0)
+
+#define MCFG_INTERPRO_IOGA_NMI_CB(_out_nmi) \
+ devcb = &interpro_ioga_device::static_set_out_nmi_callback(*device, DEVCB_##_out_nmi);
+
+#define MCFG_INTERPRO_IOGA_IRQ_CB(_out_int) \
+ devcb = &interpro_ioga_device::static_set_out_int_callback(*device, DEVCB_##_out_int);
+
+#define MCFG_INTERPRO_IOGA_DMA_CB(_channel, _dma_r, _dma_w) \
+ devcb = &interpro_ioga_device::static_set_dma_r_callback(*device, _channel, DEVCB_##_dma_r); \
+ devcb = &interpro_ioga_device::static_set_dma_w_callback(*device, _channel, DEVCB_##_dma_w);
+
+#define MCFG_INTERPRO_IOGA_FDCTC_CB(_tc) \
+ devcb = &interpro_ioga_device::static_set_fdc_tc_callback(*device, DEVCB_##_tc);
+
+#define MCFG_INTERPRO_IOGA_DMA_BUS(_mmu, _space)
+
+// timer 0 seem to be a 60Hz cycle
+#define IOGA_TIMER0_IRQ 14
+
+// best guess for timer 1 is 10MHz based on typical prescaler value of 1000 and timer value of 100 for a delay of 100ms
+#define IOGA_TIMER1_IRQ 15
+#define IOGA_TIMER1_VMASK 0xffff
+#define IOGA_TIMER1_START 0x10000
+#define IOGA_TIMER1_EXPIRED 0x20000
+
+// best guess for timer 3 is 12.5MHz based on typical value of 12500 for a delay of 1ms
+#define IOGA_TIMER3_CLOCK XTAL_12_5MHz
+#define IOGA_TIMER3_IRQ 1
+#define IOGA_TIMER3_VMASK 0x3fffffff
+#define IOGA_TIMER3_START 0x40000000
+#define IOGA_TIMER3_EXPIRED 0x80000000
+
+#define IOGA_INTERRUPT_COUNT 19
+#define IOGA_INTERRUPT_PENDING 0x0100
+#define IOGA_INTERRUPT_ENABLE_EXTERNAL 0x0200
+#define IOGA_INTERRUPT_EDGE 0x0400
+#define IOGA_INTERRUPT_NEGPOL 0x0800
+#define IOGA_INTERRUPT_ENABLE_INTERNAL 0x1000
+
+#define IOGA_NMI_EDGE 0x02
+#define IOGA_NMI_PENDING 0x08
+#define IOGA_NMI_ENABLE_IN 0x10
+#define IOGA_NMI_ENABLE (IOGA_NMI_EDGE | IOGA_NMI_ENABLE_IN)
+
+#define IOGA_INTERRUPT_NMI 1
+#define IOGA_INTERRUPT_INTERNAL 2
+#define IOGA_INTERRUPT_EXTERNAL 3
+#define IOGA_INTERRUPT_SOFT_LO 4
+#define IOGA_INTERRUPT_SOFT_HI 5
+
+#define IOGA_DMA_CHANNELS 4
+#define IOGA_DMA_PLOTTER 0
+#define IOGA_DMA_SCSI 1
+#define IOGA_DMA_FLOPPY 2
+#define IOGA_DMA_SERIAL 3
+
+// dma write values
+#define IOGA_DMA_CTRL_WMASK 0xfd000e00
+#define IOGA_DMA_CTRL_RESET_L 0x61000000 // do not clear bus error bit
+#define IOGA_DMA_CTRL_RESET 0x60400000 // clear bus error bit
+
+#define IOGA_DMA_CTRL_START 0x63000800 // perhaps start a transfer? - maybe the 8 is the channel?
+#define IOGA_DMA_CTRL_UNK1 0x60000000 // don't know yet
+#define IOGA_DMA_CTRL_UNK2 0x67000600 // forced berr with nmi and interrupts disabled
+
+// read values
+#define IOGA_DMA_CTRL_BUSY 0x02000000
+#define IOGA_DMA_CTRL_BERR 0x00400000 // iogadiag code expects 0x60400000 on bus error
+// iogadiag expects 0x64400800 after forced berr with nmi/interrupts disabled
+
+
+// bus arbitration bus grant bits
+#define IOGA_ARBCTL_BGR_ETHC 0x0001
+#define IOGA_ARBCTL_BGR_SCSI 0x0002
+#define IOGA_ARBCTL_BGR_PLOT 0x0004
+#define IOGA_ARBCTL_BGR_FDC 0x0008
+#define IOGA_ARBCTL_BGR_SER0 0x0010
+#define IOGA_ARBCTL_BGR_SER1 0x0020
+#define IOGA_ARBCTL_BGR_SER2 0x0040
+#define IOGA_ARBCTL_BGR_ETHB 0x0080
+#define IOGA_ARBCTL_BGR_ETHA 0x0100
+
+class interpro_ioga_device : public device_t
+{
+public:
+ interpro_ioga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ template<class _Object> static devcb_base &static_set_out_nmi_callback(device_t &device, _Object object) { return downcast<interpro_ioga_device &>(device).m_out_nmi_func.set_callback(object); }
+ template<class _Object> static devcb_base &static_set_out_int_callback(device_t &device, _Object object) { return downcast<interpro_ioga_device &>(device).m_out_int_func.set_callback(object); }
+
+ template<class _Object> static devcb_base &static_set_dma_r_callback(device_t &device, int channel, _Object object) { return downcast<interpro_ioga_device &>(device).m_dma_channel[channel].device_r.set_callback(object); }
+ template<class _Object> static devcb_base &static_set_dma_w_callback(device_t &device, int channel, _Object object) { return downcast<interpro_ioga_device &>(device).m_dma_channel[channel].device_w.set_callback(object); }
+
+ template<class _Object> static devcb_base &static_set_fdc_tc_callback(device_t &device, _Object object) { return downcast<interpro_ioga_device &>(device).m_fdc_tc_func.set_callback(object); }
+
+ virtual DECLARE_ADDRESS_MAP(map, 32);
+
+ // external interrupt lines
+ DECLARE_WRITE_LINE_MEMBER(ir0_w) { set_irq_line(2, state); }
+ DECLARE_WRITE_LINE_MEMBER(ir1_w) { set_irq_line(3, state); }
+ DECLARE_WRITE_LINE_MEMBER(ir2_w) { set_irq_line(4, state); }
+ DECLARE_WRITE_LINE_MEMBER(ir3_w) { set_irq_line(5, state); }
+ DECLARE_WRITE_LINE_MEMBER(ir4_w) { set_irq_line(6, state); }
+ DECLARE_WRITE_LINE_MEMBER(ir5_w) { set_irq_line(7, state); }
+ DECLARE_WRITE_LINE_MEMBER(ir6_w) { set_irq_line(8, state); }
+ DECLARE_WRITE_LINE_MEMBER(ir7_w) { set_irq_line(9, state); }
+ DECLARE_WRITE_LINE_MEMBER(ir8_w) { set_irq_line(10, state); }
+ // FIXME: this is a workaround for the mc146818 code which inverts the normal irq state convention
+ DECLARE_WRITE_LINE_MEMBER(ir9_w) { set_irq_line(11, !state); }
+ DECLARE_WRITE_LINE_MEMBER(ir10_w) { set_irq_line(12, state); }
+ DECLARE_WRITE_LINE_MEMBER(ir11_w) { set_irq_line(17, state); }
+ DECLARE_WRITE_LINE_MEMBER(ir12_w) { set_irq_line(18, state); }
+
+ IRQ_CALLBACK_MEMBER(inta_cb);
+
+ DECLARE_WRITE_LINE_MEMBER(drq_plotter) { drq(state, IOGA_DMA_PLOTTER); }
+ DECLARE_WRITE_LINE_MEMBER(drq_scsi) { drq(state, IOGA_DMA_SCSI); }
+ DECLARE_WRITE_LINE_MEMBER(drq_floppy) { drq(state, IOGA_DMA_FLOPPY); }
+
+ DECLARE_READ32_MEMBER(timer_prescaler_r) { return m_prescaler; }
+ DECLARE_READ32_MEMBER(timer0_r) { return m_timer_reg[0]; }
+ DECLARE_READ32_MEMBER(timer1_r);
+ DECLARE_READ16_MEMBER(arbctl_r) { return m_arbctl; }
+ DECLARE_WRITE16_MEMBER(arbctl_w) { m_arbctl = data; }
+ DECLARE_READ32_MEMBER(timer2_r) { return m_timer_reg[2]; }
+ DECLARE_READ32_MEMBER(timer3_r);
+
+ DECLARE_WRITE32_MEMBER(timer_prescaler_w) {
+ // this logic satisfies prescaler tests, but fails timer prescaler tests
+ if ((data & 0x7fff) < 0x100 && (data & 0x7fff) != 0)
+ m_prescaler = (data ^ 0xffff0000);
+ else
+ m_prescaler = (data ^ 0xffff0000) - 0x10000;
+
+ //logerror("prescaler: input 0x%08x output 0x%08x\n", data, m_prescaler);
+ }
+ DECLARE_WRITE32_MEMBER(timer0_w) { write_timer(0, data, IOGA_TIMER_0); }
+ DECLARE_WRITE32_MEMBER(timer1_w) { write_timer(1, data, IOGA_TIMER_1); }
+ DECLARE_WRITE32_MEMBER(timer2_w) { write_timer(2, data, IOGA_TIMER_2); }
+ DECLARE_WRITE32_MEMBER(timer3_w) { write_timer(3, data, IOGA_TIMER_3); }
+
+ DECLARE_READ16_MEMBER(icr_r) { return m_int_vector[offset]; }
+ DECLARE_WRITE16_MEMBER(icr_w);
+ DECLARE_READ16_MEMBER(icr18_r) { return icr_r(space, 18, mem_mask); }
+ DECLARE_WRITE16_MEMBER(icr18_w) { icr_w(space, 18, data, mem_mask); }
+
+ DECLARE_READ8_MEMBER(softint_r) { return m_softint; }
+ DECLARE_WRITE8_MEMBER(softint_w);
+ DECLARE_READ8_MEMBER(nmictrl_r) { return m_nmictrl; }
+ DECLARE_WRITE8_MEMBER(nmictrl_w);
+
+ DECLARE_READ16_MEMBER(softint_vector_r) { return m_softint_vector[offset]; }
+ DECLARE_WRITE16_MEMBER(softint_vector_w);
+
+ DECLARE_READ32_MEMBER(dma_plotter_r) { return dma_r(space, offset, mem_mask, IOGA_DMA_PLOTTER); }
+ DECLARE_WRITE32_MEMBER(dma_plotter_w) { dma_w(space, offset, data, mem_mask, IOGA_DMA_PLOTTER); }
+ DECLARE_READ32_MEMBER(dma_scsi_r) { return dma_r(space, offset, mem_mask, IOGA_DMA_SCSI); }
+ DECLARE_WRITE32_MEMBER(dma_scsi_w) { dma_w(space, offset, data, mem_mask, IOGA_DMA_SCSI); }
+ DECLARE_READ32_MEMBER(dma_floppy_r) { return dma_r(space, offset, mem_mask, IOGA_DMA_FLOPPY); }
+ DECLARE_WRITE32_MEMBER(dma_floppy_w) { dma_w(space, offset, data, mem_mask, IOGA_DMA_FLOPPY); }
+
+ DECLARE_READ32_MEMBER(dma_plotter_eosl_r) { return m_dma_plotter_eosl; }
+ DECLARE_WRITE32_MEMBER(dma_plotter_eosl_w) { m_dma_plotter_eosl = data; }
+
+ DECLARE_READ32_MEMBER(error_address_r) { return m_error_address; }
+ DECLARE_READ32_MEMBER(error_businfo_r) { return m_error_businfo; }
+ void bus_error(uint32_t address, uint32_t cycle_type) { m_error_address = address; m_error_businfo = cycle_type; }
+
+protected:
+ // device-level overrides
+ 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;
+
+private:
+ static const device_timer_id IOGA_TIMER_0 = 0;
+ static const device_timer_id IOGA_TIMER_1 = 1;
+ static const device_timer_id IOGA_TIMER_2 = 2;
+ static const device_timer_id IOGA_TIMER_3 = 3;
+
+ static const device_timer_id IOGA_TIMER_DMA = 4;
+
+ void set_nmi_line(int state);
+ void set_irq_line(int irq, int state);
+ void set_irq_soft(int irq, int state);
+ void write_timer(int timer, uint32_t value, device_timer_id id);
+
+ void update_interrupt(int state);
+
+ void drq(int state, int channel);
+ devcb_write_line m_out_nmi_func;
+ devcb_write_line m_out_int_func;
+ address_space *m_memory_space;
+
+ // dma channels
+ struct dma
+ {
+ uint32_t real_address;
+ uint32_t virtual_address;
+ uint32_t transfer_count;
+ uint32_t control;
+
+ bool dma_active;
+ int drq_state;
+ devcb_read8 device_r;
+ devcb_write8 device_w;
+ } m_dma_channel[IOGA_DMA_CHANNELS];
+ uint32_t m_dma_plotter_eosl;
+
+ devcb_write_line m_fdc_tc_func;
+
+ bool m_nmi_pending;
+ uint32_t m_interrupt_active;
+ uint32_t m_irq_current;
+ uint32_t m_irq_forced;
+
+ uint16_t m_int_vector[IOGA_INTERRUPT_COUNT];
+ uint8_t m_softint;
+ uint8_t m_nmictrl;
+ uint16_t m_softint_vector[8];
+
+ uint32_t m_prescaler;
+ uint32_t m_timer_reg[3];
+ uint16_t m_timer1_count;
+ uint32_t m_timer3_count;
+ emu_timer *m_timer[4];
+
+ // dma state
+ emu_timer *m_dma_timer;
+
+ uint32_t dma_r(address_space &space, offs_t offset, uint32_t mem_mask, int channel);
+ void dma_w(address_space &space, offs_t offset, uint32_t data, uint32_t mem_mask, int channel);
+
+ uint16_t m_arbctl;
+
+ uint32_t m_error_address;
+ uint32_t m_error_businfo;
+};
+
+// device type definition
+extern const device_type INTERPRO_IOGA;
+
+#endif \ No newline at end of file
diff --git a/src/mame/machine/interpro_mcga.cpp b/src/mame/machine/interpro_mcga.cpp
new file mode 100644
index 00000000000..d807f571bab
--- /dev/null
+++ b/src/mame/machine/interpro_mcga.cpp
@@ -0,0 +1,89 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+* An implementation of the MCGA device found on Intergraph InterPro family workstations. There is no
+* public documentation on this device, so the implementation is being built to follow the logic of the
+* system boot ROM and its diagnostic tests.
+*
+* Please be aware that code in here is not only broken, it's likely wrong in many cases.
+*
+* TODO
+* - too long to list
+*/
+#include "interpro_mcga.h"
+
+#define VERBOSE 0
+#if VERBOSE
+#define LOG_MCGA(...) logerror(__VA_ARGS__)
+#else
+#define LOG_MCGA(...) {}
+#endif
+
+DEVICE_ADDRESS_MAP_START(map, 16, interpro_mcga_device)
+ AM_RANGE(0x00, 0x3f) AM_READWRITE16(read, write, 0xffff)
+ADDRESS_MAP_END
+
+const device_type INTERPRO_MCGA = &device_creator<interpro_mcga_device>;
+
+interpro_mcga_device::interpro_mcga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, INTERPRO_MCGA, "InterPro MCGA", tag, owner, clock, "mcga", __FILE__)
+{
+}
+
+void interpro_mcga_device::device_start()
+{
+}
+
+void interpro_mcga_device::device_reset()
+{
+ m_reg[0] = 0x00ff; // 0x00
+ m_reg[2] = MCGA_CTRL_ENREFRESH | MCGA_CTRL_CBITFRCSUB | MCGA_CTRL_CBITFRCRD; // 0x08 ctrl
+ //m_mcga[4] = 0x8000; // 0x10 error
+ m_reg[10] = 0x00ff; // 0x28
+ m_reg[14] = 0x0340; // 0x38 memsize
+}
+
+WRITE16_MEMBER(interpro_mcga_device::write)
+{
+ /*
+ read MEMSIZE 0x38 mask 0xffff
+ read 0x00 mask 0x0000
+ write CBSUB 0x20 mask 0x00ff data 0
+ write FRCRD 0x18 mask 0x00ff data 0
+ read ERROR 0x10 mask 0xffff
+ read 0x00 mask 0xffff
+
+ (0x38 >> 8) & 0xF == 3?
+
+ if (0x00 != 0xFF) -> register reset error
+
+ 0x00 = 0x0055 (test value & 0xff)
+ r7 = 0x00 & 0xff
+ */
+ LOG_MCGA("mcga write offset = 0x%08x, mask = 0x%08x, data = 0x%08x, pc = 0x%08x\n", offset, mem_mask, data, space.device().safe_pc());
+ switch (offset)
+ {
+ case 0x02: // MCGA_CTRL
+ // HACK: set or clear error status depending on ENMMBE bit
+ if (data & MCGA_CTRL_ENMMBE)
+ m_reg[4] |= MCGA_ERROR_VALID;
+ // else
+ // m_reg[4] &= ~MCGA_ERROR_VALID;
+
+ default:
+ m_reg[offset] = data;
+ break;
+ }
+}
+
+READ16_MEMBER(interpro_mcga_device::read)
+{
+ LOG_MCGA("mcga read offset = 0x%08x, mask = 0x%08x, pc = 0x%08x\n", offset, mem_mask, space.device().safe_pc());
+
+ switch (offset)
+ {
+ default:
+ return m_reg[offset];
+ }
+} \ No newline at end of file
diff --git a/src/mame/machine/interpro_mcga.h b/src/mame/machine/interpro_mcga.h
new file mode 100644
index 00000000000..4f3ecde78cc
--- /dev/null
+++ b/src/mame/machine/interpro_mcga.h
@@ -0,0 +1,45 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#pragma once
+
+#ifndef INTERPRO_MCGA_H_
+#define INTERPRO_MCGA_H_
+
+#include "emu.h"
+
+// mcga control register
+#define MCGA_CTRL_OPTMASK 0x00000003
+#define MCGA_CTRL_CBITFRCRD 0x00000004
+#define MCGA_CTRL_CBITFRCSUB 0x00000008
+#define MCGA_CTRL_ENREFRESH 0x00000010
+#define MCGA_CTRL_ENMSBE 0x00000100
+#define MCGA_CTRL_ENMMBE 0x00000200
+#define MCGA_CTRL_ENECC 0x00000400
+#define MCGA_CTRL_WRPROT 0x00008000
+
+// mcga error register
+#define MCGA_ERROR_VALID 0x00008000
+
+class interpro_mcga_device : public device_t
+{
+public:
+ interpro_mcga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual DECLARE_ADDRESS_MAP(map, 32);
+
+ DECLARE_WRITE16_MEMBER(write);
+ DECLARE_READ16_MEMBER(read);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ uint16_t m_reg[32];
+};
+
+// device type definition
+extern const device_type INTERPRO_MCGA;
+
+#endif \ No newline at end of file
diff --git a/src/mame/machine/interpro_sga.cpp b/src/mame/machine/interpro_sga.cpp
new file mode 100644
index 00000000000..102c58a2f0b
--- /dev/null
+++ b/src/mame/machine/interpro_sga.cpp
@@ -0,0 +1,88 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+* An implementation of the SGA device found on Intergraph InterPro family workstations. There is no
+* public documentation on this device, so the implementation is being built to follow the logic of the
+* system boot ROM and its diagnostic tests.
+*
+* Please be aware that code in here is not only broken, it's likely wrong in many cases.
+*
+* TODO
+* - too long to list
+*/
+#include "interpro_sga.h"
+
+#define VERBOSE 0
+
+DEVICE_ADDRESS_MAP_START(map, 32, interpro_sga_device)
+ AM_RANGE(0x00, 0x03) AM_READWRITE(gcs_r, gcs_w)
+ AM_RANGE(0x04, 0x07) AM_READWRITE(ipoll_r, ipoll_w)
+ AM_RANGE(0x08, 0x0b) AM_READWRITE(imask_r, imask_w)
+ AM_RANGE(0x0c, 0x0f) AM_READWRITE(range_base_r, range_base_w)
+ AM_RANGE(0x10, 0x13) AM_READWRITE(range_end_r, range_end_w)
+ AM_RANGE(0x14, 0x17) AM_READWRITE(cttag_r, cttag_w)
+ AM_RANGE(0x18, 0x1b) AM_READWRITE(address_r, address_w)
+ AM_RANGE(0x1c, 0x1f) AM_READWRITE(dmacs_r, dmacs_w)
+ AM_RANGE(0x20, 0x23) AM_READWRITE(edmacs_r, edmacs_w)
+
+ AM_RANGE(0xa4, 0xa7) AM_READWRITE(dspad1_r, dspad1_w)
+ AM_RANGE(0xa8, 0xab) AM_READWRITE(dsoff1_r, dsoff1_w)
+
+ AM_RANGE(0xb4, 0xb7) AM_READWRITE(unknown1_r, unknown1_w)
+ AM_RANGE(0xb8, 0xbb) AM_READWRITE(unknown2_r, unknown2_w)
+ AM_RANGE(0xbc, 0xbf) AM_READWRITE(ddtc1_r, ddtc1_w)
+ADDRESS_MAP_END
+
+const device_type INTERPRO_SGA = &device_creator<interpro_sga_device>;
+
+interpro_sga_device::interpro_sga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, INTERPRO_SGA, "InterPro SGA", tag, owner, clock, "sga", __FILE__)
+{
+}
+
+void interpro_sga_device::device_start()
+{
+}
+
+void interpro_sga_device::device_reset()
+{
+}
+
+WRITE32_MEMBER(interpro_sga_device::ddtc1_w)
+{
+ // we assume that when this register is written, we should start a
+ // memory to memory dma transfer
+
+ logerror(" gcs = 0x%08x dmacs = 0x%08x\n", m_gcs, m_dmacs);
+ logerror(" ipoll = 0x%08x imask = 0x%08x\n", m_ipoll, m_imask);
+ logerror("dspad1 = 0x%08x dsoff1 = 0x%08x\n", m_dspad1, m_dsoff1);
+ logerror(" unk1 = 0x%08x unk2 = 0x%08x\n", m_unknown1, m_unknown2);
+ logerror(" ddtc1 = 0x%08x\n", data);
+
+ m_ddtc1 = data;
+
+ // when complete, we indicate by setting DMAEND(2) - 2 is probably the channel
+ // we also turn off the INTBERR and INTMMBE flags
+ m_ipoll &= ~(0x20000 | 0x10000);
+ m_ipoll |= 0x200;
+
+ // if the address is invalid, fake a bus error
+ if (m_dspad1 == 0x40000000 || m_unknown1 == 0x40000000
+ || m_dspad1 == 0x40000200 || m_unknown1 == 0x40000200)
+ {
+ m_ipoll |= 0x10000;
+
+ // error cycle - bit 0x10 indicates source address error (dspad1)
+ // now expecting 0x5463?
+#if 0
+ if ((m_dspad1 & 0xfffff000) == 0x40000000)
+ m_ioga->bus_error(m_dspad1, 0x5433);
+ else
+ m_ioga->bus_error(m_unknown1, 0x5423);
+#endif
+ // 0x5423 = BERR|SNAPOK | BG(ICAMMU)? | CT(23)
+ // 0x5433 = BERR|SNAPOK | BG(ICAMMU)? | CT(33)
+ // 0x5463 = BERR|SNAPOK | BG(ICAMMU)? | TAG(1) | CT(23)
+ }
+}
diff --git a/src/mame/machine/interpro_sga.h b/src/mame/machine/interpro_sga.h
new file mode 100644
index 00000000000..06c2d1fba8f
--- /dev/null
+++ b/src/mame/machine/interpro_sga.h
@@ -0,0 +1,71 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#pragma once
+
+#ifndef INTERPRO_SGA_H_
+#define INTERPRO_SGA_H_
+
+#include "emu.h"
+
+class interpro_sga_device : public device_t
+{
+public:
+ interpro_sga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual DECLARE_ADDRESS_MAP(map, 32);
+
+ DECLARE_READ32_MEMBER(gcs_r) { return m_gcs; }
+ DECLARE_WRITE32_MEMBER(gcs_w) { m_gcs = data; }
+ DECLARE_READ32_MEMBER(ipoll_r) { return m_ipoll; }
+ DECLARE_WRITE32_MEMBER(ipoll_w) { m_ipoll = data; }
+ DECLARE_READ32_MEMBER(imask_r) { return m_imask; }
+ DECLARE_WRITE32_MEMBER(imask_w) { m_imask = data; }
+ DECLARE_READ32_MEMBER(range_base_r) { return m_range_base; }
+ DECLARE_WRITE32_MEMBER(range_base_w) { m_range_base = data; }
+ DECLARE_READ32_MEMBER(range_end_r) { return m_range_end; }
+ DECLARE_WRITE32_MEMBER(range_end_w) { m_range_end = data; }
+ DECLARE_READ32_MEMBER(cttag_r) { return m_cttag; }
+ DECLARE_WRITE32_MEMBER(cttag_w) { m_cttag = data; }
+ DECLARE_READ32_MEMBER(address_r) { return m_address; }
+ DECLARE_WRITE32_MEMBER(address_w) { m_address = data; }
+ DECLARE_READ32_MEMBER(dmacs_r) { return m_dmacs; }
+ DECLARE_WRITE32_MEMBER(dmacs_w) { m_dmacs = data; }
+ DECLARE_READ32_MEMBER(edmacs_r) { return m_edmacs; }
+ DECLARE_WRITE32_MEMBER(edmacs_w) { m_edmacs = data; }
+ DECLARE_READ32_MEMBER(dspad1_r) { return m_dspad1; }
+ DECLARE_WRITE32_MEMBER(dspad1_w) { m_dspad1 = data; }
+ DECLARE_READ32_MEMBER(dsoff1_r) { return m_dsoff1; }
+ DECLARE_WRITE32_MEMBER(dsoff1_w) { m_dsoff1 = data; }
+ DECLARE_READ32_MEMBER(unknown1_r) { return m_unknown1; }
+ DECLARE_WRITE32_MEMBER(unknown1_w) { m_unknown1 = data; }
+ DECLARE_READ32_MEMBER(unknown2_r) { return m_unknown2; }
+ DECLARE_WRITE32_MEMBER(unknown2_w) { m_unknown2 = data; }
+ DECLARE_READ32_MEMBER(ddtc1_r) { return m_ddtc1; }
+ DECLARE_WRITE32_MEMBER(ddtc1_w);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ uint32_t m_gcs; // general control/status
+ uint32_t m_ipoll; // interrupt poll
+ uint32_t m_imask; // interrupt mask
+ uint32_t m_range_base;
+ uint32_t m_range_end;
+ uint32_t m_cttag; // error cycletype/tag
+ uint32_t m_address;
+ uint32_t m_dmacs; // dma control/status
+ uint32_t m_edmacs; // extended dma control/status
+ uint32_t m_dspad1;
+ uint32_t m_dsoff1;
+ uint32_t m_unknown1;
+ uint32_t m_unknown2;
+ uint32_t m_ddtc1;
+};
+
+// device type definition
+extern const device_type INTERPRO_SGA;
+
+#endif \ No newline at end of file
diff --git a/src/mame/machine/namco_c148.cpp b/src/mame/machine/namco_c148.cpp
index e7e60b8aeb7..a12ece76d55 100644
--- a/src/mame/machine/namco_c148.cpp
+++ b/src/mame/machine/namco_c148.cpp
@@ -111,6 +111,14 @@ void namco_c148_device::device_start()
m_out_ext2_cb.resolve_safe();
// TODO: link to SCI, EX and the screen device controller devices
+
+ save_item(NAME(m_irqlevel.cpu));
+ save_item(NAME(m_irqlevel.ex));
+ save_item(NAME(m_irqlevel.sci));
+ save_item(NAME(m_irqlevel.pos));
+ save_item(NAME(m_irqlevel.vblank));
+ save_item(NAME(m_posirq_line));
+ save_item(NAME(m_bus_reg));
}
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index 1cbafedb3b8..6b697552df4 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -1414,6 +1414,8 @@ dolphntr // (c) 1996
dolphntra // (c) 1996
dolphntrb
dolphntru // (c) 1996
+dolphntrce
+drgneye
dynajack
eldorda5
eforsta5 // (c) 1995
@@ -1425,6 +1427,7 @@ genmagi
gnomeatw
goldpyr // (c) 1997
goldpyra // (c) 1997
+goldpyrb
goldenra
incasun
incasunsp
@@ -1444,6 +1447,7 @@ magimaska // (c) 2000
magtcha5
marmagic // (c) 2000
marmagicu // (c) 2000
+marmagicua
minemine // (c) 1996
monmouse
montree
@@ -1460,7 +1464,10 @@ pengpay
pengpaya
pengpayb
pengpayu // (c) 1997
+penpir2
petshop
+petshopa
+phantpay
przfight
qcash
qnile
@@ -1469,6 +1476,7 @@ qnileb // (c) 1997
qnilec
qnileu // (c) 1997
qnilemax
+qtbird
rainwrce
reelrock // (c) 1998
retrsam
@@ -1493,6 +1501,8 @@ wamazonv
wildbill
wcougar
wcougaru // (c) 1997
+wizways
+wnpost
wthing
wtiger // (c) 1999
@@ -12216,7 +12226,7 @@ fb01 // 1986 FB-01
fc100 //
@source:fccpu20.cpp
-fccpu20
+fccpu20sbc
@source:fccpu30.cpp
fccpu30
@@ -14288,6 +14298,7 @@ elecbowl // Marx
elecdet // Ideal
esbattle // Entex
esoccer // Entex
+f2pbball // Fonas
fxmcr165 // Gakken
ginv1000 // Gakken
gjackpot // Gakken
@@ -14771,6 +14782,9 @@ instruct //
hector1 //
interact //
+@source:interpro.cpp
+ip2800 // Intergraph InterPro 28xx workstation
+
@source:intrscti.cpp
intrscti // ????
@@ -28806,6 +28820,7 @@ kof99 // 0251 (c) 1999 SNK
kof99e // 0251 (c) 1999 SNK
kof99h // 0251 (c) 1999 SNK
kof99k // 0152 (c) 1999 SNK
+kof99ka // 0152 (c) 1999 SNK
kof99p // 0251 (c) 1999 SNK
kog // bootleg of kof97
kotm // 0016 (c) 1991 SNK
@@ -34662,9 +34677,11 @@ sarukani // 1997.01 (c) 1997 Kaneko / Mediaworks (Japan)
sengekis // 1997.?? (c) 1997 Kaneko / Warashi (Asia)
sengekisj // 1997.07 (c) 1997 Kaneko / Warashi (Japan)
senknow // 1999.04 (c) 1999 Kaneko / Kouyousha (Japan)
-skns //
+skns // - BIOS - various regions
teljan // 1999.11 (c) 1999 Electro Design Co. (Japan)
-vblokbrk // 1997.?? (c) 1997 Kaneko / Mediaworks (Asia)
+vblokbrk // 1997.?? (c) 1997 Kaneko / Mediaworks (Europe)
+vblokbrka // 1997.?? (c) 1997 Kaneko / Mediaworks (Asia)
+
@source:suprridr.cpp
suprridr // (c) 1983 Venture Line + Taito license
diff --git a/src/mame/mess.flt b/src/mame/mess.flt
index 7864f2ec890..d9ef0963233 100644
--- a/src/mame/mess.flt
+++ b/src/mame/mess.flt
@@ -268,6 +268,7 @@ indigo.cpp
indy_indigo2.cpp
instruct.cpp
interact.cpp
+interpro.cpp
intv.cpp
ipc.cpp
ipds.cpp
diff --git a/src/mame/video/powervr2.cpp b/src/mame/video/powervr2.cpp
index 641c2c4b60e..50a8f00a4df 100644
--- a/src/mame/video/powervr2.cpp
+++ b/src/mame/video/powervr2.cpp
@@ -3499,6 +3499,7 @@ WRITE32_MEMBER( powervr2_device::pvr2_ta_w )
//printf("PVR2 %08x %08x\n",reg,dat);
}
+// TODO: move to specific device
READ32_MEMBER( powervr2_device::elan_regs_r )
{
switch(offset)
diff --git a/src/osd/modules/render/bgfx/shaders/shader.mk b/src/osd/modules/render/bgfx/shaders/shader.mk
index 8f73be5445c..f9cdeb91f95 100644
--- a/src/osd/modules/render/bgfx/shaders/shader.mk
+++ b/src/osd/modules/render/bgfx/shaders/shader.mk
@@ -1,5 +1,5 @@
#
-# Copyright 2011-2016 Branimir Karadzic. All rights reserved.
+# Copyright 2011-2017 Branimir Karadzic. All rights reserved.
# License: http://www.opensource.org/licenses/BSD-2-Clause
#
diff --git a/src/osd/modules/sound/pa_sound.cpp b/src/osd/modules/sound/pa_sound.cpp
index b866c510f55..071fbe8c598 100644
--- a/src/osd/modules/sound/pa_sound.cpp
+++ b/src/osd/modules/sound/pa_sound.cpp
@@ -13,7 +13,7 @@
#ifndef NO_USE_PORTAUDIO
-#include "portaudio/include/portaudio.h"
+#include <portaudio.h>
#include "modules/lib/osdobj_common.h"
#include <iostream>
diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp
index e1667a9b9e7..0a8c8680438 100644
--- a/src/tools/unidasm.cpp
+++ b/src/tools/unidasm.cpp
@@ -79,6 +79,7 @@ CPU_DISASSEMBLE( avr8 );
CPU_DISASSEMBLE( ccpu );
CPU_DISASSEMBLE( cdp1801 );
CPU_DISASSEMBLE( cdp1802 );
+CPU_DISASSEMBLE( clipper );
CPU_DISASSEMBLE( coldfire );
CPU_DISASSEMBLE( cop410 );
CPU_DISASSEMBLE( cop420 );
@@ -248,6 +249,7 @@ static const dasm_table_entry dasm_table[] =
{ "ccpu", _8bit, 0, CPU_DISASSEMBLE_NAME(ccpu) },
{ "cdp1801", _8bit, 0, CPU_DISASSEMBLE_NAME(cdp1801) },
{ "cdp1802", _8bit, 0, CPU_DISASSEMBLE_NAME(cdp1802) },
+ { "clipper", _16le, 0, CPU_DISASSEMBLE_NAME(clipper) },
{ "coldfire", _16be, 0, CPU_DISASSEMBLE_NAME(coldfire) },
{ "cop410", _8bit, 0, CPU_DISASSEMBLE_NAME(cop410) },
{ "cop420", _8bit, 0, CPU_DISASSEMBLE_NAME(cop420) },