t/html; charset=UTF-8 Last-Modified: Sat, 03 May 2025 02:16:35 GMT Expires: Tue, 01 May 2035 02:16:35 GMT mame - MAME - Multiple Arcade Machine Emulator
summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--src/mame/drivers/coinmstr.c18
-rw-r--r--src/mame/drivers/eolith.c44
-rw-r--r--src/mame/drivers/gei.c138
-rw-r--r--src/mame/drivers/magic10.c26
-rw-r--r--src/mame/drivers/mcr.c57
-rw-r--r--src/mame/drivers/pingpong.c34
-rw-r--r--src/mame/drivers/pzletime.c4
-rw-r--r--src/mame/drivers/stlforce.c10
-rw-r--r--src/mame/drivers/tgtpanic.c4
-rw-r--r--src/mame/drivers/vegaeo.c6
10 files changed, 197 insertions, 144 deletions
diff --git a/src/mame/drivers/coinmstr.c b/src/mame/drivers/coinmstr.c
index 98da44f036c..f644f979e07 100644
--- a/src/mame/drivers/coinmstr.c
+++ b/src/mame/drivers/coinmstr.c
@@ -981,7 +981,7 @@ static const mc6845_interface h46505_intf =
static MACHINE_DRIVER_START( coinmstr )
- MDRV_CPU_ADD("cpu",Z80,8000000) // ?
+ MDRV_CPU_ADD("maincpu",Z80,8000000) // ?
MDRV_CPU_PROGRAM_MAP(coinmstr_map)
MDRV_CPU_VBLANK_INT("screen", irq0_line_hold)
@@ -1015,25 +1015,25 @@ MACHINE_DRIVER_END
static MACHINE_DRIVER_START( quizmstr )
MDRV_IMPORT_FROM(coinmstr)
- MDRV_CPU_MODIFY("cpu")
+ MDRV_CPU_MODIFY("maincpu")
MDRV_CPU_IO_MAP(quizmstr_io_map)
MACHINE_DRIVER_END
static MACHINE_DRIVER_START( trailblz )
MDRV_IMPORT_FROM(coinmstr)
- MDRV_CPU_MODIFY("cpu")
+ MDRV_CPU_MODIFY("maincpu")
MDRV_CPU_IO_MAP(trailblz_io_map)
MACHINE_DRIVER_END
static MACHINE_DRIVER_START( supnudg2 )
MDRV_IMPORT_FROM(coinmstr)
- MDRV_CPU_MODIFY("cpu")
+ MDRV_CPU_MODIFY("maincpu")
MDRV_CPU_IO_MAP(supnudg2_io_map)
MACHINE_DRIVER_END
static MACHINE_DRIVER_START( pokeroul )
MDRV_IMPORT_FROM(coinmstr)
- MDRV_CPU_MODIFY("cpu")
+ MDRV_CPU_MODIFY("maincpu")
MDRV_CPU_IO_MAP(pokeroul_io_map)
MACHINE_DRIVER_END
@@ -1080,7 +1080,7 @@ CN1/2 is connector for top ROM board * - unpopulated socket
*/
ROM_START( quizmstr )
- ROM_REGION( 0x10000, "cpu", ROMREGION_ERASEFF )
+ ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF )
ROM_LOAD( "nm_qm4_11.ic9", 0x0000, 0x4000, CRC(3a233bf0) SHA1(7b91b6f19093e67dd5513a000138421d4ef6f0af) )
ROM_LOAD( "np_qm4_21.ic6", 0x4000, 0x4000, CRC(a1cd39e4) SHA1(420b0726577471c762ae470bc2138c035f295ad9) )
/* 0x8000 - 0xbfff empty */
@@ -1114,7 +1114,7 @@ ROM_END
ROM_START( trailblz )
- ROM_REGION( 0x10000, "cpu", ROMREGION_ERASEFF )
+ ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF )
ROM_LOAD( "1-4.09", 0x0000, 0x4000, CRC(7c34749c) SHA1(3847188a734b32979f376f51f74dff050b610dfb) )
ROM_LOAD( "2-4.06", 0x4000, 0x4000, CRC(81a9809b) SHA1(4d2bfd5223713a9e2e15130a3176118d400ee63e) )
/* 0x8000 - 0xbfff empty */
@@ -1129,7 +1129,7 @@ ROM_END
ROM_START( supnudg2 )
- ROM_REGION( 0x10000, "cpu", 0 )
+ ROM_REGION( 0x10000, "maincpu", 0 )
ROM_LOAD( "u3.bin", 0x0000, 0x8000, CRC(ed04e2cc) SHA1(7d90a588cca2d113487710e897771f9d99e37e62) )
ROM_LOAD( "u4.bin", 0x8000, 0x8000, CRC(0551e859) SHA1(b71640097cc75b78f3013f0e77de328bf1a205b1) )
@@ -1182,7 +1182,7 @@ ROM_END
*/
ROM_START( pokeroul )
- ROM_REGION( 0x10000, "cpu", 0 )
+ ROM_REGION( 0x10000, "maincpu", 0 )
ROM_LOAD( "poker1.ic3", 0x0000, 0x8000, CRC(bfe78d09) SHA1(7cc0f57714ff808a41ce20027a283e5dff60f752) )
ROM_LOAD( "poker2.ic4", 0x8000, 0x8000, CRC(34c1b55c) SHA1(fa562d230a57dce3fff176c21c86b461a02749f6) )
diff --git a/src/mame/drivers/eolith.c b/src/mame/drivers/eolith.c
index c419fa567dd..f557cafe20b 100644
--- a/src/mame/drivers/eolith.c
+++ b/src/mame/drivers/eolith.c
@@ -135,7 +135,7 @@ static ADDRESS_MAP_START( eolith_map, ADDRESS_SPACE_PROGRAM, 32 )
AM_RANGE(0xfca00000, 0xfca00003) AM_READ_PORT("DSW1")
AM_RANGE(0xfcc00000, 0xfcc0005b) AM_WRITENOP // crt registers ?
AM_RANGE(0xfd000000, 0xfeffffff) AM_ROM AM_REGION("user1", 0)
- AM_RANGE(0xfff80000, 0xffffffff) AM_ROM AM_REGION("cpu", 0)
+ AM_RANGE(0xfff80000, 0xffffffff) AM_ROM AM_REGION("maincpu", 0)
ADDRESS_MAP_END
@@ -324,7 +324,7 @@ INPUT_PORTS_END
static MACHINE_DRIVER_START( eolith45 )
- MDRV_CPU_ADD("cpu", E132N, 45000000) /* 45 MHz */
+ MDRV_CPU_ADD("maincpu", E132N, 45000000) /* 45 MHz */
MDRV_CPU_PROGRAM_MAP(eolith_map)
MDRV_CPU_VBLANK_INT_HACK(eolith_speedup,262)
@@ -351,12 +351,12 @@ MACHINE_DRIVER_END
static MACHINE_DRIVER_START( eolith50 )
MDRV_IMPORT_FROM(eolith45)
- MDRV_CPU_REPLACE("cpu", E132N, 50000000) /* 50 MHz */
+ MDRV_CPU_REPLACE("maincpu", E132N, 50000000) /* 50 MHz */
MACHINE_DRIVER_END
static MACHINE_DRIVER_START( ironfort )
MDRV_IMPORT_FROM(eolith45)
- MDRV_CPU_REPLACE("cpu", E132N, 44900000) /* Normaly 45MHz??? but PCB actually had a 44.9MHz OSC, so it's value is used */
+ MDRV_CPU_REPLACE("maincpu", E132N, 44900000) /* Normaly 45MHz??? but PCB actually had a 44.9MHz OSC, so it's value is used */
MACHINE_DRIVER_END
@@ -418,7 +418,7 @@ Notes:
*/
ROM_START( ironfort )
- ROM_REGION( 0x80000, "cpu", 0 ) /* Hyperstone CPU Code */
+ ROM_REGION( 0x80000, "maincpu", 0 ) /* Hyperstone CPU Code */
ROM_LOAD( "u43", 0x00000, 0x80000, CRC(29f55825) SHA1(e048ec0f5d83d4b64aa48d706fa0947afcdc1a3d) ) /* 27C040 eprom with no label */
ROM_REGION32_BE( 0x2000000, "user1", ROMREGION_ERASE00 ) /* Game Data - banked ROM, swapping necessary */
@@ -446,7 +446,7 @@ ROM_END
/* Hidden Catch */
ROM_START( hidnctch )
- ROM_REGION( 0x80000, "cpu", 0 ) /* Hyperstone CPU Code */
+ ROM_REGION( 0x80000, "maincpu", 0 ) /* Hyperstone CPU Code */
ROM_LOAD( "hc_u43.bin", 0x00000, 0x80000, CRC(635b4478) SHA1(31ea4a9725e0c329447c7d221c22494c905f6940) )
ROM_REGION32_BE( 0x2000000, "user1", ROMREGION_ERASE00 ) /* Game Data - banked ROM, swapping necessary */
@@ -519,7 +519,7 @@ Notes:
*/
ROM_START( nhidctch )
- ROM_REGION( 0x80000, "cpu", 0 ) /* Hyperstone CPU Code */
+ ROM_REGION( 0x80000, "maincpu", 0 ) /* Hyperstone CPU Code */
ROM_LOAD( "u43", 0x00000, 0x80000, CRC(44296fdb) SHA1(1faf7061342d4c86f6ca416d922cb98ffb72f250) )
ROM_REGION32_BE( 0x2000000, "user1", ROMREGION_ERASE00 ) /* Game Data - banked ROM, swapping necessary */
@@ -595,7 +595,7 @@ Notes:
*/
ROM_START( hidctch2 )
- ROM_REGION( 0x80000, "cpu", 0 ) /* Hyperstone CPU Code */
+ ROM_REGION( 0x80000, "maincpu", 0 ) /* Hyperstone CPU Code */
ROM_LOAD( "u43", 0x00000, 0x80000, CRC(326d1dbc) SHA1(b33434cd263dc40ee2b6562f72a87a0439a9833e) )
ROM_REGION32_BE( 0x2000000, "user1", ROMREGION_ERASE00 ) /* Game Data - banked ROM, swapping necessary */
@@ -698,7 +698,7 @@ All ROMs 27C160 EPROM
*/
ROM_START( raccoon )
- ROM_REGION( 0x80000, "cpu", 0 ) /* Hyperstone CPU Code */
+ ROM_REGION( 0x80000, "maincpu", 0 ) /* Hyperstone CPU Code */
ROM_LOAD( "racoon-u.43", 0x00000, 0x80000, CRC(711ee026) SHA1(c55dfaa24cbaa7a613657cfb25e7f0085f1e4cbf) )
ROM_REGION32_BE( 0x2000000, "user1", ROMREGION_ERASE00 ) /* Game Data - banked ROM, swapping necessary */
@@ -729,7 +729,7 @@ ROM_END
/* Land Breaker */
ROM_START( landbrk )
- ROM_REGION( 0x80000, "cpu", 0 ) /* Hyperstone CPU Code */
+ ROM_REGION( 0x80000, "maincpu", 0 ) /* Hyperstone CPU Code */
ROM_LOAD( "rom3.u43", 0x00000, 0x80000, CRC(8429189a) SHA1(f38e4792426ca2c138c44053a6c7525906281dff) )
ROM_REGION32_BE( 0x2000000, "user1", ROMREGION_ERASE00 ) /* Game Data - banked ROM, swapping necessary */
@@ -767,7 +767,7 @@ ROM_START( landbrk )
ROM_END
ROM_START( landbrka )
- ROM_REGION( 0x80000, "cpu", 0 ) /* Hyperstone CPU Code */
+ ROM_REGION( 0x80000, "maincpu", 0 ) /* Hyperstone CPU Code */
ROM_LOAD( "lb_1.u43", 0x00000, 0x80000, CRC(f8bbcf44) SHA1(ad85a890ae2f921cd08c1897b4d9a230ccf9e072) )
ROM_REGION32_BE( 0x2000000, "user1", ROMREGION_ERASE00 ) /* Game Data - banked ROM, swapping necessary */
@@ -800,7 +800,7 @@ ROM_END
/* Fortress 2 Blue */
ROM_START( fort2b )
- ROM_REGION( 0x80000, "cpu", 0 ) /* Hyperstone CPU Code */
+ ROM_REGION( 0x80000, "maincpu", 0 ) /* Hyperstone CPU Code */
ROM_LOAD( "1.u43", 0x00000, 0x80000, CRC(b2279485) SHA1(022591b260be28820f04a1c1fdd61cb9b68d6703) )
ROM_REGION32_BE( 0x2000000, "user1", ROMREGION_ERASE00 ) /* Game Data - banked ROM, swapping necessary */
@@ -838,7 +838,7 @@ ROM_START( fort2b )
ROM_END
ROM_START( fort2ba )
- ROM_REGION( 0x80000, "cpu", 0 ) /* Hyperstone CPU Code */
+ ROM_REGION( 0x80000, "maincpu", 0 ) /* Hyperstone CPU Code */
ROM_LOAD( "ftii012.u43", 0x00000, 0x80000, CRC(6424e05f) SHA1(2f02f103de180561e372ce897f8410a11c4cb58d) )
ROM_REGION32_BE( 0x2000000, "user1", ROMREGION_ERASE00 ) /* Game Data - banked ROM, swapping necessary */
@@ -870,7 +870,7 @@ ROM_END
/* Puzzle King */
ROM_START( puzzlekg )
- ROM_REGION( 0x80000, "cpu", 0 ) /* Hyperstone CPU Code */
+ ROM_REGION( 0x80000, "maincpu", 0 ) /* Hyperstone CPU Code */
ROM_LOAD( "u43.bin", 0x00000, 0x80000, CRC(c3db7424) SHA1(5ee2be0f06fddb0c74fc6e82679b275cc4e86bcc) )
ROM_REGION32_BE( 0x2000000, "user1", ROMREGION_ERASE00 ) /* Game Data - banked ROM, swapping necessary */
@@ -959,7 +959,7 @@ Notes:
*/
ROM_START( hidctch3 )
- ROM_REGION( 0x80000, "cpu", 0 ) /* Hyperstone CPU Code */
+ ROM_REGION( 0x80000, "maincpu", 0 ) /* Hyperstone CPU Code */
ROM_LOAD( "u43", 0x00000, 0x80000, CRC(7b861339) SHA1(fca7d47d7d538774ec6462deebc0a367ac073b67) )
ROM_REGION32_BE( 0x2000000, "user1", ROMREGION_ERASE00 ) /* Game Data - banked ROM, swapping necessary */
@@ -1012,7 +1012,7 @@ static DRIVER_INIT( landbrka )
//it fails compares with memories:
//$4002d338 -> $4002d348 .... $4002d33f -> $4002d34f
//related with bits 0x100 - 0x200 read at startup from input(0) ?
- UINT32 *rombase = (UINT32*)memory_region(machine, "cpu");
+ UINT32 *rombase = (UINT32*)memory_region(machine, "maincpu");
rombase[0x14f00/4] = (rombase[0x14f00/4] & 0xffff) | 0x03000000; /* Change BR to NOP */
coin_counter_bit = 0x2000;
@@ -1022,22 +1022,22 @@ static DRIVER_INIT( landbrka )
static DRIVER_INIT( hidctch2 )
{
//it fails compares in memory like in landbrka
- UINT32 *rombase = (UINT32*)memory_region(machine, "cpu");
+ UINT32 *rombase = (UINT32*)memory_region(machine, "maincpu");
rombase[0xbcc8/4] = (rombase[0xbcc8/4] & 0xffff) | 0x03000000; /* Change BR to NOP */
init_eolith_speedup(machine);
}
static DRIVER_INIT( hidctch3 )
{
- memory_nop_write(cputag_get_address_space(machine, "cpu", ADDRESS_SPACE_PROGRAM), 0xfc200000, 0xfc200003, 0, 0); // this generates pens vibration
+ memory_nop_write(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0xfc200000, 0xfc200003, 0, 0); // this generates pens vibration
// It is not clear why the first reads are needed too
- memory_install_read32_handler(cputag_get_address_space(machine, "cpu", ADDRESS_SPACE_PROGRAM), 0xfce00000, 0xfce00003, 0, 0, hidctch3_pen1_r);
- memory_install_read32_handler(cputag_get_address_space(machine, "cpu", ADDRESS_SPACE_PROGRAM), 0xfce80000, 0xfce80003, 0, 0, hidctch3_pen1_r);
+ memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0xfce00000, 0xfce00003, 0, 0, hidctch3_pen1_r);
+ memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0xfce80000, 0xfce80003, 0, 0, hidctch3_pen1_r);
- memory_install_read32_handler(cputag_get_address_space(machine, "cpu", ADDRESS_SPACE_PROGRAM), 0xfcf00000, 0xfcf00003, 0, 0, hidctch3_pen2_r);
- memory_install_read32_handler(cputag_get_address_space(machine, "cpu", ADDRESS_SPACE_PROGRAM), 0xfcf80000, 0xfcf80003, 0, 0, hidctch3_pen2_r);
+ memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0xfcf00000, 0xfcf00003, 0, 0, hidctch3_pen2_r);
+ memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0xfcf80000, 0xfcf80003, 0, 0, hidctch3_pen2_r);
init_eolith_speedup(machine);
}
diff --git a/src/mame/drivers/gei.c b/src/mame/drivers/gei.c
index 40c14cf5e02..5ab77af9ddd 100644
--- a/src/mame/drivers/gei.c
+++ b/src/mame/drivers/gei.c
@@ -133,7 +133,7 @@ static WRITE8_DEVICE_HANDLER( lamps_w )
static WRITE8_DEVICE_HANDLER( sound_w )
{
- const address_space *space = cputag_get_address_space(device->machine, "cpu", ADDRESS_SPACE_PROGRAM);
+ const address_space *space = cputag_get_address_space(device->machine, "maincpu", ADDRESS_SPACE_PROGRAM);
/* bit 3 - coin lockout, lamp10 in poker / lamp6 in trivia test modes */
coin_lockout_global_w(device->machine, ~data & 0x08);
@@ -174,7 +174,7 @@ static WRITE8_DEVICE_HANDLER( lamps2_w )
static WRITE8_DEVICE_HANDLER( nmi_w )
{
- const address_space *space = cputag_get_address_space(device->machine, "cpu", ADDRESS_SPACE_PROGRAM);
+ const address_space *space = cputag_get_address_space(device->machine, "maincpu", ADDRESS_SPACE_PROGRAM);
/* bit 4 - play/raise button lamp, lamp 9 in selection test mode */
set_led_status(device->machine, 8,data & 0x10);
@@ -200,68 +200,68 @@ static READ8_DEVICE_HANDLER( portC_r )
static WRITE8_HANDLER( banksel_main_w )
{
- memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "cpu") + 0x8000);
+ memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "maincpu") + 0x8000);
}
static WRITE8_HANDLER( banksel_1_w )
{
- memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "cpu") + 0x10000);
+ memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "maincpu") + 0x10000);
}
static WRITE8_HANDLER( banksel_2_w )
{
- memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "cpu") + 0x18000);
+ memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "maincpu") + 0x18000);
}
static WRITE8_HANDLER( banksel_3_w )
{
- memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "cpu") + 0x20000);
+ memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "maincpu") + 0x20000);
}
static WRITE8_HANDLER( banksel_4_w )
{
- memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "cpu") + 0x28000);
+ memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "maincpu") + 0x28000);
}
static WRITE8_HANDLER( banksel_5_w )
{
- memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "cpu") + 0x30000);
+ memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "maincpu") + 0x30000);
}
static WRITE8_HANDLER( banksel_1_1_w )
{
- memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "cpu") + 0x10000);
+ memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "maincpu") + 0x10000);
}
static WRITE8_HANDLER( banksel_2_1_w )
{
- memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "cpu") + 0x14000);
+ memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "maincpu") + 0x14000);
}
static WRITE8_HANDLER( banksel_3_1_w )
{
- memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "cpu") + 0x18000);
+ memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "maincpu") + 0x18000);
}
static WRITE8_HANDLER( banksel_4_1_w )
{
- memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "cpu") + 0x1c000);
+ memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "maincpu") + 0x1c000);
}
static WRITE8_HANDLER( banksel_5_1_w )
{
- memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "cpu") + 0x20000);
+ memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "maincpu") + 0x20000);
}
static WRITE8_HANDLER( banksel_1_2_w )
{
- memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "cpu") + 0x12000);
+ memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "maincpu") + 0x12000);
}
static WRITE8_HANDLER( banksel_2_2_w )
{
- memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "cpu") + 0x16000);
+ memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "maincpu") + 0x16000);
}
static WRITE8_HANDLER( banksel_3_2_w )
{
- memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "cpu") + 0x1a000);
+ memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "maincpu") + 0x1a000);
}
static WRITE8_HANDLER( banksel_4_2_w )
{
- memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "cpu") + 0x1e000);
+ memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "maincpu") + 0x1e000);
}
static WRITE8_HANDLER( banksel_5_2_w )
{
- memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "cpu") + 0x22000);
+ memory_set_bankptr(space->machine, "bank1",memory_region(space->machine, "maincpu") + 0x22000);
}
static WRITE8_HANDLER(geimulti_bank_w)
@@ -1002,7 +1002,7 @@ static MACHINE_RESET( gselect )
}
static MACHINE_DRIVER_START( getrivia )
- MDRV_CPU_ADD("cpu",Z80,4000000) /* 4 MHz */
+ MDRV_CPU_ADD("maincpu",Z80,4000000) /* 4 MHz */
MDRV_CPU_PROGRAM_MAP(getrivia_map)
MDRV_CPU_VBLANK_INT("screen", nmi_line_pulse)
@@ -1036,7 +1036,7 @@ MACHINE_DRIVER_END
static MACHINE_DRIVER_START( findout )
MDRV_IMPORT_FROM(getrivia)
- MDRV_CPU_MODIFY("cpu")
+ MDRV_CPU_MODIFY("maincpu")
MDRV_CPU_PROGRAM_MAP(findout_map)
MDRV_PPI8255_RECONFIG( "ppi8255_0", findout_ppi8255_intf[0] )
@@ -1048,7 +1048,7 @@ static MACHINE_DRIVER_START( gselect )
/* basic machine hardware */
MDRV_IMPORT_FROM(getrivia)
- MDRV_CPU_MODIFY("cpu")
+ MDRV_CPU_MODIFY("maincpu")
MDRV_CPU_PROGRAM_MAP(gselect_map)
MDRV_MACHINE_RESET(gselect)
@@ -1062,7 +1062,7 @@ static MACHINE_DRIVER_START( jokpokera )
/* basic machine hardware */
MDRV_IMPORT_FROM(getrivia)
- MDRV_CPU_MODIFY("cpu")
+ MDRV_CPU_MODIFY("maincpu")
MDRV_CPU_PROGRAM_MAP(gselect_map)
MDRV_MACHINE_RESET(gselect)
@@ -1074,7 +1074,7 @@ static MACHINE_DRIVER_START( amuse )
/* basic machine hardware */
MDRV_IMPORT_FROM(getrivia)
- MDRV_CPU_MODIFY("cpu")
+ MDRV_CPU_MODIFY("maincpu")
MDRV_CPU_PROGRAM_MAP(amuse_map)
MACHINE_DRIVER_END
@@ -1083,7 +1083,7 @@ static MACHINE_DRIVER_START( gepoker )
/* basic machine hardware */
MDRV_IMPORT_FROM(getrivia)
- MDRV_CPU_MODIFY("cpu")
+ MDRV_CPU_MODIFY("maincpu")
MDRV_CPU_PROGRAM_MAP(gepoker_map)
MACHINE_DRIVER_END
@@ -1091,7 +1091,7 @@ static MACHINE_DRIVER_START( amuse1 )
MDRV_IMPORT_FROM(getrivia)
- MDRV_CPU_MODIFY("cpu")
+ MDRV_CPU_MODIFY("maincpu")
MDRV_CPU_PROGRAM_MAP(amuse1_map)
MACHINE_DRIVER_END
@@ -1099,7 +1099,7 @@ static MACHINE_DRIVER_START( suprpokr )
MDRV_IMPORT_FROM(getrivia)
- MDRV_CPU_MODIFY("cpu")
+ MDRV_CPU_MODIFY("maincpu")
MDRV_CPU_PROGRAM_MAP(suprpokr_map)
MACHINE_DRIVER_END
@@ -1107,7 +1107,7 @@ static MACHINE_DRIVER_START( geimulti )
MDRV_IMPORT_FROM(getrivia)
- MDRV_CPU_MODIFY("cpu")
+ MDRV_CPU_MODIFY("maincpu")
MDRV_CPU_PROGRAM_MAP(geimulti_map)
MACHINE_DRIVER_END
@@ -1115,7 +1115,7 @@ static MACHINE_DRIVER_START( sprtauth )
MDRV_IMPORT_FROM(getrivia)
- MDRV_CPU_MODIFY("cpu")
+ MDRV_CPU_MODIFY("maincpu")
MDRV_CPU_PROGRAM_MAP(sprtauth_map)
MACHINE_DRIVER_END
@@ -1132,14 +1132,14 @@ PCB labeled M075
****************************************************/
ROM_START( jokpoker )
- ROM_REGION( 0x24000, "cpu", 0 )
+ ROM_REGION( 0x24000, "maincpu", 0 )
ROM_LOAD( "m075.1", 0x00000, 0x1000, CRC(ad42465b) SHA1(3f06847a9aecb0592f99419dba9be5f18005d57b) ) /* rom board UMV-1A */
ROM_LOAD( "m075.2", 0x01000, 0x1000, CRC(bd129fc2) SHA1(2e05ba34922c16d127be32941447013efea05bcd) )
ROM_LOAD( "m075.3", 0x02000, 0x1000, CRC(45725bc9) SHA1(9e6dcbec955ef8190f2307ddb367b24b7f34338d) )
ROM_END
ROM_START( jokpokera )
- ROM_REGION( 0x24000, "cpu", 0 )
+ ROM_REGION( 0x24000, "maincpu", 0 )
ROM_LOAD( "jpbiwr930-1.bin", 0x00000, 0x2000, CRC(d0f4fec5) SHA1(5fcc72522df66464759d5ba3d5209bc7a3a80002) ) /* rom board UMV-7C */
ROM_LOAD( "jpbiwr930-2.bin", 0x02000, 0x2000, CRC(824d1aee) SHA1(6eebde351c3b5bbed3796846d8d651b41ed6f84a) )
ROM_END
@@ -1153,7 +1153,7 @@ UVM 7S REV A romboard
*/
ROM_START( jokpokerb )
- ROM_REGION( 0x24000, "cpu", 0 )
+ ROM_REGION( 0x24000, "maincpu", 0 )
ROM_LOAD( "jp_bi_10-19-88.e1", 0x00000, 0x2000, CRC(d59a78e2) SHA1(d8463675f30a52e0f93c5ea5c2ee663095d3d5ea) )
ROM_LOAD( "jp_bi_10-19-88.e2", 0x02000, 0x2000, CRC(1a34dc80) SHA1(27dff743e661ae7421fef0b046e3ae205b842603) )
ROM_END
@@ -1167,7 +1167,7 @@ UVM7-C romboard
*/
ROM_START( jokpokerc )
- ROM_REGION( 0x24000, "cpu", 0 )
+ ROM_REGION( 0x24000, "maincpu", 0 )
ROM_LOAD( "jp_bi_5-10-85.1", 0x00000, 0x2000, CRC(d0f4fec5) SHA1(5fcc72522df66464759d5ba3d5209bc7a3a80002) )
ROM_LOAD( "jp_bi_5-10-85.2", 0x02000, 0x2000, CRC(9f8bee22) SHA1(8d894d2a07bd18d731b7a54a16bb9b9230c79306) )
ROM_END
@@ -1183,7 +1183,7 @@ Contains:
****************************************************/
ROM_START( superbwl )
- ROM_REGION( 0x24000, "cpu", 0 )
+ ROM_REGION( 0x24000, "maincpu", 0 )
ROM_LOAD( "super_bowl.1", 0x00000, 0x1000, CRC(82edf064) SHA1(8a26377590282f51fb39d013452ba11252e7dd05) ) /* rom board UMV-1B */
ROM_LOAD( "super_bowl.2", 0x01000, 0x1000, CRC(2438dd1f) SHA1(26bbd1cb3d0d5b93f61b92ff95948ac9de060715) )
ROM_LOAD( "super_bowl.3", 0x02000, 0x1000, CRC(9b111430) SHA1(9aaa755f3e4b369477c1a0525c994a19fe0f6107) )
@@ -1213,7 +1213,7 @@ Note: Question roms that contain "#1" (or 2 ect)
****************************************************/
ROM_START( gtsers1 ) /* Series 1 (Complete) */
- ROM_REGION( 0x24000, "cpu", 0 )
+ ROM_REGION( 0x24000, "maincpu", 0 )
ROM_LOAD( "prog101c_right", 0x00000, 0x2000, CRC(767f0e46) SHA1(5de7b54876fcbfb2328174ffe6b656ffea886fcb) ) /* rom board UMV 10 B */
ROM_LOAD( "prog101c_left", 0x0a000, 0x2000, CRC(24c0a097) SHA1(b8de58baecb92775e0882cd6eca3b9e07cf7c5a5) )
/* Question roms */
@@ -1225,7 +1225,7 @@ ROM_START( gtsers1 ) /* Series 1 (Complete) */
ROM_END
ROM_START( gtsers2 ) /* Series 2 (Complete - question roms dated 2/9) */
- ROM_REGION( 0x24000, "cpu", 0 )
+ ROM_REGION( 0x24000, "maincpu", 0 )
ROM_LOAD( "prog101c_right", 0x00000, 0x2000, CRC(767f0e46) SHA1(5de7b54876fcbfb2328174ffe6b656ffea886fcb) ) /* rom board UMV 10 B */
ROM_LOAD( "prog101c_left", 0x0a000, 0x2000, CRC(24c0a097) SHA1(b8de58baecb92775e0882cd6eca3b9e07cf7c5a5) )
/* Question roms */
@@ -1237,7 +1237,7 @@ ROM_START( gtsers2 ) /* Series 2 (Complete - question roms dated 2/9) */
ROM_END
ROM_START( gtsers3 ) /* Series 3 (Complete - question roms dated 3/9) */
- ROM_REGION( 0x24000, "cpu", 0 )
+ ROM_REGION( 0x24000, "maincpu", 0 )
ROM_LOAD( "prog102b_right", 0x00000, 0x2000, CRC(e8391f71) SHA1(a955eff87d622d4fcfd25f6d888c48ff82556879) )
ROM_LOAD( "prog102b_left", 0x0a000, 0x2000, CRC(cc7b45a7) SHA1(c708f56feb36c1241358a42bb7dce25b799f1f0b) )
/* Question roms */
@@ -1249,7 +1249,7 @@ ROM_START( gtsers3 ) /* Series 3 (Complete - question roms dated 3/9) */
ROM_END
ROM_START( gtsers4 ) /* Series 4 (Incomplete - question roms dated 4/9) */
- ROM_REGION( 0x24000, "cpu", 0 )
+ ROM_REGION( 0x24000, "maincpu", 0 )
ROM_LOAD( "prog102c_right", 0x00000, 0x2000, CRC(76fdc3a3) SHA1(212e09644b9cab334aad22ec5860e8638c6ba3fa) )
ROM_LOAD( "prog102c_left", 0x0a000, 0x2000, CRC(901fb2f9) SHA1(98e49c74d89c4911a1f4d5ccf3e6cf3226c6a178) )
/* Question roms */
@@ -1261,7 +1261,7 @@ ROM_START( gtsers4 ) /* Series 4 (Incomplete - question roms dated 4/9) */
ROM_END
ROM_START( gtsers5 ) /* Series 5 (Incomplete - question roms dated 5/9) */
- ROM_REGION( 0x24000, "cpu", 0 )
+ ROM_REGION( 0x24000, "maincpu", 0 )
ROM_LOAD( "prog102c_right", 0x00000, 0x2000, CRC(76fdc3a3) SHA1(212e09644b9cab334aad22ec5860e8638c6ba3fa) )
ROM_LOAD( "prog102c_left", 0x0a000, 0x2000, CRC(901fb2f9) SHA1(98e49c74d89c4911a1f4d5ccf3e6cf3226c6a178) )
/* Question roms */
@@ -1273,7 +1273,7 @@ ROM_START( gtsers5 ) /* Series 5 (Incomplete - question roms dated 5/9) */
ROM_END
ROM_START( gtsers7 ) /* Series 7 (Incomplete - question roms dated 7/9?) */
- ROM_REGION( 0x24000, "cpu", 0 )
+ ROM_REGION( 0x24000, "maincpu", 0 )
ROM_LOAD( "prog102c_right", 0x00000, 0x2000, CRC(76fdc3a3) SHA1(212e09644b9cab334aad22ec5860e8638c6ba3fa) )
ROM_LOAD( "prog102c_left", 0x0a000, 0x2000, CRC(901fb2f9) SHA1(98e49c74d89c4911a1f4d5ccf3e6cf3226c6a178) )
/* Question roms */
@@ -1285,7 +1285,7 @@ ROM_START( gtsers7 ) /* Series 7 (Incomplete - question roms dated 7/9?) */
ROM_END
ROM_START( gtsersa ) /* alt or older version questions */
- ROM_REGION( 0x24000, "cpu", 0 )
+ ROM_REGION( 0x24000, "maincpu", 0 )
ROM_LOAD( "prog102c_right", 0x00000, 0x2000, CRC(76fdc3a3) SHA1(212e09644b9cab334aad22ec5860e8638c6ba3fa) )
ROM_LOAD( "prog102c_left", 0x0a000, 0x2000, CRC(901fb2f9) SHA1(98e49c74d89c4911a1f4d5ccf3e6cf3226c6a178) )
/* Question roms */
@@ -1297,7 +1297,7 @@ ROM_START( gtsersa ) /* alt or older version questions */
ROM_END
ROM_START( gtsersb ) /* alt or older version questions */
- ROM_REGION( 0x24000, "cpu", 0 )
+ ROM_REGION( 0x24000, "maincpu", 0 )
ROM_LOAD( "prog102c_right", 0x00000, 0x2000, CRC(76fdc3a3) SHA1(212e09644b9cab334aad22ec5860e8638c6ba3fa) )
ROM_LOAD( "prog102c_left", 0x0a000, 0x2000, CRC(901fb2f9) SHA1(98e49c74d89c4911a1f4d5ccf3e6cf3226c6a178) )
/* Question roms */
@@ -1309,7 +1309,7 @@ ROM_START( gtsersb ) /* alt or older version questions */
ROM_END
ROM_START( sextriv1 )
- ROM_REGION( 0x24000, "cpu", 0 )
+ ROM_REGION( 0x24000, "maincpu", 0 )
ROM_LOAD( "prog1_right", 0x00000, 0x2000, CRC(73abcd12) SHA1(3b985f25a11507878cef6d11420e215065fb0906) )
ROM_LOAD( "prog1_left", 0x0a000, 0x2000, CRC(04ee6ecd) SHA1(28342fcdcf36b34fa93f1a985163ca5aab03defe) )
/* Question roms */
@@ -1320,7 +1320,7 @@ ROM_START( sextriv1 )
ROM_END
ROM_START( sextriv2 )
- ROM_REGION( 0x24000, "cpu", 0 )
+ ROM_REGION( 0x24000, "maincpu", 0 )
ROM_LOAD( "prog1_right", 0x00000, 0x2000, CRC(73abcd12) SHA1(3b985f25a11507878cef6d11420e215065fb0906) )
ROM_LOAD( "prog1_left", 0x0a000, 0x2000, CRC(04ee6ecd) SHA1(28342fcdcf36b34fa93f1a985163ca5aab03defe) )
/* Question roms */
@@ -1352,7 +1352,7 @@ sets as the alt set also included that name on the labels
****************************************************/
ROM_START( gs4002 )
- ROM_REGION( 0x18000, "cpu", 0 )
+ ROM_REGION( 0x18000, "maincpu", 0 )
ROM_LOAD( "4-1.1", 0x00000, 0x2000, CRC(a456e456) SHA1(f36b96ac31ce0f128ecb94f94d1dbdd88ee03c77) ) /* V16M 5-4-84 */
/* Banked roms */
ROM_LOAD( "bljk_3-16-84.2", 0x10000, 0x2000, CRC(c3785523) SHA1(090f324fc7adb0a36b189cf04086f0e050895ee4) )
@@ -1362,7 +1362,7 @@ ROM_START( gs4002 )
ROM_END
ROM_START( gs4002a )
- ROM_REGION( 0x18000, "cpu", 0 )
+ ROM_REGION( 0x18000, "maincpu", 0 )
ROM_LOAD( "4-1.1", 0x00000, 0x2000, CRC(a456e456) SHA1(f36b96ac31ce0f128ecb94f94d1dbdd88ee03c77) ) /* V16M 5-4-84 */
/* Banked roms */
ROM_LOAD( "bljk_3-16-84.2", 0x10000, 0x2000, CRC(c3785523) SHA1(090f324fc7adb0a36b189cf04086f0e050895ee4) )
@@ -1412,7 +1412,7 @@ The ICB set is known as the M105 set as some label sets included that name.
*/
ROM_START( gepoker ) /* v50.02 with most roms for ICB dated 8-16-84 */
- ROM_REGION( 0x1b000, "cpu", ROMREGION_ERASEFF )
+ ROM_REGION( 0x1b000, "maincpu", ROMREGION_ERASEFF )
ROM_LOAD( "control_icb_8-16", 0x00000, 0x2000, CRC(0103963d) SHA1(9bc646e721048b84111e0686eaca23bc24eee3e2) )
ROM_LOAD( "high_icb_6-25-85-5", 0x0e000, 0x2000, CRC(dfb6592e) SHA1(d68de9f537d3c14279dc576424d195bb266e3897) )
/* Banked roms */
@@ -1424,7 +1424,7 @@ ROM_START( gepoker ) /* v50.02 with most roms for ICB dated 8-16-84 */
ROM_END
ROM_START( gepoker1 ) /* v50.02 with roms for ICB dated 9-30-86 */
- ROM_REGION( 0x1b000, "cpu", ROMREGION_ERASEFF )
+ ROM_REGION( 0x1b000, "maincpu", ROMREGION_ERASEFF )
ROM_LOAD( "control_icb_9-30", 0x00000, 0x2000, CRC(08b996f2) SHA1(5f5efb5015ec9571cc94734c18debfadaa28f585) )
ROM_LOAD( "high_icb_6-25-85-5a", 0x0e000, 0x2000, CRC(6ddc1750) SHA1(ee19206b7f4a98e3e7647414127f4e09b3e9134f) )
/* Banked roms */
@@ -1436,7 +1436,7 @@ ROM_START( gepoker1 ) /* v50.02 with roms for ICB dated 9-30-86 */
ROM_END
ROM_START( gepoker2 ) /* v50.02 with control dated 9-30-84 */
- ROM_REGION( 0x1b000, "cpu", ROMREGION_ERASEFF )
+ ROM_REGION( 0x1b000, "maincpu", ROMREGION_ERASEFF )
ROM_LOAD( "control_icb_9-30", 0x00000, 0x2000, CRC(08b996f2) SHA1(5f5efb5015ec9571cc94734c18debfadaa28f585) )
ROM_LOAD( "high_icb_6-25a", 0x0e000, 0x2000, CRC(6ddc1750) SHA1(ee19206b7f4a98e3e7647414127f4e09b3e9134f) )
/* Banked roms */
@@ -1445,7 +1445,7 @@ ROM_START( gepoker2 ) /* v50.02 with control dated 9-30-84 */
ROM_END
ROM_START( amuse ) /* v50.08 with most roms for IAM dated 8-16-84 */
- ROM_REGION
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************

    input.cpp

    Handle input from the user.

