summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/bus/sms_ctrl/lphaser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/bus/sms_ctrl/lphaser.c')
-rw-r--r--src/emu/bus/sms_ctrl/lphaser.c128
1 files changed, 68 insertions, 60 deletions
diff --git a/src/emu/bus/sms_ctrl/lphaser.c b/src/emu/bus/sms_ctrl/lphaser.c
index 792e8d03721..050086aa09c 100644
--- a/src/emu/bus/sms_ctrl/lphaser.c
+++ b/src/emu/bus/sms_ctrl/lphaser.c
@@ -137,26 +137,27 @@ int sms_light_phaser_device::bright_aim_area( emu_timer *timer, int lgun_x, int
{
const int r_x_r = LGUN_RADIUS * LGUN_RADIUS;
const rectangle &visarea = m_screen->visible_area();
+ rectangle aim_area;
int beam_x = m_screen->hpos();
int beam_y = m_screen->vpos();
- int dx, dy;
- int result = 1;
- int pos_changed = 0;
+ int beam_x_orig = beam_x;
+ int beam_y_orig = beam_y;
+ int dy, result = 1;
double dx_radius;
+ bool new_check_point = false;
- while (1)
+ aim_area.min_y = MAX(lgun_y - LGUN_RADIUS, visarea.min_y);
+ aim_area.max_y = MIN(lgun_y + LGUN_RADIUS, visarea.max_y);
+
+ while (!new_check_point)
{
- /* 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)
+ /* If beam's y doesn't point to a line where the aim area is,
+ change it to the first line where the beam enters that area. */
+ if (beam_y < aim_area.min_y || beam_y > aim_area.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;
+ beam_y = aim_area.min_y;
}
+ dy = abs(beam_y - lgun_y);
/* Caculate distance in x of the radius, relative to beam's y distance.
First try some shortcuts. */
@@ -175,66 +176,73 @@ int sms_light_phaser_device::bright_aim_area( emu_timer *timer, int lgun_x, int
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)
+ aim_area.min_x = MAX(lgun_x - dx_radius, visarea.min_x);
+ aim_area.max_x = MIN(lgun_x + dx_radius, visarea.max_x);
+
+ while (!new_check_point)
{
- /* If beam's x has passed the aim area, advance to
- next line and recheck y/x coordinates. */
- if (beam_x > lgun_x)
+ /* If beam's x has passed the aim area, change it to the
+ next line and go back to recheck y/x coordinates. */
+ if (beam_x > aim_area.max_x)
{
- beam_x = 0;
+ beam_x = visarea.min_x;
beam_y++;
- continue;
+ break;
}
- beam_x = lgun_x - dx_radius;
- if (beam_x < visarea.min_x)
- beam_x = visarea.min_x;
- pos_changed = 1;
- }
- if (pos_changed)
- break;
+ /* If beam's x isn't in the aim area, change it to the
+ next point where the beam enters that area. */
+ if (beam_x < aim_area.min_x)
+ {
+ beam_x = aim_area.min_x;
+ }
- 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 (beam_x_orig != beam_x || beam_y_orig != beam_y)
+ {
+ /* adopt the new coordinates to adjust the timer */
+ new_check_point = true;
+ break;
+ }
+
+ if (m_sensor_last_state == 0)
+ {
+ /* sensor is already 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;
- color = m_port->pixel_r();
+ color = m_port->pixel_r();
- /* reference: http://www.w3.org/TR/AERT#color-contrast */
- brightness = (color.r() * 0.299) + (color.g() * 0.587) + (color.b() * 0.114);
- //printf ("color brightness: %2X for x %d y %d\n", brightness, beam_x, beam_y);
+ /* reference: http://www.w3.org/TR/AERT#color-contrast */
+ brightness = (color.r() * 0.299) + (color.g() * 0.587) + (color.b() * 0.114);
+ //printf ("color brightness: %2X for x %d y %d\n", brightness, beam_x, beam_y);
- result = (brightness >= sensor_min_brightness) ? 0 : 1;
- }
+ result = (brightness >= sensor_min_brightness) ? 0 : 1;
+ }
- 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;
+ if (result == 0) /* sensor on */
+ {
+ /* Set next check for when sensor will be off */
+ beam_x = aim_area.max_x + 1;
+
+ /* adopt the new coordinates to adjust the timer */
+ new_check_point = true;
+ }
+ else
+ {
+ /* Next check will happen after the minimum interval */
+ beam_x += LGUN_X_INTERVAL;
+ }
}
}
- timer->adjust(m_screen->time_until_pos(beam_y, beam_x));
+ timer->adjust(m_screen->time_until_pos(beam_y, beam_x));
return result;
}