(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:
Fabio Priuli 2013-06-19 06:50:07 +00:00
parent f9dbdf1920
commit d8bf9eaac5
17 changed files with 1548 additions and 735 deletions

12
.gitattributes vendored
View File

@ -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

View File

@ -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 )

View File

@ -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

View File

@ -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

View 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();
}

View 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

View 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");
}
}

View 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

View 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();
}

View 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
View 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 );
}

View 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

View 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);
}

View 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
View 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
View 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

View File

@ -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 \