****************************************************************************

    To do:
        * auto-selecting joystick configs
        * per-joystick configs?
        * test half-axis selections
        * add input test menu
        * get rid of osd_customize_inputport_list

***************************************************************************/

#include "emu.h"
#include "inputdev.h"

#include "corestr.h"



//**************************************************************************
//  CONSTANTS
//**************************************************************************

// additional expanded input codes for sequences
constexpr input_code input_seq::end_code;
constexpr input_code input_seq::default_code;
constexpr input_code input_seq::not_code;
constexpr input_code input_seq::or_code;

// constant sequences
const input_seq input_seq::empty_seq;



//**************************************************************************
//  TYPE DEFINITIONS
//**************************************************************************

// ======================> code_string_table

// simple class to match codes to strings
struct code_string_table
{
	u32 operator[](std::string_view string) const
	{
		for (const code_string_table *current = this; current->m_code != ~0; current++)
			if (current->m_string == string)
				return current->m_code;
		return ~0;
	}

	const char *operator[](u32 code) const
	{
		for (const code_string_table *current = this; current->m_code != ~0; current++)
			if (current->m_code == code)
				return current->m_string;
		return nullptr;
	}

	u32                     m_code;
	const char *            m_string;
};



//**************************************************************************
//  TOKEN/STRING TABLES
//**************************************************************************

