(MESS) sms.c: Enhancements for Sega Scope and LCD persistence and fix SMS Light Phaser TH read bug. [Enik Land]

This commit is contained in:
Wilbert Pol 2013-08-04 20:28:30 +00:00
parent 9eec05fa5d
commit 5d50b69b62
11 changed files with 91 additions and 46 deletions

View File

@ -567,6 +567,7 @@ static MACHINE_CONFIG_DERIVED( sms1_ntsc, sms_ntsc_base )
MCFG_PALETTE_INIT(sega315_5124)
MCFG_VIDEO_START_OVERRIDE(sms_state,sms1)
MCFG_VIDEO_RESET_OVERRIDE(sms_state,sms1)
MCFG_SEGA315_5124_ADD("sms_vdp", _315_5124_ntsc_intf)
MCFG_SEGA315_5124_SET_SCREEN("screen")
@ -735,6 +736,7 @@ static MACHINE_CONFIG_DERIVED( sms1_pal, sms_pal_base )
MCFG_PALETTE_INIT(sega315_5124)
MCFG_VIDEO_START_OVERRIDE(sms_state,sms1)
MCFG_VIDEO_RESET_OVERRIDE(sms_state,sms1)
MCFG_SEGA315_5124_ADD("sms_vdp", _315_5124_pal_intf)
MCFG_SEGA315_5124_SET_SCREEN("screen")

View File

@ -155,6 +155,7 @@ public:
DECLARE_MACHINE_RESET(sms);
DECLARE_VIDEO_START(gamegear);
DECLARE_VIDEO_START(sms1);
DECLARE_VIDEO_RESET(sms1);
UINT32 screen_update_gamegear(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
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);

View File

@ -234,7 +234,7 @@ int sega8_cart_slot_device::verify_cart( UINT8 *magic, int size )
void sega8_cart_slot_device::set_lphaser_xoffset( UINT8 *rom, int size )
{
static const UINT8 signatures[6][16] =
static const UINT8 signatures[7][16] =
{
/* Spacegun */
{ 0x54, 0x4d, 0x52, 0x20, 0x53, 0x45, 0x47, 0x41, 0xff, 0xff, 0x9d, 0x99, 0x10, 0x90, 0x00, 0x40 },
@ -248,6 +248,8 @@ void sega8_cart_slot_device::set_lphaser_xoffset( UINT8 *rom, int size )
{ 0x54, 0x4d, 0x52, 0x20, 0x53, 0x45, 0x47, 0x41, 0x00, 0x00, 0xb7, 0x55, 0x74, 0x70, 0x00, 0x40 },
/* Assault City */
{ 0x54, 0x4d, 0x52, 0x20, 0x53, 0x45, 0x47, 0x41, 0xff, 0xff, 0x9f, 0x74, 0x34, 0x70, 0x00, 0x40 },
/* Missile Defense 3-D */
{ 0x54, 0x4d, 0x52, 0x20, 0x53, 0x45, 0x47, 0x41, 0x41, 0x4c, 0x15, 0x4a, 0x01, 0x80, 0x00, 0x4f }
};
int xoff = 44;
@ -269,6 +271,8 @@ void sega8_cart_slot_device::set_lphaser_xoffset( UINT8 *rom, int size )
if (!memcmp(&rom[0x7ff0], signatures[5], 16))
xoff = 47;
if (!memcmp(&rom[0x7ff0], signatures[6], 16))
xoff = 46;
}
m_cart->set_lphaser_xoffs(xoff);

View File

