From aa3c3fde69e363f960c8833e7f4bf408bc54beee Mon Sep 17 00:00:00 2001 From: Dirk Best Date: Tue, 10 Apr 2018 15:23:51 +0200 Subject: [PATCH] model2: Proper default values for lightgun games This avoids the need to calibrate the lightguns in the service mode. Also clean up lightgun interface. Five percent of the full range is now declared off-screen and will act as a reload area. --- src/mame/drivers/model2.cpp | 166 ++++++++++++++++++++---------------- src/mame/includes/model2.h | 7 +- 2 files changed, 94 insertions(+), 79 deletions(-) diff --git a/src/mame/drivers/model2.cpp b/src/mame/drivers/model2.cpp index 754836cee36..cbe9e922190 100644 --- a/src/mame/drivers/model2.cpp +++ b/src/mame/drivers/model2.cpp @@ -38,7 +38,6 @@ - skytargt: short draw distance (might be down to z-sort); - srallyc: some 3d elements doesn't show up properly (tree models, last hill in course 1 is often black colored); - vcop: sound dies at enter initial screen (i.e. after played the game once) (untested); - - vcop: lightgun input is offsetted (needs to be calibrated in service mode); - vcop: missing 3d at stage select screen (priority?); - vstriker: stadium ads have terrible colors (they uses the wrong color table, @see video/model2rd.hxx) @@ -481,8 +480,13 @@ READ8_MEMBER(model2_state::model2_crx_in_r) input = m_in[m_port_1c00014]->read(); break; case 0x0c: + if (m_lightgun_mux < 8) + input = lightgun_coords_r(space, m_lightgun_mux); + else + input = lightgun_offscreen_r(space, 0); + break; case 0x0d: - input = hotd_lightgun_r(space, offset - 0x0c); + input = 0x0c; // lightgun latches? break; case 0x0e: // these must be high @@ -701,7 +705,7 @@ void model2_tgp_state::copro_tgp_bank_map(address_map &map) void model2_tgp_state::copro_tgp_io_map(address_map &map) { - map(0x0000, 0xffff).m(m_copro_tgp_bank, FUNC(address_map_bank_device::amap32)); + map(0x0000, 0xffff).m(m_copro_tgp_bank, FUNC(address_map_bank_device::amap32)); } void model2_tgp_state::copro_tgp_rf_map(address_map &map) @@ -1172,45 +1176,6 @@ WRITE32_MEMBER(model2_state::geo_w) /*****************************************************************************/ - -READ8_MEMBER(model2_state::hotd_lightgun_r) -{ - uint8_t res = 0xff; - - if(m_lightgun_mux < 8) - res = (m_lightgun_ports[m_lightgun_mux >> 1].read_safe(0) >> ((m_lightgun_mux & 1)*8)) & 0xff; - else - { - uint16_t p1x,p1y,p2x,p2y; - - res = 0xfc; - - p1x = m_lightgun_ports[1].read_safe(0); - p1y = m_lightgun_ports[0].read_safe(0); - p2x = m_lightgun_ports[3].read_safe(0); - p2y = m_lightgun_ports[2].read_safe(0); - - /* TODO: might be better, supposedly user has to calibrate guns in order to make these settings to work ... */ - if(p1x <= 0x28 || p1x >= 0x3e0 || p1y <= 0x40 || p1y >= 0x3c0) - res |= 1; - - if(p2x <= 0x28 || p2x >= 0x3e0 || p2y <= 0x40 || p2y >= 0x3c0) - res |= 2; - } - - /* upper bits are presumably related to lightgun latches */ - if (offset == 1) - return 0x0c; - else - return res; -} - -WRITE32_MEMBER(model2_state::hotd_lightgun_w) -{ - m_lightgun_mux = data; -} - - READ32_MEMBER(model2o_state::daytona_unk_r) { return 0x00400000; @@ -1472,34 +1437,53 @@ void model2_state::model2_5881_mem(address_map &map) map(0x01d90000, 0x01d9ffff).m(m_cryptdevice, FUNC(sega_315_5881_crypt_device::iomap_le)); } -READ8_MEMBER(model2_state::virtuacop_lightgun_r) +//************************************************************************** +// LIGHTGUN +//************************************************************************** + +// Interface board ID: 837-12079 +// ALTERA FLEX + Sega 315-5338A + +READ8_MEMBER( model2_state::lightgun_coords_r ) { - uint8_t res; - - res = (m_lightgun_ports[offset >> 1].read_safe(0) >> ((offset & 1)*8)) & 0xff; - - return res; + return (m_lightgun_ports[offset >> 1].read_safe(0) >> ((offset & 1)*8)) & 0xff; } -/* handles offscreen gun trigger detection here */ -READ8_MEMBER(model2_state::virtuacop_lightgun_offscreen_r) +// handles offscreen gun trigger detection here +READ8_MEMBER( model2_state::lightgun_offscreen_r ) { - uint16_t special_res = 0xfffc; - uint16_t p1x,p1y,p2x,p2y; + // 5 percent border size + const float BORDER_SIZE = 0.05; - p1x = m_lightgun_ports[1].read_safe(0); - p1y = m_lightgun_ports[0].read_safe(0); - p2x = m_lightgun_ports[3].read_safe(0); - p2y = m_lightgun_ports[2].read_safe(0); + // calculate width depending on min/max port value + const int BORDER_P1X = (m_lightgun_ports[1]->field(0x3ff)->maxval() - m_lightgun_ports[1]->field(0x3ff)->minval()) * BORDER_SIZE; + const int BORDER_P1Y = (m_lightgun_ports[0]->field(0x3ff)->maxval() - m_lightgun_ports[0]->field(0x3ff)->minval()) * BORDER_SIZE; + const int BORDER_P2X = (m_lightgun_ports[3]->field(0x3ff)->maxval() - m_lightgun_ports[3]->field(0x3ff)->minval()) * BORDER_SIZE; + const int BORDER_P2Y = (m_lightgun_ports[2]->field(0x3ff)->maxval() - m_lightgun_ports[2]->field(0x3ff)->minval()) * BORDER_SIZE; - /* TODO: might be better, supposedly user has to calibrate guns in order to make these settings to work ... */ - if(p1x <= 0x28 || p1x >= 0x3e0 || p1y <= 0x40 || p1y >= 0x3c0) - special_res |= 1; + uint16_t data = 0xfffc; - if(p2x <= 0x28 || p2x >= 0x3e0 || p2y <= 0x40 || p2y >= 0x3c0) - special_res |= 2; + const uint16_t P1X = m_lightgun_ports[1].read_safe(0); + const uint16_t P1Y = m_lightgun_ports[0].read_safe(0); + const uint16_t P2X = m_lightgun_ports[3].read_safe(0); + const uint16_t P2Y = m_lightgun_ports[2].read_safe(0); - return (special_res >> ((offset & 1)*8)) & 0xff; + // border hit test for player 1 and 2 + if (P1X <= (m_lightgun_ports[1]->field(0x3ff)->minval() + BORDER_P1X)) data |= 1; + if (P1X >= (m_lightgun_ports[1]->field(0x3ff)->maxval() - BORDER_P1X)) data |= 1; + if (P1Y <= (m_lightgun_ports[0]->field(0x3ff)->minval() + BORDER_P1Y)) data |= 1; + if (P1Y >= (m_lightgun_ports[0]->field(0x3ff)->maxval() - BORDER_P1Y)) data |= 1; + if (P2X <= (m_lightgun_ports[3]->field(0x3ff)->minval() + BORDER_P2X)) data |= 2; + if (P2X >= (m_lightgun_ports[3]->field(0x3ff)->maxval() - BORDER_P2X)) data |= 2; + if (P2Y <= (m_lightgun_ports[2]->field(0x3ff)->minval() + BORDER_P2Y)) data |= 2; + if (P2Y >= (m_lightgun_ports[2]->field(0x3ff)->maxval() - BORDER_P2Y)) data |= 2; + + return (data >> ((offset & 1)*8)) & 0xff; +} + +WRITE8_MEMBER( model2_state::lightgun_mux_w ) +{ + m_lightgun_mux = data; } /* Apparently original Model 2 doesn't have fifo control? */ @@ -1508,6 +1492,10 @@ READ32_MEMBER(model2o_state::fifo_control_2o_r) return 0xffffffff; } +//************************************************************************** +// OUTPUTS +//************************************************************************** + WRITE8_MEMBER( model2o_state::daytona_output_w ) { // 7------- leader led @@ -1577,8 +1565,8 @@ void model2o_state::model2o_mem(address_map &map) map(0x01c00000, 0x01c0001f).rw("io", FUNC(m1io_device::read), FUNC(m1io_device::write)).umask32(0x00ff00ff); map(0x01c00040, 0x01c00043).r(this, FUNC(model2o_state::daytona_unk_r)); - map(0x01c00100, 0x01c0010f).r(this, FUNC(model2o_state::virtuacop_lightgun_r)).umask32(0x00ff00ff); - map(0x01c00110, 0x01c00113).r(this, FUNC(model2o_state::virtuacop_lightgun_offscreen_r)).umask32(0x00ff00ff); + map(0x01c00100, 0x01c0010f).r(this, FUNC(model2o_state::lightgun_coords_r)).umask32(0x00ff00ff); + map(0x01c00110, 0x01c00113).r(this, FUNC(model2o_state::lightgun_offscreen_r)).umask32(0x00ff00ff); map(0x01c00200, 0x01c002ff).ram().share("backup2"); map(0x01c80000, 0x01c80003).rw(this, FUNC(model2o_state::model2_serial_r), FUNC(model2o_state::model2_serial_w)); } @@ -1671,7 +1659,7 @@ void model2a_state::model2a_crx_mem(address_map &map) map(0x01c00000, 0x01c00003).w(this, FUNC(model2a_state::ctrl0_w)); map(0x01c00008, 0x01c0000f).nopw(); map(0x01c00010, 0x01c00013).nopw(); - map(0x01c00014, 0x01c00017).w(this, FUNC(model2a_state::hotd_lightgun_w)); + map(0x01c00014, 0x01c00017).w(this, FUNC(model2a_state::lightgun_mux_w)).umask32(0x000000ff); map(0x01c0001c, 0x01c0001f).w(this, FUNC(model2a_state::analog_2b_w)); map(0x01c00040, 0x01c00043).nopw(); map(0x01c80000, 0x01c80003).rw(this, FUNC(model2a_state::model2_serial_r), FUNC(model2a_state::model2_serial_w)); @@ -1716,7 +1704,7 @@ void model2b_state::model2b_crx_mem(address_map &map) map(0x01c00000, 0x01c00003).w(this, FUNC(model2b_state::ctrl0_w)); map(0x01c00008, 0x01c0000b).nopw(); map(0x01c00010, 0x01c00013).nopw(); // gunblade - map(0x01c00014, 0x01c00017).w(this, FUNC(model2b_state::hotd_lightgun_w)); + map(0x01c00014, 0x01c00017).w(this, FUNC(model2b_state::lightgun_mux_w)).umask32(0x000000ff); map(0x01c0001c, 0x01c0001f).w(this, FUNC(model2b_state::analog_2b_w)); map(0x01c00040, 0x01c00043).nopw(); map(0x01c80000, 0x01c80003).rw(this, FUNC(model2b_state::model2_serial_r), FUNC(model2b_state::model2_serial_w)); @@ -1753,7 +1741,7 @@ void model2c_state::model2c_crx_mem(address_map &map) map(0x01c00000, 0x01c00003).w(this, FUNC(model2c_state::ctrl0_w)); map(0x01c00008, 0x01c0000b).nopw(); map(0x01c00010, 0x01c00013).nopw(); - map(0x01c00014, 0x01c00017).w(this, FUNC(model2c_state::hotd_lightgun_w)); + map(0x01c00014, 0x01c00017).w(this, FUNC(model2c_state::lightgun_mux_w)).umask32(0x000000ff); map(0x01c0001c, 0x01c0001f).w(this, FUNC(model2c_state::analog_2b_w)); map(0x01c80000, 0x01c80003).rw(this, FUNC(model2c_state::model2_serial_r), FUNC(model2c_state::model2_serial_w)); } @@ -1860,16 +1848,16 @@ static INPUT_PORTS_START( vcop ) PORT_BIT(0xfd, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START("P1_X") - PORT_BIT(0x3ff, 0x200, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_MINMAX(0, 0x3ff) PORT_SENSITIVITY(50) PORT_KEYDELTA(15) PORT_PLAYER(1) + PORT_BIT(0x3ff, 0x17c, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_MINMAX(0x083, 0x276) PORT_SENSITIVITY(50) PORT_KEYDELTA(13) PORT_PLAYER(1) PORT_START("P1_Y") - PORT_BIT(0x3ff, 0x200, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_MINMAX(0, 0x3ff) PORT_SENSITIVITY(50) PORT_KEYDELTA(15) PORT_PLAYER(1) + PORT_BIT(0x3ff, 0x0e6, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_MINMAX(0x024, 0x1a9) PORT_SENSITIVITY(50) PORT_KEYDELTA(10) PORT_PLAYER(1) PORT_START("P2_X") - PORT_BIT(0x3ff, 0x200, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_MINMAX(0, 0x3ff) PORT_SENSITIVITY(50) PORT_KEYDELTA(15) PORT_PLAYER(2) + PORT_BIT(0x3ff, 0x179, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_MINMAX(0x080, 0x273) PORT_SENSITIVITY(50) PORT_KEYDELTA(13) PORT_PLAYER(2) PORT_START("P2_Y") - PORT_BIT(0x3ff, 0x200, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_MINMAX(0, 0x3ff) PORT_SENSITIVITY(50) PORT_KEYDELTA(15) PORT_PLAYER(2) + PORT_BIT(0x3ff, 0x0e8, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_MINMAX(0x027, 0x1a9) PORT_SENSITIVITY(50) PORT_KEYDELTA(10) PORT_PLAYER(2) INPUT_PORTS_END static INPUT_PORTS_START( model2 ) @@ -1952,6 +1940,18 @@ static INPUT_PORTS_START( vcop2 ) PORT_MODIFY("IN2") PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_MODIFY("P1_X") + PORT_BIT(0x3ff, 0x17f, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_MINMAX(137, 630) PORT_SENSITIVITY(50) PORT_KEYDELTA(13) PORT_PLAYER(1) + + PORT_MODIFY("P1_Y") + PORT_BIT(0x3ff, 0x0e6, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_MINMAX( 36, 425) PORT_SENSITIVITY(50) PORT_KEYDELTA(10) PORT_PLAYER(1) + + PORT_MODIFY("P2_X") + PORT_BIT(0x3ff, 0x17c, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_MINMAX(134, 627) PORT_SENSITIVITY(50) PORT_KEYDELTA(13) PORT_PLAYER(2) + + PORT_MODIFY("P2_Y") + PORT_BIT(0x3ff, 0x0e6, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_MINMAX( 36, 425) PORT_SENSITIVITY(50) PORT_KEYDELTA(10) PORT_PLAYER(2) + PORT_START("DSW") PORT_DIPNAME( 0x01, 0x01, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SW:1") PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) @@ -2102,6 +2102,22 @@ static INPUT_PORTS_START( sgt24h ) PORT_BIT(0xff, IP_ACTIVE_HIGH, IPT_UNUSED ) INPUT_PORTS_END +static INPUT_PORTS_START( hotd ) + PORT_INCLUDE(vcop2) + + PORT_MODIFY("P1_X") + PORT_BIT(0x3ff, 0x180, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_MINMAX(173, 596) PORT_SENSITIVITY(50) PORT_KEYDELTA(13) PORT_PLAYER(1) + + PORT_MODIFY("P1_Y") + PORT_BIT(0x3ff, 0x0e9, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_MINMAX( 87, 380) PORT_SENSITIVITY(50) PORT_KEYDELTA(10) PORT_PLAYER(1) + + PORT_MODIFY("P2_X") + PORT_BIT(0x3ff, 0x17b, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_MINMAX(163, 596) PORT_SENSITIVITY(50) PORT_KEYDELTA(13) PORT_PLAYER(2) + + PORT_MODIFY("P2_Y") + PORT_BIT(0x3ff, 0x0e9, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_MINMAX( 87, 380) PORT_SENSITIVITY(50) PORT_KEYDELTA(10) PORT_PLAYER(2) +INPUT_PORTS_END + static INPUT_PORTS_START( overrev ) PORT_INCLUDE( sgt24h ) @@ -2534,7 +2550,7 @@ MACHINE_CONFIG_START(model2o_state::model2o) MCFG_DEVICE_ADD("copro_fifo_in", GENERIC_FIFO_U32, 0) MCFG_DEVICE_ADD("copro_fifo_out", GENERIC_FIFO_U32, 0) - + MCFG_MACHINE_START_OVERRIDE(model2_tgp_state,model2_tgp) MCFG_MACHINE_RESET_OVERRIDE(model2o_state,model2o) @@ -2674,7 +2690,7 @@ MACHINE_CONFIG_START(model2a_state::model2a) MCFG_DEVICE_ADD("copro_fifo_in", GENERIC_FIFO_U32, 0) MCFG_DEVICE_ADD("copro_fifo_out", GENERIC_FIFO_U32, 0) - + MCFG_MACHINE_START_OVERRIDE(model2_tgp_state,model2_tgp) MCFG_MACHINE_RESET_OVERRIDE(model2a_state,model2a) @@ -2820,7 +2836,7 @@ MACHINE_CONFIG_START(model2c_state::model2c) MCFG_DEVICE_ADD("copro_fifo_in", GENERIC_FIFO_U32, 0) MCFG_DEVICE_ADD("copro_fifo_out", GENERIC_FIFO_U32, 0) - + MCFG_MACHINE_START_OVERRIDE(model2c_state,model2c) MCFG_MACHINE_RESET_OVERRIDE(model2c_state,model2c) @@ -6554,7 +6570,7 @@ GAME( 1996, stccb, stcc, stcc, stcc, model2c_state, 0, GAME( 1996, stcca, stcc, stcc, stcc, model2c_state, 0, ROT0, "Sega", "Sega Touring Car Championship (Revision A)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS ) GAME( 1996, waverunr, 0, model2c, waverunr, model2c_state, 0, ROT0, "Sega", "Wave Runner (Japan, Revision A)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS ) GAME( 1997, bel, 0, model2c, bel, model2c_state, 0, ROT0, "Sega / EPL Productions", "Behind Enemy Lines", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS ) -GAME( 1997, hotd, 0, model2c, vcop2, model2c_state, 0, ROT0, "Sega", "The House of the Dead", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS ) +GAME( 1997, hotd, 0, model2c, hotd, model2c_state, 0, ROT0, "Sega", "The House of the Dead", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS ) GAME( 1997, overrev, 0, overrev2c, overrev, model2c_state, 0, ROT0, "Jaleco", "Over Rev (Model 2C, Revision A)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS ) GAME( 1997, rascot2, 0, model2c, model2, model2c_state, 0, ROT0, "Sega", "Royal Ascot II", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS ) GAME( 1997, segawski, 0, model2c, segawski, model2c_state, 0, ROT0, "Sega", "Sega Water Ski (Japan, Revision A)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS ) diff --git a/src/mame/includes/model2.h b/src/mame/includes/model2.h index bf572619009..b5798e9e9a7 100644 --- a/src/mame/includes/model2.h +++ b/src/mame/includes/model2.h @@ -168,8 +168,9 @@ protected: DECLARE_WRITE32_MEMBER(videoctl_w); DECLARE_WRITE32_MEMBER(rchase2_devices_w); DECLARE_WRITE32_MEMBER(srallyc_devices_w); - DECLARE_READ8_MEMBER(hotd_lightgun_r); - DECLARE_WRITE32_MEMBER(hotd_lightgun_w); + DECLARE_READ8_MEMBER(lightgun_coords_r); + DECLARE_READ8_MEMBER(lightgun_offscreen_r); + DECLARE_WRITE8_MEMBER(lightgun_mux_w); DECLARE_READ32_MEMBER(irq_request_r); DECLARE_WRITE32_MEMBER(irq_ack_w); DECLARE_READ32_MEMBER(irq_enable_r); @@ -207,8 +208,6 @@ protected: // DECLARE_WRITE_LINE_MEMBER(sound_ready_w); TIMER_DEVICE_CALLBACK_MEMBER(model2_timer_cb); DECLARE_WRITE8_MEMBER(scsp_irq); - DECLARE_READ8_MEMBER(virtuacop_lightgun_r); - DECLARE_READ8_MEMBER(virtuacop_lightgun_offscreen_r); void model2_3d_frame_start( void ); void geo_parse( void );