i8244: fix collision detection edge case [hap, bataais]

This commit is contained in:
hap 2024-12-03 21:44:04 +01:00
parent 969ee8bc74
commit c13ed02291
6 changed files with 63 additions and 36 deletions

View File

@ -831,7 +831,7 @@ distinguished by the changed copyright from Magnavox to N.A.P. (North American P
</part>
</software>
<software name="volley" supported="partial">
<software name="volley">
<description>Electronic Volleyball (Europe, USA)</description>
<year>1979</year>
<publisher>Philips</publisher>
@ -846,7 +846,7 @@ distinguished by the changed copyright from Magnavox to N.A.P. (North American P
</part>
</software>
<software name="volleyf" cloneof="volley" supported="partial">
<software name="volleyf" cloneof="volley">
<description>Volleyball (France)</description>
<year>1979</year>
<publisher>Radiola</publisher>

View File

@ -35,16 +35,15 @@ TODO:
DEFINE_DEVICE_TYPE(EF9340_1, ef9340_1_device, "ef9340_1", "Thomson EF9340+EF9341")
ef9340_1_device::ef9340_1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, EF9340_1, tag, owner, clock)
, device_video_interface(mconfig, *this)
, m_charset(*this, "ef9340_1")
, m_write_exram(*this)
, m_read_exram(*this, 0xff)
{
m_offset_x = 0;
m_offset_y = 0;
}
ef9340_1_device::ef9340_1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, EF9340_1, tag, owner, clock),
device_video_interface(mconfig, *this),
m_charset(*this, "ef9340_1"),
m_offset_x(0),
m_offset_y(0),
m_write_exram(*this),
m_read_exram(*this, 0xff)
{ }
ROM_START( ef9340_1 )

View File

@ -40,8 +40,7 @@
*/
class ef9340_1_device : public device_t,
public device_video_interface
class ef9340_1_device : public device_t, public device_video_interface
{
public:
// construction/destruction

View File

@ -32,20 +32,20 @@ DEFINE_DEVICE_TYPE(I8245, i8245_device, "i8245", "Intel 8245")
// i8244_device - constructor
//-------------------------------------------------
i8244_device::i8244_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: i8244_device(mconfig, I8244, tag, owner, clock)
i8244_device::i8244_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
i8244_device(mconfig, I8244, tag, owner, clock)
{ }
i8244_device::i8244_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, type, tag, owner, clock)
, device_sound_interface(mconfig, *this)
, device_video_interface(mconfig, *this)
, m_irq_func(*this)
, m_charset(*this, "cgrom")
i8244_device::i8244_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, type, tag, owner, clock),
device_sound_interface(mconfig, *this),
device_video_interface(mconfig, *this),
m_irq_func(*this),
m_charset(*this, "cgrom")
{ }
i8245_device::i8245_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: i8244_device(mconfig, I8245, tag, owner, clock)
i8245_device::i8245_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
i8244_device(mconfig, I8245, tag, owner, clock)
{ }
@ -685,15 +685,17 @@ void i8244_device::draw_minor(int scanline, bitmap_ind16 &bitmap, const rectangl
{
if (cliprect.contains(px, scanline))
{
u8 mask = 1 << i;
// put zoom flag on high byte for later collision detection
u16 mask = (zoom_enable ? 0x101 : 1) << i;
u8 colx = m_collision_map[px];
// check if we collide with an already drawn source object
if (m_vdc.s.collision & m_collision_map[px])
if (m_vdc.s.collision & colx)
m_collision_status |= mask;
// check if an already drawn object would collide with us
if (m_vdc.s.collision & mask)
m_collision_status |= m_collision_map[px];
m_collision_status |= colx;
m_collision_map[px] |= mask;
bitmap.pix(scanline, px) = color;
@ -714,8 +716,11 @@ u32 i8244_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, con
for (int scanline = cliprect.min_y; scanline <= cliprect.max_y; scanline++)
{
// clear collision maps
memset(m_collision_map, 0, sizeof(m_collision_map));
memset(m_priority_map, 0, sizeof(m_priority_map));
if (cliprect.min_x == screen.visible_area().min_x)
{
memset(m_collision_map, 0, sizeof(m_collision_map));
memset(m_priority_map, 0, sizeof(m_priority_map));
}
// display grid if enabled
if (m_vdc.s.control & 0x08 && scanline >= 24 && scanline <= 218)
@ -727,6 +732,35 @@ u32 i8244_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, con
draw_major(scanline, bitmap, cliprect);
draw_minor(scanline, bitmap, cliprect);
}
// go over the collision map again for edge cases on this scanline
for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
{
if (x > screen.visible_area().min_x)
{
u16 colx0 = m_collision_map[x - 1];
u16 colx1 = m_collision_map[x];
// grid or minor to the left of major
if (colx1 & 0x80)
{
if (m_vdc.s.collision & colx0 & 0x3f)
m_collision_status |= 0x80;
if (m_vdc.s.collision & 0x80)
m_collision_status |= colx0 & 0x3f;
}
// grid to the left of non-zoomed minor
u8 mask = (colx1 & 0xf) & (~colx1 >> 8);
if (m_vdc.s.collision & colx0 & 0x30)
m_collision_status |= mask;
if (m_vdc.s.collision & mask)
m_collision_status |= colx0 & 0x30;
}
}
}
return 0;

View File

@ -39,9 +39,7 @@ DECLARE_DEVICE_TYPE(I8244, i8244_device)
DECLARE_DEVICE_TYPE(I8245, i8245_device)
class i8244_device : public device_t
, public device_sound_interface
, public device_video_interface
class i8244_device : public device_t, public device_sound_interface, public device_video_interface
{
public:
// construction/destruction
@ -156,7 +154,7 @@ protected:
int m_bgate_start;
vdc_t m_vdc;
u8 m_collision_map[0x200];
u16 m_collision_map[0x200];
u8 m_priority_map[0x200];
u8 m_x_beam_pos;

View File

@ -56,9 +56,6 @@ TODO:
and writes to the ptr/color registers, but does not increment the Y regs.
Does it (ab)use an undocumented 8245 feature?
- g7400 helicopt sometimes locks up at the sea level, timing or IRQ related?
- volley has a sprite-char collision detection problem, causing the team on the
right to never serve the ball. Sprite positions are correct so it's not that,
and as seen on videos of other games, transparent pixels don't cause a collision.
- spaans has a keyboard debounce issue: if you push and hold a key after the game
revealed the answer, it will be entered in the next input field. It's a prototype
so it wouldn't be surprising there are bugs, but this issue does not happen on