summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/machine/sms.c
diff options
context:
space:
mode:
author Wilbert Pol <wilbert@jdg.info>2013-05-14 20:56:54 +0000
committer Wilbert Pol <wilbert@jdg.info>2013-05-14 20:56:54 +0000
commit335de9f804f6665d2ffbc20fa6d2bb4a14b8bdee (patch)
treed1a3a1e9f930b73561e84f0a52ed5a63d54f6528 /src/mess/machine/sms.c
parent34be6878ec112891732038e4ecdc0b8c251bdba6 (diff)
(MESS) sms.c: Change hcount calculation to use screen timings and move it to the VDP. [Enik Land]
Diffstat (limited to 'src/mess/machine/sms.c')
-rw-r--r--src/mess/machine/sms.c140
1 files changed, 59 insertions, 81 deletions
diff --git a/src/mess/machine/sms.c b/src/mess/machine/sms.c
index 2048b981479..c4b3134c616 100644
--- a/src/mess/machine/sms.c
+++ b/src/mess/machine/sms.c
@@ -279,18 +279,6 @@ WRITE8_MEMBER(sms_state::sms_input_write)
}
}
-/* FIXME: this function is a hack for Light Phaser emulation. Theoretically
- sms_vdp_hcount_latch() should be used instead, but it returns incorrect
- position for unknown reason (timing?) */
-void sms_state::vdp_hcount_lphaser( int hpos )
-{
- int hpos_tmp = hpos + m_lphaser_x_offs;
- UINT8 tmp = ((hpos_tmp - 46) >> 1) & 0xff;
-
- //printf ("sms_vdp_hcount_lphaser: hpos %3d hpos_tmp %3d => hcount %2X\n", hpos, hpos_tmp, tmp);
- m_vdp->hcount_latch_write(*m_space, 0, tmp);
-}
-
/*
Light Phaser (light gun) emulation notes:
@@ -323,12 +311,13 @@ int sms_state::lgun_bright_aim_area( emu_timer *timer, int lgun_x, int lgun_y )
int dx, dy;
int result = 0;
int pos_changed = 0;
- double dx_circ;
+ 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;
@@ -337,21 +326,38 @@ int sms_state::lgun_bright_aim_area( emu_timer *timer, int lgun_x, int lgun_y )
dy = abs(beam_y - lgun_y);
pos_changed = 1;
}
- /* 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_circ = ceil((float) sqrt((float) (r_x_r - (dy * dy))));
- dx = abs(beam_x - lgun_x);
- if (dx > dx_circ || beam_x < visarea.min_x || beam_x > visarea.max_x)
+ /* 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_circ;
+ beam_x = lgun_x - dx_radius;
if (beam_x < visarea.min_x)
beam_x = visarea.min_x;
pos_changed = 1;
@@ -389,45 +395,19 @@ int sms_state::lgun_bright_aim_area( emu_timer *timer, int lgun_x, int lgun_y )
return result;
}
-UINT8 sms_state::sms_vdp_hcount()
-{
- UINT64 cycles_per_line;
- attotime line_remaining_time;
- UINT64 line_remaining_cycles;
- UINT64 line_elapsed_cycles;
-
- /* Calculate amount of CPU cycles according to screen references.
- If some day the screen become always synced to the CPU, in the
- proportion of their speeds, this may be replaced by the screen
- hpos position only and the function be moved to the VDP file. */
- cycles_per_line = m_main_cpu->attotime_to_clocks(m_main_scr->scan_period());
- line_remaining_time = m_main_scr->time_until_pos(m_main_scr->vpos(), m_main_scr->width());
- line_remaining_cycles = m_main_cpu->attotime_to_clocks(line_remaining_time) % cycles_per_line;
- line_elapsed_cycles = cycles_per_line - line_remaining_cycles;
-
- /* HCount equation, being hpos = VDP hclocks: "(hpos - 47) / 2"
- Screen hpos based on CPU cycles: "cycles * width / cycles per line"
- Do both in same line for one-step rounding only (required). */
- return ((line_elapsed_cycles * m_main_scr->width() / cycles_per_line) - 47) / 2;
-
- /* Alternative hcount equation, restricted to the SMS clock:
- "(590 - (line_remaining_cycles * 3)) / 4"
- Posted by Flubba on SMSPower forum. */
-}
-
-void sms_state::sms_vdp_hcount_latch( address_space &space )
+void sms_state::lphaser_hcount_latch( int hpos )
{
- UINT8 value = sms_vdp_hcount();
-
- m_vdp->hcount_latch_write(space, 0, value);
+ /* A delay seems to occur when the Light Phaser latches the
+ VDP hcount, then an offset is added here to the hpos. */
+ m_vdp->hcount_latch_at_hpos(hpos + m_lphaser_x_offs);
}
UINT16 sms_state::screen_hpos_nonscaled(int scaled_hpos)
{
const rectangle &visarea = m_main_scr->visible_area();
- int offset_x = (scaled_hpos * visarea.width()) / 255;
+ int offset_x = (scaled_hpos * (visarea.max_x - visarea.min_x)) / 255;
return visarea.min_x + offset_x;
}
@@ -450,7 +430,7 @@ void sms_state::lphaser1_sensor_check()
if (m_lphaser_1_latch == 0)
{
m_lphaser_1_latch = 1;
- vdp_hcount_lphaser(x);
+ lphaser_hcount_latch(x);
}
}
}
@@ -465,7 +445,7 @@ void sms_state::lphaser2_sensor_check()
if (m_lphaser_2_latch == 0)
{
m_lphaser_2_latch = 1;
- vdp_hcount_lphaser(x);
+ lphaser_hcount_latch(x);
}
}
}
@@ -573,13 +553,13 @@ void sms_state::sms_get_inputs( address_space &space )
case 0x01: /* Light Phaser */
data = (ioport("CTRLIPT")->read() & 0x01) << 4;
- if (!(data & 0x10))
- {
- if (ioport("RFU")->read() & 0x01)
- data |= m_rapid_fire_state_1 & 0x10;
- }
- /* just consider the button (trigger) bit */
+ /* Check Rapid Fire setting for Trigger */
+ if (!(data & 0x10) && (ioport("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;
@@ -635,13 +615,13 @@ void sms_state::sms_get_inputs( address_space &space )
case 0x10: /* Light Phaser */
data = (ioport("CTRLIPT")->read() & 0x10) >> 2;
- if (!(data & 0x04))
- {
- if (ioport("RFU")->read() & 0x04)
- data |= m_rapid_fire_state_2 & 0x04;
- }
- /* just consider the button (trigger) bit */
+ /* Check Rapid Fire setting for Trigger */
+ if (!(data & 0x04) && (ioport("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;
@@ -708,14 +688,14 @@ READ8_MEMBER(sms_state::sms_fm_detect_r)
WRITE8_MEMBER(sms_state::sms_io_control_w)
{
- bool hcount_latch = false;
+ bool latch_hcount = false;
if (data & 0x08)
{
/* check if TH pin level is high (1) and was low last time */
if (data & 0x80 && !(m_ctrl_reg & 0x80))
{
- hcount_latch = true;
+ latch_hcount = true;
}
sms_input_write(space, 0, (data & 0x20) >> 5);
}
@@ -724,14 +704,14 @@ WRITE8_MEMBER(sms_state::sms_io_control_w)
{
if (data & 0x20 && !(m_ctrl_reg & 0x20))
{
- hcount_latch = true;
+ latch_hcount = true;
}
sms_input_write(space, 1, (data & 0x80) >> 7);
}
- if (hcount_latch)
+ if (latch_hcount)
{
- sms_vdp_hcount_latch(space);
+ m_vdp->hcount_latch();
}
m_ctrl_reg = data;
@@ -741,7 +721,7 @@ WRITE8_MEMBER(sms_state::sms_io_control_w)
READ8_MEMBER(sms_state::sms_count_r)
{
if (offset & 0x01)
- return m_vdp->hcount_latch_read(*m_space, offset);
+ return m_vdp->hcount_read(*m_space, offset);
else
return m_vdp->vcount_read(*m_space, offset);
}
@@ -1531,22 +1511,22 @@ int sms_state::detect_lphaser_xoffset( UINT8 *rom )
if (!(m_bios_port & IO_CARTRIDGE) && m_cartridge[m_current_cartridge].size >= 0x8000)
{
if (!memcmp(&rom[0x7ff0], signatures[0], 16) || !memcmp(&rom[0x7ff0], signatures[1], 16))
- return 40;
+ return 41;
if (!memcmp(&rom[0x7ff0], signatures[2], 16))
- return 49;
+ return 50;
if (!memcmp(&rom[0x7ff0], signatures[3], 16))
- return 47;
+ return 48;
if (!memcmp(&rom[0x7ff0], signatures[4], 16))
- return 44;
+ return 45;
if (!memcmp(&rom[0x7ff0], signatures[5], 16))
- return 53;
+ return 54;
}
- return 50;
+ return 51;
}
@@ -2260,9 +2240,7 @@ UINT32 sms_state::screen_update_sms(screen_device &screen, bitmap_rgb32 &bitmap,
VIDEO_START_MEMBER(sms_state,gamegear)
{
- screen_device *screen = machine().first_screen();
-
- screen->register_screen_bitmap(m_prev_bitmap);
+ m_main_scr->register_screen_bitmap(m_prev_bitmap);
save_item(NAME(m_prev_bitmap));
}