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 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::i8244_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: i8244_device(mconfig, I8244, tag, owner, 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) 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_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) , device_video_interface(mconfig, *this)
, m_irq_func(*this) , m_irq_func(*this)
, m_charset(*this, "cgrom") , m_charset(*this, "cgrom")
{ { }
}
i8245_device::i8245_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) i8245_device::i8245_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: i8244_device(mconfig, I8245, tag, owner, 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() 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_LOAD( "charset_i8244.bin", 0x0000, 0x0200, CRC(b46a3f31) SHA1(415382715455b47b69401b3d60bd8f0036dd7fef) )
ROM_END ROM_END
const tiny_rom_entry *i8244_device::device_rom_region() const const tiny_rom_entry *i8244_device::device_rom_region() const
{ {
return ROM_NAME( i8244 ); return ROM_NAME( i8244 );
@ -98,18 +114,33 @@ const tiny_rom_entry *i8244_device::device_rom_region() const
//------------------------------------------------- //-------------------------------------------------
// device_config_complete - perform any // i8244_palette - default palette
// operations now that the configuration is
// complete
//------------------------------------------------- //-------------------------------------------------
void i8244_device::device_config_complete() void i8244_device::i8244_palette(palette_device &palette) const
{ {
if (!has_screen()) // RGB output, before any NTSC/PAL RF encoder
return; 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()) palette.set_pen_colors(0, i8244_colors);
screen().set_raw(clock()*2, m_htotal, m_cropx, m_cropx + m_width, m_vtotal, m_cropy, m_cropy + m_height);
} }
@ -153,32 +184,9 @@ void i8244_device::device_start()
} }
void i8244_device::i8244_palette(palette_device &palette) const //-------------------------------------------------
{ // device_timer - handle timer callbacks
// 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);
}
void i8244_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) 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) offs_t i8244_device::fix_register_mirrors(offs_t offset)
{ {
// quad x/y registers are mirrored for each quad // 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); u16 color = bitswap<4>(m_vdc.s.color,6,0,1,2);
int x_grid_offset = 13; int x_grid_offset = 13;
int y_grid_offset = 24; 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 // quad objects
for (int i = ARRAY_LENGTH(m_vdc.s.quad) - 1; i >= 0; i--) 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); u16 color = 8 + ((m_vdc.s.quad[i].single[j].color >> 1) & 0x07);
for (int cx = 0; cx < 8; cx++, x += 2) 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; int x = (m_vdc.s.foreground[i].x + 5) * 2;
u16 color = 8 + ((m_vdc.s.foreground[i].color >> 1) & 0x07); u16 color = 8 + ((m_vdc.s.foreground[i].color >> 1) & 0x07);
for (int cx = 0; cx < 8; cx++, x += 2) 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--) for (int i = ARRAY_LENGTH(m_vdc.s.sprites) - 1; i >= 0; i--)
{ {
int y = m_vdc.s.sprites[i].y; 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) 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; u8 volume = m_vdc.s.sound & 0xf;

View File

@ -124,7 +124,10 @@ protected:
offs_t fix_register_mirrors(offs_t offset); offs_t fix_register_mirrors(offs_t offset);
bool invalid_register(offs_t offset, bool rw); 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 */ /* timers */
static constexpr device_timer_id TIMER_VBLANK_START = 0; static constexpr device_timer_id TIMER_VBLANK_START = 0;