summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/video
diff options
context:
space:
mode:
author enikland2 <enikland@gmx.com>2019-06-10 20:38:44 -0300
committer ajrhacker <ajrhacker@users.noreply.github.com>2019-06-10 19:38:44 -0400
commit6a8480d120e36ccc4e41bac504a53408789840b0 (patch)
tree15d5563f211ad6de53370c9613db0ae5057810d8 /src/devices/video
parentd0319edecadef1c9450e02403c0b5fea5b456edc (diff)
sms.cpp: Change NMI to be routed through VDP on SMS systems (#4871)
* sms.cpp: Change NMI to be routed through VDP on SMS systems * Implement /NMI-IN as a line write handler rather than as an input callback * Revert "Implement /NMI-IN as a line write handler rather than as an input callback" This reverts commit 35f67c50873203b13f506be32870ed9837a52ab2. * Implement /NMI-IN as a line write handler rather than as an input callback
Diffstat (limited to 'src/devices/video')
-rw-r--r--src/devices/video/315_5124.cpp106
-rw-r--r--src/devices/video/315_5124.h26
2 files changed, 88 insertions, 44 deletions
diff --git a/src/devices/video/315_5124.cpp b/src/devices/video/315_5124.cpp
index e95b3f92dd3..552df7be283 100644
--- a/src/devices/video/315_5124.cpp
+++ b/src/devices/video/315_5124.cpp
@@ -212,9 +212,10 @@ sega315_5124_device::sega315_5124_device(const machine_config &mconfig, device_t
, m_max_sprite_zoom_hcount(max_sprite_zoom_hcount)
, m_max_sprite_zoom_vcount(max_sprite_zoom_vcount)
, m_is_pal(false)
- , m_int_cb(*this)
- , m_csync_cb(*this)
- , m_pause_cb(*this)
+ , m_vblank_cb(*this)
+ , m_n_csync_cb(*this)
+ , m_n_int_cb(*this)
+ , m_n_nmi_cb(*this)
, m_space_config("videoram", ENDIANNESS_LITTLE, 8, 14, 0, address_map_constructor(FUNC(sega315_5124_device::sega315_5124), this))
, m_palette(*this, "palette")
, m_snsnd(*this, "snsnd")
@@ -374,20 +375,22 @@ u8 sega315_5124_device::vcount_read()
u8 sega315_5124_device::hcount_read()
{
+ m_hcounter_latched = false;
return m_hcounter;
}
-void sega315_5124_device::hcount_latch_at_hpos(int hpos)
+void sega315_5124_device::hcount_latch()
{
const int active_scr_start = 46; /* 9 + 2 + 14 + 8 + 13 */
/* The hcount value returned by the VDP seems to be based on the previous hpos */
- int hclock = hpos - 1;
+ int hclock = screen().hpos() - 1;
if (hclock < 0)
hclock += WIDTH;
m_hcounter = ((hclock - active_scr_start) >> 1) & 0xff;
+ m_hcounter_latched = true;
}
@@ -452,10 +455,10 @@ void sega315_5124_device::device_timer(emu_timer &timer, device_timer_id id, int
{
if (BIT(m_reg[0x00], 4))
{
- m_irq_state = 1;
+ m_n_int_state = 0;
- if (!m_int_cb.isnull())
- m_int_cb(ASSERT_LINE);
+ if (!m_n_int_cb.isnull())
+ m_n_int_cb(ASSERT_LINE);
}
}
break;
@@ -465,22 +468,45 @@ void sega315_5124_device::device_timer(emu_timer &timer, device_timer_id id, int
{
if (BIT(m_reg[0x01], 5))
{
- m_irq_state = 1;
+ m_n_int_state = 0;
- if (!m_int_cb.isnull())
- m_int_cb(ASSERT_LINE);
+ if (!m_n_int_cb.isnull())
+ m_n_int_cb(ASSERT_LINE);
}
}
break;
case TIMER_NMI:
- if (!m_pause_cb.isnull())
- m_pause_cb(0);
+ if (!m_n_nmi_in_state)
+ {
+ if (m_n_nmi_state)
+ m_n_nmi_cb(ASSERT_LINE);
+ }
+ else
+ {
+ if (!m_n_nmi_state)
+ m_n_nmi_cb(CLEAR_LINE);
+ }
+ m_n_nmi_state = m_n_nmi_in_state;
break;
}
}
+void sega315_5124_device::vblank_end(int vpos)
+{
+ m_nmi_timer->adjust(screen().time_until_pos(vpos, m_line_timing[NMI_HPOS]));
+}
+
+
+void sega315_5377_device::vblank_end(int vpos)
+{
+ // Assume the VBlank line is used to trigger the NMI logic performed by the 315-5378 chip.
+ if (!m_vblank_cb.isnull())
+ m_vblank_cb(0);
+}
+
+
void sega315_5124_device::process_line_timer()
{
const int vpos = screen().vpos();
@@ -493,7 +519,7 @@ void sega315_5124_device::process_line_timer()
m_reg8copy = m_reg[0x08];
/* Check if the /CSYNC signal must be active (low) */
- if (!m_csync_cb.isnull())
+ if (!m_n_csync_cb.isnull())
{
/* /CSYNC is signals /HSYNC and /VSYNC (both internals) ANDed together.
According to Charles MacDonald, /HSYNC goes low for 28 pixels on beginning
@@ -504,7 +530,7 @@ void sega315_5124_device::process_line_timer()
*/
if (vpos == 0 || vpos > (m_frame_timing[VERTICAL_SYNC] + 1))
{
- m_csync_cb(0);
+ m_n_csync_cb(0);
}
}
@@ -545,6 +571,8 @@ void sega315_5124_device::process_line_timer()
{
m_vint_timer->adjust(screen().time_until_pos(vpos, m_line_timing[VINT_HPOS]));
m_pending_status |= STATUS_VINT;
+ if (!m_vblank_cb.isnull())
+ m_vblank_cb(1);
}
/* Draw borders */
@@ -600,7 +628,8 @@ void sega315_5124_device::process_line_timer()
/* Check if we're on the last line of the top border */
if (vpos == vpos_limit + m_frame_timing[TOP_BORDER] - 1)
{
- m_nmi_timer->adjust(screen().time_until_pos(vpos, m_line_timing[NMI_HPOS]));
+ m_hcounter_latched = false;
+ vblank_end(vpos);
}
/* Draw borders */
@@ -697,12 +726,12 @@ u8 sega315_5124_device::control_read()
m_hint_occurred = false;
m_status = u8(~(STATUS_VINT | STATUS_SPROVR | STATUS_SPRCOL));
- if (m_irq_state == 1)
+ if (m_n_int_state == 0)
{
- m_irq_state = 0;
+ m_n_int_state = 1;
- if (!m_int_cb.isnull())
- m_int_cb(CLEAR_LINE);
+ if (!m_n_int_cb.isnull())
+ m_n_int_cb(CLEAR_LINE);
}
}
@@ -842,10 +871,10 @@ void sega315_5124_device::control_write(u8 data)
// For HINT disabling through register 00:
// "Line IRQ VCount" test, of Flubba's VDPTest ROM, disables HINT to wait
// for next VINT, but HINT occurs when the operation is about to execute.
- // So here, where the setting is done, the irq_state needs to be cleared.
+ // So here, where the setting is done, the /INT state needs to be cleared.
//
// For VINT disabling through register 01:
- // When running eagles5 on the smskr driver the irq_state is 1 because of some
+ // When running eagles5 on the smskr driver the /INT state is 0 because of some
// previous HINTs that occurred. eagles5 sets register 01 to 0x02 and expects
// the irq state to be cleared after that.
// The following bit of code takes care of that.
@@ -853,28 +882,28 @@ void sega315_5124_device::control_write(u8 data)
if ((reg_num == 0 && !BIT(m_reg[0x00], 4)) ||
(reg_num == 1 && !BIT(m_reg[0x01], 5)))
{
- if (m_irq_state == 1)
+ if (m_n_int_state == 0)
{
- m_irq_state = 0;
+ m_n_int_state = 1;
- if (!m_int_cb.isnull())
+ if (!m_n_int_cb.isnull())
{
- m_int_cb(CLEAR_LINE);
+ m_n_int_cb(CLEAR_LINE);
}
}
}
else
{
// For register 01 and VINT enabling:
- // Assert the IRQ line for the scoreboard of robocop3,
+ // Assert the /INT line for the scoreboard of robocop3,
// on the sms/smspal driver, be displayed correctly.
//
// Assume the same behavior for reg0+HINT.
//
- m_irq_state = 1;
+ m_n_int_state = 0;
- if (!m_int_cb.isnull())
- m_int_cb(ASSERT_LINE);
+ if (!m_n_int_cb.isnull())
+ m_n_int_cb(ASSERT_LINE);
}
}
m_addrmode = 0;
@@ -1876,9 +1905,10 @@ void sega315_5124_device::device_post_load()
void sega315_5124_device::device_start()
{
/* Resolve callbacks */
- m_int_cb.resolve();
- m_csync_cb.resolve();
- m_pause_cb.resolve();
+ m_vblank_cb.resolve();
+ m_n_csync_cb.resolve();
+ m_n_int_cb.resolve();
+ m_n_nmi_cb.resolve();
/* Make temp bitmap for rendering */
screen().register_screen_bitmap(m_tmpbitmap);
@@ -1911,11 +1941,14 @@ void sega315_5124_device::device_start()
save_item(NAME(m_control_write_data_latch));
save_item(NAME(m_sega315_5124_compatibility_mode));
save_item(NAME(m_display_disabled));
- save_item(NAME(m_irq_state));
+ save_item(NAME(m_n_int_state));
+ save_item(NAME(m_n_nmi_state));
+ save_item(NAME(m_n_nmi_in_state));
save_item(NAME(m_vdp_mode));
save_item(NAME(m_y_pixels));
save_item(NAME(m_line_counter));
save_item(NAME(m_hcounter));
+ save_item(NAME(m_hcounter_latched));
save_item(NAME(m_reg));
save_item(NAME(m_current_palette));
@@ -1961,9 +1994,12 @@ void sega315_5124_device::device_reset()
m_cram_dirty = true;
m_buffer = 0;
m_control_write_data_latch = 0;
- m_irq_state = 0;
+ m_n_int_state = 1;
+ m_n_nmi_state = 1;
+ m_n_nmi_in_state = 1;
m_line_counter = 0;
m_hcounter = 0;
+ m_hcounter_latched = false;
m_draw_time = DRAW_TIME_SMS;
std::fill(std::begin(m_current_palette), std::end(m_current_palette), 0);
diff --git a/src/devices/video/315_5124.h b/src/devices/video/315_5124.h
index 21d149b6729..9dab94e40b9 100644
--- a/src/devices/video/315_5124.h
+++ b/src/devices/video/315_5124.h
@@ -57,12 +57,14 @@ public:
void set_is_pal(bool is_pal) { m_is_pal = is_pal; }
- auto irq() { return m_int_cb.bind(); }
- auto csync() { return m_csync_cb.bind(); }
- auto pause() { return m_pause_cb.bind(); }
+ auto vblank() { return m_vblank_cb.bind(); }
+ auto n_csync() { return m_n_csync_cb.bind(); }
+ auto n_int() { return m_n_int_cb.bind(); }
+ auto n_nmi() { return m_n_nmi_cb.bind(); }
void psg_w(u8 data) { m_snsnd->write(data); }
void psg_stereo_w(u8 data) { m_snsnd->stereo_w(data); }
+ void n_nmi_in_write(int state) { m_n_nmi_in_state = state; } /* /NMI-IN line input, controls the /NMI state */
u8 data_read();
void data_write(u8 data);
u8 control_read();
@@ -70,8 +72,8 @@ public:
u8 vcount_read();
u8 hcount_read();
- void hcount_latch() { hcount_latch_at_hpos(screen().hpos()); };
- void hcount_latch_at_hpos(int hpos);
+ void hcount_latch();
+ bool hcount_latched() { return m_hcounter_latched; }
bitmap_rgb32 &get_bitmap() { return m_tmpbitmap; };
bitmap_ind8 &get_y1_bitmap() { return m_y1_bitmap; };
@@ -102,6 +104,7 @@ protected:
void set_display_settings();
void set_frame_timing();
+ virtual void vblank_end(int vpos);
virtual void update_palette();
virtual void write_memory(u8 data);
virtual void cram_write(u8 data);
@@ -137,6 +140,7 @@ protected:
const u8 m_cram_size; /* CRAM size */
u8 m_cram_mask; /* Mask to switch between SMS and GG CRAM sizes */
bool m_cram_dirty; /* Have there been any changes to the CRAM area */
+ bool m_hcounter_latched;
bool m_hint_occurred;
bool m_pending_hint;
bool m_pending_control_write;
@@ -144,7 +148,9 @@ protected:
u8 m_buffer;
u8 m_control_write_data_latch;
bool m_sega315_5124_compatibility_mode; /* when true, GG VDP behaves as SMS VDP */
- int m_irq_state; /* The status of the IRQ line of the VDP */
+ int m_n_int_state; /* The status of the /INT line of the VDP */
+ int m_n_nmi_state; /* The status of the /NMI line of the VDP */
+ int m_n_nmi_in_state; /* The status of the /NMI-IN line of the VDP */
int m_vdp_mode; /* Current mode of the VDP: 0,1,2,3,4 */
int m_y_pixels; /* 192, 224, 240 */
int m_draw_time;
@@ -170,9 +176,10 @@ protected:
int m_max_sprite_zoom_vcount;
int m_current_palette[32];
bool m_is_pal; /* false = NTSC, true = PAL */
- devcb_write_line m_int_cb; /* Interrupt callback function */
- devcb_write_line m_csync_cb; /* C-Sync callback function */
- devcb_write_line m_pause_cb; /* Pause callback function */
+ devcb_write_line m_vblank_cb; /* VBlank line callback function */
+ devcb_write_line m_n_csync_cb; /* /C-SYNC line callback function */
+ devcb_write_line m_n_int_cb; /* /INT (Interrupt) line callback function */
+ devcb_write_line m_n_nmi_cb; /* /NMI (Non-Maskable Interrupt) line callback function */
emu_timer *m_display_timer;
emu_timer *m_hint_timer;
emu_timer *m_vint_timer;
@@ -227,6 +234,7 @@ protected:
virtual void device_reset() override;
virtual void device_add_mconfig(machine_config &config) override;
+ virtual void vblank_end(int vpos) override;
virtual void update_palette() override;
virtual void cram_write(u8 data) override;
virtual void blit_scanline(int *line_buffer, int *priority_selected, int pixel_offset_x, int pixel_plot_y, int line) override;