summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/video/315_5313.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/video/315_5313.cpp')
-rw-r--r--src/devices/video/315_5313.cpp69
1 files changed, 35 insertions, 34 deletions
diff --git a/src/devices/video/315_5313.cpp b/src/devices/video/315_5313.cpp
index ec0a9d8dc96..f48468963be 100644
--- a/src/devices/video/315_5313.cpp
+++ b/src/devices/video/315_5313.cpp
@@ -3,16 +3,16 @@
/*
Sega 315-5313 VDP emulation, used by Mega Drive/Genesis
- TODO:
- - Video, DMA timing and HV counter seem incorrect,
- they need verification on real hardware.
- - Support 128KB VRAM configuration, did any hardware use it?
- - Is border area displayable?
- - 32X overlay with H32 mode, did all known software use this?
+TODO:
+- Video, DMA timing and HV counter are incorrect,
+ they need verification on real hardware.
+- Support 128KB VRAM configuration, did any hardware use it?
+- Is border area displayable?
+- 32X overlay with H32 mode, did all known software use this?
*/
#include "emu.h"
-#include "video/315_5313.h"
+#include "315_5313.h"
/* The VDP occupies addresses C00000h to C0001Fh.
@@ -168,7 +168,8 @@ static const unsigned hres_mul[4] = { 5, 5, 4, 4 };
inline u8 sega315_5313_device::get_hres() { return (MEGADRIVE_REG0C_RS0 | (MEGADRIVE_REG0C_RS1 << 1)) & 3; }
int sega315_5313_device::screen_hpos() { return screen().hpos() / (m_lcm_scaling ? hres_mul[get_hres()] : 1); }
-#define MAX_HPOSITION 480 // TODO: 342(H32) or 427.5(H40), each scanline used 3420 cycle
+// TODO: 342(H32) or 427.5(H40), each scanline used 3420 cycle
+#define MAX_HPOSITION 480
DEFINE_DEVICE_TYPE(SEGA315_5313, sega315_5313_device, "sega315_5313", "Sega 315-5313 Megadrive VDP")
@@ -298,10 +299,6 @@ void sega315_5313_device::device_post_load()
void sega315_5313_device::device_start()
{
- m_sndirqline_callback.resolve_safe();
- m_lv6irqline_callback.resolve_safe();
- m_lv4irqline_callback.resolve_safe();
-
m_32x_scanline_func.resolve();
m_32x_interrupt_func.resolve();
m_32x_scanline_helper_func.resolve();
@@ -369,9 +366,9 @@ void sega315_5313_device::device_start()
if (m_use_alt_timing)
save_pointer(NAME(m_render_line), 1280);
- m_irq6_on_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sega315_5313_device::irq6_on_timer_callback), this));
- m_irq4_on_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sega315_5313_device::irq4_on_timer_callback), this));
- m_render_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sega315_5313_device::render_scanline), this));
+ m_irq6_on_timer = timer_alloc(FUNC(sega315_5313_device::irq6_on_timer_callback), this);
+ m_irq4_on_timer = timer_alloc(FUNC(sega315_5313_device::irq4_on_timer_callback), this);
+ m_render_timer = timer_alloc(FUNC(sega315_5313_device::render_scanline), this);
m_space68k = &m_cpu68k->space();
@@ -432,7 +429,7 @@ void sega315_5313_device::vdp_vram_write(u16 data)
if (m_vdp_address & 1)
{
- data = ((data & 0x00ff) << 8) | ((data & 0xff00) >> 8);
+ data = swapendian_int16(data);
}
vram_w(m_vdp_address >> 1, data);
@@ -577,6 +574,9 @@ void sega315_5313_device::vdp_set_register(int regnum, u8 value)
{
m_regs[regnum] = value;
+// if (regnum == 1)
+// printf("%02x %02x (%lld %d %d)\n", regnum, value, screen().frame_number(), screen().hpos(), screen().vpos());
+
/* We need special handling for the IRQ enable registers, some games turn
off the irqs before they are taken, delaying them until the IRQ is turned
back on */
@@ -585,6 +585,12 @@ void sega315_5313_device::vdp_set_register(int regnum, u8 value)
{
//osd_printf_debug("setting reg 0, irq enable is now %d\n", MEGADRIVE_REG0_IRQ4_ENABLE);
+ // fatalrew and sesame are very fussy about pending interrupts.
+ // Former in particular will quickly enable both after the EA logo (cfr. killshow at PC=0x2267a),
+ // and irq 6 will jump to illegal addresses because the correlated routine isn't set in stack
+ // but delayed a bit.
+ // Note that irq 6 is masked for about 5 frames, leaving the assumption that it mustn't
+ // be left on during all this time.
if (m_irq4_pending)
{
if (MEGADRIVE_REG0_IRQ4_ENABLE)
@@ -592,12 +598,6 @@ void sega315_5313_device::vdp_set_register(int regnum, u8 value)
else
m_lv4irqline_callback(false);
}
-
- /* ??? Fatal Rewind needs this but I'm not sure it's accurate behavior
- it causes flickering in roadrash */
- // m_irq6_pending = 0;
- // m_irq4_pending = 0;
-
}
if (regnum == 0x01)
@@ -608,13 +608,7 @@ void sega315_5313_device::vdp_set_register(int regnum, u8 value)
m_lv6irqline_callback(true);
else
m_lv6irqline_callback(false);
-
}
-
- /* ??? */
- // m_irq6_pending = 0;
- // m_irq4_pending = 0;
-
}
// if (regnum == 0x0a)
@@ -648,7 +642,8 @@ inline u16 sega315_5313_device::vdp_get_word_from_68k_mem(u32 source)
return m_space68k->read_word(source);
else
{
- printf("DMA Read unmapped %06x\n", source);
+ // klaxp
+ logerror("DMA Read unmapped %06x\n", source);
return machine().rand();
}
}
@@ -1242,7 +1237,7 @@ u16 sega315_5313_device::get_hposition()
{
attotime time_elapsed_since_megadriv_scanline_timer;
- time_elapsed_since_megadriv_scanline_timer = m_megadriv_scanline_timer->time_elapsed();
+ time_elapsed_since_megadriv_scanline_timer = m_megadriv_scanline_timer->elapsed();
if (time_elapsed_since_megadriv_scanline_timer.attoseconds() < (ATTOSECONDS_PER_SECOND/get_framerate() /double(m_total_scanlines)))
{
@@ -1469,7 +1464,8 @@ void sega315_5313_device::render_spriteline_to_spritebuffer(int scanline)
if (pri == 1) pri = 0x80;
else pri = 0x40;
- /* todo: fix me, I'm sure this isn't right but sprite 0 + other sprite seem to do something..
+ // FIXME: Checkout this portion
+ /* I'm sure this isn't right but sprite 0 + other sprite seem to do something..
maybe spritemask |= 2 should be set for anything < 0x40 ?*/
if (xpos == 0x00) spritemask |= 1;
@@ -2252,6 +2248,7 @@ void sega315_5313_device::vdp_handle_scanline_callback(int scanline)
{
if (!m_use_alt_timing) m_scanline_counter++;
// osd_printf_debug("scanline %d\n", get_scanline_counter());
+ // TODO: arbitrary timing
m_render_timer->adjust(attotime::from_usec(1));
if (get_scanline_counter() == m_irq6_scanline)
@@ -2266,11 +2263,11 @@ void sega315_5313_device::vdp_handle_scanline_callback(int scanline)
// if (get_scanline_counter() == 0) m_irq4counter = MEGADRIVE_REG0A_HINT_VALUE;
// m_irq4counter = MEGADRIVE_REG0A_HINT_VALUE;
- if (get_scanline_counter()<=224)
+ if (get_scanline_counter() <= 224)
{
m_irq4counter--;
- if (m_irq4counter== - 1)
+ if (m_irq4counter == -1)
{
if (m_imode == 3) m_irq4counter = MEGADRIVE_REG0A_HINT_VALUE * 2;
else m_irq4counter = MEGADRIVE_REG0A_HINT_VALUE;
@@ -2279,9 +2276,12 @@ void sega315_5313_device::vdp_handle_scanline_callback(int scanline)
if (MEGADRIVE_REG0_IRQ4_ENABLE)
{
+ // TODO: arbitrary timing
m_irq4_on_timer->adjust(attotime::from_usec(1));
//osd_printf_debug("irq4 on scanline %d reload %d\n", get_scanline_counter(), MEGADRIVE_REG0A_HINT_VALUE);
}
+ else
+ m_irq4_on_timer->adjust(attotime::never);
}
}
else
@@ -2319,7 +2319,8 @@ void sega315_5313_device::vdp_handle_eof()
int scr_mul = 1;
m_vblank_flag = 0;
- //m_irq6_pending = 0; /* NO! (breaks warlock) */
+ // Not here, breaks warlock
+ //m_irq6_pending = 0;
/* Set it to -1 here, so it becomes 0 when the first timer kicks in */
if (!m_use_alt_timing) m_scanline_counter = -1;