// license:BSD-3-Clause
// copyright-holders:Pierpaolo Prazzoli
/***************************************************************************
Nintendo 8080 video emulation
***************************************************************************/
#include "emu.h"
#include "includes/n8080.h"
WRITE8_MEMBER(n8080_state::n8080_video_control_w)
{
m_sheriff_color_mode = (data >> 3) & 3;
m_sheriff_color_data = (data >> 0) & 7;
flip_screen_set(data & 0x20);
}
PALETTE_INIT_MEMBER(n8080_state,n8080)
{
int i;
for (i = 0; i < 8; i++)
palette.set_pen_color(i, pal1bit(i >> 0), pal1bit(i >> 1), pal1bit(i >> 2));
}
PALETTE_INIT_MEMBER(n8080_state,helifire)
{
int i;
PALETTE_INIT_NAME(n8080)(palette);
for (i = 0; i < 0x100; i++)
{
int level = 0xff * exp(-3 * i / 255.); /* capacitor discharge */
palette.set_pen_color(0x000 + 8 + i, rgb_t(0x00, 0x00, level)); /* shades of blue */
palette.set_pen_color(0x100 + 8 + i, rgb_t(0x00, 0xC0, level)); /* shades of blue w/ green star */
palette.set_pen_color(0x200 + 8 + i, rgb_t(level, 0x00, 0x00)); /* shades of red */
palette.set_pen_color(0x300 + 8 + i, rgb_t(level, 0xC0, 0x00)); /* shades of red w/ green star */
}
}
void n8080_state::spacefev_start_red_cannon( )
{
m_spacefev_red_cannon = 1;
m_cannon_timer->adjust(attotime::from_usec(550 * 68 * 10));
}
TIMER_CALLBACK_MEMBER(n8080_state::spacefev_stop_red_cannon)
{
m_spacefev_red_cannon = 0;
m_cannon_timer->adjust(attotime::never);
}
void n8080_state::helifire_next_line( )
{
m_helifire_mv++;
if (m_helifire_sc % 4 == 2)
{
m_helifire_mv %= 256;
}
else
{
if (flip_screen())
m_helifire_mv %= 255;
else
m_helifire_mv %= 257;
}
if (m_helifire_mv == 128)
{
m_helifire_sc++;
}
}
VIDEO_START_MEMBER(n8080_state,spacefev)
{
m_cannon_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(n8080_state::spacefev_stop_red_cannon),this));
flip_screen_set(0);
save_item(NAME(m_spacefev_red_screen));
save_item(NAME(m_spacefev_red_cannon));
}
VIDEO_START_MEMBER(n8080_state,sheriff)
{
flip_screen_set(0);
save_item(NAME(m_sheriff_color_mode));
save_item(NAME(m_sheriff_color_data));
}
VIDEO_START_MEMBER(n8080_state,helifire)
{
uint8_t data = 0;
int i;
save_item(NAME(m_helifire_mv));
save_item(NAME(m_helifire_sc));
save_item(NAME(m_helifire_flash));
save_item(NAME(m_helifire_LSFR));
for (i = 0; i < 63; i++)
{
int bit =
(data >> 6) ^
(data >> 7) ^ 1;
data = (data << 1) | (bit & 1);
m_helifire_LSFR[i] = data;
}
flip_screen_set(0);
}
uint32_t n8080_state::screen_update_spacefev(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
uint8_t mask = flip_screen() ? 0xff : 0x00;
int x;
int y;
const uint8_t* pRAM = m_videoram;
const uint8_t* pPROM = memregion("proms")->base();
for (y = 0; y < 256; y++)
{
uint16_t* pLine = &bitmap.pix16(y ^ mask);
for (x = 0; x < 256; x += 8)
{
int n;
uint8_t color = 0;
if (m_spacefev_red_screen)
color = 1;
else
{
uint8_t val = pPROM[x >> 3];
if ((x >> 3) == 0x06)
{
color = m_spacefev_red_cannon ? 1 : 7;
}
if ((x >> 3) == 0x1b)
{
static const uint8_t ufo_color[] =
{
1, /* red */
2, /* green */
7, /* white */
3, /* yellow */
5, /* magenta */
6, /* cyan */
};
int cycle = screen.frame_number() / 32;
color = ufo_color[cycle % 6];
}
for (n = color + 1; n < 8; n++)
{
if (~val & (1 << n))
{
color = n;
}
}
}
for (n = 0; n < 8; n++)
{
pLine[(x + n) ^ mask] = (pRAM[x >> 3] & (1 << n)) ? color : 0;
}
}
pRAM += 32;
}
return 0;
}
uint32_t n8080_state::screen_update_sheriff(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
uint8_t mask = flip_screen() ? 0xff : 0x00;
const uint8_t* pPROM = memregion("proms")->base();
int x;
int y;
const uint8_t* pRAM = m_videoram;
for (y = 0; y < 256; y++)
{
uint16_t* pLine = &bitmap.pix16(y ^ mask);
for (x = 0; x < 256; x += 8)
{
int n;
uint8_t color = pPROM[32 * (y >> 3) + (x >> 3)];
if (m_sheriff_color_mode == 1 && !(color & 8))
color = m_sheriff_color_data ^ 7;
if (m_sheriff_color_mode == 2)
color = m_sheriff_color_data ^ 7;
if (m_sheriff_color_mode == 3)
color = 7;
for (n = 0; n < 8; n++)
{
pLine[(x + n) ^ mask] = ((pRAM[x >> 3] >> n) & 1) ? (color & 7) : 0;
}
}
pRAM += 32;
}
return 0;
}
uint32_t n8080_state::screen_update_helifire(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
int SUN_BRIGHTNESS = ioport("POT0")->read();
int SEA_BRIGHTNESS = ioport("POT1")->read();
static const int wave[8] = { 0, 1, 2, 2, 2, 1, 0, 0 };
unsigned saved_mv = m_helifire_mv;
unsigned saved_sc = m_helifire_sc;
int x;
int y;
for (y = 0; y < 256; y++)
{
uint16_t* pLine = &bitmap.pix16(y);
int level = 120 + wave[m_helifire_mv & 7];
/* draw sky */
for (x = level; x < 256; x++)
{
pLine[x] = 0x200 + 8 + SUN_BRIGHTNESS + x - level;
}
/* draw stars */
if (m_helifire_mv % 8 == 4) /* upper half */
{
int step = (320 * (m_helifire_mv - 0)) % sizeof m_helifire_LSFR;
int data =
((m_helifire_LSFR[step] & 1) << 6) |
((m_helifire_LSFR[step] & 2) << 4) |
((m_helifire_LSFR[step] & 4) << 2) |
((m_helifire_LSFR[step] & 8) << 0);
pLine[0x80 + data] |= 0x100;
}
if (m_helifire_mv % 8 == 5) /* lower half */
{
int step = (320 * (m_helifire_mv - 1)) % sizeof m_helifire_LSFR;
int data =
((m_helifire_LSFR[step] & 1) << 6) |
((m_helifire_LSFR[step] & 2) << 4) |
((m_helifire_LSFR[step] & 4) << 2) |
((m_helifire_LSFR[step] & 8) << 0);
pLine[0x00 + data] |= 0x100;
}
/* draw sea */
for (x = 0; x < level; x++)
{
pLine[x] = 8 + SEA_BRIGHTNESS + x;
}
/* draw foreground */
for (x = 0; x < 256; x += 8)
{
int offset = 32 * y + (x >> 3);
int n;
for (n = 0; n < 8; n++)
{
if (flip_screen())
{
if ((m_videoram[offset ^ 0x1fff] << n) & 0x80)
{
pLine[x + n] = m_colorram[offset ^ 0x1fff] & 7;
}
}
else
{
if ((m_videoram[offset] >> n) & 1)
{
pLine[x + n] = m_colorram[offset] & 7;
}
}
}
}
/* next line */
helifire_next_line();
}
m_helifire_mv = saved_mv;
m_helifire_sc = saved_sc;
return 0;
}
WRITE_LINE_MEMBER(n8080_state::screen_vblank_helifire)
{
// falling edge
if (!state)
{
int n = (m_screen->frame_number() >> 1) % sizeof m_helifire_LSFR;
int i;
for (i = 0; i < 8; i++)
{
int R = (i & 1);
int G = (i & 2);
int B = (i & 4);
if (m_helifire_flash)
{
if (m_helifire_LSFR[n] & 0x20)
{
G |= B;
}
if (m_screen->frame_number() & 0x04)
{
R |= G;
}
}
m_palette->set_pen_color(i,
R ? 255 : 0,
G ? 255 : 0,
B ? 255 : 0);
}
for (i = 0; i < 256; i++)
{
helifire_next_line();
}
}
}