// token strings for device classes
static const code_string_table devclass_token_table[] =
{
	{ DEVICE_CLASS_KEYBOARD, "KEYCODE" },
	{ DEVICE_CLASS_MOUSE,    "MOUSECODE" },
	{ DEVICE_CLASS_LIGHTGUN, "GUNCODE" },
	{ DEVICE_CLASS_JOYSTICK, "JOYCODE" },
	{ ~0U,                   "UNKCODE" }
};

// friendly strings for device classes
static const code_string_table devclass_string_table[] =
{
	{ DEVICE_CLASS_KEYBOARD, "Kbd" },
	{ DEVICE_CLASS_MOUSE,    "Mouse" },
	{ DEVICE_CLASS_LIGHTGUN, "Gun" },
	{ DEVICE_CLASS_JOYSTICK, "Joy" },
	{ ~0U,                   "Unk" }
};

// token strings for item modifiers
static const code_string_table modifier_token_table[] =
{
	{ ITEM_MODIFIER_POS,     "POS" },
	{ ITEM_MODIFIER_NEG,     "NEG" },
	{ ITEM_MODIFIER_LEFT,    "LEFT" },
	{ ITEM_MODIFIER_RIGHT,   "RIGHT" },
	{ ITEM_MODIFIER_UP,      "UP" },
	{ ITEM_MODIFIER_DOWN,    "DOWN" },
	{ ~0U,                   "" }
};

