mirror of
https://github.com/holub/mame
synced 2025-04-25 09:50:04 +03:00
(MESS) sms: Converted SMS inputs to use slot devices. You now select
controllers in the Slot Devices menu of the internal UI, not in the Driver Configurations anymore. [Enik]
This commit is contained in:
parent
f9dbdf1920
commit
d8bf9eaac5
12
.gitattributes
vendored
12
.gitattributes
vendored
@ -7762,6 +7762,18 @@ src/mess/machine/smartmed.h svneol=native#text/plain
|
||||
src/mess/machine/smc92x4.c svneol=native#text/plain
|
||||
src/mess/machine/smc92x4.h svneol=native#text/plain
|
||||
src/mess/machine/sms.c svneol=native#text/plain
|
||||
src/mess/machine/sms_joypad.c svneol=native#text/plain
|
||||
src/mess/machine/sms_joypad.h svneol=native#text/plain
|
||||
src/mess/machine/sms_lphaser.c svneol=native#text/plain
|
||||
src/mess/machine/sms_lphaser.h svneol=native#text/plain
|
||||
src/mess/machine/sms_paddle.c svneol=native#text/plain
|
||||
src/mess/machine/sms_paddle.h svneol=native#text/plain
|
||||
src/mess/machine/sms_rfu.c svneol=native#text/plain
|
||||
src/mess/machine/sms_rfu.h svneol=native#text/plain
|
||||
src/mess/machine/sms_sports.c svneol=native#text/plain
|
||||
src/mess/machine/sms_sports.h svneol=native#text/plain
|
||||
src/mess/machine/smsctrl.c svneol=native#text/plain
|
||||
src/mess/machine/smsctrl.h svneol=native#text/plain
|
||||
src/mess/machine/snescx4.c svneol=native#text/plain
|
||||
src/mess/machine/snescx4.h svneol=native#text/plain
|
||||
src/mess/machine/sns_bsx.c svneol=native#text/plain
|
||||
|
@ -276,18 +276,18 @@ static ADDRESS_MAP_START( sms_io, AS_IO, 8, sms_state )
|
||||
AM_RANGE(0x40, 0x7f) AM_DEVWRITE("segapsg", segapsg_device, write)
|
||||
AM_RANGE(0x80, 0x80) AM_MIRROR(0x3e) AM_DEVREADWRITE("sms_vdp", sega315_5124_device, vram_read, vram_write)
|
||||
AM_RANGE(0x81, 0x81) AM_MIRROR(0x3e) AM_DEVREADWRITE("sms_vdp", sega315_5124_device, register_read, register_write)
|
||||
AM_RANGE(0xc0, 0xc0) AM_MIRROR(0x1e) AM_READ(sms_input_port_0_r)
|
||||
AM_RANGE(0xc1, 0xc1) AM_MIRROR(0x1e) AM_READ(sms_input_port_1_r)
|
||||
AM_RANGE(0xe0, 0xe0) AM_MIRROR(0x0e) AM_READ(sms_input_port_0_r)
|
||||
AM_RANGE(0xe1, 0xe1) AM_MIRROR(0x0e) AM_READ(sms_input_port_1_r)
|
||||
AM_RANGE(0xf0, 0xf0) AM_READWRITE(sms_input_port_0_r, sms_ym2413_register_port_0_w)
|
||||
AM_RANGE(0xf1, 0xf1) AM_READWRITE(sms_input_port_1_r, sms_ym2413_data_port_0_w)
|
||||
AM_RANGE(0xc0, 0xc0) AM_MIRROR(0x1e) AM_READ(sms_input_port_dc_r)
|
||||
AM_RANGE(0xc1, 0xc1) AM_MIRROR(0x1e) AM_READ(sms_input_port_dd_r)
|
||||
AM_RANGE(0xe0, 0xe0) AM_MIRROR(0x0e) AM_READ(sms_input_port_dc_r)
|
||||
AM_RANGE(0xe1, 0xe1) AM_MIRROR(0x0e) AM_READ(sms_input_port_dd_r)
|
||||
AM_RANGE(0xf0, 0xf0) AM_READWRITE(sms_input_port_dc_r, sms_ym2413_register_port_w)
|
||||
AM_RANGE(0xf1, 0xf1) AM_READWRITE(sms_input_port_dd_r, sms_ym2413_data_port_w)
|
||||
AM_RANGE(0xf2, 0xf2) AM_READWRITE(sms_fm_detect_r, sms_fm_detect_w)
|
||||
AM_RANGE(0xf3, 0xf3) AM_READ(sms_input_port_1_r)
|
||||
AM_RANGE(0xf4, 0xf4) AM_MIRROR(0x02) AM_READ(sms_input_port_0_r)
|
||||
AM_RANGE(0xf5, 0xf5) AM_MIRROR(0x02) AM_READ(sms_input_port_1_r)
|
||||
AM_RANGE(0xf8, 0xf8) AM_MIRROR(0x06) AM_READ(sms_input_port_0_r)
|
||||
AM_RANGE(0xf9, 0xf9) AM_MIRROR(0x06) AM_READ(sms_input_port_1_r)
|
||||
AM_RANGE(0xf3, 0xf3) AM_READ(sms_input_port_dd_r)
|
||||
AM_RANGE(0xf4, 0xf4) AM_MIRROR(0x02) AM_READ(sms_input_port_dc_r)
|
||||
AM_RANGE(0xf5, 0xf5) AM_MIRROR(0x02) AM_READ(sms_input_port_dd_r)
|
||||
AM_RANGE(0xf8, 0xf8) AM_MIRROR(0x06) AM_READ(sms_input_port_dc_r)
|
||||
AM_RANGE(0xf9, 0xf9) AM_MIRROR(0x06) AM_READ(sms_input_port_dd_r)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
|
||||
@ -299,18 +299,18 @@ static ADDRESS_MAP_START( sms_no3e3f_io, AS_IO, 8, sms_state )
|
||||
AM_RANGE(0x40, 0x7f) AM_DEVWRITE("segapsg", segapsg_device, write)
|
||||
AM_RANGE(0x80, 0x80) AM_MIRROR(0x3e) AM_DEVREADWRITE("sms_vdp", sega315_5124_device, vram_read, vram_write)
|
||||
AM_RANGE(0x81, 0x81) AM_MIRROR(0x3e) AM_DEVREADWRITE("sms_vdp", sega315_5124_device, register_read, register_write)
|
||||
AM_RANGE(0xc0, 0xc0) AM_MIRROR(0x1e) AM_READ(sms_input_port_0_r)
|
||||
AM_RANGE(0xc1, 0xc1) AM_MIRROR(0x1e) AM_READ(sms_input_port_1_r)
|
||||
AM_RANGE(0xe0, 0xe0) AM_MIRROR(0x0e) AM_READ(sms_input_port_0_r)
|
||||
AM_RANGE(0xe1, 0xe1) AM_MIRROR(0x0e) AM_READ(sms_input_port_1_r)
|
||||
AM_RANGE(0xf0, 0xf0) AM_READWRITE(sms_input_port_0_r, sms_ym2413_register_port_0_w)
|
||||
AM_RANGE(0xf1, 0xf1) AM_READWRITE(sms_input_port_1_r, sms_ym2413_data_port_0_w)
|
||||
AM_RANGE(0xc0, 0xc0) AM_MIRROR(0x1e) AM_READ(sms_input_port_dc_r)
|
||||
AM_RANGE(0xc1, 0xc1) AM_MIRROR(0x1e) AM_READ(sms_input_port_dd_r)
|
||||
AM_RANGE(0xe0, 0xe0) AM_MIRROR(0x0e) AM_READ(sms_input_port_dc_r)
|
||||
AM_RANGE(0xe1, 0xe1) AM_MIRROR(0x0e) AM_READ(sms_input_port_dd_r)
|
||||
AM_RANGE(0xf0, 0xf0) AM_READWRITE(sms_input_port_dc_r, sms_ym2413_register_port_w)
|
||||
AM_RANGE(0xf1, 0xf1) AM_READWRITE(sms_input_port_dd_r, sms_ym2413_data_port_w)
|
||||
AM_RANGE(0xf2, 0xf2) AM_READWRITE(sms_fm_detect_r, sms_fm_detect_w)
|
||||
AM_RANGE(0xf3, 0xf3) AM_READ(sms_input_port_1_r)
|
||||
AM_RANGE(0xf4, 0xf4) AM_MIRROR(0x02) AM_READ(sms_input_port_0_r)
|
||||
AM_RANGE(0xf5, 0xf5) AM_MIRROR(0x02) AM_READ(sms_input_port_1_r)
|
||||
AM_RANGE(0xf8, 0xf8) AM_MIRROR(0x06) AM_READ(sms_input_port_0_r)
|
||||
AM_RANGE(0xf9, 0xf9) AM_MIRROR(0x06) AM_READ(sms_input_port_1_r)
|
||||
AM_RANGE(0xf3, 0xf3) AM_READ(sms_input_port_dd_r)
|
||||
AM_RANGE(0xf4, 0xf4) AM_MIRROR(0x02) AM_READ(sms_input_port_dc_r)
|
||||
AM_RANGE(0xf5, 0xf5) AM_MIRROR(0x02) AM_READ(sms_input_port_dd_r)
|
||||
AM_RANGE(0xf8, 0xf8) AM_MIRROR(0x06) AM_READ(sms_input_port_dc_r)
|
||||
AM_RANGE(0xf9, 0xf9) AM_MIRROR(0x06) AM_READ(sms_input_port_dd_r)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
|
||||
@ -327,18 +327,18 @@ static ADDRESS_MAP_START( sms_kor_io, AS_IO, 8, sms_state )
|
||||
AM_RANGE(0x40, 0x7f) AM_DEVWRITE("segapsg", segapsg_device, write)
|
||||
AM_RANGE(0x80, 0x80) AM_MIRROR(0x3e) AM_DEVREADWRITE("sms_vdp", sega315_5124_device, vram_read, vram_write)
|
||||
AM_RANGE(0x81, 0x81) AM_MIRROR(0x3e) AM_DEVREADWRITE("sms_vdp", sega315_5124_device, register_read, register_write)
|
||||
AM_RANGE(0xc0, 0xc0) AM_MIRROR(0x1e) AM_READ(sms_input_port_0_r)
|
||||
AM_RANGE(0xc1, 0xc1) AM_MIRROR(0x1e) AM_READ(sms_input_port_1_r)
|
||||
AM_RANGE(0xe0, 0xe0) AM_MIRROR(0x0e) AM_READ(sms_input_port_0_r)
|
||||
AM_RANGE(0xe1, 0xe1) AM_MIRROR(0x0e) AM_READ(sms_input_port_1_r)
|
||||
AM_RANGE(0xf0, 0xf0) AM_READWRITE(sms_input_port_0_r, sms_ym2413_register_port_0_w)
|
||||
AM_RANGE(0xf1, 0xf1) AM_READWRITE(sms_input_port_1_r, sms_ym2413_data_port_0_w)
|
||||
AM_RANGE(0xc0, 0xc0) AM_MIRROR(0x1e) AM_READ(sms_input_port_dc_r)
|
||||
AM_RANGE(0xc1, 0xc1) AM_MIRROR(0x1e) AM_READ(sms_input_port_dd_r)
|
||||
AM_RANGE(0xe0, 0xe0) AM_MIRROR(0x0e) AM_READ(sms_input_port_dc_r)
|
||||
AM_RANGE(0xe1, 0xe1) AM_MIRROR(0x0e) AM_READ(sms_input_port_dd_r)
|
||||
AM_RANGE(0xf0, 0xf0) AM_READWRITE(sms_input_port_dc_r, sms_ym2413_register_port_w)
|
||||
AM_RANGE(0xf1, 0xf1) AM_READWRITE(sms_input_port_dd_r, sms_ym2413_data_port_w)
|
||||
AM_RANGE(0xf2, 0xf2) AM_READWRITE(sms_fm_detect_r, sms_fm_detect_w)
|
||||
AM_RANGE(0xf3, 0xf3) AM_READ(sms_input_port_1_r)
|
||||
AM_RANGE(0xf4, 0xf4) AM_MIRROR(0x02) AM_READ(sms_input_port_0_r)
|
||||
AM_RANGE(0xf5, 0xf5) AM_MIRROR(0x02) AM_READ(sms_input_port_1_r)
|
||||
AM_RANGE(0xf8, 0xf8) AM_MIRROR(0x06) AM_READ(sms_input_port_0_r)
|
||||
AM_RANGE(0xf9, 0xf9) AM_MIRROR(0x06) AM_READ(sms_input_port_1_r)
|
||||
AM_RANGE(0xf3, 0xf3) AM_READ(sms_input_port_dd_r)
|
||||
AM_RANGE(0xf4, 0xf4) AM_MIRROR(0x02) AM_READ(sms_input_port_dc_r)
|
||||
AM_RANGE(0xf5, 0xf5) AM_MIRROR(0x02) AM_READ(sms_input_port_dd_r)
|
||||
AM_RANGE(0xf8, 0xf8) AM_MIRROR(0x06) AM_READ(sms_input_port_dc_r)
|
||||
AM_RANGE(0xf9, 0xf9) AM_MIRROR(0x06) AM_READ(sms_input_port_dd_r)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static ADDRESS_MAP_START( gg_io, AS_IO, 8, sms_state )
|
||||
@ -358,101 +358,17 @@ static ADDRESS_MAP_START( gg_io, AS_IO, 8, sms_state )
|
||||
AM_RANGE(0x40, 0x7f) AM_DEVWRITE("gamegear", gamegear_device, write)
|
||||
AM_RANGE(0x80, 0x80) AM_MIRROR(0x3e) AM_DEVREADWRITE("sms_vdp", sega315_5124_device, vram_read, vram_write)
|
||||
AM_RANGE(0x81, 0x81) AM_MIRROR(0x3e) AM_DEVREADWRITE("sms_vdp", sega315_5124_device, register_read, register_write)
|
||||
AM_RANGE(0xc0, 0xc0) AM_READ_PORT("PORT_DC")
|
||||
AM_RANGE(0xc1, 0xc1) AM_READ_PORT("PORT_DD")
|
||||
AM_RANGE(0xdc, 0xdc) AM_READ_PORT("PORT_DC")
|
||||
AM_RANGE(0xdd, 0xdd) AM_READ_PORT("PORT_DD")
|
||||
AM_RANGE(0xc0, 0xc0) AM_READ_PORT("GG_PORT_DC")
|
||||
AM_RANGE(0xc1, 0xc1) AM_READ_PORT("GG_PORT_DD")
|
||||
AM_RANGE(0xdc, 0xdc) AM_READ_PORT("GG_PORT_DC")
|
||||
AM_RANGE(0xdd, 0xdd) AM_READ_PORT("GG_PORT_DD")
|
||||
ADDRESS_MAP_END
|
||||
|
||||
|
||||
static INPUT_PORTS_START( sms )
|
||||
PORT_START("PORT_DC")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_8WAY PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00)
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_8WAY PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00)
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_8WAY PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00)
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_8WAY PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00)
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00)
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00)
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) PORT_8WAY PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00)
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) PORT_8WAY PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00)
|
||||
|
||||
PORT_START("PORT_DD")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) PORT_8WAY PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00)
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_8WAY PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00)
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00)
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00)
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) /* Software Reset bit */
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) /* Port A TH */
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) /* Port B TH */
|
||||
|
||||
PORT_START("PAUSE")
|
||||
PORT_BIT( 0x7f, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START ) PORT_NAME(DEF_STR(Pause))
|
||||
|
||||
PORT_START("LPHASER0") /* Light phaser X - player 1 */
|
||||
PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_CROSSHAIR( X, 1.0, 0.0, 0 ) PORT_SENSITIVITY(50) PORT_KEYDELTA(15) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, sms_state, lgun1_changed, NULL) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01)
|
||||
|
||||
PORT_START("LPHASER1") /* Light phaser Y - player 1 */
|
||||
PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y ) PORT_CROSSHAIR( Y, 1.0, 0.0, 0 ) PORT_SENSITIVITY(50) PORT_KEYDELTA(15) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, sms_state, lgun1_changed, NULL) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01)
|
||||
|
||||
PORT_START("LPHASER2") /* Light phaser X - player 2 */
|
||||
PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_CROSSHAIR( X, 1.0, 0.0, 0 ) PORT_SENSITIVITY(50) PORT_KEYDELTA(15) PORT_PLAYER(2) PORT_CHANGED_MEMBER(DEVICE_SELF, sms_state, lgun2_changed, NULL) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10)
|
||||
|
||||
PORT_START("LPHASER3") /* Light phaser Y - player 2 */
|
||||
PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y ) PORT_CROSSHAIR( Y, 1.0, 0.0, 0 ) PORT_SENSITIVITY(50) PORT_KEYDELTA(15) PORT_PLAYER(2) PORT_CHANGED_MEMBER(DEVICE_SELF, sms_state, lgun2_changed, NULL) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10)
|
||||
|
||||
PORT_START("RFU") /* Rapid Fire Unit */
|
||||
PORT_CONFNAME( 0x03, 0x00, "Rapid Fire Unit - Player 1" )
|
||||
PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_CONFSETTING( 0x01, "Button A" )
|
||||
PORT_CONFSETTING( 0x02, "Button B" )
|
||||
PORT_CONFSETTING( 0x03, "Button A + B" )
|
||||
PORT_CONFNAME( 0x0c, 0x00, "Rapid Fire Unit - Player 2" )
|
||||
PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_CONFSETTING( 0x04, "Button A" )
|
||||
PORT_CONFSETTING( 0x08, "Button B" )
|
||||
PORT_CONFSETTING( 0x0c, "Button A + B" )
|
||||
|
||||
PORT_START("PADDLE0") /* Paddle player 1 */
|
||||
PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_SENSITIVITY(40) PORT_KEYDELTA(20) PORT_CENTERDELTA(0) PORT_MINMAX(0,255) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x02)
|
||||
|
||||
PORT_START("PADDLE1") /* Paddle player 2 */
|
||||
PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_SENSITIVITY(40) PORT_KEYDELTA(20) PORT_CENTERDELTA(0) PORT_MINMAX(0,255) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x20)
|
||||
|
||||
PORT_START("CTRLIPT") /* Light Phaser and Paddle Control buttons */
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01)
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x02)
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x04)
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x04)
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10)
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x20)
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x40)
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x40)
|
||||
|
||||
PORT_START("CTRLSEL") /* Controller selection */
|
||||
PORT_CONFNAME( 0x0f, 0x00, "Player 1 Controller" )
|
||||
PORT_CONFSETTING( 0x00, DEF_STR( Joystick ) )
|
||||
PORT_CONFSETTING( 0x01, "Light Phaser" )
|
||||
PORT_CONFSETTING( 0x02, "Sega Paddle Control" )
|
||||
PORT_CONFSETTING( 0x04, "Sega Sports Pad" )
|
||||
PORT_CONFNAME( 0xf0, 0x00, "Player 2 Controller" )
|
||||
PORT_CONFSETTING( 0x00, DEF_STR( Joystick ) )
|
||||
PORT_CONFSETTING( 0x10, "Light Phaser" )
|
||||
PORT_CONFSETTING( 0x20, "Sega Paddle Control" )
|
||||
PORT_CONFSETTING( 0x40, "Sega Sports Pad" )
|
||||
|
||||
PORT_START("SPORT0") /* Player 1 Sports Pad X axis */
|
||||
PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40) PORT_RESET PORT_REVERSE PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x04)
|
||||
|
||||
PORT_START("SPORT1") /* Player 1 Sports Pad Y axis */
|
||||
PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40) PORT_RESET PORT_REVERSE PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x04)
|
||||
|
||||
PORT_START("SPORT2") /* Player 2 Sports Pad X axis */
|
||||
PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40) PORT_RESET PORT_REVERSE PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x40)
|
||||
|
||||
PORT_START("SPORT3") /* Player 2 Sports Pad Y axis */
|
||||
PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40) PORT_RESET PORT_REVERSE PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x40)
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME(DEF_STR(Pause)) PORT_CODE(KEYCODE_1)
|
||||
INPUT_PORTS_END
|
||||
|
||||
static INPUT_PORTS_START( sms1 )
|
||||
@ -476,7 +392,7 @@ static INPUT_PORTS_START( sms1 )
|
||||
INPUT_PORTS_END
|
||||
|
||||
static INPUT_PORTS_START( gg )
|
||||
PORT_START("PORT_DC")
|
||||
PORT_START("GG_PORT_DC")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_8WAY
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_8WAY
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_8WAY
|
||||
@ -485,7 +401,7 @@ static INPUT_PORTS_START( gg )
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)
|
||||
PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
|
||||
PORT_START("PORT_DD")
|
||||
PORT_START("GG_PORT_DD")
|
||||
PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
|
||||
PORT_START("START")
|
||||
@ -595,6 +511,14 @@ static MACHINE_CONFIG_START( sms_ntsc_base, sms_state )
|
||||
MCFG_SMS_CARTRIDGE_ADD("slot", sms_cart, NULL)
|
||||
|
||||
MCFG_SOFTWARE_LIST_ADD("cart_list","sms")
|
||||
|
||||
MCFG_SMS_CONTROL_PORT_ADD(CONTROL1_TAG, sms_control_port_devices, "joypad")
|
||||
MCFG_SMS_CONTROL_PORT_TH_INPUT_HANDLER(WRITE16(sms_state, sms_ctrl1_th_input))
|
||||
MCFG_SMS_CONTROL_PORT_PIXEL_HANDLER(READ32(sms_state, sms_pixel_color))
|
||||
|
||||
MCFG_SMS_CONTROL_PORT_ADD(CONTROL2_TAG, sms_control_port_devices, "joypad")
|
||||
MCFG_SMS_CONTROL_PORT_TH_INPUT_HANDLER(WRITE16(sms_state, sms_ctrl2_th_input))
|
||||
MCFG_SMS_CONTROL_PORT_PIXEL_HANDLER(READ32(sms_state, sms_pixel_color))
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( sms2_ntsc, sms_ntsc_base )
|
||||
@ -721,6 +645,14 @@ static MACHINE_CONFIG_START( sms_sdisp, smssdisp_state )
|
||||
MCFG_SMS_CARD_ADD("slot32", sms_cart, NULL)
|
||||
|
||||
MCFG_SOFTWARE_LIST_ADD("cart_list","sms")
|
||||
|
||||
MCFG_SMS_CONTROL_PORT_ADD(CONTROL1_TAG, sms_control_port_devices, "joypad")
|
||||
MCFG_SMS_CONTROL_PORT_TH_INPUT_HANDLER(WRITE16(sms_state, sms_ctrl1_th_input))
|
||||
MCFG_SMS_CONTROL_PORT_PIXEL_HANDLER(READ32(sms_state, sms_pixel_color))
|
||||
|
||||
MCFG_SMS_CONTROL_PORT_ADD(CONTROL2_TAG, sms_control_port_devices, "joypad")
|
||||
MCFG_SMS_CONTROL_PORT_TH_INPUT_HANDLER(WRITE16(sms_state, sms_ctrl2_th_input))
|
||||
MCFG_SMS_CONTROL_PORT_PIXEL_HANDLER(READ32(sms_state, sms_pixel_color))
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
static MACHINE_CONFIG_START( sms_pal_base, sms_state )
|
||||
@ -743,6 +675,14 @@ static MACHINE_CONFIG_START( sms_pal_base, sms_state )
|
||||
MCFG_SMS_CARTRIDGE_ADD("slot", sms_cart, NULL)
|
||||
|
||||
MCFG_SOFTWARE_LIST_ADD("cart_list","sms")
|
||||
|
||||
MCFG_SMS_CONTROL_PORT_ADD(CONTROL1_TAG, sms_control_port_devices, "joypad")
|
||||
MCFG_SMS_CONTROL_PORT_TH_INPUT_HANDLER(WRITE16(sms_state, sms_ctrl1_th_input))
|
||||
MCFG_SMS_CONTROL_PORT_PIXEL_HANDLER(READ32(sms_state, sms_pixel_color))
|
||||
|
||||
MCFG_SMS_CONTROL_PORT_ADD(CONTROL2_TAG, sms_control_port_devices, "joypad")
|
||||
MCFG_SMS_CONTROL_PORT_TH_INPUT_HANDLER(WRITE16(sms_state, sms_ctrl2_th_input))
|
||||
MCFG_SMS_CONTROL_PORT_PIXEL_HANDLER(READ32(sms_state, sms_pixel_color))
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( sms2_pal, sms_pal_base )
|
||||
|
@ -16,20 +16,16 @@
|
||||
|
||||
#define MAX_CARTRIDGES 16
|
||||
|
||||
#define CONTROL1_TAG "ctrl1"
|
||||
#define CONTROL2_TAG "ctrl2"
|
||||
|
||||
#include "machine/smsctrl.h"
|
||||
#include "machine/sega8_slot.h"
|
||||
|
||||
|
||||
class sms_state : public driver_device
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
TIMER_RAPID_FIRE,
|
||||
TIMER_LIGHTGUN_TICK,
|
||||
TIMER_LPHASER_1,
|
||||
TIMER_LPHASER_2
|
||||
};
|
||||
|
||||
sms_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
@ -40,24 +36,11 @@ public:
|
||||
m_cartslot(*this, "slot"),
|
||||
m_card(*this, "mycard"),
|
||||
m_region_maincpu(*this, "maincpu"),
|
||||
m_port_dd(*this, "PORT_DD"),
|
||||
m_port_dc(*this, "PORT_DC"),
|
||||
m_port_ctrl1(*this, CONTROL1_TAG),
|
||||
m_port_ctrl2(*this, CONTROL2_TAG),
|
||||
m_port_pause(*this, "PAUSE"),
|
||||
m_port_reset(*this, "RESET"),
|
||||
m_port_start(*this, "START"),
|
||||
m_port_ctrlsel(*this, "CTRLSEL"),
|
||||
m_port_lphas0(*this, "LPHASER0"),
|
||||
m_port_lphas1(*this, "LPHASER1"),
|
||||
m_port_lphas2(*this, "LPHASER2"),
|
||||
m_port_lphas3(*this, "LPHASER3"),
|
||||
m_port_rfu(*this, "RFU"),
|
||||
m_port_paddle0(*this, "PADDLE0"),
|
||||
m_port_paddle1(*this, "PADDLE1"),
|
||||
m_port_ctrlipt(*this, "CTRLIPT"),
|
||||
m_port_sport0(*this, "SPORT0"),
|
||||
m_port_sport1(*this, "SPORT1"),
|
||||
m_port_sport2(*this, "SPORT2"),
|
||||
m_port_sport3(*this, "SPORT3"),
|
||||
m_port_scope(*this, "SEGASCOPE"),
|
||||
m_port_persist(*this, "PERSISTENCE"),
|
||||
m_is_gamegear(0),
|
||||
@ -78,24 +61,11 @@ public:
|
||||
required_device<sega8_cart_slot_device> m_cartslot;
|
||||
optional_device<sega8_card_slot_device> m_card;
|
||||
required_memory_region m_region_maincpu;
|
||||
required_ioport m_port_dd;
|
||||
required_ioport m_port_dc;
|
||||
optional_device<sms_control_port_device> m_port_ctrl1;
|
||||
optional_device<sms_control_port_device> m_port_ctrl2;
|
||||
optional_ioport m_port_pause;
|
||||
optional_ioport m_port_reset;
|
||||
optional_ioport m_port_start;
|
||||
optional_ioport m_port_ctrlsel;
|
||||
optional_ioport m_port_lphas0;
|
||||
optional_ioport m_port_lphas1;
|
||||
optional_ioport m_port_lphas2;
|
||||
optional_ioport m_port_lphas3;
|
||||
optional_ioport m_port_rfu;
|
||||
optional_ioport m_port_paddle0;
|
||||
optional_ioport m_port_paddle1;
|
||||
optional_ioport m_port_ctrlipt;
|
||||
optional_ioport m_port_sport0;
|
||||
optional_ioport m_port_sport1;
|
||||
optional_ioport m_port_sport2;
|
||||
optional_ioport m_port_sport3;
|
||||
optional_ioport m_port_scope;
|
||||
optional_ioport m_port_persist;
|
||||
|
||||
@ -105,13 +75,13 @@ public:
|
||||
|
||||
UINT8 m_bios_page_count;
|
||||
UINT8 m_fm_detect;
|
||||
UINT8 m_ctrl_reg;
|
||||
UINT8 m_io_ctrl_reg;
|
||||
int m_paused;
|
||||
UINT8 m_bios_port;
|
||||
UINT8 *m_BIOS;
|
||||
UINT8 m_mapper[4];
|
||||
UINT8 m_input_port0;
|
||||
UINT8 m_input_port1;
|
||||
UINT8 m_port_dc_reg;
|
||||
UINT8 m_port_dd_reg;
|
||||
UINT8 m_gg_sio[5];
|
||||
|
||||
// [0] for 0x400-0x3fff, [1] for 0x4000-0x7fff, [2] for 0x8000-0xffff, [3] for 0x0000-0x0400
|
||||
@ -135,32 +105,9 @@ public:
|
||||
UINT8 m_has_bios;
|
||||
UINT8 m_has_fm;
|
||||
|
||||
// Data needed for Rapid Fire Unit support
|
||||
emu_timer *m_rapid_fire_timer;
|
||||
UINT8 m_rapid_fire_state_1;
|
||||
UINT8 m_rapid_fire_state_2;
|
||||
|
||||
// Data needed for Paddle Control controller
|
||||
UINT32 m_last_paddle_read_time;
|
||||
UINT8 m_paddle_read_state;
|
||||
|
||||
// Data needed for Sports Pad controller
|
||||
UINT32 m_last_sports_pad_time_1;
|
||||
UINT32 m_last_sports_pad_time_2;
|
||||
UINT8 m_sports_pad_state_1;
|
||||
UINT8 m_sports_pad_state_2;
|
||||
UINT8 m_sports_pad_last_data_1;
|
||||
UINT8 m_sports_pad_last_data_2;
|
||||
UINT8 m_sports_pad_1_x;
|
||||
UINT8 m_sports_pad_1_y;
|
||||
UINT8 m_sports_pad_2_x;
|
||||
UINT8 m_sports_pad_2_y;
|
||||
|
||||
// Data needed for Light Phaser
|
||||
emu_timer *m_lphaser_1_timer;
|
||||
emu_timer *m_lphaser_2_timer;
|
||||
UINT8 m_lphaser_1_latch;
|
||||
UINT8 m_lphaser_2_latch;
|
||||
UINT8 m_ctrl1_th_latch;
|
||||
UINT8 m_ctrl2_th_latch;
|
||||
int m_lphaser_x_offs; /* Needed to 'calibrate' lphaser; set at cart loading */
|
||||
|
||||
// Data needed for SegaScope (3D glasses)
|
||||
@ -174,15 +121,14 @@ public:
|
||||
sega8_card_slot_device *m_cards[16];
|
||||
|
||||
/* Cartridge slot info */
|
||||
DECLARE_WRITE8_MEMBER(sms_input_write);
|
||||
DECLARE_WRITE8_MEMBER(sms_fm_detect_w);
|
||||
DECLARE_READ8_MEMBER(sms_fm_detect_r);
|
||||
DECLARE_WRITE8_MEMBER(sms_io_control_w);
|
||||
DECLARE_READ8_MEMBER(sms_count_r);
|
||||
DECLARE_READ8_MEMBER(sms_input_port_0_r);
|
||||
DECLARE_READ8_MEMBER(sms_input_port_1_r);
|
||||
DECLARE_WRITE8_MEMBER(sms_ym2413_register_port_0_w);
|
||||
DECLARE_WRITE8_MEMBER(sms_ym2413_data_port_0_w);
|
||||
DECLARE_READ8_MEMBER(sms_input_port_dc_r);
|
||||
DECLARE_READ8_MEMBER(sms_input_port_dd_r);
|
||||
DECLARE_WRITE8_MEMBER(sms_ym2413_register_port_w);
|
||||
DECLARE_WRITE8_MEMBER(sms_ym2413_data_port_w);
|
||||
DECLARE_READ8_MEMBER(gg_input_port_2_r);
|
||||
DECLARE_READ8_MEMBER(sms_sscope_r);
|
||||
DECLARE_WRITE8_MEMBER(sms_sscope_w);
|
||||
@ -211,27 +157,18 @@ public:
|
||||
UINT32 screen_update_sms(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
UINT32 screen_update_sms1(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
void screen_vblank_sms1(screen_device &screen, bool state);
|
||||
DECLARE_INPUT_CHANGED_MEMBER(lgun1_changed);
|
||||
DECLARE_INPUT_CHANGED_MEMBER(lgun2_changed);
|
||||
TIMER_CALLBACK_MEMBER(rapid_fire_callback);
|
||||
TIMER_CALLBACK_MEMBER(lightgun_tick);
|
||||
TIMER_CALLBACK_MEMBER(lphaser_1_callback);
|
||||
TIMER_CALLBACK_MEMBER(lphaser_2_callback);
|
||||
DECLARE_WRITE_LINE_MEMBER(sms_int_callback);
|
||||
DECLARE_WRITE_LINE_MEMBER(sms_pause_callback);
|
||||
DECLARE_READ32_MEMBER(sms_pixel_color);
|
||||
DECLARE_WRITE16_MEMBER(sms_ctrl1_th_input);
|
||||
DECLARE_WRITE16_MEMBER(sms_ctrl2_th_input);
|
||||
|
||||
protected:
|
||||
void setup_bios();
|
||||
void setup_rom();
|
||||
void setup_sms_cart();
|
||||
void lphaser_hcount_latch(int hpos);
|
||||
void lphaser1_sensor_check();
|
||||
void lphaser2_sensor_check();
|
||||
UINT16 screen_hpos_nonscaled(int scaled_hpos);
|
||||
UINT16 screen_vpos_nonscaled(int scaled_vpos);
|
||||
int lgun_bright_aim_area(emu_timer *timer, int lgun_x, int lgun_y);
|
||||
void sms_get_inputs(address_space &space);
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||
};
|
||||
|
||||
class smssdisp_state : public sms_state
|
||||
|
@ -13,205 +13,6 @@
|
||||
#define ENABLE_CART 3
|
||||
#define ENABLE_BIOS 4
|
||||
|
||||
#define LGUN_RADIUS 6
|
||||
#define LGUN_X_INTERVAL 4
|
||||
|
||||
void sms_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case TIMER_RAPID_FIRE:
|
||||
rapid_fire_callback(ptr, param);
|
||||
break;
|
||||
case TIMER_LIGHTGUN_TICK:
|
||||
lightgun_tick(ptr, param);
|
||||
break;
|
||||
case TIMER_LPHASER_1:
|
||||
lphaser_1_callback(ptr, param);
|
||||
break;
|
||||
case TIMER_LPHASER_2:
|
||||
lphaser_2_callback(ptr, param);
|
||||
break;
|
||||
default:
|
||||
assert_always(FALSE, "Unknown id in sms_state::device_timer");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TIMER_CALLBACK_MEMBER(sms_state::rapid_fire_callback)
|
||||
{
|
||||
m_rapid_fire_state_1 ^= 0xff;
|
||||
m_rapid_fire_state_2 ^= 0xff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
WRITE8_MEMBER(sms_state::sms_input_write)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
switch (m_port_ctrlsel->read_safe(0x00) & 0x0f)
|
||||
{
|
||||
case 0x04: /* Sports Pad */
|
||||
if (data != m_sports_pad_last_data_1)
|
||||
{
|
||||
UINT32 cpu_cycles = m_maincpu->total_cycles();
|
||||
|
||||
m_sports_pad_last_data_1 = data;
|
||||
if (cpu_cycles - m_last_sports_pad_time_1 > 512)
|
||||
{
|
||||
m_sports_pad_state_1 = 3;
|
||||
m_sports_pad_1_x = m_port_sport0->read();
|
||||
m_sports_pad_1_y = m_port_sport1->read();
|
||||
}
|
||||
m_last_sports_pad_time_1 = cpu_cycles;
|
||||
m_sports_pad_state_1 = (m_sports_pad_state_1 + 1) & 3;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
switch (m_port_ctrlsel->read_safe(0x00) & 0xf0)
|
||||
{
|
||||
case 0x40: /* Sports Pad */
|
||||
if (data != m_sports_pad_last_data_2)
|
||||
{
|
||||
UINT32 cpu_cycles = m_maincpu->total_cycles();
|
||||
|
||||
m_sports_pad_last_data_2 = data;
|
||||
if (cpu_cycles - m_last_sports_pad_time_2 > 2048)
|
||||
{
|
||||
m_sports_pad_state_2 = 3;
|
||||
m_sports_pad_2_x = m_port_sport2->read();
|
||||
m_sports_pad_2_y = m_port_sport3->read();
|
||||
}
|
||||
m_last_sports_pad_time_2 = cpu_cycles;
|
||||
m_sports_pad_state_2 = (m_sports_pad_state_2 + 1) & 3;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Light Phaser (light gun) emulation notes:
|
||||
- The sensor is activated based on color brightness of some individual
|
||||
pixels being drawn by the beam, at circular area where the gun is aiming.
|
||||
- Currently, brightness is calculated based only on single pixels.
|
||||
- In general, after the trigger is pressed, games draw the next frame using
|
||||
a light color pattern, to make sure sensor will be activated. If emulation
|
||||
skips that frame, sensor may stay deactivated. Frameskip set to 0 (no skip) is
|
||||
recommended to avoid problems.
|
||||
- When sensor switches from off to on, a value is latched for HCount register
|
||||
and a flag is set. The emulation uses the flag to avoid sequential latches and
|
||||
to signal that TH line is activated when the status of the input port is read.
|
||||
When the status is read, the flag is cleared, or else it is cleared later when
|
||||
the Pause status is read (end of a frame). This is necessary because the
|
||||
"Color & Switch Test" ROM only reads the TH bit after the VINT line.
|
||||
- The gun test of "Color & Switch Test" is an example that requires checks
|
||||
of sensor status independent of other events, like trigger press or TH bit
|
||||
reads. Another example is the title screen of "Hang-On & Safari Hunt", where
|
||||
the game only reads HCount register in a loop, expecting a latch by the gun.
|
||||
- The whole procedure is managed by a timer callback, that always reschedule
|
||||
itself to run in some intervals when the beam is at the circular area.
|
||||
*/
|
||||
int sms_state::lgun_bright_aim_area( emu_timer *timer, int lgun_x, int lgun_y )
|
||||
{
|
||||
const int r_x_r = LGUN_RADIUS * LGUN_RADIUS;
|
||||
const rectangle &visarea = m_main_scr->visible_area();
|
||||
int beam_x = m_main_scr->hpos();
|
||||
int beam_y = m_main_scr->vpos();
|
||||
int dx, dy;
|
||||
int result = 0;
|
||||
int pos_changed = 0;
|
||||
double dx_radius;
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* If beam's y isn't at a line where the aim area is, change it
|
||||
the next line it enters that area. */
|
||||
dy = abs(beam_y - lgun_y);
|
||||
if (dy > LGUN_RADIUS || beam_y < visarea.min_y || beam_y > visarea.max_y)
|
||||
{
|
||||
beam_y = lgun_y - LGUN_RADIUS;
|
||||
if (beam_y < visarea.min_y)
|
||||
beam_y = visarea.min_y;
|
||||
dy = abs(beam_y - lgun_y);
|
||||
pos_changed = 1;
|
||||
}
|
||||
|
||||
/* Caculate distance in x of the radius, relative to beam's y distance.
|
||||
First try some shortcuts. */
|
||||
switch (dy)
|
||||
{
|
||||
case LGUN_RADIUS:
|
||||
dx_radius = 0;
|
||||
break;
|
||||
case 0:
|
||||
dx_radius = LGUN_RADIUS;
|
||||
break;
|
||||
default:
|
||||
/* step 1: r^2 = dx^2 + dy^2 */
|
||||
/* step 2: dx^2 = r^2 - dy^2 */
|
||||
/* step 3: dx = sqrt(r^2 - dy^2) */
|
||||
dx_radius = ceil((float) sqrt((float) (r_x_r - (dy * dy))));
|
||||
}
|
||||
|
||||
/* If beam's x isn't in the circular aim area, change it
|
||||
to the next point it enters that area. */
|
||||
dx = abs(beam_x - lgun_x);
|
||||
if (dx > dx_radius || beam_x < visarea.min_x || beam_x > visarea.max_x)
|
||||
{
|
||||
/* If beam's x has passed the aim area, advance to
|
||||
next line and recheck y/x coordinates. */
|
||||
if (beam_x > lgun_x)
|
||||
{
|
||||
beam_x = 0;
|
||||
beam_y++;
|
||||
continue;
|
||||
}
|
||||
beam_x = lgun_x - dx_radius;
|
||||
if (beam_x < visarea.min_x)
|
||||
beam_x = visarea.min_x;
|
||||
pos_changed = 1;
|
||||
}
|
||||
|
||||
if (!pos_changed)
|
||||
{
|
||||
bitmap_rgb32 &bitmap = m_vdp->get_bitmap();
|
||||
|
||||
/* brightness of the lightgray color in the frame drawn by Light Phaser games */
|
||||
const UINT8 sensor_min_brightness = 0x7f;
|
||||
|
||||
/* TODO: Check how Light Phaser behaves for border areas. For Gangster Town, should */
|
||||
/* a shot at right border (HC~=0x90) really appear at active scr, near to left border? */
|
||||
if (beam_x < SEGA315_5124_LBORDER_START + SEGA315_5124_LBORDER_WIDTH || beam_x >= SEGA315_5124_LBORDER_START + SEGA315_5124_LBORDER_WIDTH + 256)
|
||||
return 0;
|
||||
|
||||
rgb_t color = bitmap.pix32(beam_y, beam_x);
|
||||
|
||||
/* reference: http://www.w3.org/TR/AERT#color-contrast */
|
||||
UINT8 brightness = (RGB_RED(color) * 0.299) + (RGB_GREEN(color) * 0.587) + (RGB_BLUE(color) * 0.114);
|
||||
//printf ("color brightness: %2X for x %d y %d\n", brightness, beam_x, beam_y);
|
||||
|
||||
result = (brightness >= sensor_min_brightness) ? 1 : 0;
|
||||
|
||||
/* next check at same line */
|
||||
beam_x += LGUN_X_INTERVAL;
|
||||
pos_changed = 1;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
timer->adjust(m_main_scr->time_until_pos(beam_y, beam_x));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void sms_state::lphaser_hcount_latch( int hpos )
|
||||
{
|
||||
@ -221,258 +22,45 @@ void sms_state::lphaser_hcount_latch( int hpos )
|
||||
}
|
||||
|
||||
|
||||
UINT16 sms_state::screen_hpos_nonscaled(int scaled_hpos)
|
||||
WRITE16_MEMBER(sms_state::sms_ctrl1_th_input)
|
||||
{
|
||||
const rectangle &visarea = m_main_scr->visible_area();
|
||||
int offset_x = (scaled_hpos * (visarea.max_x - visarea.min_x)) / 255;
|
||||
return visarea.min_x + offset_x;
|
||||
}
|
||||
|
||||
|
||||
UINT16 sms_state::screen_vpos_nonscaled(int scaled_vpos)
|
||||
{
|
||||
const rectangle &visarea = m_main_scr->visible_area();
|
||||
int offset_y = (scaled_vpos * (visarea.max_y - visarea.min_y)) / 255;
|
||||
return visarea.min_y + offset_y;
|
||||
}
|
||||
|
||||
|
||||
void sms_state::lphaser1_sensor_check()
|
||||
{
|
||||
const int x = screen_hpos_nonscaled(m_port_lphas0->read());
|
||||
const int y = screen_vpos_nonscaled(m_port_lphas1->read());
|
||||
|
||||
if (lgun_bright_aim_area(m_lphaser_1_timer, x, y))
|
||||
if (m_ctrl1_th_latch == 0)
|
||||
{
|
||||
if (m_lphaser_1_latch == 0)
|
||||
{
|
||||
m_lphaser_1_latch = 1;
|
||||
lphaser_hcount_latch(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sms_state::lphaser2_sensor_check()
|
||||
{
|
||||
const int x = screen_hpos_nonscaled(m_port_lphas2->read());
|
||||
const int y = screen_vpos_nonscaled(m_port_lphas3->read());
|
||||
|
||||
if (lgun_bright_aim_area(m_lphaser_2_timer, x, y))
|
||||
{
|
||||
if (m_lphaser_2_latch == 0)
|
||||
{
|
||||
m_lphaser_2_latch = 1;
|
||||
lphaser_hcount_latch(x);
|
||||
}
|
||||
m_ctrl1_th_latch = 1;
|
||||
lphaser_hcount_latch(data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// at each input port read we check if lightguns are enabled in one of the ports:
|
||||
// if so, we turn on crosshair and the lightgun timer
|
||||
TIMER_CALLBACK_MEMBER(sms_state::lightgun_tick)
|
||||
WRITE16_MEMBER(sms_state::sms_ctrl2_th_input)
|
||||
{
|
||||
if ((m_port_ctrlsel->read_safe(0x00) & 0x0f) == 0x01)
|
||||
if (m_ctrl2_th_latch == 0)
|
||||
{
|
||||
/* enable crosshair */
|
||||
crosshair_set_screen(machine(), 0, CROSSHAIR_SCREEN_ALL);
|
||||
if (!m_lphaser_1_timer->enabled())
|
||||
lphaser1_sensor_check();
|
||||
m_ctrl2_th_latch = 1;
|
||||
lphaser_hcount_latch(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* disable crosshair */
|
||||
crosshair_set_screen(machine(), 0, CROSSHAIR_SCREEN_NONE);
|
||||
m_lphaser_1_timer->enable(0);
|
||||
}
|
||||
|
||||
if ((m_port_ctrlsel->read_safe(0x00) & 0xf0) == 0x10)
|
||||
{
|
||||
/* enable crosshair */
|
||||
crosshair_set_screen(machine(), 1, CROSSHAIR_SCREEN_ALL);
|
||||
if (!m_lphaser_2_timer->enabled())
|
||||
lphaser2_sensor_check();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* disable crosshair */
|
||||
crosshair_set_screen(machine(), 1, CROSSHAIR_SCREEN_NONE);
|
||||
m_lphaser_2_timer->enable(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TIMER_CALLBACK_MEMBER(sms_state::lphaser_1_callback)
|
||||
{
|
||||
lphaser1_sensor_check();
|
||||
}
|
||||
|
||||
|
||||
TIMER_CALLBACK_MEMBER(sms_state::lphaser_2_callback)
|
||||
{
|
||||
lphaser2_sensor_check();
|
||||
}
|
||||
|
||||
|
||||
INPUT_CHANGED_MEMBER(sms_state::lgun1_changed)
|
||||
{
|
||||
if (!m_lphaser_1_timer ||
|
||||
(m_port_ctrlsel->read_safe(0x00) & 0x0f) != 0x01)
|
||||
return;
|
||||
|
||||
if (newval != oldval)
|
||||
lphaser1_sensor_check();
|
||||
}
|
||||
|
||||
INPUT_CHANGED_MEMBER(sms_state::lgun2_changed)
|
||||
{
|
||||
if (!m_lphaser_2_timer ||
|
||||
(m_port_ctrlsel->read_safe(0x00) & 0xf0) != 0x10)
|
||||
return;
|
||||
|
||||
if (newval != oldval)
|
||||
lphaser2_sensor_check();
|
||||
}
|
||||
|
||||
|
||||
void sms_state::sms_get_inputs( address_space &space )
|
||||
{
|
||||
UINT8 data = 0x00;
|
||||
UINT32 cpu_cycles = m_maincpu->total_cycles();
|
||||
UINT8 data;
|
||||
|
||||
m_input_port0 = 0xff;
|
||||
m_input_port1 = 0xff;
|
||||
m_port_dc_reg = 0xff;
|
||||
m_port_dd_reg = 0xff;
|
||||
|
||||
if (cpu_cycles - m_last_paddle_read_time > 256)
|
||||
{
|
||||
m_paddle_read_state ^= 0xff;
|
||||
m_last_paddle_read_time = cpu_cycles;
|
||||
}
|
||||
data = m_port_ctrl1->port_r();
|
||||
m_port_dc_reg &= ~0x0F | data; // Up, Down, Left, Right
|
||||
m_port_dc_reg &= ~0x10 | (data >> 1); // TL (Button 1)
|
||||
m_port_dc_reg &= ~0x20 | (data >> 2); // TR (Button 2)
|
||||
m_port_dd_reg &= ~0x40 | data; // TH
|
||||
|
||||
/* Check if lightgun has been chosen as input: if so, enable crosshair */
|
||||
timer_set(attotime::zero, TIMER_LIGHTGUN_TICK);
|
||||
|
||||
/* Player 1 */
|
||||
switch (m_port_ctrlsel->read_safe(0x00) & 0x0f)
|
||||
{
|
||||
case 0x00: /* Joystick */
|
||||
data = m_port_dc->read();
|
||||
/* Check Rapid Fire setting for Button A */
|
||||
if (!(data & 0x10) && (m_port_rfu->read() & 0x01))
|
||||
data |= m_rapid_fire_state_1 & 0x10;
|
||||
|
||||
/* Check Rapid Fire setting for Button B */
|
||||
if (!(data & 0x20) && (m_port_rfu->read() & 0x02))
|
||||
data |= m_rapid_fire_state_1 & 0x20;
|
||||
|
||||
m_input_port0 = (m_input_port0 & 0xc0) | (data & 0x3f);
|
||||
break;
|
||||
|
||||
case 0x01: /* Light Phaser */
|
||||
data = (m_port_ctrlipt->read() & 0x01) << 4;
|
||||
/* Check Rapid Fire setting for Trigger */
|
||||
if (!(data & 0x10) && (m_port_rfu->read() & 0x01))
|
||||
data |= m_rapid_fire_state_1 & 0x10;
|
||||
|
||||
/* just consider the trigger (button) bit */
|
||||
data |= ~0x10;
|
||||
|
||||
m_input_port0 = (m_input_port0 & 0xc0) | (data & 0x3f);
|
||||
break;
|
||||
|
||||
case 0x02: /* Paddle Control */
|
||||
/* Get button A state */
|
||||
data = m_port_paddle0->read();
|
||||
|
||||
if (m_paddle_read_state)
|
||||
data = data >> 4;
|
||||
|
||||
m_input_port0 = (m_input_port0 & 0xc0) | (data & 0x0f) | (m_paddle_read_state & 0x20)
|
||||
| ((m_port_ctrlipt->read() & 0x02) << 3);
|
||||
break;
|
||||
|
||||
case 0x04: /* Sega Sports Pad */
|
||||
switch (m_sports_pad_state_1)
|
||||
{
|
||||
case 0:
|
||||
data = (m_sports_pad_1_x >> 4) & 0x0f;
|
||||
break;
|
||||
case 1:
|
||||
data = m_sports_pad_1_x & 0x0f;
|
||||
break;
|
||||
case 2:
|
||||
data = (m_sports_pad_1_y >> 4) & 0x0f;
|
||||
break;
|
||||
case 3:
|
||||
data = m_sports_pad_1_y & 0x0f;
|
||||
break;
|
||||
}
|
||||
m_input_port0 = (m_input_port0 & 0xc0) | data | ((m_port_ctrlipt->read() & 0x0c) << 2);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Player 2 */
|
||||
switch (m_port_ctrlsel->read_safe(0x00) & 0xf0)
|
||||
{
|
||||
case 0x00: /* Joystick */
|
||||
data = m_port_dc->read();
|
||||
m_input_port0 = (m_input_port0 & 0x3f) | (data & 0xc0);
|
||||
|
||||
data = m_port_dd->read();
|
||||
/* Check Rapid Fire setting for Button A */
|
||||
if (!(data & 0x04) && (m_port_rfu->read() & 0x04))
|
||||
data |= m_rapid_fire_state_2 & 0x04;
|
||||
|
||||
/* Check Rapid Fire setting for Button B */
|
||||
if (!(data & 0x08) && (m_port_rfu->read() & 0x08))
|
||||
data |= m_rapid_fire_state_2 & 0x08;
|
||||
|
||||
m_input_port1 = (m_input_port1 & 0xf0) | (data & 0x0f);
|
||||
break;
|
||||
|
||||
case 0x10: /* Light Phaser */
|
||||
data = (m_port_ctrlipt->read() & 0x10) >> 2;
|
||||
/* Check Rapid Fire setting for Trigger */
|
||||
if (!(data & 0x04) && (m_port_rfu->read() & 0x04))
|
||||
data |= m_rapid_fire_state_2 & 0x04;
|
||||
|
||||
/* just consider the trigger (button) bit */
|
||||
data |= ~0x04;
|
||||
|
||||
m_input_port1 = (m_input_port1 & 0xf0) | (data & 0x0f);
|
||||
break;
|
||||
|
||||
case 0x20: /* Paddle Control */
|
||||
/* Get button A state */
|
||||
data = m_port_paddle1->read();
|
||||
if (m_paddle_read_state)
|
||||
data = data >> 4;
|
||||
|
||||
m_input_port0 = (m_input_port0 & 0x3f) | ((data & 0x03) << 6);
|
||||
m_input_port1 = (m_input_port1 & 0xf0) | ((data & 0x0c) >> 2) | (m_paddle_read_state & 0x08)
|
||||
| ((m_port_ctrlipt->read() & 0x20) >> 3);
|
||||
break;
|
||||
|
||||
case 0x40: /* Sega Sports Pad */
|
||||
switch (m_sports_pad_state_2)
|
||||
{
|
||||
case 0:
|
||||
data = m_sports_pad_2_x & 0x0f;
|
||||
break;
|
||||
case 1:
|
||||
data = (m_sports_pad_2_x >> 4) & 0x0f;
|
||||
break;
|
||||
case 2:
|
||||
data = m_sports_pad_2_y & 0x0f;
|
||||
break;
|
||||
case 3:
|
||||
data = (m_sports_pad_2_y >> 4) & 0x0f;
|
||||
break;
|
||||
}
|
||||
m_input_port0 = (m_input_port0 & 0x3f) | ((data & 0x03) << 6);
|
||||
m_input_port1 = (m_input_port1 & 0xf0) | (data >> 2) | ((m_port_ctrlipt->read() & 0xc0) >> 4);
|
||||
break;
|
||||
}
|
||||
data = m_port_ctrl2->port_r();
|
||||
m_port_dc_reg &= ~0xc0 | (data << 6); // Up, Down
|
||||
m_port_dd_reg &= ~0x03 | (data >> 2); // Left, Right
|
||||
m_port_dd_reg &= ~0x04 | (data >> 3); // TL (Button 1)
|
||||
m_port_dd_reg &= ~0x08 | (data >> 4); // TR (Button 2)
|
||||
m_port_dd_reg &= ~0x80 | (data << 1); // TH
|
||||
}
|
||||
|
||||
|
||||
@ -498,40 +86,75 @@ READ8_MEMBER(sms_state::sms_fm_detect_r)
|
||||
else
|
||||
{
|
||||
sms_get_inputs(space);
|
||||
return m_input_port0;
|
||||
return m_port_dc_reg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WRITE8_MEMBER(sms_state::sms_io_control_w)
|
||||
{
|
||||
bool latch_hcount = false;
|
||||
UINT8 ctrl1_port_data = 0xff;
|
||||
UINT8 ctrl2_port_data = 0xff;
|
||||
|
||||
if (data & 0x08)
|
||||
// Controller Port 1:
|
||||
|
||||
// check if TR or TH are set to output (0).
|
||||
if ((data & 0x03) != 0x03)
|
||||
{
|
||||
/* check if TH pin level is high (1) and was low last time */
|
||||
if (data & 0x80 && !(m_ctrl_reg & 0x80))
|
||||
if (!(data & 0x01)) // TR set to output
|
||||
{
|
||||
latch_hcount = true;
|
||||
ctrl1_port_data &= ~0x80 | (data << 3);
|
||||
}
|
||||
sms_input_write(space, 0, (data & 0x20) >> 5);
|
||||
if (!(data & 0x02)) // TH set to output
|
||||
{
|
||||
ctrl1_port_data &= ~0x40 | (data << 1);
|
||||
}
|
||||
if (!m_is_gamegear)
|
||||
m_port_ctrl1->port_w(ctrl1_port_data);
|
||||
}
|
||||
|
||||
// check if TH is set to input (1).
|
||||
if (data & 0x02)
|
||||
{
|
||||
if (data & 0x20 && !(m_ctrl_reg & 0x20))
|
||||
{
|
||||
UINT8 th_level = (m_port_ctrl1->port_r() & 0x40) >> 1;
|
||||
|
||||
// check if TH pin level is high (1) and was low (0)
|
||||
if ((th_level & 0x20) && !(m_io_ctrl_reg & 0x20))
|
||||
latch_hcount = true;
|
||||
}
|
||||
|
||||
// Controller Port 2:
|
||||
|
||||
// check if TR or TH are set to output (0).
|
||||
if ((data & 0x0c) != 0x0c)
|
||||
{
|
||||
if (!(data & 0x04)) // TR set to output
|
||||
{
|
||||
ctrl2_port_data &= ~0x80 | (data << 1);
|
||||
}
|
||||
sms_input_write(space, 1, (data & 0x80) >> 7);
|
||||
if (!(data & 0x08)) // TH set to output
|
||||
{
|
||||
ctrl2_port_data &= ~0x40 | (data >> 1);
|
||||
}
|
||||
if (!m_is_gamegear)
|
||||
m_port_ctrl2->port_w(ctrl2_port_data);
|
||||
}
|
||||
// check if TH is set to input (1).
|
||||
if (data & 0x08)
|
||||
{
|
||||
UINT8 th_level = (m_port_ctrl2->port_r() & 0x40) << 1;
|
||||
|
||||
// check if TH pin level is high (1) and was low (0)
|
||||
if ((th_level & 0x80) && !(m_io_ctrl_reg & 0x80))
|
||||
latch_hcount = true;
|
||||
}
|
||||
|
||||
if (latch_hcount)
|
||||
{
|
||||
m_vdp->hcount_latch();
|
||||
}
|
||||
|
||||
m_ctrl_reg = data;
|
||||
m_io_ctrl_reg = data;
|
||||
}
|
||||
|
||||
|
||||
@ -563,12 +186,13 @@ WRITE_LINE_MEMBER(sms_state::sms_pause_callback)
|
||||
else
|
||||
m_paused = 0;
|
||||
|
||||
/* clear Light Phaser latch flags for next frame */
|
||||
m_lphaser_1_latch = 0;
|
||||
m_lphaser_2_latch = 0;
|
||||
// clear TH latch of the controller ports
|
||||
m_ctrl1_th_latch = 0;
|
||||
m_ctrl2_th_latch = 0;
|
||||
}
|
||||
|
||||
READ8_MEMBER(sms_state::sms_input_port_0_r)
|
||||
|
||||
READ8_MEMBER(sms_state::sms_input_port_dc_r)
|
||||
{
|
||||
if (m_bios_port & IO_CHIP)
|
||||
{
|
||||
@ -577,63 +201,82 @@ READ8_MEMBER(sms_state::sms_input_port_0_r)
|
||||
else
|
||||
{
|
||||
sms_get_inputs(space);
|
||||
return m_input_port0;
|
||||
|
||||
// Check if TR of controller port 1 is set to output (0)
|
||||
if (!(m_io_ctrl_reg & 0x01))
|
||||
{
|
||||
// Read TR state set through IO control port
|
||||
m_port_dc_reg &= ~0x20 | (m_is_region_japan ? 0x00 : (m_io_ctrl_reg & 0x10) << 1);
|
||||
}
|
||||
|
||||
return m_port_dc_reg;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
READ8_MEMBER(sms_state::sms_input_port_1_r)
|
||||
READ8_MEMBER(sms_state::sms_input_port_dd_r)
|
||||
{
|
||||
if (m_bios_port & IO_CHIP)
|
||||
return 0xff;
|
||||
|
||||
sms_get_inputs(space);
|
||||
|
||||
/* Reset Button */
|
||||
m_input_port1 = (m_input_port1 & 0xef) | (m_port_reset->read_safe(0x01) & 0x01) << 4;
|
||||
// Reset Button
|
||||
m_port_dd_reg &= ~0x10 | (m_port_reset->read_safe(0x01) & 0x01) << 4;
|
||||
|
||||
/* Do region detection if TH of ports A and B are set to output (0) */
|
||||
if (!(m_ctrl_reg & 0x0a))
|
||||
// Check if TR of controller port 2 is set to output (0)
|
||||
if (!(m_io_ctrl_reg & 0x04))
|
||||
{
|
||||
/* Move bits 7,5 of IO control port into bits 7, 6 */
|
||||
m_input_port1 = (m_input_port1 & 0x3f) | (m_ctrl_reg & 0x80) | (m_ctrl_reg & 0x20) << 1;
|
||||
|
||||
/* Inverse region detect value for Japanese machines */
|
||||
if (m_is_region_japan)
|
||||
m_input_port1 ^= 0xc0;
|
||||
// Read TR state set through IO control port
|
||||
m_port_dd_reg &= ~0x08 | (m_is_region_japan ? 0x00 : (m_io_ctrl_reg & 0x40) >> 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_ctrl_reg & 0x02 && m_lphaser_1_latch)
|
||||
{
|
||||
m_input_port1 &= ~0x40;
|
||||
m_lphaser_1_latch = 0;
|
||||
}
|
||||
|
||||
if (m_ctrl_reg & 0x08 && m_lphaser_2_latch)
|
||||
// Check if TH of controller port 1 is set to output (0)
|
||||
if (!(m_io_ctrl_reg & 0x02))
|
||||
{
|
||||
// Read TH state set through IO control port
|
||||
m_port_dd_reg &= ~0x40 | (m_is_region_japan ? 0x00 : (m_io_ctrl_reg & 0x20) << 1);
|
||||
}
|
||||
else // TH set to input (1)
|
||||
{
|
||||
if (m_ctrl1_th_latch)
|
||||
{
|
||||
m_input_port1 &= ~0x80;
|
||||
m_lphaser_2_latch = 0;
|
||||
m_port_dd_reg &= ~0x40;
|
||||
m_ctrl1_th_latch = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return m_input_port1;
|
||||
// Check if TH of controller port 2 is set to output (0)
|
||||
if (!(m_io_ctrl_reg & 0x08))
|
||||
{
|
||||
// Read TH state set through IO control port
|
||||
m_port_dd_reg &= ~0x80 | (m_is_region_japan ? 0x00 : (m_io_ctrl_reg & 0x80));
|
||||
}
|
||||
else // TH set to input (1)
|
||||
{
|
||||
if (m_ctrl2_th_latch)
|
||||
{
|
||||
m_port_dd_reg &= ~0x80;
|
||||
m_ctrl2_th_latch = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return m_port_dd_reg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
WRITE8_MEMBER(sms_state::sms_ym2413_register_port_0_w)
|
||||
WRITE8_MEMBER(sms_state::sms_ym2413_register_port_w)
|
||||
{
|
||||
if (m_has_fm)
|
||||
m_ym->write(space, 0, (data & 0x3f));
|
||||
}
|
||||
|
||||
|
||||
WRITE8_MEMBER(sms_state::sms_ym2413_data_port_0_w)
|
||||
WRITE8_MEMBER(sms_state::sms_ym2413_data_port_w)
|
||||
{
|
||||
if (m_has_fm)
|
||||
{
|
||||
logerror("data_port_0_w %x %x\n", offset, data);
|
||||
logerror("data_port_w %x %x\n", offset, data);
|
||||
m_ym->write(space, 1, data);
|
||||
}
|
||||
}
|
||||
@ -1056,19 +699,10 @@ MACHINE_START_MEMBER(sms_state,sms)
|
||||
{
|
||||
char str[7];
|
||||
|
||||
m_rapid_fire_timer = timer_alloc(TIMER_RAPID_FIRE);
|
||||
m_rapid_fire_timer->adjust(attotime::from_hz(10), 0, attotime::from_hz(10));
|
||||
|
||||
m_lphaser_1_timer = timer_alloc(TIMER_LPHASER_1);
|
||||
m_lphaser_2_timer = timer_alloc(TIMER_LPHASER_2);
|
||||
|
||||
m_left_lcd = machine().device("left_lcd");
|
||||
m_right_lcd = machine().device("right_lcd");
|
||||
m_space = &m_maincpu->space(AS_PROGRAM);
|
||||
|
||||
/* Check if lightgun has been chosen as input: if so, enable crosshair */
|
||||
timer_set(attotime::zero, TIMER_LIGHTGUN_TICK);
|
||||
|
||||
// alibaba and blockhol are ports of games for the MSX system. The
|
||||
// MSX bios usually initializes callback "vectors" at the top of RAM.
|
||||
// The code in alibaba does not do this so the IRQ vector only contains
|
||||
@ -1083,32 +717,18 @@ MACHINE_START_MEMBER(sms_state,sms)
|
||||
}
|
||||
|
||||
save_item(NAME(m_fm_detect));
|
||||
save_item(NAME(m_ctrl_reg));
|
||||
save_item(NAME(m_io_ctrl_reg));
|
||||
save_item(NAME(m_paused));
|
||||
save_item(NAME(m_bios_port));
|
||||
save_item(NAME(m_mapper));
|
||||
save_item(NAME(m_input_port0));
|
||||
save_item(NAME(m_input_port1));
|
||||
save_item(NAME(m_port_dc_reg));
|
||||
save_item(NAME(m_port_dd_reg));
|
||||
save_item(NAME(m_gg_sio));
|
||||
save_item(NAME(m_bank_enabled));
|
||||
save_item(NAME(m_bios_page));
|
||||
|
||||
save_item(NAME(m_rapid_fire_state_1));
|
||||
save_item(NAME(m_rapid_fire_state_2));
|
||||
save_item(NAME(m_last_paddle_read_time));
|
||||
save_item(NAME(m_paddle_read_state));
|
||||
save_item(NAME(m_last_sports_pad_time_1));
|
||||
save_item(NAME(m_last_sports_pad_time_2));
|
||||
save_item(NAME(m_sports_pad_state_1));
|
||||
save_item(NAME(m_sports_pad_state_2));
|
||||
save_item(NAME(m_sports_pad_last_data_1));
|
||||
save_item(NAME(m_sports_pad_last_data_2));
|
||||
save_item(NAME(m_sports_pad_1_x));
|
||||
save_item(NAME(m_sports_pad_1_y));
|
||||
save_item(NAME(m_sports_pad_2_x));
|
||||
save_item(NAME(m_sports_pad_2_y));
|
||||
save_item(NAME(m_lphaser_1_latch));
|
||||
save_item(NAME(m_lphaser_2_latch));
|
||||
save_item(NAME(m_ctrl1_th_latch));
|
||||
save_item(NAME(m_ctrl2_th_latch));
|
||||
save_item(NAME(m_sscope_state));
|
||||
save_item(NAME(m_frame_sscope_state));
|
||||
|
||||
@ -1142,7 +762,7 @@ MACHINE_START_MEMBER(sms_state,sms)
|
||||
|
||||
MACHINE_RESET_MEMBER(sms_state,sms)
|
||||
{
|
||||
m_ctrl_reg = 0xff;
|
||||
m_io_ctrl_reg = 0xff;
|
||||
if (m_has_fm)
|
||||
m_fm_detect = 0x01;
|
||||
|
||||
@ -1168,25 +788,8 @@ MACHINE_RESET_MEMBER(sms_state,sms)
|
||||
|
||||
setup_rom();
|
||||
|
||||
m_rapid_fire_state_1 = 0;
|
||||
m_rapid_fire_state_2 = 0;
|
||||
|
||||
m_last_paddle_read_time = 0;
|
||||
m_paddle_read_state = 0;
|
||||
|
||||
m_last_sports_pad_time_1 = 0;
|
||||
m_last_sports_pad_time_2 = 0;
|
||||
m_sports_pad_state_1 = 0;
|
||||
m_sports_pad_state_2 = 0;
|
||||
m_sports_pad_last_data_1 = 0;
|
||||
m_sports_pad_last_data_2 = 0;
|
||||
m_sports_pad_1_x = 0;
|
||||
m_sports_pad_1_y = 0;
|
||||
m_sports_pad_2_x = 0;
|
||||
m_sports_pad_2_y = 0;
|
||||
|
||||
m_lphaser_1_latch = 0;
|
||||
m_lphaser_2_latch = 0;
|
||||
m_ctrl1_th_latch = 0;
|
||||
m_ctrl2_th_latch = 0;
|
||||
m_lphaser_x_offs = (m_cartslot->m_cart) ? m_cartslot->m_cart->get_lphaser_xoffs() : 51;
|
||||
|
||||
m_sscope_state = 0;
|
||||
@ -1206,8 +809,8 @@ WRITE8_MEMBER(smssdisp_state::sms_store_cart_select_w)
|
||||
|
||||
logerror("switching in part of %s slot #%d\n", slottype ? "card" : "cartridge", slot );
|
||||
/* cartridge? slot #0 */
|
||||
// if (slottype == 0)
|
||||
// m_current_cartridge = slot;
|
||||
//if (slottype == 0)
|
||||
// m_current_cartridge = slot;
|
||||
|
||||
setup_rom();
|
||||
}
|
||||
@ -1336,6 +939,16 @@ VIDEO_START_MEMBER(sms_state,sms1)
|
||||
}
|
||||
|
||||
|
||||
READ32_MEMBER(sms_state::sms_pixel_color)
|
||||
{
|
||||
bitmap_rgb32 &vdp_bitmap = m_vdp->get_bitmap();
|
||||
int beam_x = m_main_scr->hpos();
|
||||
int beam_y = m_main_scr->vpos();
|
||||
|
||||
return vdp_bitmap.pix32(beam_y, beam_x);
|
||||
}
|
||||
|
||||
|
||||
void sms_state::screen_vblank_sms1(screen_device &screen, bool state)
|
||||
{
|
||||
// on falling edge
|
||||
|
77
src/mess/machine/sms_joypad.c
Normal file
77
src/mess/machine/sms_joypad.c
Normal file
@ -0,0 +1,77 @@
|
||||
/**********************************************************************
|
||||
|
||||
Sega Master System "Control Pad"/generic joystick emulation
|
||||
|
||||
Copyright MESS Team.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "sms_joypad.h"
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// DEVICE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
const device_type SMS_JOYPAD = &device_creator<sms_joypad_device>;
|
||||
|
||||
|
||||
static INPUT_PORTS_START( sms_joypad )
|
||||
PORT_START("JOYPAD")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) // TH
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) // TR
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// input_ports - device-specific input ports
|
||||
//-------------------------------------------------
|
||||
|
||||
ioport_constructor sms_joypad_device::device_input_ports() const
|
||||
{
|
||||
return INPUT_PORTS_NAME( sms_joypad );
|
||||
}
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// sms_joypad_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
sms_joypad_device::sms_joypad_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
||||
device_t(mconfig, SMS_JOYPAD, "Control Pad", tag, owner, clock, "sms_joypad", __FILE__),
|
||||
device_sms_control_port_interface(mconfig, *this),
|
||||
m_joypad(*this, "JOYPAD")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void sms_joypad_device::device_start()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// sms_peripheral_r - joypad read
|
||||
//-------------------------------------------------
|
||||
|
||||
UINT8 sms_joypad_device::peripheral_r()
|
||||
{
|
||||
return m_joypad->read();
|
||||
}
|
53
src/mess/machine/sms_joypad.h
Normal file
53
src/mess/machine/sms_joypad.h
Normal file
@ -0,0 +1,53 @@
|
||||
/**********************************************************************
|
||||
|
||||
Sega Master System "Control Pad"/generic joystick emulation
|
||||
|
||||
Copyright MESS Team.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __SMS_JOYPAD__
|
||||
#define __SMS_JOYPAD__
|
||||
|
||||
|
||||
#include "emu.h"
|
||||
#include "machine/smsctrl.h"
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> sms_joypad_device
|
||||
|
||||
class sms_joypad_device : public device_t,
|
||||
public device_sms_control_port_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
sms_joypad_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
// optional information overrides
|
||||
virtual ioport_constructor device_input_ports() const;
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start();
|
||||
|
||||
// device_sms_control_port_interface overrides
|
||||
virtual UINT8 peripheral_r();
|
||||
|
||||
private:
|
||||
required_ioport m_joypad;
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
extern const device_type SMS_JOYPAD;
|
||||
|
||||
|
||||
#endif
|
251
src/mess/machine/sms_lphaser.c
Normal file
251
src/mess/machine/sms_lphaser.c
Normal file
@ -0,0 +1,251 @@
|
||||
/**********************************************************************
|
||||
|
||||
Sega Master System "Light Phaser" (light gun) emulation
|
||||
|
||||
Copyright MESS Team.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "sms_lphaser.h"
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// DEVICE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
const device_type SMS_LIGHT_PHASER = &device_creator<sms_light_phaser_device>;
|
||||
|
||||
|
||||
#define LGUN_RADIUS 6
|
||||
#define LGUN_X_INTERVAL 4
|
||||
|
||||
|
||||
INPUT_CHANGED_MEMBER( sms_light_phaser_device::th_pin_w )
|
||||
{
|
||||
m_port->th_pin_w(newval);
|
||||
}
|
||||
|
||||
|
||||
INPUT_CHANGED_MEMBER( sms_light_phaser_device::position_changed )
|
||||
{
|
||||
if (newval != oldval)
|
||||
sensor_check();
|
||||
}
|
||||
|
||||
|
||||
static INPUT_PORTS_START( sms_light_phaser )
|
||||
PORT_START("CTRL_PORT")
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL (trigger)
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_CHANGED_MEMBER(DEVICE_SELF, sms_light_phaser_device, th_pin_w, 0)
|
||||
PORT_BIT( 0x9f, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
|
||||
PORT_START("LPHASER_X")
|
||||
PORT_BIT( 0xff, 0x00, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(15) PORT_CHANGED_MEMBER(DEVICE_SELF, sms_light_phaser_device, position_changed, 0)
|
||||
|
||||
PORT_START("LPHASER_Y")
|
||||
PORT_BIT( 0xff, 0x00, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(15) PORT_CHANGED_MEMBER(DEVICE_SELF, sms_light_phaser_device, position_changed, 0)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// input_ports - device-specific input ports
|
||||
//-------------------------------------------------
|
||||
|
||||
ioport_constructor sms_light_phaser_device::device_input_ports() const
|
||||
{
|
||||
return INPUT_PORTS_NAME( sms_light_phaser );
|
||||
}
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// sms_light_phaser_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
sms_light_phaser_device::sms_light_phaser_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
||||
device_t(mconfig, SMS_LIGHT_PHASER, "Light Phaser", tag, owner, clock, "sms_light_phaser", __FILE__),
|
||||
device_sms_control_port_interface(mconfig, *this),
|
||||
m_lphaser_pins(*this, "CTRL_PORT"),
|
||||
m_lphaser_x(*this, "LPHASER_X"),
|
||||
m_lphaser_y(*this, "LPHASER_Y")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void sms_light_phaser_device::device_start()
|
||||
{
|
||||
m_screen = machine().first_screen();
|
||||
m_lphaser_timer = timer_alloc(TIMER_LPHASER);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// sms_peripheral_r - light phaser read
|
||||
//-------------------------------------------------
|
||||
|
||||
UINT8 sms_light_phaser_device::peripheral_r()
|
||||
{
|
||||
return m_lphaser_pins->read();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Light Phaser (light gun) emulation notes:
|
||||
- The sensor is activated based on color brightness of some individual
|
||||
pixels being drawn by the beam, at circular area where the gun is aiming.
|
||||
- Currently, brightness is calculated based only on single pixels.
|
||||
- In general, after the trigger is pressed, games draw the next frame using
|
||||
a light color pattern, to make sure sensor will be activated. If emulation
|
||||
skips that frame, sensor may stay deactivated. Frameskip set to 0 (no skip) is
|
||||
recommended to avoid problems.
|
||||
- When sensor switches from off to on, a value is latched for HCount register
|
||||
and a flag is set. The emulation uses the flag to avoid sequential latches and
|
||||
to signal that TH line is activated when the status of the input port is read.
|
||||
When the status is read, the flag is cleared, or else it is cleared later when
|
||||
the Pause status is read (end of a frame). This is necessary because the
|
||||
"Color & Switch Test" ROM only reads the TH bit after the VINT line.
|
||||
- The gun test of "Color & Switch Test" is an example that requires checks
|
||||
of sensor status independent of other events, like trigger press or TH bit
|
||||
reads. Another example is the title screen of "Hang-On & Safari Hunt", where
|
||||
the game only reads HCount register in a loop, expecting a latch by the gun.
|
||||
- The whole procedure is managed by a timer callback, that always reschedule
|
||||
itself to run in some intervals when the beam is at the circular area.
|
||||
*/
|
||||
int sms_light_phaser_device::bright_aim_area( emu_timer *timer, int lgun_x, int lgun_y )
|
||||
{
|
||||
const int r_x_r = LGUN_RADIUS * LGUN_RADIUS;
|
||||
const rectangle &visarea = m_screen->visible_area();
|
||||
int beam_x = m_screen->hpos();
|
||||
int beam_y = m_screen->vpos();
|
||||
int dx, dy;
|
||||
int result = 0;
|
||||
int pos_changed = 0;
|
||||
double dx_radius;
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* If beam's y isn't at a line where the aim area is, change it
|
||||
the next line it enters that area. */
|
||||
dy = abs(beam_y - lgun_y);
|
||||
if (dy > LGUN_RADIUS || beam_y < visarea.min_y || beam_y > visarea.max_y)
|
||||
{
|
||||
beam_y = lgun_y - LGUN_RADIUS;
|
||||
if (beam_y < visarea.min_y)
|
||||
beam_y = visarea.min_y;
|
||||
dy = abs(beam_y - lgun_y);
|
||||
pos_changed = 1;
|
||||
}
|
||||
|
||||
/* Caculate distance in x of the radius, relative to beam's y distance.
|
||||
First try some shortcuts. */
|
||||
switch (dy)
|
||||
{
|
||||
case LGUN_RADIUS:
|
||||
dx_radius = 0;
|
||||
break;
|
||||
case 0:
|
||||
dx_radius = LGUN_RADIUS;
|
||||
break;
|
||||
default:
|
||||
/* step 1: r^2 = dx^2 + dy^2 */
|
||||
/* step 2: dx^2 = r^2 - dy^2 */
|
||||
/* step 3: dx = sqrt(r^2 - dy^2) */
|
||||
dx_radius = ceil((float) sqrt((float) (r_x_r - (dy * dy))));
|
||||
}
|
||||
|
||||
/* If beam's x isn't in the circular aim area, change it
|
||||
to the next point it enters that area. */
|
||||
dx = abs(beam_x - lgun_x);
|
||||
if (dx > dx_radius || beam_x < visarea.min_x || beam_x > visarea.max_x)
|
||||
{
|
||||
/* If beam's x has passed the aim area, advance to
|
||||
next line and recheck y/x coordinates. */
|
||||
if (beam_x > lgun_x)
|
||||
{
|
||||
beam_x = 0;
|
||||
beam_y++;
|
||||
continue;
|
||||
}
|
||||
beam_x = lgun_x - dx_radius;
|
||||
if (beam_x < visarea.min_x)
|
||||
beam_x = visarea.min_x;
|
||||
pos_changed = 1;
|
||||
}
|
||||
|
||||
if (!pos_changed)
|
||||
{
|
||||
/* brightness of the lightgray color in the frame drawn by Light Phaser games */
|
||||
const UINT8 sensor_min_brightness = 0x7f;
|
||||
|
||||
rgb_t color = m_port->pixel_r();
|
||||
|
||||
/* reference: http://www.w3.org/TR/AERT#color-contrast */
|
||||
UINT8 brightness = (RGB_RED(color) * 0.299) + (RGB_GREEN(color) * 0.587) + (RGB_BLUE(color) * 0.114);
|
||||
//printf ("color brightness: %2X for x %d y %d\n", brightness, beam_x, beam_y);
|
||||
|
||||
result = (brightness >= sensor_min_brightness) ? 1 : 0;
|
||||
|
||||
/* next check at same line */
|
||||
beam_x += LGUN_X_INTERVAL;
|
||||
pos_changed = 1;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
timer->adjust(m_screen->time_until_pos(beam_y, beam_x));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
UINT16 sms_light_phaser_device::screen_hpos_nonscaled(int scaled_hpos)
|
||||
{
|
||||
const rectangle &visarea = m_screen->visible_area();
|
||||
int offset_x = (scaled_hpos * (visarea.max_x - visarea.min_x)) / 255;
|
||||
return visarea.min_x + offset_x;
|
||||
}
|
||||
|
||||
|
||||
UINT16 sms_light_phaser_device::screen_vpos_nonscaled(int scaled_vpos)
|
||||
{
|
||||
const rectangle &visarea = m_screen->visible_area();
|
||||
int offset_y = (scaled_vpos * (visarea.max_y - visarea.min_y)) / 255;
|
||||
return visarea.min_y + offset_y;
|
||||
}
|
||||
|
||||
|
||||
void sms_light_phaser_device::sensor_check()
|
||||
{
|
||||
const int x = screen_hpos_nonscaled(m_lphaser_x->read());
|
||||
const int y = screen_vpos_nonscaled(m_lphaser_y->read());
|
||||
|
||||
if (bright_aim_area(m_lphaser_timer, x, y))
|
||||
{
|
||||
m_port->th_pin_w(x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void sms_light_phaser_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case TIMER_LPHASER:
|
||||
sensor_check();
|
||||
break;
|
||||
default:
|
||||
assert_always(FALSE, "Unknown id in sms_light_phaser_device::device_timer");
|
||||
}
|
||||
}
|
||||
|
||||
|
68
src/mess/machine/sms_lphaser.h
Normal file
68
src/mess/machine/sms_lphaser.h
Normal file
@ -0,0 +1,68 @@
|
||||
/**********************************************************************
|
||||
|
||||
Sega Master System "Light Phaser" (light gun) emulation
|
||||
|
||||
Copyright MESS Team.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __SMS_LIGHT_PHASER__
|
||||
#define __SMS_LIGHT_PHASER__
|
||||
|
||||
|
||||
#include "emu.h"
|
||||
#include "machine/smsctrl.h"
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> sms_light_phaser_device
|
||||
|
||||
class sms_light_phaser_device : public device_t,
|
||||
public device_sms_control_port_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
sms_light_phaser_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
// optional information overrides
|
||||
virtual ioport_constructor device_input_ports() const;
|
||||
|
||||
DECLARE_INPUT_CHANGED_MEMBER( th_pin_w );
|
||||
DECLARE_INPUT_CHANGED_MEMBER( position_changed );
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start();
|
||||
|
||||
// device_sms_control_port_interface overrides
|
||||
virtual UINT8 peripheral_r();
|
||||
|
||||
private:
|
||||
required_ioport m_lphaser_pins;
|
||||
required_ioport m_lphaser_x;
|
||||
required_ioport m_lphaser_y;
|
||||
|
||||
screen_device *m_screen;
|
||||
emu_timer *m_lphaser_timer;
|
||||
static const device_timer_id TIMER_LPHASER = 0;
|
||||
|
||||
void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||
void sensor_check();
|
||||
int bright_aim_area( emu_timer *timer, int lgun_x, int lgun_y );
|
||||
UINT16 screen_hpos_nonscaled(int scaled_hpos);
|
||||
UINT16 screen_vpos_nonscaled(int scaled_vpos);
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
extern const device_type SMS_LIGHT_PHASER;
|
||||
|
||||
|
||||
#endif
|
112
src/mess/machine/sms_paddle.c
Normal file
112
src/mess/machine/sms_paddle.c
Normal file
@ -0,0 +1,112 @@
|
||||
/**********************************************************************
|
||||
|
||||
Sega Master System "Paddle Control" emulation
|
||||
|
||||
Copyright MESS Team.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "sms_paddle.h"
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// DEVICE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
const device_type SMS_PADDLE = &device_creator<sms_paddle_device>;
|
||||
|
||||
|
||||
#define PADDLE_INTERVAL attotime::from_hz(XTAL_53_693175MHz/15/256)
|
||||
|
||||
|
||||
DECLARE_CUSTOM_INPUT_MEMBER( sms_paddle_device::dir_pins_r )
|
||||
{
|
||||
UINT8 data = m_paddle_x->read();
|
||||
|
||||
if (m_paddle_read_state)
|
||||
data >>= 4;
|
||||
|
||||
// Return the inverted value for the PORT_BIT mapping.
|
||||
return ~data;
|
||||
}
|
||||
|
||||
|
||||
DECLARE_CUSTOM_INPUT_MEMBER( sms_paddle_device::tr_pin_r )
|
||||
{
|
||||
// Return the inverted value for the PORT_BIT mapping.
|
||||
return ~m_paddle_read_state;
|
||||
}
|
||||
|
||||
|
||||
static INPUT_PORTS_START( sms_paddle )
|
||||
PORT_START("CTRL_PORT")
|
||||
PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, sms_paddle_device, dir_pins_r, NULL) // Directional pins
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) // TH
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, sms_paddle_device, tr_pin_r, NULL)
|
||||
|
||||
PORT_START("PADDLE_X") // Paddle knob
|
||||
PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_SENSITIVITY(40) PORT_KEYDELTA(20) PORT_CENTERDELTA(0) PORT_MINMAX(0,255)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// input_ports - device-specific input ports
|
||||
//-------------------------------------------------
|
||||
|
||||
ioport_constructor sms_paddle_device::device_input_ports() const
|
||||
{
|
||||
return INPUT_PORTS_NAME( sms_paddle );
|
||||
}
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// sms_paddle_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
sms_paddle_device::sms_paddle_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
||||
device_t(mconfig, SMS_PADDLE, "Paddle", tag, owner, clock, "sms_paddle", __FILE__),
|
||||
device_sms_control_port_interface(mconfig, *this),
|
||||
m_paddle_pins(*this, "CTRL_PORT"),
|
||||
m_paddle_x(*this, "PADDLE_X"),
|
||||
m_paddle_interval(PADDLE_INTERVAL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void sms_paddle_device::device_start()
|
||||
{
|
||||
save_item(NAME(m_paddle_read_state));
|
||||
}
|
||||
|
||||
|
||||
void sms_paddle_device::device_reset()
|
||||
{
|
||||
m_paddle_read_state = 0;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// sms_peripheral_r - paddle read
|
||||
//-------------------------------------------------
|
||||
|
||||
UINT8 sms_paddle_device::peripheral_r()
|
||||
{
|
||||
int n_intervals = machine().time().as_double() / m_paddle_interval.as_double();
|
||||
m_paddle_read_state = n_intervals & 1;
|
||||
|
||||
return m_paddle_pins->read();
|
||||
}
|
||||
|
61
src/mess/machine/sms_paddle.h
Normal file
61
src/mess/machine/sms_paddle.h
Normal file
@ -0,0 +1,61 @@
|
||||
/**********************************************************************
|
||||
|
||||
Sega Master System "Paddle Control" emulation
|
||||
|
||||
Copyright MESS Team.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __SMS_PADDLE__
|
||||
#define __SMS_PADDLE__
|
||||
|
||||
|
||||
#include "emu.h"
|
||||
#include "machine/smsctrl.h"
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> sms_paddle_device
|
||||
|
||||
class sms_paddle_device : public device_t,
|
||||
public device_sms_control_port_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
sms_paddle_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
// optional information overrides
|
||||
virtual ioport_constructor device_input_ports() const;
|
||||
|
||||
CUSTOM_INPUT_MEMBER( dir_pins_r );
|
||||
CUSTOM_INPUT_MEMBER( tr_pin_r );
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
|
||||
// device_sms_control_port_interface overrides
|
||||
virtual UINT8 peripheral_r();
|
||||
|
||||
private:
|
||||
required_ioport m_paddle_pins;
|
||||
required_ioport m_paddle_x;
|
||||
|
||||
UINT8 m_paddle_read_state;
|
||||
const attotime m_paddle_interval;
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
extern const device_type SMS_PADDLE;
|
||||
|
||||
|
||||
#endif
|
143
src/mess/machine/sms_rfu.c
Normal file
143
src/mess/machine/sms_rfu.c
Normal file
@ -0,0 +1,143 @@
|
||||
/**********************************************************************
|
||||
|
||||
Sega Master System "Rapid Fire Unit" emulation
|
||||
|
||||
Copyright MESS Team.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "sms_rfu.h"
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// DEVICE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
const device_type SMS_RAPID_FIRE = &device_creator<sms_rapid_fire_device>;
|
||||
|
||||
|
||||
#define RAPID_FIRE_INTERVAL attotime::from_hz(10)
|
||||
|
||||
|
||||
static INPUT_PORTS_START( sms_rapid_fire )
|
||||
PORT_START("rfu_sw") // Rapid Fire Unit switches
|
||||
PORT_CONFNAME( 0x03, 0x00, "Rapid Fire Unit" )
|
||||
PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_CONFSETTING( 0x01, "Button 1" )
|
||||
PORT_CONFSETTING( 0x02, "Button 2" )
|
||||
PORT_CONFSETTING( 0x03, "Button 1 + 2" )
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// input_ports - device-specific input ports
|
||||
//-------------------------------------------------
|
||||
|
||||
ioport_constructor sms_rapid_fire_device::device_input_ports() const
|
||||
{
|
||||
return INPUT_PORTS_NAME( sms_rapid_fire );
|
||||
}
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// sms_rapid_fire_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
sms_rapid_fire_device::sms_rapid_fire_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
||||
device_t(mconfig, SMS_RAPID_FIRE, "Rapid Fire", tag, owner, clock, "sms_rapid_fire", __FILE__),
|
||||
device_sms_control_port_interface(mconfig, *this),
|
||||
m_rfire_sw(*this, "rfu_sw"),
|
||||
m_subctrl_port(*this, "ctrl"),
|
||||
m_rapid_fire_interval(RAPID_FIRE_INTERVAL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void sms_rapid_fire_device::device_start()
|
||||
{
|
||||
save_item(NAME(m_rapid_fire_state));
|
||||
m_subctrl_port->device_start();
|
||||
}
|
||||
|
||||
|
||||
void sms_rapid_fire_device::device_reset()
|
||||
{
|
||||
m_rapid_fire_state = 0;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// sms_peripheral_r - rapid fire read
|
||||
//-------------------------------------------------
|
||||
|
||||
UINT8 sms_rapid_fire_device::peripheral_r()
|
||||
{
|
||||
UINT8 data = 0xff;
|
||||
|
||||
int n_intervals = machine().time().as_double() / m_rapid_fire_interval.as_double();
|
||||
m_rapid_fire_state = n_intervals & 1;
|
||||
|
||||
data = m_subctrl_port->port_r();
|
||||
|
||||
/* Check Rapid Fire switch for Button 1 (TL) */
|
||||
if (!(data & 0x20) && (m_rfire_sw->read() & 0x01))
|
||||
data |= m_rapid_fire_state << 5;
|
||||
|
||||
/* Check Rapid Fire switch for Button 2 (TR) */
|
||||
if (!(data & 0x80) && (m_rfire_sw->read() & 0x02))
|
||||
data |= m_rapid_fire_state << 7;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// sms_peripheral_w - rapid fire write
|
||||
//-------------------------------------------------
|
||||
|
||||
void sms_rapid_fire_device::peripheral_w(UINT8 data)
|
||||
{
|
||||
m_subctrl_port->port_w(data);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// machine_config_additions - device-specific
|
||||
// machine configurations
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE16_MEMBER( sms_rapid_fire_device::th_pin_w )
|
||||
{
|
||||
m_port->th_pin_w(data);
|
||||
}
|
||||
|
||||
|
||||
READ32_MEMBER( sms_rapid_fire_device::pixel_r )
|
||||
{
|
||||
return m_port->pixel_r();
|
||||
}
|
||||
|
||||
|
||||
static MACHINE_CONFIG_FRAGMENT( rfire_slot )
|
||||
MCFG_SMS_CONTROL_PORT_ADD("ctrl", sms_control_port_devices, "joypad")
|
||||
MCFG_SMS_CONTROL_PORT_TH_INPUT_HANDLER(WRITE16(sms_rapid_fire_device, th_pin_w))
|
||||
MCFG_SMS_CONTROL_PORT_PIXEL_HANDLER(READ32(sms_rapid_fire_device, pixel_r))
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
||||
machine_config_constructor sms_rapid_fire_device::device_mconfig_additions() const
|
||||
{
|
||||
return MACHINE_CONFIG_NAME( rfire_slot );
|
||||
}
|
||||
|
63
src/mess/machine/sms_rfu.h
Normal file
63
src/mess/machine/sms_rfu.h
Normal file
@ -0,0 +1,63 @@
|
||||
/**********************************************************************
|
||||
|
||||
Sega Master System "Rapid Fire Unit" emulation
|
||||
|
||||
Copyright MESS Team.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __SMS_RAPID_FIRE__
|
||||
#define __SMS_RAPID_FIRE__
|
||||
|
||||
|
||||
#include "emu.h"
|
||||
#include "machine/smsctrl.h"
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> sms_rapid_fire_device
|
||||
|
||||
class sms_rapid_fire_device : public device_t,
|
||||
public device_sms_control_port_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
sms_rapid_fire_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
// optional information overrides
|
||||
virtual ioport_constructor device_input_ports() const;
|
||||
|
||||
WRITE16_MEMBER(th_pin_w);
|
||||
READ32_MEMBER(pixel_r);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
virtual machine_config_constructor device_mconfig_additions() const;
|
||||
|
||||
// device_sms_control_port_interface overrides
|
||||
virtual UINT8 peripheral_r();
|
||||
virtual void peripheral_w(UINT8 data);
|
||||
|
||||
private:
|
||||
required_ioport m_rfire_sw;
|
||||
required_device<sms_control_port_device> m_subctrl_port;
|
||||
|
||||
UINT8 m_rapid_fire_state;
|
||||
const attotime m_rapid_fire_interval;
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
extern const device_type SMS_RAPID_FIRE;
|
||||
|
||||
|
||||
#endif
|
164
src/mess/machine/sms_sports.c
Normal file
164
src/mess/machine/sms_sports.c
Normal file
@ -0,0 +1,164 @@
|
||||
/**********************************************************************
|
||||
|
||||
Sega Master System "Sports Pad" emulation
|
||||
|
||||
Copyright MESS Team.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "sms_sports.h"
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// DEVICE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
const device_type SMS_SPORTS_PAD = &device_creator<sms_sports_pad_device>;
|
||||
|
||||
|
||||
#define SPORTS_PAD_INTERVAL attotime::from_hz(XTAL_53_693175MHz/15/512)
|
||||
|
||||
|
||||
DECLARE_CUSTOM_INPUT_MEMBER( sms_sports_pad_device::dir_pins_r )
|
||||
{
|
||||
UINT8 data = 0xff;
|
||||
|
||||
switch (m_sports_pad_state)
|
||||
{
|
||||
case 0:
|
||||
data = (m_sports_x->read() >> 4);
|
||||
break;
|
||||
case 1:
|
||||
data = m_sports_x->read();
|
||||
break;
|
||||
case 2:
|
||||
data = (m_sports_y->read() >> 4);
|
||||
break;
|
||||
case 3:
|
||||
data = m_sports_y->read();
|
||||
break;
|
||||
}
|
||||
|
||||
// Return the inverted value for the PORT_BIT mapping.
|
||||
return ~(data & 0x0f);
|
||||
}
|
||||
|
||||
|
||||
DECLARE_CUSTOM_INPUT_MEMBER( sms_sports_pad_device::th_pin_r )
|
||||
{
|
||||
return m_sports_pad_last_data;
|
||||
}
|
||||
|
||||
|
||||
DECLARE_INPUT_CHANGED_MEMBER( sms_sports_pad_device::th_pin_w )
|
||||
{
|
||||
attotime cur_time = machine().time();
|
||||
|
||||
if (cur_time - m_sports_pad_last_time > m_sports_pad_interval)
|
||||
{
|
||||
m_sports_pad_state = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sports_pad_state = (m_sports_pad_state + 1) & 3;
|
||||
}
|
||||
m_sports_pad_last_time = cur_time;
|
||||
m_sports_pad_last_data = newval;
|
||||
}
|
||||
|
||||
|
||||
static INPUT_PORTS_START( sms_sports_pad )
|
||||
PORT_START("SPORTS_IN")
|
||||
PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, sms_sports_pad_device, dir_pins_r, NULL) // Directional pins
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL (Button 1)
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CUSTOM_MEMBER(DEVICE_SELF, sms_sports_pad_device, th_pin_r, NULL)
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) // TR (Button 2)
|
||||
|
||||
PORT_START("SPORTS_OUT")
|
||||
PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_UNUSED ) // Directional pins
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) // TL (Button 1)
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_OUTPUT ) PORT_CHANGED_MEMBER(DEVICE_SELF, sms_sports_pad_device, th_pin_w, NULL)
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) // TR (Button 2)
|
||||
|
||||
PORT_START("SPORTS_X") /* Sports Pad X axis */
|
||||
PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40) PORT_RESET PORT_REVERSE
|
||||
|
||||
PORT_START("SPORTS_Y") /* Sports Pad Y axis */
|
||||
PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40) PORT_RESET PORT_REVERSE
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// input_ports - device-specific input ports
|
||||
//-------------------------------------------------
|
||||
|
||||
ioport_constructor sms_sports_pad_device::device_input_ports() const
|
||||
{
|
||||
return INPUT_PORTS_NAME( sms_sports_pad );
|
||||
}
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// sms_sports_pad_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
sms_sports_pad_device::sms_sports_pad_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
||||
device_t(mconfig, SMS_SPORTS_PAD, "Sports Pad", tag, owner, clock, "sms_sports_pad", __FILE__),
|
||||
device_sms_control_port_interface(mconfig, *this),
|
||||
m_sports_in(*this, "SPORTS_IN"),
|
||||
m_sports_out(*this, "SPORTS_OUT"),
|
||||
m_sports_x(*this, "SPORTS_X"),
|
||||
m_sports_y(*this, "SPORTS_Y"),
|
||||
m_sports_pad_interval(SPORTS_PAD_INTERVAL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void sms_sports_pad_device::device_start()
|
||||
{
|
||||
save_item(NAME(m_sports_pad_state));
|
||||
save_item(NAME(m_sports_pad_last_data));
|
||||
save_item(NAME(m_sports_pad_last_time));
|
||||
}
|
||||
|
||||
|
||||
void sms_sports_pad_device::device_reset()
|
||||
{
|
||||
m_sports_pad_state = 0;
|
||||
m_sports_pad_last_data = 0;
|
||||
m_sports_pad_last_time = machine().time();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// sms_peripheral_r - sports pad read
|
||||
//-------------------------------------------------
|
||||
|
||||
UINT8 sms_sports_pad_device::peripheral_r()
|
||||
{
|
||||
return m_sports_in->read();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// sms_peripheral_w - sports pad write
|
||||
//-------------------------------------------------
|
||||
|
||||
void sms_sports_pad_device::peripheral_w(UINT8 data)
|
||||
{
|
||||
m_sports_out->write(data);
|
||||
}
|
||||
|
67
src/mess/machine/sms_sports.h
Normal file
67
src/mess/machine/sms_sports.h
Normal file
@ -0,0 +1,67 @@
|
||||
/**********************************************************************
|
||||
|
||||
Sega Master System "Sports Pad" emulation
|
||||
|
||||
Copyright MESS Team.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __SMS_SPORTS_PAD__
|
||||
#define __SMS_SPORTS_PAD__
|
||||
|
||||
|
||||
#include "emu.h"
|
||||
#include "machine/smsctrl.h"
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> sms_sports_pad_device
|
||||
|
||||
class sms_sports_pad_device : public device_t,
|
||||
public device_sms_control_port_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
sms_sports_pad_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
// optional information overrides
|
||||
virtual ioport_constructor device_input_ports() const;
|
||||
|
||||
CUSTOM_INPUT_MEMBER( dir_pins_r );
|
||||
CUSTOM_INPUT_MEMBER( th_pin_r );
|
||||
INPUT_CHANGED_MEMBER( th_pin_w );
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
|
||||
// device_sms_control_port_interface overrides
|
||||
virtual UINT8 peripheral_r();
|
||||
virtual void peripheral_w(UINT8 data);
|
||||
|
||||
private:
|
||||
required_ioport m_sports_in;
|
||||
required_ioport m_sports_out;
|
||||
required_ioport m_sports_x;
|
||||
required_ioport m_sports_y;
|
||||
|
||||
UINT8 m_sports_pad_state;
|
||||
UINT8 m_sports_pad_last_data;
|
||||
const attotime m_sports_pad_interval;
|
||||
attotime m_sports_pad_last_time;
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
extern const device_type SMS_SPORTS_PAD;
|
||||
|
||||
|
||||
#endif
|
122
src/mess/machine/smsctrl.c
Normal file
122
src/mess/machine/smsctrl.c
Normal file
@ -0,0 +1,122 @@
|
||||
/**********************************************************************
|
||||
|
||||
Sega Master System controller port emulation
|
||||
|
||||
Copyright MESS Team.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "machine/smsctrl.h"
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// GLOBAL VARIABLES
|
||||
//**************************************************************************
|
||||
|
||||
const device_type SMS_CONTROL_PORT = &device_creator<sms_control_port_device>;
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// CARD INTERFACE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_sms_control_port_interface - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
device_sms_control_port_interface::device_sms_control_port_interface(const machine_config &mconfig, device_t &device)
|
||||
: device_slot_card_interface(mconfig,device)
|
||||
{
|
||||
m_port = dynamic_cast<sms_control_port_device *>(device.owner());
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// ~device_sms_control_port_interface - destructor
|
||||
//-------------------------------------------------
|
||||
|
||||
device_sms_control_port_interface::~device_sms_control_port_interface()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// sms_control_port_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
sms_control_port_device::sms_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
||||
device_t(mconfig, SMS_CONTROL_PORT, "Sega SMS control port", tag, owner, clock),
|
||||
device_slot_interface(mconfig, *this),
|
||||
m_th_pin_handler(*this),
|
||||
m_pixel_handler(*this)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// sms_control_port_device - destructor
|
||||
//-------------------------------------------------
|
||||
|
||||
sms_control_port_device::~sms_control_port_device()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void sms_control_port_device::device_start()
|
||||
{
|
||||
m_device = dynamic_cast<device_sms_control_port_interface *>(get_card_device());
|
||||
|
||||
m_th_pin_handler.resolve_safe();
|
||||
m_pixel_handler.resolve_safe(0);
|
||||
}
|
||||
|
||||
|
||||
UINT8 sms_control_port_device::port_r()
|
||||
{
|
||||
UINT8 data = 0xff;
|
||||
if (m_device)
|
||||
data = m_device->peripheral_r();
|
||||
return data;
|
||||
}
|
||||
|
||||
void sms_control_port_device::port_w( UINT8 data )
|
||||
{
|
||||
if (m_device)
|
||||
m_device->peripheral_w(data);
|
||||
}
|
||||
|
||||
|
||||
void sms_control_port_device::th_pin_w(UINT16 data)
|
||||
{
|
||||
m_th_pin_handler(data);
|
||||
}
|
||||
|
||||
UINT32 sms_control_port_device::pixel_r()
|
||||
{
|
||||
return m_pixel_handler();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// SLOT_INTERFACE( sms_control_port_devices )
|
||||
//-------------------------------------------------
|
||||
|
||||
SLOT_INTERFACE_START( sms_control_port_devices )
|
||||
SLOT_INTERFACE("joypad", SMS_JOYPAD)
|
||||
SLOT_INTERFACE("lphaser", SMS_LIGHT_PHASER)
|
||||
SLOT_INTERFACE("paddle", SMS_PADDLE)
|
||||
SLOT_INTERFACE("sportspad", SMS_SPORTS_PAD)
|
||||
SLOT_INTERFACE("rapidfire", SMS_RAPID_FIRE)
|
||||
SLOT_INTERFACE_END
|
124
src/mess/machine/smsctrl.h
Normal file
124
src/mess/machine/smsctrl.h
Normal file
@ -0,0 +1,124 @@
|
||||
/**********************************************************************
|
||||
|
||||
Sega Master System controller port emulation
|
||||
|
||||
Copyright MESS Team.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
|
||||
**********************************************************************
|
||||
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __SMS_CONTROL_PORT__
|
||||
#define __SMS_CONTROL_PORT__
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// INTERFACE CONFIGURATION MACROS
|
||||
//**************************************************************************
|
||||
|
||||
#define MCFG_SMS_CONTROL_PORT_ADD(_tag, _slot_intf, _def_slot) \
|
||||
MCFG_DEVICE_ADD(_tag, SMS_CONTROL_PORT, 0) \
|
||||
MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false)
|
||||
|
||||
|
||||
#define MCFG_SMS_CONTROL_PORT_TH_INPUT_HANDLER(_devcb) \
|
||||
devcb = &sms_control_port_device::set_th_input_handler(*device, DEVCB2_##_devcb);
|
||||
|
||||
|
||||
#define MCFG_SMS_CONTROL_PORT_PIXEL_HANDLER(_devcb) \
|
||||
devcb = &sms_control_port_device::set_pixel_handler(*device, DEVCB2_##_devcb);
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> sms_control_port_device
|
||||
|
||||
class device_sms_control_port_interface;
|
||||
|
||||
class sms_control_port_device : public device_t,
|
||||
public device_slot_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
sms_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
virtual ~sms_control_port_device();
|
||||
|
||||
// static configuration helpers
|
||||
template<class _Object> static devcb2_base &set_th_input_handler(device_t &device, _Object object) { return downcast<sms_control_port_device &>(device).m_th_pin_handler.set_callback(object); }
|
||||
|
||||
template<class _Object> static devcb2_base &set_pixel_handler(device_t &device, _Object object) { return downcast<sms_control_port_device &>(device).m_pixel_handler.set_callback(object); }
|
||||
|
||||
// Physical DE-9 connector interface
|
||||
|
||||
// Data returned by the port_r methods:
|
||||
// bit 0 - pin 1 - Up
|
||||
// bit 1 - pin 2 - Down
|
||||
// bit 2 - pin 3 - Left
|
||||
// bit 3 - pin 4 - Right
|
||||
// bit 4 - pin 5 - Vcc (no data)
|
||||
// bit 5 - pin 6 - TL (Button 1/Light Phaser Trigger)
|
||||
// bit 6 - pin 7 - TH (Light Phaser sensor)
|
||||
// pin 8 - GND
|
||||
// bit 7 - pin 9 - TR (Button 2)
|
||||
//
|
||||
UINT8 port_r();
|
||||
void port_w( UINT8 data );
|
||||
|
||||
void th_pin_w(UINT16 data);
|
||||
UINT32 pixel_r();
|
||||
|
||||
//protected:
|
||||
// device-level overrides
|
||||
virtual void device_start();
|
||||
|
||||
device_sms_control_port_interface *m_device;
|
||||
|
||||
private:
|
||||
devcb2_write16 m_th_pin_handler;
|
||||
devcb2_read32 m_pixel_handler;
|
||||
};
|
||||
|
||||
|
||||
// ======================> device_sms_control_port_interface
|
||||
|
||||
// class representing interface-specific live sms_expansion card
|
||||
class device_sms_control_port_interface : public device_slot_card_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
device_sms_control_port_interface(const machine_config &mconfig, device_t &device);
|
||||
virtual ~device_sms_control_port_interface();
|
||||
|
||||
virtual UINT8 peripheral_r() { return 0xff; };
|
||||
virtual void peripheral_w(UINT8 data) { };
|
||||
|
||||
protected:
|
||||
sms_control_port_device *m_port;
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
extern const device_type SMS_CONTROL_PORT;
|
||||
|
||||
|
||||
// slot devices
|
||||
#include "machine/sms_joypad.h"
|
||||
#include "machine/sms_lphaser.h"
|
||||
#include "machine/sms_paddle.h"
|
||||
#include "machine/sms_sports.h"
|
||||
#include "machine/sms_rfu.h"
|
||||
|
||||
SLOT_INTERFACE_EXTERN( sms_control_port_devices );
|
||||
|
||||
|
||||
#endif
|
@ -1928,7 +1928,13 @@ $(MESSOBJ)/sega.a: \
|
||||
$(MESS_MACHINE)/sat_bram.o \
|
||||
$(MESS_DRIVERS)/saturn.o \
|
||||
$(MESS_MACHINE)/sms.o \
|
||||
$(MESS_MACHINE)/sega8_slot.o \
|
||||
$(MESS_MACHINE)/smsctrl.o \
|
||||
$(MESS_MACHINE)/sms_joypad.o \
|
||||
$(MESS_MACHINE)/sms_lphaser.o \
|
||||
$(MESS_MACHINE)/sms_paddle.o \
|
||||
$(MESS_MACHINE)/sms_sports.o \
|
||||
$(MESS_MACHINE)/sms_rfu.o \
|
||||
$(MESS_MACHINE)/sega8_slot.o \
|
||||
$(MESS_MACHINE)/sega8_rom.o \
|
||||
$(MESS_DRIVERS)/sms.o \
|
||||
$(MESS_DRIVERS)/svmu.o \
|
||||
|
Loading…
Reference in New Issue
Block a user