summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/machine/sms.c
diff options
context:
space:
mode:
author Fabio Priuli <etabeta78@users.noreply.github.com>2013-06-19 06:50:07 +0000
committer Fabio Priuli <etabeta78@users.noreply.github.com>2013-06-19 06:50:07 +0000
commitd8bf9eaac5907e5eafd17217dcd90f07585323fc (patch)
treeb5486ece6d48150e794abffb1f81cf5b31fba1fe /src/mess/machine/sms.c
parentf9dbdf1920fc5890518bd6016e8be88a7aa1fc43 (diff)
(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]
Diffstat (limited to 'src/mess/machine/sms.c')
-rw-r--r--src/mess/machine/sms.c659
1 files changed, 136 insertions, 523 deletions
diff --git a/src/mess/machine/sms.c b/src/mess/machine/sms.c
index c75f71794d3..98886294bb9 100644
--- a/src/mess/machine/sms.c
+++ b/src/mess/machine/sms.c
@@ -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)
-{
- 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_lphaser_1_latch == 0)
- {
- m_lphaser_1_latch = 1;
- lphaser_hcount_latch(x);
- }
- }
-}
-
-void sms_state::lphaser2_sensor_check()
+WRITE16_MEMBER(sms_state::sms_ctrl1_th_input)
{
- 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_ctrl1_th_latch == 0)
{
- 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)
- {
- /* enable crosshair */
- crosshair_set_screen(machine(), 0, CROSSHAIR_SCREEN_ALL);
- if (!m_lphaser_1_timer->enabled())
- lphaser1_sensor_check();
- }
- 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)
+ if (m_ctrl2_th_latch == 0)
{
- /* enable crosshair */
- crosshair_set_screen(machine(), 1, CROSSHAIR_SCREEN_ALL);
- if (!m_lphaser_2_timer->enabled())
- lphaser2_sensor_check();
+ m_ctrl2_th_latch = 1;
+ lphaser_hcount_latch(data);
}
- 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();
-
- m_input_port0 = 0xff;
- m_input_port1 = 0xff;
-
- if (cpu_cycles - m_last_paddle_read_time > 256)
- {
- m_paddle_read_state ^= 0xff;
- m_last_paddle_read_time = cpu_cycles;
- }
+ UINT8 data;
- /* Check if lightgun has been chosen as input: if so, enable crosshair */
- timer_set(attotime::zero, TIMER_LIGHTGUN_TICK);
+ m_port_dc_reg = 0xff;
+ m_port_dd_reg = 0xff;
- /* 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;
- }
+ 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
- /* 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);
+ }
+ if (!(data & 0x02)) // TH set to output
+ {
+ ctrl1_port_data &= ~0x40 | (data << 1);
}
- sms_input_write(space, 0, (data & 0x20) >> 5);
+ 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;
+ // Read TR state set through IO control port
+ m_port_dd_reg &= ~0x08 | (m_is_region_japan ? 0x00 : (m_io_ctrl_reg & 0x40) >> 3);
+ }
- /* Inverse region detect value for Japanese machines */
- if (m_is_region_japan)
- m_input_port1 ^= 0xc0;
+ // 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
+ else // TH set to input (1)
{
- if (m_ctrl_reg & 0x02 && m_lphaser_1_latch)
+ if (m_ctrl1_th_latch)
{
- m_input_port1 &= ~0x40;
- m_lphaser_1_latch = 0;
+ m_port_dd_reg &= ~0x40;
+ m_ctrl1_th_latch = 0;
}
+ }
- if (m_ctrl_reg & 0x08 && m_lphaser_2_latch)
+ // 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_input_port1 &= ~0x80;
- m_lphaser_2_latch = 0;
+ m_port_dd_reg &= ~0x80;
+ m_ctrl2_th_latch = 0;
}
}
- return m_input_port1;
+ 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