// friendly strings for item modifiers
static const code_string_table modifier_string_table[] =
{
	{ ITEM_MODIFIER_POS,     "+" },
	{ ITEM_MODIFIER_NEG,     "-" },
	{ ITEM_MODIFIER_LEFT,    "Left" },
	{ ITEM_MODIFIER_RIGHT,   "Right" },
	{ ITEM_MODIFIER_UP,      "Up" },
	{ ITEM_MODIFIER_DOWN,    "Down" },
	{ ~0U,                   "" }
};

// token strings for item classes
static const code_string_table itemclass_token_table[] =
{
	{ ITEM_CLASS_SWITCH,     "SWITCH" },
	{ ITEM_CLASS_ABSOLUTE,   "ABSOLUTE" },
	{ ITEM_CLASS_RELATIVE,   "RELATIVE" },
	{ ~0U,                   "" }
};

// token strings for standard item ids
static const code_string_table itemid_token_table[] =
{
	// standard keyboard codes
	{ ITEM_ID_A,             "A" },
	{ ITEM_ID_B,             "B" },
	{ ITEM_ID_C,             "C" },
	{ ITEM_ID_D,             "D" },
	{ ITEM_ID_E,             "E" },
	{ ITEM_ID_F,             "F" },
	{ ITEM_ID_G,             "G" },
	{ ITEM_ID_H,             "H" },
	{ ITEM_ID_I,             "I" },
	{ ITEM_ID_J,             "J" },
	{ ITEM_ID_K,             "K" },
	{ ITEM_ID_L,             "L" },
	{ ITEM_ID_M,             "M" },
	{ ITEM_ID_N,             "N" },
	{ ITEM_ID_O,             "O" },
	{ ITEM_ID_P,             "P" },
	{ ITEM_ID_Q,             "Q" },
	{ ITEM_ID_R,             "R" },
	{ ITEM_ID_S,             "S" },
	{ ITEM_ID_T,             "T" },
	{ ITEM_ID_U,             "U" },
	{ ITEM_ID_V,             "V" },
	{ ITEM_ID_W,             "W" },
	{ ITEM_ID_X,             "X" },
	{ ITEM_ID_Y,             "Y" },
	{ ITEM_ID_Z,             "Z" },
	{ ITEM_ID_0,             "0" },
	{ ITEM_ID_1,             "1" },
	{ ITEM_ID_2,             "2" },
	{ ITEM_ID_3,             "3" },
	{ ITEM_ID_4,             "4" },
	{ ITEM_ID_5,             "5" },
	{ ITEM_ID_6,             "6" },
	{ ITEM_ID_7,             "7" },
	{ ITEM_ID_8,             "8" },
	{ ITEM_ID_9,             "9" },
	{ ITEM_ID_F1,            "F1" },
	{ ITEM_ID_F2,            "F2" },
	{ ITEM_ID_F3,            "F3" },
	{ ITEM_ID_F4,            "F4" },
	{ ITEM_ID_F5,            "F5" },
	{ ITEM_ID_F6,            "F6" },
	{ ITEM_ID_F7,            "F7" },
	{ ITEM_ID_F8,            "F8" },
	{ ITEM_ID_F9,            "F9" },
	{ ITEM_ID_F10,           "F10" },
	{ ITEM_ID_F11,           "F11" },
	{ ITEM_ID_F12,           "F12" },
	{ ITEM_ID_F13,           "F13" },
	{ ITEM_ID_F14,           "F14" },
	{ ITEM_ID_F15,           "F15" },
	{ ITEM_ID_F16,           "F16" },
	{ ITEM_ID_F17,           "F17" },
	{ ITEM_ID_F18,           "F18" },
	{ ITEM_ID_F19,           "F19" },
	{ ITEM_ID_F20,           "F20" },
	{ ITEM_ID_ESC,           "ESC" },
	{ ITEM_ID_TILDE,         "TILDE" },
	{ ITEM_ID_MINUS,         "MINUS" },
	{ ITEM_ID_EQUALS,        "EQUALS" },
	{ ITEM_ID_BACKSPACE,     "BACKSPACE" },
	{ ITEM_ID_TAB,           "TAB" },
	{ ITEM_ID_OPENBRACE,     "OPENBRACE" },
	{ ITEM_ID_CLOSEBRACE,    "CLOSEBRACE" },
	{ ITEM_ID_ENTER,         "ENTER" },
	{ ITEM_ID_COLON,         "COLON" },
	{ ITEM_ID_QUOTE,         "QUOTE" },
	{ ITEM_ID_BACKSLASH,     "BACKSLASH" },
	{ ITEM_ID_BACKSLASH2,    "BACKSLASH2" },
	{ ITEM_ID_COMMA,         "COMMA" },
	{ ITEM_ID_STOP,          "STOP" },
	{ ITEM_ID_SLASH,         "SLASH" },
	{ ITEM_ID_SPACE,         "SPACE" },
	{ ITEM_ID_INSERT,        "INSERT" },
	{ ITEM_ID_DEL,           "DEL" },
	{ ITEM_ID_HOME,          "HOME" },
	{ ITEM_ID_END,           "END" },
	{ ITEM_ID_PGUP,          "PGUP" },
	{ ITEM_ID_PGDN,          "PGDN" },
	{ ITEM_ID_LEFT,          "LEFT" },
	{ ITEM_ID_RIGHT,         "RIGHT" },
	{ ITEM_ID_UP,            "UP" },
	{ ITEM_ID_DOWN,          "DOWN" },
	{ ITEM_ID_0_PAD,         "0PAD" },
	{ ITEM_ID_1_PAD,         "1PAD" },
	{ ITEM_ID_2_PAD,         "2PAD" },
	{ ITEM_ID_3_PAD,         "3PAD" },
	{ ITEM_ID_4_PAD,         "4PAD" },
	{ ITEM_ID_5_PAD,         "5PAD" },
	{ ITEM_ID_6_PAD,         "6PAD" },
	{ ITEM_ID_7_PAD,         "7PAD" },
	{ ITEM_ID_8_PAD,         "8PAD" },
	{ ITEM_ID_9_PAD,         "9PAD" },
	{ ITEM_ID_SLASH_PAD,     "SLASHPAD" },
	{ ITEM_ID_ASTERISK,      "ASTERISK" },
	{ ITEM_ID_MINUS_PAD,     "MINUSPAD" },
	{ ITEM_ID_PLUS_PAD,      "PLUSPAD" },
	{ ITEM_ID_DEL_PAD,       "DELPAD" },
	{ ITEM_ID_ENTER_PAD,     "ENTERPAD" },
	{ ITEM_ID_BS_PAD,        "BSPAD" },
	{ ITEM_ID_TAB_PAD,       "TABPAD" },
	{ ITEM_ID_00_PAD,        "00PAD" },
	{ ITEM_ID_000_PAD,       "000PAD" },
	{ ITEM_ID_PRTSCR,        "PRTSCR" },
	{ ITEM_ID_PAUSE,         "PAUSE" },
	{ ITEM_ID_LSHIFT,        "LSHIFT" },
	{ ITEM_ID_RSHIFT,        "RSHIFT" },
	{ ITEM_ID_LCONTROL,      "LCONTROL" },
	{ ITEM_ID_RCONTROL,      "RCONTROL" },
	{ ITEM_ID_LALT,          "LALT" },
	{ ITEM_ID_RALT,          "RALT" },
	{ ITEM_ID_SCRLOCK,       "SCRLOCK" },
	{ ITEM_ID_NUMLOCK,       "NUMLOCK" },
	{ ITEM_ID_CAPSLOCK,      "CAPSLOCK" },
	{ ITEM_ID_LWIN,          "LWIN" },
	{ ITEM_ID_RWIN,          "RWIN" },
	{ ITEM_ID_MENU,          "MENU" },
	{ ITEM_ID_CANCEL,        "CANCEL" },

	// standard mouse/joystick/gun codes
	{ ITEM_ID_XAXIS,         "XAXIS" },
	{ ITEM_ID_YAXIS,         "YAXIS" },
	{ ITEM_ID_ZAXIS,         "ZAXIS" },
	{ ITEM_ID_RXAXIS,        "RXAXIS" },
	{ ITEM_ID_RYAXIS,        "RYAXIS" },
	{ ITEM_ID_RZAXIS,        "RZAXIS" },
	{ ITEM_ID_SLIDER1,       "SLIDER1" },
	{ ITEM_ID_SLIDER2,       "SLIDER2" },
	{ ITEM_ID_BUTTON1,       "BUTTON1" },
	{ ITEM_ID_BUTTON2,       "BUTTON2" },
	{ ITEM_ID_BUTTON3,       "BUTTON3" },
	{ ITEM_ID_BUTTON4,       "BUTTON4" },
	{ ITEM_ID_BUTTON5,       "BUTTON5" },
	{ ITEM_ID_BUTTON6,       "BUTTON6" },
	{ ITEM_ID_BUTTON7,       "BUTTON7" },
	{ ITEM_ID_BUTTON8,       "BUTTON8" },
	{ ITEM_ID_BUTTON9,       "BUTTON9" },
	{ ITEM_ID_BUTTON10,      "BUTTON10" },
	{ ITEM_ID_BUTTON11,      "BUTTON11" },
	{ ITEM_ID_BUTTON12,      "BUTTON12" },
	{ ITEM_ID_BUTTON13,      "BUTTON13" },
	{ ITEM_ID_BUTTON14,      "BUTTON14" },
	{ ITEM_ID_BUTTON15,      "BUTTON15" },
	{ ITEM_ID_BUTTON16,      "BUTTON16" },
	{ ITEM_ID_BUTTON17,      "BUTTON17" },
	{ ITEM_ID_BUTTON18,      "BUTTON18" },
	{ ITEM_ID_BUTTON19,      "BUTTON19" },
	{ ITEM_ID_BUTTON20,      "BUTTON20" },
	{ ITEM_ID_BUTTON21,      "BUTTON21" },
	{ ITEM_ID_BUTTON22,      "BUTTON22" },
	{ ITEM_ID_BUTTON23,      "BUTTON23" },
	{ ITEM_ID_BUTTON24,      "BUTTON24" },
	{ ITEM_ID_BUTTON25,      "BUTTON25" },
	{ ITEM_ID_BUTTON26,      "BUTTON26" },
	{ ITEM_ID_BUTTON27,      "BUTTON27" },
	{ ITEM_ID_BUTTON28,      "BUTTON28" },
	{ ITEM_ID_BUTTON29,      "BUTTON29" },
	{ ITEM_ID_BUTTON30,      "BUTTON30" },
	{ ITEM_ID_BUTTON31,      "BUTTON31" },
	{ ITEM_ID_BUTTON32,      "BUTTON32" },
	{ ITEM_ID_START,         "START" },
	{ ITEM_ID_SELECT,        "SELECT" },

	// Hats
	{ ITEM_ID_HAT1UP,        "HAT1UP" },
	{ ITEM_ID_HAT1DOWN,      "HAT1DOWN" },
	{ ITEM_ID_HAT1LEFT,      "HAT1LEFT" },
	{ ITEM_ID_HAT1RIGHT,     "HAT1RIGHT" },
	{ ITEM_ID_HAT2UP,        "HAT2UP" },
	{ ITEM_ID_HAT2DOWN,      "HAT2DOWN" },
	{ ITEM_ID_HAT2LEFT,      "HAT2LEFT" },
	{ ITEM_ID_HAT2RIGHT,     "HAT2RIGHT" },
	{ ITEM_ID_HAT3UP,        "HAT3UP" },
	{ ITEM_ID_HAT3DOWN,      "HAT3DOWN" },
	{ ITEM_ID_HAT3LEFT,      "HAT3LEFT" },
	{ ITEM_ID_HAT3RIGHT,     "HAT3RIGHT" },
	{ ITEM_ID_HAT4UP,        "HAT4UP" },
	{ ITEM_ID_HAT4DOWN,      "HAT4DOWN" },
	{ ITEM_ID_HAT4LEFT,      "HAT4LEFT" },
	{ ITEM_ID_HAT4RIGHT,     "HAT4RIGHT" },

	// Additional IDs
	{ ITEM_ID_ADD_SWITCH1,   "ADDSW1" },
	{ ITEM_ID_ADD_SWITCH2,   "ADDSW2" },
	{ ITEM_ID_ADD_SWITCH3,   "ADDSW3" },
	{ ITEM_ID_ADD_SWITCH4,   "ADDSW4" },
	{ ITEM_ID_ADD_SWITCH5,   "ADDSW5" },
	{ ITEM_ID_ADD_SWITCH6,   "ADDSW6" },
	{ ITEM_ID_ADD_SWITCH7,   "ADDSW7" },
	{ ITEM_ID_ADD_SWITCH8,   "ADDSW8" },
	{ ITEM_ID_ADD_SWITCH9,   "ADDSW9" },
	{ ITEM_ID_ADD_SWITCH10,  "ADDSW10" },
	{ ITEM_ID_ADD_SWITCH11,  "ADDSW11" },
	{ ITEM_ID_ADD_SWITCH12,  "ADDSW12" },
	{ ITEM_ID_ADD_SWITCH13,  "ADDSW13" },
	{ ITEM_ID_ADD_SWITCH14,  "ADDSW14" },
	{ ITEM_ID_ADD_SWITCH15,  "ADDSW15" },
	{ ITEM_ID_ADD_SWITCH16,  "ADDSW16" },
	{ ITEM_ID_ADD_ABSOLUTE1, "ADDAXIS1" },
	{ ITEM_ID_ADD_ABSOLUTE2, "ADDAXIS2" },
	{ ITEM_ID_ADD_ABSOLUTE3, "ADDAXIS3" },
	{ ITEM_ID_ADD_ABSOLUTE4, "ADDAXIS4" },
	{ ITEM_ID_ADD_ABSOLUTE5, "ADDAXIS5" },
	{ ITEM_ID_ADD_ABSOLUTE6, "ADDAXIS6" },
	{ ITEM_ID_ADD_ABSOLUTE7, "ADDAXIS7" },
	{ ITEM_ID_ADD_ABSOLUTE8, "ADDAXIS8" },
	{ ITEM_ID_ADD_ABSOLUTE9, "ADDAXIS9" },
	{ ITEM_ID_ADD_ABSOLUTE10,"ADDAXIS10" },
	{ ITEM_ID_ADD_ABSOLUTE11,"ADDAXIS11" },
	{ ITEM_ID_ADD_ABSOLUTE12,"ADDAXIS12" },
	{ ITEM_ID_ADD_ABSOLUTE13,"ADDAXIS13" },
	{ ITEM_ID_ADD_ABSOLUTE14,"ADDAXIS14" },
	{ ITEM_ID_ADD_ABSOLUTE15,"ADDAXIS15" },
	{ ITEM_ID_ADD_ABSOLUTE16,"ADDAXIS16" },
	{ ITEM_ID_ADD_RELATIVE1, "ADDREL1" },
	{ ITEM_ID_ADD_RELATIVE2, "ADDREL2" },
	{ ITEM_ID_ADD_RELATIVE3, "ADDREL3" },
	{ ITEM_ID_ADD_RELATIVE4, "ADDREL4" },
	{ ITEM_ID_ADD_RELATIVE5, "ADDREL5" },
	{ ITEM_ID_ADD_RELATIVE6, "ADDREL6" },
	{ ITEM_ID_ADD_RELATIVE7, "ADDREL7" },
	{ ITEM_ID_ADD_RELATIVE8, "ADDREL8" },
	{ ITEM_ID_ADD_RELATIVE9, "ADDREL9" },
	{ ITEM_ID_ADD_RELATIVE10,"ADDREL10" },
	{ ITEM_ID_ADD_RELATIVE11,"ADDREL11" },
	{ ITEM_ID_ADD_RELATIVE12,"ADDREL12" },
	{ ITEM_ID_ADD_RELATIVE13,"ADDREL13" },
	{ ITEM_ID_ADD_RELATIVE14,"ADDREL14" },
	{ ITEM_ID_ADD_RELATIVE15,"ADDREL15" },
	{ ITEM_ID_ADD_RELATIVE16,"ADDREL16" },

	{ ~0U,                   nullptr }
};



