vt100: Implement AVO attributes by merging with Rainbow video emulation

This commit is contained in:
AJR 2020-01-03 23:42:43 -05:00
parent 3969a9e9b5
commit d0fa593c1e
3 changed files with 26 additions and 104 deletions

View File

@ -119,9 +119,8 @@ void vt100_state::vt100_mem(address_map &map)
{
map.unmap_value_high();
map(0x0000, 0x1fff).rom(); // ROM ( 4 * 2K)
map(0x2000, 0x2bff).ram().share("p_ram"); // Screen and scratch RAM
map(0x2c00, 0x2fff).ram(); // AVO Screen RAM
map(0x3000, 0x3fff).ram(); // AVO Attribute RAM (4 bits wide)
map(0x2000, 0x3fff).ram().share("p_ram"); // Screen and scratch RAM
//map(0x3000, 0x3fff).ram(); // AVO Attribute RAM (4 bits wide)
// 0x4000, 0x7fff is unassigned
map(0x8000, 0x9fff).rom(); // Program memory expansion ROM (4 * 2K)
map(0xa000, 0xbfff).rom(); // Program memory expansion ROM (1 * 8K)

View File

@ -139,7 +139,9 @@ void vt100_video_device::device_start()
void vt100_video_device::device_reset()
{
m_palette->set_pen_color(0, 0x00, 0x00, 0x00); // black
m_palette->set_pen_color(1, 0xff, 0xff, 0xff); // white
m_palette->set_pen_color(1, 0xff - 100, 0xff - 100, 0xff - 100); // WHITE (dim)
m_palette->set_pen_color(2, 0xff - 50, 0xff - 50, 0xff - 50); // WHITE NORMAL
m_palette->set_pen_color(3, 0xff, 0xff, 0xff); // WHITE (brighter)
m_height = 25;
m_height_MAX = 25;
@ -363,80 +365,12 @@ WRITE8_MEMBER(vt100_video_device::brightness_w)
void vt100_video_device::display_char(bitmap_ind16 &bitmap, uint8_t code, int x, int y, uint8_t scroll_region, uint8_t display_type)
{
uint8_t line = 0;
int bit = 0, prevbit, invert = 0, j;
int double_width = (display_type == 2) ? 1 : 0;
int char_lines = m_linedoubler ? 20 : 10;
for (int i = 0; i < char_lines; i++)
{
int yy = y * char_lines + i;
assert(yy < bitmap.height());
switch (display_type)
{
case 0: // bottom half, double height
j = (i >> (m_linedoubler ? 2 : 1)) + 5; break;
case 1: // top half, double height
j = i >> (m_linedoubler ? 2 : 1); break;
case 2: // double width
case 3: // normal
j = i >> (m_linedoubler ? 1 : 0); break;
default: j = 0; break;
}
// modify line since that is how it is stored in rom
if (j == 0) j = 15; else j = j - 1;
line = m_char_rom[(code & 0x7f) * 16 + j];
if (m_basic_attribute == 1)
{
if ((code & 0x80) == 0x80)
invert = 1;
else
invert = 0;
}
for (int b = 0; b < 8; b++)
{
prevbit = bit;
bit = BIT((line << b), 7);
if (double_width)
{
bitmap.pix16(yy, x * 20 + b * 2) = (bit | prevbit) ^ invert;
bitmap.pix16(yy, x * 20 + b * 2 + 1) = bit ^ invert;
}
else
{
bitmap.pix16(yy, x * 10 + b) = (bit | prevbit) ^ invert;
}
}
prevbit = bit;
// char interleave is filled with last bit
if (double_width)
{
bitmap.pix16(yy, x * 20 + 16) = (bit | prevbit) ^ invert;
bitmap.pix16(yy, x * 20 + 17) = bit ^ invert;
bitmap.pix16(yy, x * 20 + 18) = bit ^ invert;
bitmap.pix16(yy, x * 20 + 19) = bit ^ invert;
}
else
{
bitmap.pix16(yy, x * 10 + 8) = (bit | prevbit) ^ invert;
bitmap.pix16(yy, x * 10 + 9) = bit ^ invert;
}
}
}
void vt100_video_device::video_update(bitmap_ind16 &bitmap, const rectangle &cliprect)
{
uint16_t addr = 0;
int line = 0;
int xpos = 0;
int ypos = 0;
uint8_t code;
int x = 0;
uint8_t scroll_region = 1; // binary 1
uint8_t display_type = 3; // binary 11
@ -454,24 +388,24 @@ void vt100_video_device::video_update(bitmap_ind16 &bitmap, const rectangle &cli
}
while (line < vert_charlines_MAX)
{
code = m_read_ram(addr + xpos);
uint8_t code = m_read_ram(addr + xpos);
if (code == 0x7f)
{
// end of line, fill empty till end of line
if (line >= fill_lines)
{
for (x = xpos; x < ((display_type == 2) ? (m_columns / 2) : m_columns); x++)
for (x = xpos; x < ((display_type != 3) ? (m_columns / 2) : m_columns); x++)
{
display_char(bitmap, code, x, ypos, scroll_region, display_type);
display_char(bitmap, code, x, ypos, scroll_region, display_type, false, false, false, false, false);
}
}
// move to new data
temp = m_read_ram(addr + xpos + 1) * 256 + m_read_ram(addr + xpos + 2);
addr = (temp)& 0x1fff;
// if A12 is 1 then it is 0x2000 block, if 0 then 0x4000 (AVO)
if (addr & 0x1000) addr &= 0xfff; else addr |= 0x2000;
// if A12 is 1 then it is 0x2000 block, if 0 then 0x4000 (AVO - not actually implemented?)
/*if (addr & 0x1000)*/ addr &= 0xfff; /*else addr |= 0x2000;*/
scroll_region = (temp >> 15) & 1;
display_type = (temp >> 13) & 3;
display_type = bitswap<2>((temp >> 13) & 3, 0, 1);
if (line >= fill_lines)
ypos++;
xpos = 0;
@ -484,7 +418,8 @@ void vt100_video_device::video_update(bitmap_ind16 &bitmap, const rectangle &cli
// display regular char
if (line >= fill_lines)
{
display_char(bitmap, code, xpos, ypos, scroll_region, display_type);
uint8_t attr = m_read_ram(0x1000 + addr + xpos);
display_char(bitmap, code & 0x7f, xpos, ypos, scroll_region, display_type, BIT(code, 7), !BIT(attr, 2), !BIT(attr, 0), !BIT(attr, 1), false);
}
xpos++;
if (xpos > m_columns)
@ -515,11 +450,11 @@ void vt100_video_device::video_update(bitmap_ind16 &bitmap, const rectangle &cli
// LINE ATTRIBUTE 'double_height' always is interpreted as 'double width + double height'
// ATTRIBUTES: No attributes = 0x0E
// 1 = display char. in REVERSE (encoded as 8 in display_type) HIGH ACTIVE
// 0 = display char. in BOLD (encoded as 16 in display_type) LOW ACTIVE
// 0 = display char. w. BLINK (encoded as 32 in display_type) LOW ACTIVE
// 0 = display char. w. UNDERLINE (encoded as 64 in display_type) LOW ACTIVE
void rainbow_video_device::display_char(bitmap_ind16 &bitmap, uint8_t code, int x, int y, uint8_t scroll_region, uint8_t display_type)
// 1 = display char. in REVERSE (encoded as 1 in attribute) HIGH ACTIVE
// 0 = display char. in BOLD (encoded as 2 in attribute) LOW ACTIVE
// 0 = display char. w. BLINK (encoded as 4 in attribute) LOW ACTIVE
// 0 = display char. w. UNDERLINE (encoded as 8 in attribute) LOW ACTIVE
void vt100_video_device::display_char(bitmap_ind16 &bitmap, uint8_t code, int x, int y, uint8_t scroll_region, uint8_t display_type, bool invert, bool bold, bool blink, bool underline, bool blank)
{
uint16_t x_preset = x << 3; // x_preset = x * 9 (= 132 column mode)
x_preset += x;
@ -540,12 +475,6 @@ void rainbow_video_device::display_char(bitmap_ind16 &bitmap, uint8_t code, int
int fg_intensity;
int back_intensity, back_default_intensity;
int invert = (display_type & 8) ? 1 : 0; // REVERSE
int bold = (display_type & 16) ? 0 : 1; // BIT 4
int blink = (display_type & 32) ? 0 : 1; // BIT 5
int underline = (display_type & 64) ? 0 : 1; // BIT 6
bool blank = (display_type & 128) ? true : false; // BIT 7
display_type = display_type & 3;
// * SCREEN ATTRIBUTES (see VT-180 manual 6-30) *
@ -746,17 +675,18 @@ void rainbow_video_device::video_update(bitmap_ind16 &bitmap, const rectangle &c
{
code = m_read_ram(addr + xpos);
bool force_blank;
if (code == 0x00) // TODO: investigate side effect on regular zero character!
display_type |= 0x80; // DEFAULT: filler chars (till end of line) and empty lines (00) will be blanked
force_blank = true; // DEFAULT: filler chars (till end of line) and empty lines (00) will be blanked
else
display_type &= 0x7f; // else activate display.
force_blank = false; // else activate display.
if (code == 0xff) // end of line, fill empty till end of line
{
// HINT: display_type is already shifted! All except 3 is DOUBLE WIDTH 40 or 66 chars per line
// All except 3 is DOUBLE WIDTH 40 or 66 chars per line
for (x = xpos; x < ((display_type != 3) ? (m_columns / 2) : m_columns); x++)
{
display_char(bitmap, code, x, ypos, scroll_region, display_type | 0x80);
display_char(bitmap, code, x, ypos, scroll_region, display_type, false, false, false, false, true);
}
// LINE ATTRIBUTE - valid for all chars on next line ** DO NOT SHUFFLE **
@ -783,10 +713,10 @@ void rainbow_video_device::video_update(bitmap_ind16 &bitmap, const rectangle &c
else
{
attr_addr = 0x1000 | ((addr + xpos) & 0x0fff);
temp = (m_read_ram(attr_addr) & 15) << 3; // get character attributes
temp = (m_read_ram(attr_addr) & 15); // get character attributes
// see 'display_char' for an explanation of attribute encoding -
display_char(bitmap, code, xpos, ypos, scroll_region, display_type | temp);
display_char(bitmap, code, xpos, ypos, scroll_region, display_type, BIT(temp, 0), !BIT(temp, 1), !BIT(temp, 2), !BIT(temp, 3), force_blank);
xpos++;
if (xpos > m_columns)
@ -918,11 +848,6 @@ TIMER_CALLBACK_MEMBER(vt100_video_device::lba3_change)
//-------------------------------------------------
void vt100_video_device::device_add_mconfig(machine_config &config)
{
PALETTE(config, m_palette, palette_device::MONOCHROME);
}
void rainbow_video_device::device_add_mconfig(machine_config &config)
{
PALETTE(config, m_palette).set_entries(4);
}

View File

@ -48,7 +48,7 @@ protected:
// internal state
void recompute_parameters();
void vblank_callback(screen_device &screen, bool state);
virtual void display_char(bitmap_ind16 &bitmap, uint8_t code, int x, int y, uint8_t scroll_region, uint8_t display_type);
void display_char(bitmap_ind16 &bitmap, uint8_t code, int x, int y, uint8_t scroll_region, uint8_t display_type, bool invert, bool bold, bool blink, bool underline, bool blank);
TIMER_CALLBACK_MEMBER(lba3_change);
TIMER_CALLBACK_MEMBER(lba7_change);
virtual void notify_vblank(bool choice) { }
@ -101,10 +101,8 @@ public:
void palette_select(int choice);
protected:
virtual void display_char(bitmap_ind16 &bitmap, uint8_t code, int x, int y, uint8_t scroll_region, uint8_t display_type) override;
virtual void notify_vblank(bool choice) override;
virtual void device_reset() override;
virtual void device_add_mconfig(machine_config &config) override;
};
DECLARE_DEVICE_TYPE(VT100_VIDEO, vt100_video_device)