// license:BSD-3-Clause
// copyright-holders:Stefan Jokisch
/***************************************************************************
Atari Sprint 8 video emulation
***************************************************************************/
#include "emu.h"
#include "includes/sprint8.h"
void sprint8_state::sprint8_palette(palette_device &palette) const
{
for (int i = 0; i < 0x10; i++)
{
palette.set_pen_indirect(2 * i + 0, 0x10);
palette.set_pen_indirect(2 * i + 1, i);
}
palette.set_pen_indirect(0x20, 0x10);
palette.set_pen_indirect(0x21, 0x10);
palette.set_pen_indirect(0x22, 0x10);
palette.set_pen_indirect(0x23, 0x11);
}
void sprint8_state::set_pens()
{
for (int i = 0; i < 0x10; i += 8)
{
if (m_team)
{
m_palette->set_indirect_color(i + 0, rgb_t(0xff, 0x00, 0x00)); // red
m_palette->set_indirect_color(i + 1, rgb_t(0x00, 0x00, 0xff)); // blue
m_palette->set_indirect_color(i + 2, rgb_t(0xff, 0xff, 0x00)); // yellow
m_palette->set_indirect_color(i + 3, rgb_t(0x00, 0xff, 0x00)); // green
m_palette->set_indirect_color(i + 4, rgb_t(0xff, 0x00, 0xff)); // magenta
m_palette->set_indirect_color(i + 5, rgb_t(0xe0, 0xc0, 0x70)); // puce
m_palette->set_indirect_color(i + 6, rgb_t(0x00, 0xff, 0xff)); // cyan
m_palette->set_indirect_color(i + 7, rgb_t(0xff, 0xaa, 0xaa)); // pink
}
else
{
m_palette->set_indirect_color(i + 0, rgb_t(0xff, 0x00, 0x00)); // red
m_palette->set_indirect_color(i + 1, rgb_t(0x00, 0x00, 0xff)); // blue
m_palette->set_indirect_color(i + 2, rgb_t(0xff, 0x00, 0x00)); // red
m_palette->set_indirect_color(i + 3, rgb_t(0x00, 0x00, 0xff)); // blue
m_palette->set_indirect_color(i + 4, rgb_t(0xff, 0x00, 0x00)); // red
m_palette->set_indirect_color(i + 5, rgb_t(0x00, 0x00, 0xff)); // blue
m_palette->set_indirect_color(i + 6, rgb_t(0xff, 0x00, 0x00)); // red
m_palette->set_indirect_color(i + 7, rgb_t(0x00, 0x00, 0xff)); // blue
}
}
m_palette->set_indirect_color(0x10, rgb_t(0x00, 0x00, 0x00));
m_palette->set_indirect_color(0x11, rgb_t(0xff, 0xff, 0xff));
}
TILE_GET_INFO_MEMBER(sprint8_state::get_tile_info1)
{
uint8_t code = m_video_ram[tile_index];
int color = 0;
if ((code & 0x30) != 0x30) /* ? */
color = 17;
else
{
if ((tile_index + 1) & 0x010)
color |= 1;
if (code & 0x80)
color |= 2;
if (tile_index & 0x200)
color |= 4;
}
SET_TILE_INFO_MEMBER(code >> 7, code, color, (code & 0x40) ? (TILE_FLIPX | TILE_FLIPY) : 0);
}
TILE_GET_INFO_MEMBER(sprint8_state::get_tile_info2)
{
uint8_t code = m_video_ram[tile_index];
int color = 0;
if ((code & 0x38) != 0x28)
color = 16;
else
color = 17;
SET_TILE_INFO_MEMBER(code >> 7, code, color, (code & 0x40) ? (TILE_FLIPX | TILE_FLIPY) : 0);
}
WRITE8_MEMBER(sprint8_state::video_ram_w)
{
m_video_ram[offset] = data;
m_tilemap1->mark_tile_dirty(offset);
m_tilemap2->mark_tile_dirty(offset);
}
void sprint8_state::video_start()
{
m_screen->register_screen_bitmap(m_helper1);
m_screen->register_screen_bitmap(m_helper2);
m_tilemap1 = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(sprint8_state::get_tile_info1)), TILEMAP_SCAN_ROWS, 16, 8, 32, 32);
m_tilemap2 = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(sprint8_state::get_tile_info2)), TILEMAP_SCAN_ROWS, 16, 8, 32, 32);
m_tilemap1->set_scrolly(0, +24);
m_tilemap2->set_scrolly(0, +24);
m_collision_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sprint8_state::collision_callback),this));
}
void sprint8_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
{
for (int i = 0; i < 16; i++)
{
uint8_t code = m_pos_d_ram[i];
int x = m_pos_h_ram[i];
int y = m_pos_v_ram[i];
if (code & 0x80)
x |= 0x100;
m_gfxdecode->gfx(2)->transpen(bitmap,cliprect,
code ^ 7,
i,
!(code & 0x10), !(code & 0x08),
496 - x, y - 31, 0);
}
}
TIMER_CALLBACK_MEMBER(sprint8_state::collision_callback)
{
set_collision(param);
}
uint32_t sprint8_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
set_pens();
m_tilemap1->draw(screen, bitmap, cliprect, 0, 0);
draw_sprites(bitmap, cliprect);
return 0;
}
WRITE_LINE_MEMBER(sprint8_state::screen_vblank)
{
// rising edge
if (state)
{
const rectangle &visarea = m_screen->visible_area();
m_tilemap2->draw(*m_screen, m_helper2, visarea, 0, 0);
m_helper1.fill(0x20, visarea);
draw_sprites(m_helper1, visarea);
for (int y = visarea.top(); y <= visarea.bottom(); y++)
{
const uint16_t* p1 = &m_helper1.pix16(y);
const uint16_t* p2 = &m_helper2.pix16(y);
for (int x = visarea.left(); x <= visarea.right(); x++)
if (p1[x] != 0x20 && p2[x] == 0x23)
m_collision_timer->adjust(m_screen->time_until_pos(y + 24, x), m_palette->pen_indirect(p1[x]));
}
}
}