//**************************************************************************
//  INPUT SEQ
//**************************************************************************

//-------------------------------------------------
//  operator+= - append a code to the end of an
//  input sequence
//-------------------------------------------------

input_seq &input_seq::operator+=(input_code code) noexcept
{
	// if not enough room, return false
	const int curlength = length();
	if (curlength < m_code.size())
	{
		m_code[curlength] = code;
		if ((curlength + 1) < m_code.size())
			m_code[curlength + 1] = end_code;
	}
	return *this;
}


//-------------------------------------------------
//  operator|= - append a code to a sequence; if
//  the sequence is non-empty, insert an OR
//  before the new code
//-------------------------------------------------

input_seq &input_seq::operator|=(input_code code) noexcept
{
	// overwrite end/default with the new code
	if (m_code[0] == default_code)
	{
		m_code[0] = code;
		m_code[1] = end_code;
	}
	else
	{
		// otherwise, append an OR token and then the new code
		const int curlength = length();
		if ((curlength + 1) < m_code.size())
		{
			m_code[curlength] = or_code;
			m_code[curlength + 1] = code;
			if ((curlength + 2) < m_code.size())
				m_code[curlength + 2] = end_code;
		}
	}
	return *this;
}


//-------------------------------------------------
//  length - return the length of the sequence
//-------------------------------------------------

