i8244: split big screen_update function into several pieces

This commit is contained in:
hap 2021-01-13 18:37:42 +01:00
parent 429ab3ca12
commit 31fb8f5c51
2 changed files with 277 additions and 239 deletions

View File

@ -4,8 +4,16 @@
/***************************************************************************
Intel 8244 (NTSC)/8245 (PAL) Graphics and sound chip
Exclusively used in Odyssey 2 series.
Exclusively used in Odyssey 2 series. See driver file for known problems.
Features summary:
- 9*8 grid
- major system (predefined 8*7 objects, 12 single + 4 quads)
- minor system (4 user-defined 8*8 sprites)
- collision detection between all layers
- 1-bit sound
See Odyssey 2 driver file for known problems.
***************************************************************************/
@ -26,9 +34,7 @@ DEFINE_DEVICE_TYPE(I8245, i8245_device, "i8245", "Intel 8245")
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)
@ -36,13 +42,24 @@ i8244_device::i8244_device(const machine_config &mconfig, device_type type, cons
, 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)
{ }
//-------------------------------------------------
// device configuration
//-------------------------------------------------
void i8244_device::device_config_complete()
{
if (!has_screen())
return;
if (!screen().refresh_attoseconds())
screen().set_raw(clock()*2, m_htotal, m_cropx, m_cropx + m_width, m_vtotal, m_cropy, m_cropy + m_height);
}
void i8244_device::set_default_params()
@ -90,7 +107,6 @@ ROM_START( i8244 )
ROM_LOAD( "charset_i8244.bin", 0x0000, 0x0200, CRC(b46a3f31) SHA1(415382715455b47b69401b3d60bd8f0036dd7fef) )
ROM_END
const tiny_rom_entry *i8244_device::device_rom_region() const
{
return ROM_NAME( i8244 );
@ -98,18 +114,33 @@ const tiny_rom_entry *i8244_device::device_rom_region() const
//-------------------------------------------------
// device_config_complete - perform any
// operations now that the configuration is
// complete
// i8244_palette - default palette
//-------------------------------------------------
void i8244_device::device_config_complete()
void i8244_device::i8244_palette(palette_device &palette) const
{
if (!has_screen())
return;
// RGB output, before any NTSC/PAL RF encoder
static constexpr rgb_t i8244_colors[16] =
{
{ 0x00, 0x00, 0x00 }, // i r g b
{ 0xb6, 0x00, 0x00 }, // i R g b
{ 0x00, 0xb6, 0x00 }, // i r G b
{ 0xb6, 0xb6, 0x00 }, // i R G b
{ 0x00, 0x00, 0xb6 }, // i r g B
{ 0xb6, 0x00, 0xb6 }, // i R g B
{ 0x00, 0xb6, 0xb6 }, // i r G B
{ 0xb6, 0xb6, 0xb6 }, // i R G B
{ 0x49, 0x49, 0x49 }, // I r g b
{ 0xff, 0x49, 0x49 }, // I R g b
{ 0x49, 0xff, 0x49 }, // I r G b
{ 0xff, 0xff, 0x49 }, // I R G b
{ 0x49, 0x49, 0xff }, // I r g B
{ 0xff, 0x49, 0xff }, // I R g B
{ 0x49, 0xff, 0xff }, // I r G B
{ 0xff, 0xff, 0xff } // I R G B
};
if (!screen().refresh_attoseconds())
screen().set_raw(clock()*2, m_htotal, m_cropx, m_cropx + m_width, m_vtotal, m_cropy, m_cropy + m_height);
palette.set_pen_colors(0, i8244_colors);
}
@ -153,32 +184,9 @@ void i8244_device::device_start()
}
void i8244_device::i8244_palette(palette_device &palette) const
{
// RGB output, before any NTSC/PAL RF encoder
static constexpr rgb_t i8244_colors[16] =
{
{ 0x00, 0x00, 0x00 }, // i r g b
{ 0xb6, 0x00, 0x00 }, // i R g b
{ 0x00, 0xb6, 0x00 }, // i r G b
{ 0xb6, 0xb6, 0x00 }, // i R G b
{ 0x00, 0x00, 0xb6 }, // i r g B
{ 0xb6, 0x00, 0xb6 }, // i R g B
{ 0x00, 0xb6, 0xb6 }, // i r G B
{ 0xb6, 0xb6, 0xb6 }, // i R G B
{ 0x49, 0x49, 0x49 }, // I r g b
{ 0xff, 0x49, 0x49 }, // I R g b
{ 0x49, 0xff, 0x49 }, // I r G b
{ 0xff, 0xff, 0x49 }, // I R G b
{ 0x49, 0x49, 0xff }, // I r g B
{ 0xff, 0x49, 0xff }, // I R g B
{ 0x49, 0xff, 0xff }, // I r G B
{ 0xff, 0xff, 0xff } // I R G B
};
palette.set_pen_colors(0, i8244_colors);
}
//-------------------------------------------------
// device_timer - handle timer callbacks
//-------------------------------------------------
void i8244_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
@ -201,6 +209,10 @@ void i8244_device::device_timer(emu_timer &timer, device_timer_id id, int param,
}
/***************************************************************************
I/O
***************************************************************************/
offs_t i8244_device::fix_register_mirrors(offs_t offset)
{
// quad x/y registers are mirrored for each quad
@ -472,58 +484,12 @@ void i8244_device::write_cx(int x, bool cx)
}
void i8244_device::draw_char(u8 index, int x, int y, u8 pixel, u16 color, bitmap_ind16 &bitmap, const rectangle &cliprect)
/***************************************************************************
RENDER
***************************************************************************/
void i8244_device::draw_grid(int scanline, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
for (int px = x; px < x + 2; px++)
{
if (cliprect.contains(px, y))
{
u8 colx = m_collision_map[px];
// check collision with self
if (index < m_priority_map[px])
{
m_control_status |= 0x80;
// TODO: much more complex on actual console (weird glitches happen)
if (colx & 0x80)
continue;
}
else
m_priority_map[px] = index;
if (pixel)
{
// check if we collide with an already drawn source object
if (m_vdc.s.collision & colx)
m_collision_status |= 0x80;
// check if an already drawn object would collide with us
if (m_vdc.s.collision & 0x80)
m_collision_status |= colx;
m_collision_map[px] |= 0x80;
bitmap.pix(y, px) = color;
}
}
}
}
u32 i8244_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
// draw background color
bitmap.fill(bitswap<3>(m_vdc.s.color,3,4,5), cliprect);
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));
// display grid if enabled
if (m_vdc.s.control & 0x08)
{
u16 color = bitswap<4>(m_vdc.s.color,6,0,1,2);
int x_grid_offset = 13;
int y_grid_offset = 24;
@ -611,11 +577,49 @@ u32 i8244_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, con
}
}
}
}
}
// display objects if enabled
if (m_vdc.s.control & 0x20 && scanline <= 242)
void i8244_device::char_pixel(u8 index, int x, int y, u8 pixel, u16 color, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
for (int px = x; px < x + 2; px++)
{
if (cliprect.contains(px, y))
{
u8 colx = m_collision_map[px];
// check collision with self
if (index < m_priority_map[px])
{
m_control_status |= 0x80;
// TODO: much more complex on actual console (weird glitches happen)
if (colx & 0x80)
continue;
}
else
m_priority_map[px] = index;
if (pixel)
{
// check if we collide with an already drawn source object
if (m_vdc.s.collision & colx)
m_collision_status |= 0x80;
// check if an already drawn object would collide with us
if (m_vdc.s.collision & 0x80)
m_collision_status |= colx;
m_collision_map[px] |= 0x80;
bitmap.pix(y, px) = color;
}
}
}
}
void i8244_device::draw_major(int scanline, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
// quad objects
for (int i = ARRAY_LENGTH(m_vdc.s.quad) - 1; i >= 0; i--)
{
@ -637,7 +641,7 @@ u32 i8244_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, con
u16 color = 8 + ((m_vdc.s.quad[i].single[j].color >> 1) & 0x07);
for (int cx = 0; cx < 8; cx++, x += 2)
draw_char(4 * j + 16 * i + 0x40, x, scanline, BIT(m_charset[offset & 0x1ff], cx ^ 7), color, bitmap, cliprect);
char_pixel(4 * j + 16 * i + 0x40, x, scanline, BIT(m_charset[offset & 0x1ff], cx ^ 7), color, bitmap, cliprect);
}
}
}
@ -659,11 +663,15 @@ u32 i8244_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, con
int x = (m_vdc.s.foreground[i].x + 5) * 2;
u16 color = 8 + ((m_vdc.s.foreground[i].color >> 1) & 0x07);
for (int cx = 0; cx < 8; cx++, x += 2)
draw_char(4 * i + 0x10, x, scanline, BIT(m_charset[offset & 0x1ff], cx ^ 7), color, bitmap, cliprect);
char_pixel(4 * i + 0x10, x, scanline, BIT(m_charset[offset & 0x1ff], cx ^ 7), color, bitmap, cliprect);
}
}
}
// sprites
void i8244_device::draw_minor(int scanline, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
// minor system (sprites)
for (int i = ARRAY_LENGTH(m_vdc.s.sprites) - 1; i >= 0; i--)
{
int y = m_vdc.s.sprites[i].y;
@ -721,6 +729,29 @@ u32 i8244_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, con
}
}
}
}
u32 i8244_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
// draw background color
bitmap.fill(bitswap<3>(m_vdc.s.color,3,4,5), cliprect);
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));
// display grid if enabled
if (m_vdc.s.control & 0x08 && scanline >= 24 && scanline <= 218)
draw_grid(scanline, bitmap, cliprect);
// display objects if enabled
if (m_vdc.s.control & 0x20 && scanline <= 242)
{
draw_major(scanline, bitmap, cliprect);
draw_minor(scanline, bitmap, cliprect);
}
}
@ -728,6 +759,10 @@ u32 i8244_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, con
}
/***************************************************************************
SOUND
***************************************************************************/
void i8244_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
{
u8 volume = m_vdc.s.sound & 0xf;

View File

@ -124,7 +124,10 @@ protected:
offs_t fix_register_mirrors(offs_t offset);
bool invalid_register(offs_t offset, bool rw);
void draw_char(u8 index, int x, int y, u8 pixel, u16 color, bitmap_ind16 &bitmap, const rectangle &cliprect);
void draw_grid(int scanline, bitmap_ind16 &bitmap, const rectangle &cliprect);
void draw_major(int scanline, bitmap_ind16 &bitmap, const rectangle &cliprect);
void draw_minor(int scanline, bitmap_ind16 &bitmap, const rectangle &cliprect);
void char_pixel(u8 index, int x, int y, u8 pixel, u16 color, bitmap_ind16 &bitmap, const rectangle &cliprect);
/* timers */
static constexpr device_timer_id TIMER_VBLANK_START = 0;