// license:BSD-3-Clause
// copyright-holders:Curt Coder
/*****************************************************************************
*
* video/abc802.c
*
****************************************************************************/
#include "emu.h"
#include "includes/abc80x.h"
#include "screen.h"
//-------------------------------------------------
// MC6845_UPDATE_ROW( abc802_update_row )
//-------------------------------------------------
MC6845_UPDATE_ROW( abc802_state::abc802_update_row )
{
/*
PAL16R4 equation:
IF (VCC) *OS = FC + RF / RC
*RG: = HS / *RG + *ATE / *RG + ATD / *RG + LL /
*RG + AT1 / *RG + AT0 / ATE + *ATD + *LL +
*AT1 + *AT0
*RI: = *RI + *INV / *RI + LL / *INV + *LL
*RF: = HS / *RF + *ATE / *RF + ATD / *RF + LL /
*RF + AT1 / *RF + AT0 / ATE + *ATD + *LL +
*AT1 + AT0
*RC: = HS / *RC + *ATE / *RC + *ATD / *RC + LL /
*RC + *ATI / *RC + AT0 / ATE + *LL + *AT1 +
*AT0
IF (VCC) *O0 = *CUR + *AT0 / *CUR + ATE
*O1 = *CUR + *AT1 / *CUR + ATE
+ = AND
/ = OR
* = Inverted
ATD Attribute data
ATE Attribute enable
AT0,AT1 Attribute address
CUR Cursor
FC FLSH clock
HS Horizontal sync
INV Inverted signal input
LL Load when Low
OEL Output Enable when Low
RC Row clear
RF Row flash
RG Row graphic
RI Row inverted
*/
const pen_t *pen = m_palette->pens();
int rf = 0, rc = 0, rg = 0;
y += vbp;
for (int column = 0; column < x_count; column++)
{
uint8_t code = m_char_ram[(ma + column) & 0x7ff];
uint16_t address = code << 4;
uint8_t ra_latch = ra;
uint8_t data;
int ri = (code & ABC802_INV) ? 1 : 0;
if (column == cursor_x)
{
ra_latch = 0x0f;
}
if ((m_flshclk && rf) || rc)
{
ra_latch = 0x0e;
}
if (rg)
{
address |= 0x800;
}
data = m_char_rom->base()[(address + ra_latch) & 0xfff];
if (data & ABC802_ATE)
{
int attr = data & 0x03;
int value = (data & ABC802_ATD) ? 1 : 0;
switch (attr)
{
case 0x00:
// Row Graphic
rg = value;
break;
case 0x01:
// Row Flash
rf = value;
break;
case 0x02:
// Row Clear
rc = value;
break;
case 0x03:
// undefined
break;
}
}
else
{
data <<= 2;
if (m_80_40_mux)
{
for (int bit = 0; bit < ABC800_CHAR_WIDTH; bit++)
{
int x = hbp + ((column + 3) * ABC800_CHAR_WIDTH) + bit;
int color = (BIT(data, 7) ^ ri) && de;
bitmap.pix32(y, x) = pen[color];
data <<= 1;
}
}
else
{
for (int bit = 0; bit < ABC800_CHAR_WIDTH; bit++)
{
int x = hbp + ((column + 3) * ABC800_CHAR_WIDTH) + (bit << 1);
int color = (BIT(data, 7) ^ ri) && de;
bitmap.pix32(y, x) = pen[color];
bitmap.pix32(y, x + 1) = pen[color];
data <<= 1;
}
column++;
}
}
}
}
//-------------------------------------------------
// vs_w - vertical sync write
//-------------------------------------------------
WRITE_LINE_MEMBER( abc802_state::vs_w )
{
if (!state)
{
// flash clock
if (m_flshclk_ctr & 0x20)
{
m_flshclk = !m_flshclk;
m_flshclk_ctr = 0;
}
else
{
m_flshclk_ctr++;
}
}
}
//-------------------------------------------------
// machine_config( abc802_video )
//-------------------------------------------------
void abc802_state::abc802_video(machine_config &config)
{
mc6845_device &mc6845(MC6845(config, MC6845_TAG, ABC800_CCLK));
mc6845.set_screen(SCREEN_TAG);
mc6845.set_show_border_area(true);
mc6845.set_char_width(ABC800_CHAR_WIDTH);
mc6845.set_update_row_callback(FUNC(abc802_state::abc802_update_row));
mc6845.out_vsync_callback().set(FUNC(abc802_state::vs_w));
mc6845.out_vsync_callback().append(m_dart, FUNC(z80dart_device::rib_w)).invert();
screen_device &screen(SCREEN(config, SCREEN_TAG, SCREEN_TYPE_RASTER, rgb_t::amber()));
screen.set_screen_update(MC6845_TAG, FUNC(mc6845_device::screen_update));
screen.set_raw(XTAL(12'000'000), 0x300, 0, 0x1e0, 0x13a, 0, 0xf0);
PALETTE(config, m_palette, palette_device::MONOCHROME);
}