int input_seq::length() const noexcept
{
	// find the end token; error if none found
	for (int seqnum = 0; seqnum < m_code.size(); seqnum++)
		if (m_code[seqnum] == end_code)
			return seqnum;
	return m_code.size();
}


//-------------------------------------------------
//  is_valid - return true if a given sequence is
//  valid
//-------------------------------------------------

bool input_seq::is_valid() const noexcept
{
	// "default" can only be of length 1
	if (m_code[0] == default_code)
		return m_code[1] == end_code;

	// scan the sequence for valid codes
	input_item_class lastclass = ITEM_CLASS_INVALID;
	input_code lastcode = INPUT_CODE_INVALID;
	decltype(m_code) positive_codes;
	decltype(m_code) negative_codes;
	auto positive_codes_end = positive_codes.begin();
	auto negative_codes_end = negative_codes.begin();
	for (input_code code : m_code)
	{
		// invalid codes are never permitted
		if (code == INPUT_CODE_INVALID)
			return false;

		// if we hit an OR or the end, validate the previous chunk
		if (code == or_code || code == end_code)
		{
			// must be at least one positive code
			if (positive_codes.begin() == positive_codes_end)
				return false;

			// last code must not have been an internal code
			if (lastcode.internal())
				return false;

			// if this is the end, we're OK
			if (code == end_code)
				return true;

			// reset the state for the next chunk
			positive_codes_end = positive_codes.begin();
			negative_codes_end = negative_codes.begin();
			lastclass = ITEM_CLASS_INVALID;
		}
		else if (code == not_code)
		{
			// if we hit a NOT, make sure we don't have a double
			if (lastcode == not_code)
				return false;
		}
		else
		{
			// track positive codes, and don't allow positive and negative for the same code
			if (lastcode != not_code)
			{
				*positive_codes_end++ = code;
				if (std::find(negative_codes.begin(), negative_codes_end, code) != negative_codes_end)
					return false;
			}
			else
			{
				*negative_codes_end++ = code;
				if (std::find(positive_codes.begin(), positive_codes_end, code) != positive_codes_end)
					return false;
			}

			// non-switch items can't have a NOT
			input_item_class itemclass = code.item_class();
			if (itemclass != ITEM_CLASS_SWITCH && lastcode == not_code)
				return false;

			// absolute/relative items must all be the same class
			if ((lastclass == ITEM_CLASS_ABSOLUTE && itemclass != ITEM_CLASS_ABSOLUTE) ||
				(lastclass == ITEM_CLASS_RELATIVE && itemclass != ITEM_CLASS_RELATIVE))
				return false;
		}

		// remember the last code
		lastcode = code;
	}

	// if we got here, we were missing an END token; fail
	return false;
}


//-------------------------------------------------
//  backspace - "backspace" over the last entry in
//  a sequence
//-------------------------------------------------

void input_seq::backspace() noexcept
{
	// if we have at least one entry, remove it
	const int curlength = length();
	if (curlength > 0)
		m_code[curlength - 1] = end_code;
}


//-------------------------------------------------
//  replace - replace all instances of oldcode
//  with newcode in a sequence
//-------------------------------------------------

void input_seq::replace(input_code oldcode, input_code newcode) noexcept
{
	for (input_code &elem : m_code)
		if (elem == oldcode)
			elem = newcode;
}



//**************************************************************************
//  INPUT MANAGER
//**************************************************************************

//-------------------------------------------------
//  input_manager - constructor
//-------------------------------------------------