@ -965,6 +965,20 @@ VIDEO_START_MEMBER(sms_state,sms1)
}
VIDEO_RESET_MEMBER(sms_state,sms1)
{
if (m_port_scope->read())
{
UINT8 sscope_binocular_hack = ioport("SSCOPE_BINOCULAR")->read();
if (sscope_binocular_hack & 0x01)
m_prevleft_bitmap.fill(RGB_BLACK);
if (sscope_binocular_hack & 0x02)
m_prevright_bitmap.fill(RGB_BLACK);
}
}
READ32_MEMBER(sms_state::sms_pixel_color)
{
bitmap_rgb32 &vdp_bitmap = m_vdp->get_bitmap();
@ -999,7 +1013,7 @@ UINT32 sms_state::screen_update_sms1(screen_device &screen, bitmap_rgb32 &bitmap
if (&screen != m_main_scr)
{
sscope = m_port_scope->read_safe(0x00);
sscope = m_port_scope->read();
if (!sscope)
{
// without SegaScope, both LCDs for glasses go black
@ -1088,11 +1102,22 @@ UINT32 sms_state::screen_update_gamegear(screen_device &screen, bitmap_rgb32 &bi
{
int x, y;
bitmap_rgb32 &vdp_bitmap = m_vdp->get_bitmap();
static bool prev_bitmap_copied = false;
if (!m_port_persist->read())
{
copybitmap(bitmap, vdp_bitmap, 0, 0, 0, 0, cliprect);
if (prev_bitmap_copied)
{
m_prev_bitmap.fill(RGB_BLACK);
prev_bitmap_copied = false;
}
}
else if (!prev_bitmap_copied)
{
copybitmap(bitmap, vdp_bitmap, 0, 0, 0, 0, cliprect);
copybitmap(m_prev_bitmap, vdp_bitmap, 0, 0, 0, 0, cliprect);
prev_bitmap_copied = true;
}
else
{

View File

@ -22,10 +22,10 @@ const device_type SMS_LIGHT_PHASER = &device_creator<sms_light_phaser_device>;
#define LGUN_X_INTERVAL 4
INPUT_CHANGED_MEMBER( sms_light_phaser_device::th_pin_w )
CUSTOM_INPUT_MEMBER( sms_light_phaser_device::th_pin_r )
{
if (newval != oldval)
m_port->th_pin_w(newval);
// The returned value is inverted due to IP_ACTIVE_LOW mapping.
return ~m_sensor_last_state;
}
@ -39,11 +39,11 @@ INPUT_CHANGED_MEMBER( sms_light_phaser_device::position_changed )
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( 0x40, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, sms_light_phaser_device, th_pin_r, NULL)
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_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)
@ -86,8 +86,14 @@ sms_light_phaser_device::sms_light_phaser_device(const machine_config &mconfig,
void sms_light_phaser_device::device_start()
{
save_item(NAME(m_sensor_last_state));
m_lphaser_timer = timer_alloc(TIMER_LPHASER);
m_last_state = 1;
}
void sms_light_phaser_device::device_reset()
{
m_sensor_last_state = 1; // off (1)
}
@ -185,24 +191,21 @@ int sms_light_phaser_device::bright_aim_area( emu_timer *timer, int lgun_x, int
pos_changed = 1;
}
if (!pos_changed)
if (pos_changed)
break;
if (m_sensor_last_state == 0) /* sensor is on */
{
/* keep sensor on until out of the aim area */
result = 0;
}
else
{
rgb_t color;
UINT8 brightness;
/* brightness of the lightgray color in the frame drawn by Light Phaser games */
const UINT8 sensor_min_brightness = 0x7f;
if (m_last_state == 0) /* sensor is on */
{
/* keep sensor on until out of the aim area */
result = 0;
/* Set next check for when sensor will be off */
beam_x = lgun_x + dx_radius + 1;
if (beam_x > visarea.max_x)
beam_x = visarea.max_x + 1;
break;
}
color = m_port->pixel_r();
/* reference: http://www.w3.org/TR/AERT#color-contrast */
@ -210,13 +213,22 @@ int sms_light_phaser_device::bright_aim_area( emu_timer *timer, int lgun_x, int
//printf ("color brightness: %2X for x %d y %d\n", brightness, beam_x, beam_y);
result = (brightness >= sensor_min_brightness) ? 0 : 1;
}
/* next check at same line */
if (result == 0)
{
/* Set next check for when sensor will be off */
beam_x = lgun_x + dx_radius + 1;
if (beam_x > visarea.max_x)
beam_x = visarea.max_x + 1;
break;
}
else
{
/* Next check after the minimum interval */
beam_x += LGUN_X_INTERVAL;
pos_changed = 1;
}
else
break;
}
timer->adjust(m_screen->time_until_pos(beam_y, beam_x));
@ -242,16 +254,16 @@ UINT16 sms_light_phaser_device::screen_vpos_nonscaled(int scaled_vpos)
void sms_light_phaser_device::sensor_check()
{
int new_state;
int sensor_new_state;
const int x = screen_hpos_nonscaled(m_lphaser_x->read());
const int y = screen_vpos_nonscaled(m_lphaser_y->read());
new_state = bright_aim_area(m_lphaser_timer, x, y);
if (new_state != m_last_state)
sensor_new_state = bright_aim_area(m_lphaser_timer, x, y);
if (sensor_new_state != m_sensor_last_state)
{
m_port->th_pin_w(new_state);
m_last_state = new_state;
m_port->th_pin_w(sensor_new_state);
m_sensor_last_state = sensor_new_state;
}
}

View File

@ -35,12 +35,13 @@ public:
// optional information overrides
virtual ioport_constructor device_input_ports() const;
DECLARE_INPUT_CHANGED_MEMBER( th_pin_w );
DECLARE_CUSTOM_INPUT_MEMBER( th_pin_r );
DECLARE_INPUT_CHANGED_MEMBER( position_changed );
protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
// device_sms_control_port_interface overrides
virtual UINT8 peripheral_r();
@ -50,7 +51,7 @@ private:
required_ioport m_lphaser_x;
required_ioport m_lphaser_y;
int m_last_state;
int m_sensor_last_state;
emu_timer *m_lphaser_timer;
static const device_timer_id TIMER_LPHASER = 0;

View File

@ -21,21 +21,21 @@ 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 )
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.
// The returned value is inverted due to IP_ACTIVE_LOW mapping.
return ~data;
}
DECLARE_CUSTOM_INPUT_MEMBER( sms_paddle_device::tr_pin_r )
CUSTOM_INPUT_MEMBER( sms_paddle_device::tr_pin_r )
{
// Return the inverted value for the PORT_BIT mapping.
// The returned value is inverted due to IP_ACTIVE_LOW mapping.
return ~m_paddle_read_state;
}

View File

@ -34,8 +34,8 @@ public:
// optional information overrides
virtual ioport_constructor device_input_ports() const;
CUSTOM_INPUT_MEMBER( dir_pins_r );
CUSTOM_INPUT_MEMBER( tr_pin_r );
DECLARE_CUSTOM_INPUT_MEMBER( dir_pins_r );
DECLARE_CUSTOM_INPUT_MEMBER( tr_pin_r );
protected:
// device-level overrides

View File

@ -34,8 +34,8 @@ public:
// optional information overrides
virtual ioport_constructor device_input_ports() const;
WRITE_LINE_MEMBER(th_pin_w);
READ32_MEMBER(pixel_r);
DECLARE_WRITE_LINE_MEMBER(th_pin_w);
DECLARE_READ32_MEMBER(pixel_r);
protected:
// device-level overrides

View File

@ -21,7 +21,7 @@ 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 )
CUSTOM_INPUT_MEMBER( sms_sports_pad_device::dir_pins_r )
{
UINT8 data = 0xff;
@ -41,18 +41,18 @@ DECLARE_CUSTOM_INPUT_MEMBER( sms_sports_pad_device::dir_pins_r )
break;
}
// Return the inverted value for the PORT_BIT mapping.
// The returned value is inverted due to IP_ACTIVE_LOW mapping.
return ~(data & 0x0f);
}
DECLARE_CUSTOM_INPUT_MEMBER( sms_sports_pad_device::th_pin_r )
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 )
INPUT_CHANGED_MEMBER( sms_sports_pad_device::th_pin_w )
{
attotime cur_time = machine().time();
@ -74,7 +74,7 @@ static INPUT_PORTS_START( sms_sports_pad )
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( 0x40, IP_ACTIVE_LOW, IPT_SPECIAL ) 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")

View File

@ -34,9 +34,9 @@ public:
// 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 );
DECLARE_CUSTOM_INPUT_MEMBER( dir_pins_r );
DECLARE_CUSTOM_INPUT_MEMBER( th_pin_r );
DECLARE_INPUT_CHANGED_MEMBER( th_pin_w );
protected:
// device-level overrides