diff options
author | 2017-01-26 19:55:37 +0100 | |
---|---|---|
committer | 2017-01-26 19:55:37 +0100 | |
commit | f603c763fe35a81bd3a7f41ab8a53c61c953e2cb (patch) | |
tree | 26b3659573426ea0111c3d5203b3eea78e508357 /src | |
parent | 4e5f922341d962577d19a62ee4ed21c7de1fc8f0 (diff) | |
parent | 4ba1c0f2cad36dc23613e0dec24e7e439d3e80fd (diff) |
Merge branch 'master' of https://github.com/mamedev/mame
Diffstat (limited to 'src')
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 ¶m) { 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 ¶m) { 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 ¶m) { 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 ¶m) { @@ -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 ¶m) 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) }, |