input_manager::input_manager(running_machine &machine) : m_machine(machine)
{
	// reset code memory
	reset_memory();

	// create pointers for the classes
	m_class[DEVICE_CLASS_KEYBOARD] = std::make_unique<input_class_keyboard>(*this);
	m_class[DEVICE_CLASS_MOUSE] = std::make_unique<input_class_mouse>(*this);
	m_class[DEVICE_CLASS_LIGHTGUN] = std::make_unique<input_class_lightgun>(*this);
	m_class[DEVICE_CLASS_JOYSTICK] = std::make_unique<input_class_joystick>(*this);

#ifdef MAME_DEBUG
	for (input_device_class devclass = DEVICE_CLASS_FIRST_VALID; devclass <= DEVICE_CLASS_LAST_VALID; ++devclass)
	{
		assert(m_class[devclass] != nullptr);
		assert(m_class[devclass]->devclass() == devclass);
	}
#endif
}


//-------------------------------------------------
//  input_manager - destructor
//-------------------------------------------------

input_manager::~input_manager()
{
}


//-------------------------------------------------
//  code_value - return the value of a given
//  input code
//-------------------------------------------------

s32 input_manager::code_value(input_code code)
{
	g_profiler.start(PROFILER_INPUT);
	s32 result = 0;

	// dummy loop to allow clean early exits
	do
	{
		// return 0 for any invalid devices
		input_device *device = device_from_code(code);
		if (device == nullptr)
			break;

		// also return 0 if the device class is disabled
		input_class &devclass = *m_class[code.device_class()];
		if (!devclass.enabled())
			break;

		// if this is not a multi device, only return data for item 0 and iterate over all
		int startindex = code.device_index();
		int stopindex = startindex;
		if (!devclass.multi())
		{
			if (startindex != 0)
				break;
			stopindex = devclass.maxindex();
		}

		// iterate over all device indices
		input_item_class targetclass = code.item_class();
		for (int curindex = startindex; curindex <= stopindex; curindex++)
		{
			// lookup the item for the appropriate index
			code.set_device_index(curindex);
			input_device_item *item = item_from_code(code);
			if (item == nullptr)
				continue;

			// process items according to their native type
			switch (targetclass)
			{
				case ITEM_CLASS_ABSOLUTE:
					if (result == 0)
						result = item->read_as_absolute(code.item_modifier());
					break;

				case ITEM_CLASS_RELATIVE:
					result += item->read_as_relative(code.item_modifier());
					break;

				case ITEM_CLASS_SWITCH:
					result |= item->read_as_switch(code.item_modifier());
					break;

				default:
					break;
			}
		}
	} while (0);

	// stop the profiler before exiting
	g_profiler.stop();
	return result;
}


//-------------------------------------------------
//  code_pressed_once - return non-zero if a given
//  input code has transitioned from off to on
//  since the last call
//-------------------------------------------------

bool input_manager::code_pressed_once(input_code code)
{
	// look for the code in the memory
	bool curvalue = code_pressed(code);
	int empty = -1;
	for (int memnum = 0; memnum < std::size(m_switch_memory); memnum++)
	{
		// were we previous pressed on the last time through here?
		if (m_switch_memory[memnum] == code)
		{
			// if no longer pressed, clear entry
			if (!curvalue)
				m_switch_memory[memnum] = INPUT_CODE_INVALID;

			// always return false
			return false;
		}

		// remember the first empty entry
		if (empty == -1 && m_switch_memory[memnum] == INPUT_CODE_INVALID)
			empty = memnum;
	}

	// if we get here, we were not previously pressed; if still not pressed, return false
	if (!curvalue)
		return false;

	// otherwise, add the code to the memory and return true
	assert(empty != -1);
	if (empty != -1)
		m_switch_memory[empty] = code;
	return true;
}


//-------------------------------------------------
//  device_from_code - given an input_code return
//  a pointer to the associated device
//-------------------------------------------------

input_device *input_manager::device_from_code(input_code code) const
{
	// if the class is valid, return the appropriate device pointer
	input_device_class devclass = code.device_class();
	if (devclass >= DEVICE_CLASS_FIRST_VALID && devclass <= DEVICE_CLASS_LAST_VALID)
		return m_class[devclass]->device(code.device_index());

	// otherwise, return nullptr
	return nullptr;
}


//-------------------------------------------------
//  item_from_code - given an input_code return
//  a pointer to the appropriate input_device_item
//-------------------------------------------------

input_device_item *input_manager::item_from_code(input_code code) const
{
	// first get the device; if none, then we don't have an item
	input_device *device = device_from_code(code);
	if (device == nullptr)
		return nullptr;

	// then return the device's item
	return device->item(code.item_id());
}


//-------------------------------------------------
//  reset_memory - reset the array of memory for
//  pressed switches
//-------------------------------------------------

void input_manager::reset_memory()
{
	// reset all entries in switch memory to invalid
	for (auto & elem : m_switch_memory)
		elem = INPUT_CODE_INVALID;
}


//-------------------------------------------------
//  code_from_itemid - translates an input_item_id
//  to an input_code
//-------------------------------------------------

input_code input_manager::code_from_itemid(input_item_id itemid) const
{
	// iterate over device classes and devices
	for (input_device_class devclass = DEVICE_CLASS_FIRST_VALID; devclass <= DEVICE_CLASS_LAST_VALID; ++devclass)
		for (int devnum = 0; devnum <= m_class[devclass]->maxindex(); devnum++)
		{
			input_device *device = m_class[devclass]->device(devnum);
			if (device != nullptr)
			{
				input_device_item *item = device->item(itemid);
				if (item != nullptr)
					return item->code();
			}
		}

	return INPUT_CODE_INVALID;
}


//-------------------------------------------------
//  code_name - convert an input code into a
//  friendly name
//-------------------------------------------------

std::string input_manager::code_name(input_code code) const
{
	// if nothing there, return an empty string
	input_device_item *item = item_from_code(code);
	if (item == nullptr)
		return std::string();

	// determine the devclass part
	const char *devclass = (*devclass_string_table)[code.device_class()];

	// determine the devindex part
	std::string devindex = string_format("%d", code.device_index() + 1);

	// if we're unifying all devices, don't display a number
	if (!m_class[code.device_class()]->multi())
		devindex.clear();

	// keyboard 0 doesn't show a class or index if it is the only one
	input_device_class device_class = item->device().devclass();
	if (device_class == DEVICE_CLASS_KEYBOARD && m_class[device_class]->maxindex() == 0)
	{
		devclass = "";
		devindex.clear();
	}

	// devcode part comes from the item name
	std::string_view devcode = item->name();

	// determine the modifier part
	const char *modifier = (*modifier_string_table)[code.item_modifier()];

	// devcode is redundant with joystick switch left/right/up/down
	if (device_class == DEVICE_CLASS_JOYSTICK && code.item_class() == ITEM_CLASS_SWITCH)
		if (code.item_modifier() >= ITEM_MODIFIER_LEFT && code.item_modifier() <= ITEM_MODIFIER_DOWN)
			devcode = std::string_view();

	// concatenate the strings
	std::string str(devclass);
	if (!devindex.empty())
		str.append(" ").append(devindex);
	if (!devcode.empty())
		str.append(" ").append(devcode);
	if (modifier != nullptr)
		str.append(" ").append(modifier);

	// delete any leading spaces
	return std::string(strtrimspace(str));
}


//-------------------------------------------------
//  code_to_token - create a token for a given code
//-------------------------------------------------

std::string input_manager::code_to_token(input_code code) const
{
	using namespace std::literals;

	// determine the devclass part
	const char *devclass = (*devclass_token_table)[code.device_class()];
	if (devclass == nullptr)
		return "INVALID";

	// determine the devindex part; keyboard 0 doesn't show an index
	std::string devindex = string_format("%d", code.device_index() + 1);
	if (code.device_class() == DEVICE_CLASS_KEYBOARD && code.device_index() == 0)
		devindex.clear();

	// determine the itemid part; look up in the table if we don't have a token
	input_device_item *item = item_from_code(code);
	std::string_view devcode = item ? item->token() : "UNKNOWN"sv;

	// determine the modifier part
	const char *modifier = (*modifier_token_table)[code.item_modifier()];

	// determine the itemclass part; if we match the native class, we don't include this
	const char *itemclass = "";
	if (!item || (item->itemclass() != code.item_class()))
		itemclass = (*itemclass_token_table)[code.item_class()];

	// concatenate the strings
	std::string str(devclass);
	if (!devindex.empty())
		str.append("_").append(devindex);
	if (devcode[0] != 0)
		str.append("_").append(devcode);
	if (modifier != nullptr)
		str.append("_").append(modifier);
	if (itemclass != nullptr && itemclass[0] != 0)
		str.append("_").append(itemclass);
	return str;
}


//-------------------------------------------------
//  code_from_token - extract an input code from a
//  token
//-------------------------------------------------

input_code input_manager::code_from_token(std::string_view _token)
{
	// copy the token and break it into pieces
	std::string token[6];
	int numtokens = 0;
	while (numtokens < std::size(token))
	{
		// make a token up to the next underscore
		std::string_view::size_type score = _token.find('_');
		token[numtokens++].assign(_token, 0, (std::string_view::npos == score) ? _token.length() : score);

		// if we hit the end, we're done, else advance our pointer
		if (std::string_view::npos == score)
			break;
		_token.remove_prefix(score + 1);
	}

	// first token should be the devclass
	int curtok = 0;
	input_device_class devclass = input_device_class((*devclass_token_table)[token[curtok++]]);
	if (devclass == ~input_device_class(0))
		return INPUT_CODE_INVALID;

	// second token might be index; look for number
	int devindex = 0;
	if (numtokens > 2 && sscanf(token[curtok].c_str(), "%d", &devindex) == 1)
	{
		curtok++;
		devindex--;
	}
	if (curtok >= numtokens)
		return INPUT_CODE_INVALID;

	// next token is the item ID
	input_item_id itemid = input_item_id((*itemid_token_table)[token[curtok]]);
	bool standard = (itemid != ~input_item_id(0));

	// if we're a standard code, default the itemclass based on it
	input_item_class itemclass = ITEM_CLASS_INVALID;
	if (standard)
		itemclass = m_class[devclass]->standard_item_class(itemid);

	// otherwise, keep parsing
	else
	{
		// if this is an invalid device, we have nothing to look up
		input_device *device = m_class[devclass]->device(devindex);
		if (device == nullptr)
			return INPUT_CODE_INVALID;

		// if not a standard code, look it up in the device specific codes
		for (itemid = ITEM_ID_FIRST_VALID; itemid <= device->maxitem(); ++itemid)
		{
			input_device_item *item = device->item(itemid);
			if (item != nullptr && token[curtok].compare(item->token()) == 0)
			{
				// take the itemclass from the item
				itemclass = item->itemclass();
				break;
			}
		}

		// bail on fail
		if (itemid > device->maxitem())
			return INPUT_CODE_INVALID;
	}
	curtok++;

	// if we have another token, it is probably a modifier
	input_item_modifier modifier = ITEM_MODIFIER_NONE;
	if (curtok < numtokens)
	{
		modifier = input_item_modifier((*modifier_token_table)[token[curtok]]);
		if (modifier != ~input_item_modifier(0))
			curtok++;
		else
			modifier = ITEM_MODIFIER_NONE;
	}

	// if we have another token, it is the item class
	if (curtok < numtokens)
	{
		u32 temp = (*itemclass_token_table)[token[curtok]];
		if (temp != ~0)
		{
			curtok++;
			itemclass = input_item_class(temp);
		}
	}

	// we should have consumed all tokens
	if (curtok != numtokens)
		return INPUT_CODE_INVALID;

	// assemble the final code
	return input_code(devclass, devindex, itemclass, modifier, itemid);
}


//-------------------------------------------------
//  standard_token - return the standard token for
//  the given input item ID
//-------------------------------------------------

const char *input_manager::standard_token(input_item_id itemid) const
{
	return itemid <= ITEM_ID_MAXIMUM ? (*itemid_token_table)[itemid] : nullptr;
}


//-------------------------------------------------
//  seq_pressed - return true if the given sequence
//  of switch inputs is "pressed"
//-------------------------------------------------

bool input_manager::seq_pressed(const input_seq &seq)
{
	// iterate over all of the codes
	bool result = false;
	bool invert = false;
	bool first = true;
	for (int codenum = 0; ; codenum++)
	{
		input_code code = seq[codenum];
		if (code == input_seq::not_code)
		{
			// handle NOT
			invert = true;
		}
		else if (code == input_seq::or_code || code == input_seq::end_code)
		{
			// handle OR and END

			// if we have a positive result from the previous set, we're done
			if (result || code == input_seq::end_code)
				break;

			// otherwise, reset our state
			result = false;
			invert = false;
			first = true;
		}
		else
		{
			// handle everything else as a series of ANDs

			// if this is the first in the sequence, result is set equal
			if (first)
				result = code_pressed(code) ^ invert;

			// further values are ANDed
			else if (result)
				result &= code_pressed(code) ^ invert;

			// no longer first, and clear the invert flag
			first = invert = false;
		}
	}

	// return the result if we queried at least one switch
	return result;
}


//-------------------------------------------------
//  seq_axis_value - return the value of an axis
//  defined in an input sequence
//-------------------------------------------------

s32 input_manager::seq_axis_value(const input_seq &seq, input_item_class &itemclass)
{
	// start with no valid classes
	input_item_class itemclasszero = ITEM_CLASS_INVALID;
	itemclass = ITEM_CLASS_INVALID;

	// iterate over all of the codes
	s32 result = 0;
	bool invert = false;
	bool enable = true;
	for (int codenum = 0; ; codenum++)
	{
		// handle NOT
		input_code code = seq[codenum];
		if (code == input_seq::not_code)
			invert = true;

		// handle OR and END
		else if (code == input_seq::or_code || code == input_seq::end_code)
		{
			// if we have a positive result from the previous set, we're done
			if (itemclass != ITEM_CLASS_INVALID || code == input_seq::end_code)
				break;

			// otherwise, reset our state
			result = 0;
			invert = false;
			enable = true;
		}

		// handle everything else only if we're still enabled
		else if (enable)
		{
			// switch codes serve as enables
			if (code.item_class() == ITEM_CLASS_SWITCH)
			{
				// AND against previous digital codes
				if (enable)
					enable &= code_pressed(code) ^ invert;
			}

			// non-switch codes are analog values
			else
			{
				s32 value = code_value(code);

				// if we got a 0 value, don't do anything except remember the first type
				if (value == 0)
				{
					if (itemclasszero == ITEM_CLASS_INVALID)
						itemclasszero = code.item_class();
				}

				// non-zero absolute values stick
				else if (code.item_class() == ITEM_CLASS_ABSOLUTE)
				{
					itemclass = ITEM_CLASS_ABSOLUTE;
					result = value;
				}

				// non-zero relative values accumulate
				else if (code.item_class() == ITEM_CLASS_RELATIVE)
				{
					itemclass = ITEM_CLASS_RELATIVE;
					result += value;
				}
			}

			// clear the invert flag
			invert = false;
		}
	}

	// if the caller wants to know the type, provide it
	if (result == 0)
		itemclass = itemclasszero;
	return result;
}


//-------------------------------------------------
//  seq_clean - clean the sequence, removing
//  any invalid bits
//-------------------------------------------------

input_seq input_manager::seq_clean(const input_seq &seq) const
{
	// make a copy of our sequence, removing any invalid bits
	input_seq clean_codes;
	int clean_index = 0;
	for (int codenum = 0; seq[codenum] != input_seq::end_code; codenum++)
	{
		// if this is a code item which is not valid, don't copy it and remove any preceding ORs/NOTs
		input_code code = seq[codenum];
		if (!code.internal() && code_name(code).empty())
		{
			while (clean_index > 0 && clean_codes[clean_index - 1].internal())
			{
				clean_codes.backspace();
				clean_index--;
			}
		}
		else if (clean_index > 0 || !code.internal() || code == input_seq::not_code)
		{
			clean_codes += code;
			clean_index++;
		}
	}
	return clean_codes;
}


//-------------------------------------------------
//  seq_name - generate the friendly name of a
//  sequence
//-------------------------------------------------

std::string input_manager::seq_name(const input_seq &seq) const
{
	// make a copy of our sequence, removing any invalid bits
	input_seq cleaned_seq = seq_clean(seq);

	// special case: empty
	if (cleaned_seq[0] == input_seq::end_code)
		return std::string(seq.empty() ? "None" : "n/a");

	// start with an empty buffer
	std::string str;

	// loop until we hit the end
	for (int codenum = 0; cleaned_seq[codenum] != input_seq::end_code; codenum++)
	{
		// append a space if not the first code
		if (codenum != 0)
			str.append(" ");

		// handle OR/NOT codes here
		input_code code = cleaned_seq[codenum];
		if (code == input_seq::or_code)
			str.append("or");
		else if (code == input_seq::not_code)
			str.append("not");

		// otherwise, assume it is an input code and ask the input system to generate it
		else
			str.append(code_name(code));
	}
	return str;
}


//-------------------------------------------------
//  seq_to_tokens - generate the tokenized form of
//  a sequence
//-------------------------------------------------

std::string input_manager::seq_to_tokens(const input_seq &seq) const
{
	// start with an empty buffer
	std::string str;

	// loop until we hit the end
	for (int codenum = 0; seq[codenum] != input_seq::end_code; codenum++)
	{
		// append a space if not the first code
		if (codenum != 0)
			str.append(" ");

		// handle OR/NOT codes here
		input_code code = seq[codenum];
		if (code == input_seq::or_code)
			str.append("OR");
		else if (code == input_seq::not_code)
			str.append("NOT");
		else if (code == input_seq::default_code)
			str.append("DEFAULT");

		// otherwise, assume it is an input code and ask the input system to generate it
		else
			str.append(code_to_token(code));
	}
	return str;
}


//-------------------------------------------------
//  seq_from_tokens - generate the tokenized form
//  of a sequence
//-------------------------------------------------

void input_manager::seq_from_tokens(input_seq &seq, std::string_view string)
{
	// start with a blank sequence
	seq.reset();

	// loop until we're done
	unsigned operators = 0;
	while (1)
	{
		// trim any leading spaces
		while (!string.empty() && isspace(u8(string[0])))
			string.remove_prefix(1);

		// bail if we're done
		if (string.empty())
			return;

		// find the end of the token and make it upper-case along the way
		std::string token;
		while (!string.empty() && !isspace(u8(string[0])))
		{
			token.push_back(toupper(u8(string[0])));
			string.remove_prefix(1);
		}

		// look for common stuff
		input_code code;
		bool is_operator;
		if (token == "OR")
		{
			code = input_seq::or_code;
			is_operator = true;
		}
		else if (token == "NOT")
		{
			code = input_seq::not_code;
			is_operator = true;
		}
		else if (token == "DEFAULT")
		{
			code = input_seq::default_code;
			is_operator = false;
		}
		else
		{
			code = code_from_token(token);
			is_operator = false;
		}

		// translate and add to the sequence
		if (is_operator)
		{
			++operators;
			seq += code;
		}
		else
		{
			if (code.device_class() < DEVICE_CLASS_FIRST_VALID)
			{
				osd_printf_warning("Input: Dropping invalid input token %s\n", token);
				while (operators)
				{
					seq.backspace();
					--operators;
				}
			}
			else
			{
				operators = 0;
				seq += code;
			}
		}

		// advance
		if (string.empty())
			return;
		string.remove_prefix(1);
	}
}

//-------------------------------------------------
//  map_device_to_controller - map device to
//  controller based on device map table
//-------------------------------------------------

bool input_manager::map_device_to_controller(const devicemap_table &table)
{
	for (const auto &it : table)
	{
		std::string_view deviceid = it.first;
		std::string_view controllername = it.second;

		// tokenize the controller name into device class and index (i.e. controller name should be of the form "GUNCODE_1")
		std::string token[2];
		int numtokens = 0;
		std::string_view _token = controllername;
		while (numtokens < std::size(token))
		{
			// make a token up to the next underscore
			std::string_view::size_type score = _token.find('_');
			token[numtokens++].assign(_token, 0, (std::string_view::npos == score) ? _token.length() : score);

			// if we hit the end, we're done, else advance our pointer
			if (std::string_view::npos == score)
				break;
			_token.remove_prefix(score + 1);
		}
		if (2 != numtokens)
			return false;

		// first token should be the devclass
		input_device_class devclass = input_device_class((*devclass_token_table)[strmakeupper(token[0])]);
		if (devclass == ~input_device_class(0))
			return false;

		// second token should be the devindex
		int devindex = 0;
		if (1 != sscanf(token[1].c_str(), "%d", &devindex))
			return false;
		devindex--;

		if (devindex >= DEVICE_INDEX_MAXIMUM)
			return false;

		// enumerate through devices and look for a match
		input_class *input_devclass = m_class[devclass].get();
		for (int devnum = 0; devnum <= input_devclass->maxindex(); devnum++)
		{
			input_device *device = input_devclass->device(devnum);
			if (device && device->match_device_id(deviceid))
			{
				// remap devindex
				input_devclass->remap_device_index(device->devindex(), devindex);
				osd_printf_verbose("Input: Remapped %s #%d: %s (device id: %s)\n", input_devclass->name(), devindex, device->name(), device->id());

				break;
			}
		}
	}

	return true;
}