summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/video/mc6845.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/video/mc6845.cpp')
-rw-r--r--src/devices/video/mc6845.cpp859
1 files changed, 244 insertions, 615 deletions
diff --git a/src/devices/video/mc6845.cpp b/src/devices/video/mc6845.cpp
index 84c8e6eeaab..8054b08a4f7 100644
--- a/src/devices/video/mc6845.cpp
+++ b/src/devices/video/mc6845.cpp
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol, Bartman/Abyss (HD6345)
+// copyright-holders:Wilbert Pol,Nigel Barnes
/**********************************************************************
Motorola MC6845 and compatible CRT controller emulation
@@ -31,12 +31,10 @@
is true
- Support 'interlace and video' mode
- - mos8563
-
- - horizontal scroll
- - vertical scroll
- - bitmap modes
- - display enable begin/end
+ - hd6345
+ - smooth scrolling
+ - second cursor
+ - interrupt request
*/
@@ -45,12 +43,12 @@
#include "screen.h"
-#define LOG_SETUP (1 << 1U)
-#define LOG_REGS (1 << 2U)
-#define LOG_CONF (1 << 3U)
+#define LOG_SETUP (1U << 1)
+#define LOG_REGS (1U << 2)
+#define LOG_CONF (1U << 3)
//#define VERBOSE (LOG_SETUP|LOG_CONF|LOG_REGS)
-//#define LOG_OUTPUT_STREAM std::cout
+//#define LOG_OUTPUT_FUNC osd_printf_info
#include "logmacro.h"
@@ -65,11 +63,8 @@ DEFINE_DEVICE_TYPE(C6545_1, c6545_1_device, "c6545_1", "C6545-1 CRTC")
DEFINE_DEVICE_TYPE(HD6845S, hd6845s_device, "hd6845s", "Hitachi HD6845S CRTC") // same as HD46505S
DEFINE_DEVICE_TYPE(SY6545_1, sy6545_1_device, "sy6545_1", "Synertek SY6545-1 CRTC")
DEFINE_DEVICE_TYPE(SY6845E, sy6845e_device, "sy6845e", "Synertek SY6845E CRTC")
-DEFINE_DEVICE_TYPE(HD6345, hd6345_device, "hd6345", "Hitachi HD6345 CRTC")
-DEFINE_DEVICE_TYPE(AMS40041, ams40041_device, "ams40041", "AMS40041 CRTC")
+DEFINE_DEVICE_TYPE(HD6345, hd6345_device, "hd6345", "Hitachi HD6345 CRTC-II")
DEFINE_DEVICE_TYPE(AMS40489, ams40489_device, "ams40489", "AMS40489 ASIC (CRTC)")
-DEFINE_DEVICE_TYPE(MOS8563, mos8563_device, "mos8563", "MOS 8563 VDC")
-DEFINE_DEVICE_TYPE(MOS8568, mos8568_device, "mos8568", "MOS 8568 VDC")
/* mode macros */
@@ -83,44 +78,29 @@ DEFINE_DEVICE_TYPE(MOS8568, mos8568_device, "mos8568", "MOS 8568 VDC")
#define MODE_ROW_COLUMN_ADDRESSING ((m_mode_control & 0x04) != 0)
#define MODE_INTERLACE_AND_VIDEO ((m_mode_control & 0x03) == 3)
-#define VSS_CBRATE BIT(m_vert_scroll, 5)
-#define VSS_RVS BIT(m_vert_scroll, 6)
-#define VSS_COPY BIT(m_vert_scroll, 7)
-
-#define HSS_DBL BIT(m_horiz_scroll, 4)
-#define HSS_SEMI BIT(m_horiz_scroll, 5)
-#define HSS_ATTR BIT(m_horiz_scroll, 6)
-#define HSS_TEXT BIT(m_horiz_scroll, 7)
-
-#define ATTR_COLOR (attr & 0x0f)
-#define ATTR_BACKGROUND (attr & 0x0f)
-#define ATTR_FOREGROUND (attr >> 4)
-#define ATTR_BLINK BIT(attr, 4)
-#define ATTR_UNDERLINE BIT(attr, 5)
-#define ATTR_REVERSE BIT(attr, 6)
-#define ATTR_ALTERNATE_CHARSET BIT(attr, 7)
-
mc6845_device::mc6845_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, type, tag, owner, clock),
- device_video_interface(mconfig, *this, false),
- m_show_border_area(true),
- m_interlace_adjust(0),
- m_clk_scale(1),
- m_visarea_adjust_min_x(0),
- m_visarea_adjust_max_x(0),
- m_visarea_adjust_min_y(0),
- m_visarea_adjust_max_y(0),
- m_hpixels_per_column(0),
- m_reconfigure_cb(*this),
- m_begin_update_cb(*this),
- m_update_row_cb(*this),
- m_end_update_cb(*this),
- m_on_update_addr_changed_cb(*this),
- m_out_de_cb(*this),
- m_out_cur_cb(*this),
- m_out_hsync_cb(*this),
- m_out_vsync_cb(*this)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_video_interface(mconfig, *this, false)
+ , m_line_timer(nullptr)
+ , m_show_border_area(true)
+ , m_noninterlace_adjust(0)
+ , m_interlace_adjust(0)
+ , m_clk_scale(1)
+ , m_visarea_adjust_min_x(0)
+ , m_visarea_adjust_max_x(0)
+ , m_visarea_adjust_min_y(0)
+ , m_visarea_adjust_max_y(0)
+ , m_hpixels_per_column(0)
+ , m_reconfigure_cb(*this)
+ , m_begin_update_cb(*this)
+ , m_update_row_cb(*this)
+ , m_end_update_cb(*this)
+ , m_on_update_addr_changed_cb(*this)
+ , m_out_de_cb(*this)
+ , m_out_cur_cb(*this)
+ , m_out_hsync_cb(*this)
+ , m_out_vsync_cb(*this)
{
}
@@ -185,7 +165,7 @@ void mc6845_device::transparent_update()
{
m_update_addr++;
m_update_addr &= 0x3fff;
- call_on_update_address(0);
+ call_on_update_address(MODE_UPDATE_STROBE);
}
else
{
@@ -210,6 +190,7 @@ uint8_t mc6845_device::register_r()
case 0x0d: ret = m_supports_disp_start_addr_r ? (m_disp_start_addr >> 0) & 0xff : 0; break;
case 0x0e: ret = (m_cursor_addr >> 8) & 0xff; break;
case 0x0f: ret = (m_cursor_addr >> 0) & 0xff; break;
+ // FIXME: status flag should not be reset if LPEN input is held high
case 0x10: ret = (m_light_pen_addr >> 8) & 0xff; m_light_pen_latched = false; break;
case 0x11: ret = (m_light_pen_addr >> 0) & 0xff; m_light_pen_latched = false; break;
case 0x1f: transparent_update(); break;
@@ -234,7 +215,7 @@ void mc6845_device::register_w(uint8_t data)
{{ "R0 - Horizontal Total", "R1 - Horizontal Displayed", "R2 - Horizontal Sync Position",
"R3 - Sync Width", "R4 - Vertical Total", "R5 - Vertical Total Adjust",
"R6 - Vertical Displayed", "R7 - Vertical Sync Position", "R8 - Interlace & Skew",
- "R9 - Maximum Raster Address", "R10 - Cursor Start Address", "R11 - Cursor End Address",
+ "R9 - Maximum Raster Address", "R10 - Cursor Start Raster", "R11 - Cursor End Raster",
"R12 - Start Address (H)", "R13 - Start Address (L)", "R14 - Cursor (H)",
"R15 - Cursor (L)" }}[(m_register_address_latch & 0x0f)]);
@@ -263,7 +244,7 @@ void mc6845_device::register_w(uint8_t data)
{
m_update_addr = ((data & 0x3f) << 8) | (m_update_addr & 0x00ff);
if(MODE_TRANSPARENT_PHI2)
- call_on_update_address(0);
+ call_on_update_address(MODE_UPDATE_STROBE);
}
break;
case 0x13:
@@ -271,7 +252,7 @@ void mc6845_device::register_w(uint8_t data)
{
m_update_addr = ((data & 0xff) << 0) | (m_update_addr & 0xff00);
if(MODE_TRANSPARENT_PHI2)
- call_on_update_address(0);
+ call_on_update_address(MODE_UPDATE_STROBE);
}
break;
case 0x1f: transparent_update(); break;
@@ -287,145 +268,6 @@ void mc6845_device::register_w(uint8_t data)
}
-void mos8563_device::address_w(uint8_t data)
-{
- m_register_address_latch = data & 0x3f;
-}
-
-
-uint8_t mos8563_device::status_r()
-{
- uint8_t ret = m_revision;
-
- /* VBLANK bit */
- if (!m_line_enable_ff)
- ret = ret | 0x20;
-
- /* light pen latched */
- if (m_light_pen_latched)
- ret = ret | 0x40;
-
- /* UPDATE ready */
- if (m_update_ready_bit)
- ret = ret | 0x80;
-
- return ret;
-}
-
-
-uint8_t mos8563_device::register_r()
-{
- uint8_t ret = 0xff;
-
- switch (m_register_address_latch)
- {
- case 0x00: ret = m_horiz_char_total; break;
- case 0x01: ret = m_horiz_disp; break;
- case 0x02: ret = m_horiz_sync_pos; break;
- case 0x03: ret = m_sync_width; break;
- case 0x04: ret = m_vert_char_total; break;
- case 0x05: ret = m_vert_total_adj | 0xc0; break;
- case 0x06: ret = m_vert_disp; break;
- case 0x07: ret = m_vert_sync_pos; break;
- case 0x08: ret = m_mode_control | 0xfc; break;
- case 0x09: ret = m_max_ras_addr | 0xe0; break;
- case 0x0a: ret = m_cursor_start_ras | 0x80; break;
- case 0x0b: ret = m_cursor_end_ras | 0xe0; break;
- case 0x0c: ret = (m_disp_start_addr >> 8) & 0xff; break;
- case 0x0d: ret = (m_disp_start_addr >> 0) & 0xff; break;
- case 0x0e: ret = (m_cursor_addr >> 8) & 0xff; break;
- case 0x0f: ret = (m_cursor_addr >> 0) & 0xff; break;
- case 0x10: ret = (m_light_pen_addr >> 8) & 0xff; m_light_pen_latched = false; break;
- case 0x11: ret = (m_light_pen_addr >> 0) & 0xff; m_light_pen_latched = false; break;
- case 0x12: ret = (m_update_addr >> 8) & 0xff; break;
- case 0x13: ret = (m_update_addr >> 0) & 0xff; break;
- case 0x14: ret = (m_attribute_addr >> 8) & 0xff; break;
- case 0x15: ret = (m_attribute_addr >> 0) & 0xff; break;
- case 0x16: ret = m_horiz_char; break;
- case 0x17: ret = m_vert_char_disp | 0xe0; break;
- case 0x18: ret = m_vert_scroll; break;
- case 0x19: ret = m_horiz_scroll; break;
- case 0x1a: ret = m_color; break;
- case 0x1b: ret = m_row_addr_incr; break;
- case 0x1c: ret = m_char_base_addr | 0x1f; break;
- case 0x1d: ret = m_underline_ras | 0xe0; break;
- case 0x1e: ret = m_word_count; break;
- case 0x1f: ret = read_videoram(m_update_addr++); break;
- case 0x20: ret = (m_block_addr >> 8) & 0xff; break;
- case 0x21: ret = (m_block_addr >> 0) & 0xff; break;
- case 0x22: ret = (m_de_begin >> 8) & 0xff; break;
- case 0x23: ret = (m_de_begin >> 0) & 0xff; break;
- case 0x24: ret = m_dram_refresh | 0xf0; break;
- case 0x25: ret = m_sync_polarity | 0x3f; break;
- }
-
- return ret;
-}
-
-
-void mos8563_device::register_w(uint8_t data)
-{
- LOGREGS("%s:MOS8563 reg 0x%02x = 0x%02x\n", machine().describe_context(), m_register_address_latch, data);
-
- switch (m_register_address_latch)
- {
- case 0x00: m_horiz_char_total = data & 0xff; break;
- case 0x01: m_horiz_disp = data & 0xff; break;
- case 0x02: m_horiz_sync_pos = data & 0xff; break;
- case 0x03: m_sync_width = data & 0xff; break;
- case 0x04: m_vert_char_total = data & 0xff; break;
- case 0x05: m_vert_total_adj = data & 0x1f; break;
- case 0x06: m_vert_disp = data & 0xff; break;
- case 0x07: m_vert_sync_pos = data & 0xff; break;
- case 0x08: m_mode_control = data & 0x03; break;
- case 0x09: m_max_ras_addr = data & 0x1f; break;
- case 0x0a: m_cursor_start_ras = data & 0x7f; break;
- case 0x0b: m_cursor_end_ras = data & 0x1f; break;
- case 0x0c: m_disp_start_addr = ((data & 0xff) << 8) | (m_disp_start_addr & 0x00ff); break;
- case 0x0d: m_disp_start_addr = ((data & 0xff) << 0) | (m_disp_start_addr & 0xff00); break;
- case 0x0e: m_cursor_addr = ((data & 0xff) << 8) | (m_cursor_addr & 0x00ff); break;
- case 0x0f: m_cursor_addr = ((data & 0xff) << 0) | (m_cursor_addr & 0xff00); break;
- case 0x10: /* read-only */ break;
- case 0x11: /* read-only */ break;
- case 0x12: m_update_addr = ((data & 0xff) << 8) | (m_update_addr & 0x00ff); break;
- case 0x13: m_update_addr = ((data & 0xff) << 0) | (m_update_addr & 0xff00); break;
- case 0x14: m_attribute_addr = ((data & 0xff) << 8) | (m_attribute_addr & 0x00ff); break;
- case 0x15: m_attribute_addr = ((data & 0xff) << 0) | (m_attribute_addr & 0xff00); break;
- case 0x16: m_horiz_char = data & 0xff; break;
- case 0x17: m_vert_char_disp = data & 0x1f; break;
- case 0x18: m_vert_scroll = data & 0xff; break;
- case 0x19:
- {
- int dbl = HSS_DBL;
- m_horiz_scroll = data & 0xff;
- if (dbl && !HSS_DBL) { m_clk_scale = 4; recompute_parameters(true); }
- if (!dbl && HSS_DBL) { m_clk_scale = 8; recompute_parameters(true); }
- break;
- }
- case 0x1a: m_color = data & 0xff; break;
- case 0x1b: m_row_addr_incr = data & 0xff; break;
- case 0x1c: m_char_base_addr = data & 0xe0; break;
- case 0x1d: m_underline_ras = data & 0x1f; break;
- case 0x1e:
- m_word_count = data & 0xff;
- m_update_ready_bit = 0;
- m_block_copy_timer->adjust(cclks_to_attotime(1));
- break;
- case 0x1f:
- m_data = data & 0xff;
- write_videoram(m_update_addr++, m_data);
- break;
- case 0x20: m_block_addr = ((data & 0xff) << 8) | (m_block_addr & 0x00ff); break;
- case 0x21: m_block_addr = ((data & 0xff) << 0) | (m_block_addr & 0xff00); break;
- case 0x22: m_de_begin = ((data & 0xff) << 8) | (m_de_begin & 0x00ff); break;
- case 0x23: m_de_begin = ((data & 0xff) << 0) | (m_de_begin & 0xff00); break;
- case 0x24: m_dram_refresh = data & 0x0f; break;
- case 0x25: m_sync_polarity = data & 0xc0; break;
- }
-
- recompute_parameters(false);
-}
-
void hd6345_device::address_w(uint8_t data)
{
m_register_address_latch = data & 0x3f;
@@ -434,17 +276,34 @@ void hd6345_device::address_w(uint8_t data)
uint8_t hd6345_device::register_r()
{
- uint8_t ret = 0xff;
+ uint8_t ret = 0;
switch (m_register_address_latch)
{
- case 0x0c: ret = m_supports_disp_start_addr_r ? (m_disp_start_addr >> 8) & 0xff : 0; break;
- case 0x0d: ret = m_supports_disp_start_addr_r ? (m_disp_start_addr >> 0) & 0xff : 0; break;
- case 0x0e: ret = (m_cursor_addr >> 8) & 0xff; break;
- case 0x0f: ret = (m_cursor_addr >> 0) & 0xff; break;
- case 0x10: ret = (m_light_pen_addr >> 8) & 0xff; m_light_pen_latched = false; break;
- case 0x11: ret = (m_light_pen_addr >> 0) & 0xff; m_light_pen_latched = false; break;
- // TODO: REST
+ case 0x0c: ret = (m_disp_start_addr >> 8) & 0xff; break;
+ case 0x0d: ret = (m_disp_start_addr >> 0) & 0xff; break;
+ case 0x0e: ret = (m_cursor_addr >> 8) & 0xff; break;
+ case 0x0f: ret = (m_cursor_addr >> 0) & 0xff; break;
+ case 0x10: ret = (m_light_pen_addr >> 8) & 0xff; m_light_pen_latched = false; break;
+ case 0x11: ret = (m_light_pen_addr >> 0) & 0xff; m_light_pen_latched = false; break;
+ case 0x12: ret = m_disp2_pos; break;
+ case 0x13: ret = (m_disp2_start_addr >> 8) & 0xff; break;
+ case 0x14: ret = (m_disp2_start_addr >> 0) & 0xff; break;
+ case 0x15: ret = m_disp3_pos; break;
+ case 0x16: ret = (m_disp3_start_addr >> 8) & 0xff; break;
+ case 0x17: ret = (m_disp3_start_addr >> 0) & 0xff; break;
+ case 0x18: ret = m_disp4_pos; break;
+ case 0x19: ret = (m_disp4_start_addr >> 8) & 0xff; break;
+ case 0x1a: ret = (m_disp4_start_addr >> 0) & 0xff; break;
+ case 0x1b: ret = m_vert_sync_pos_adj; break;
+ case 0x1c: /* TODO: light pen raster */ break;
+ case 0x1d: ret = m_smooth_scroll_ras; break;
+ case 0x1f: /* TODO: status */ break;
+ case 0x21: ret = m_mem_width_offs; break;
+ case 0x24: ret = (m_cursor2_addr >> 8) & 0xff; break;
+ case 0x25: ret = (m_cursor2_addr >> 0) & 0xff; break;
+ case 0x26: ret = m_cursor_width; break;
+ case 0x27: ret = m_cursor2_width; break;
}
return ret;
@@ -454,6 +313,26 @@ void hd6345_device::register_w(uint8_t data)
{
LOGREGS("%s:HD6345 reg 0x%02x = 0x%02x\n", machine().describe_context(), m_register_address_latch, data);
+ /* Omits LOGSETUP logs of cursor registers as they tend to be spammy */
+ if (m_register_address_latch < 0x28 &&
+ m_register_address_latch != 0x0a && m_register_address_latch != 0x0a &&
+ m_register_address_latch != 0x0e && m_register_address_latch != 0x0f)
+ LOGSETUP(" * %02x <= %3u [%02x] %s\n", m_register_address_latch, data, data, std::array<char const *, 40>
+ {{ "R0 - Horizontal Total", "R1 - Horizontal Displayed", "R2 - Horizontal Sync Position",
+ "R3 - Sync Width", "R4 - Vertical Total", "R5 - Vertical Total Adjust",
+ "R6 - Vertical Displayed", "R7 - Vertical Sync Position", "R8 - Interlace Mode & Skew",
+ "R9 - Maximum Raster Address", "R10 - Cursor 1 Start", "R11 - Cursor 1 End",
+ "R12 - Screen 1 Start Address (H)", "R13 - Screen 1 Start Address (L)", "R14 - Cursor 1 Address (H)",
+ "R15 - Cursor 1 Address (L)", "R16 - Light Pen (H)", "R17 - Light Pen (L)",
+ "R18 - Screen 2 Start Position", "R19 - Screen 2 Start Address (H)", "R20 - Screen 2 Start Address (L)",
+ "R21 - Screen 3 Start Position", "R22 - Screen 3 Start Address (H)", "R23 - Screen 3 Start Address (L)",
+ "R24 - Screen 4 Start Position", "R25 - Screen 4 Start Address (H)", "R26 - Screen 4 Start Address (L)",
+ "R27 - Vertical Sync Position Adj", "R28 - Light Pen Raster", "R29 - Smooth Scrolling",
+ "R30 - Control 1", "R31 - Control 2", "R32 - Control 3",
+ "R33 - Memory Width Offset", "R34 - Cursor 2 Start", "R35 - Cursor 2 End",
+ "R36 - Cursor 2 Address (H)", "R37 - Cursor 2 Address (L)", "R38 - Cursor 1 Width",
+ "R39 - Cursor 2 Width" }}[(m_register_address_latch & 0x3f)]);
+
switch (m_register_address_latch)
{
case 0x00: m_horiz_char_total = data & 0xff; break;
@@ -464,7 +343,7 @@ void hd6345_device::register_w(uint8_t data)
case 0x05: m_vert_total_adj = data & 0x1f; break;
case 0x06: m_vert_disp = data & 0xff; break;
case 0x07: m_vert_sync_pos = data & 0xff; break;
- case 0x08: m_mode_control = data & 0xff; break;
+ case 0x08: m_mode_control = data & 0xf3; break;
case 0x09: m_max_ras_addr = data & 0x1f; break;
case 0x0a: m_cursor_start_ras = data & 0x7f; break;
case 0x0b: m_cursor_end_ras = data & 0x1f; break;
@@ -474,43 +353,53 @@ void hd6345_device::register_w(uint8_t data)
case 0x0f: m_cursor_addr = ((data & 0xff) << 0) | (m_cursor_addr & 0xff00); break;
case 0x10: /* read-only */ break;
case 0x11: /* read-only */ break;
- // TODO: rest
+ case 0x12: m_disp2_pos = data & 0xff; break;
+ case 0x13: m_disp2_start_addr = ((data & 0x3f) << 8) | (m_disp2_start_addr & 0x00ff); break;
+ case 0x14: m_disp2_start_addr = ((data & 0xff) << 0) | (m_disp2_start_addr & 0xff00); break;
+ case 0x15: m_disp3_pos = data & 0xff; break;
+ case 0x16: m_disp3_start_addr = ((data & 0x3f) << 8) | (m_disp3_start_addr & 0x00ff); break;
+ case 0x17: m_disp3_start_addr = ((data & 0xff) << 0) | (m_disp3_start_addr & 0xff00); break;
+ case 0x18: m_disp4_pos = data & 0xff; break;
+ case 0x19: m_disp4_start_addr = ((data & 0x3f) << 8) | (m_disp4_start_addr & 0x00ff); break;
+ case 0x1a: m_disp4_start_addr = ((data & 0xff) << 0) | (m_disp4_start_addr & 0xff00); break;
+ case 0x1b: m_vert_sync_pos_adj = data & 0x1f; break;
+ case 0x1c: /* read-only */ break;
+ case 0x1d: m_smooth_scroll_ras = data & 0x1f; break;
+ case 0x1e: m_control1 = data & 0xff; break;
+ case 0x1f: m_control2 = data & 0xf8; break;
+ case 0x20: m_control3 = data & 0xfe; break;
+ case 0x21: m_mem_width_offs = data & 0xff; break;
+ case 0x22: m_cursor2_start_ras = data & 0x7f; break;
+ case 0x23: m_cursor2_end_ras = data & 0x1f; break;
+ case 0x24: m_cursor2_addr = ((data & 0x3f) << 8) | (m_cursor2_addr & 0x00ff); break;
+ case 0x25: m_cursor2_addr = ((data & 0xff) << 0) | (m_cursor2_addr & 0xff00); break;
+ case 0x26: m_cursor_width = data & 0xff; break;
+ case 0x27: m_cursor2_width = data & 0xff; break;
}
recompute_parameters(false);
}
-inline uint8_t mos8563_device::read_videoram(offs_t offset)
-{
- return space(0).read_byte(offset);
-}
-
-inline void mos8563_device::write_videoram(offs_t offset, uint8_t data)
-{
- space(0).write_byte(offset, data);
-}
-
-
-READ_LINE_MEMBER( mc6845_device::de_r )
+int mc6845_device::de_r()
{
return m_de;
}
-READ_LINE_MEMBER( mc6845_device::cursor_r )
+int mc6845_device::cursor_r()
{
return m_cur;
}
-READ_LINE_MEMBER( mc6845_device::hsync_r )
+int mc6845_device::hsync_r()
{
return m_hsync;
}
-READ_LINE_MEMBER( mc6845_device::vsync_r )
+int mc6845_device::vsync_r()
{
return m_vsync;
}
@@ -616,6 +505,10 @@ void mc6845_device::recompute_parameters(bool postload)
m_hsync_off_pos = hsync_off_pos;
m_vsync_on_pos = vsync_on_pos;
m_vsync_off_pos = vsync_off_pos;
+ if (m_line_timer && !m_line_timer->enabled() && m_has_valid_parameters)
+ {
+ m_line_timer->adjust(cclks_to_attotime(m_horiz_char_total + 1));
+ }
if ( (!m_reconfigure_cb.isnull()) && (!postload) )
m_line_counter = 0;
}
@@ -780,7 +673,7 @@ bool hd6845s_device::check_cursor_visible(uint16_t ra, uint16_t line_addr)
}
-void mc6845_device::handle_line_timer()
+TIMER_CALLBACK_MEMBER(mc6845_device::handle_line_timer)
{
bool new_vsync = m_vsync;
@@ -869,7 +762,7 @@ void mc6845_device::handle_line_timer()
m_cursor_x = m_cursor_addr - m_line_address;
/* Schedule CURSOR ON signal */
- m_cur_on_timer->adjust(cclks_to_attotime(m_cursor_x));
+ m_cursor_on_timer->adjust(cclks_to_attotime(m_cursor_x));
}
}
@@ -885,99 +778,65 @@ void mc6845_device::handle_line_timer()
}
-void mc6845_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(mc6845_device::de_off_tick)
{
- switch (id)
- {
- case TIMER_LINE:
- handle_line_timer();
- break;
-
- case TIMER_DE_OFF:
- set_de( false );
- break;
-
- case TIMER_CUR_ON:
- set_cur( true );
-
- /* Schedule CURSOR off signal */
- m_cur_off_timer->adjust(cclks_to_attotime(1));
- break;
-
- case TIMER_CUR_OFF:
- set_cur( false );
- break;
-
- case TIMER_HSYNC_ON:
- {
- uint8_t hsync_width = ( m_sync_width & 0x0f ) ? ( m_sync_width & 0x0f ) : 0x10;
-
- m_hsync_width_counter = 0;
- set_hsync( true );
+ set_de( false );
+}
- /* Schedule HSYNC off signal */
- m_hsync_off_timer->adjust(cclks_to_attotime(hsync_width));
- }
- break;
+TIMER_CALLBACK_MEMBER(mc6845_device::cursor_on)
+{
+ set_cur(true);
- case TIMER_HSYNC_OFF:
- set_hsync( false );
- break;
+ /* Schedule CURSOR off signal */
+ m_cursor_off_timer->adjust(cclks_to_attotime(1));
+}
- case TIMER_LIGHT_PEN_LATCH:
- m_light_pen_addr = get_ma();
- m_light_pen_latched = true;
- break;
+TIMER_CALLBACK_MEMBER(mc6845_device::cursor_off)
+{
+ set_cur(false);
+}
- case TIMER_UPD_ADR:
- /* fire a update address strobe */
- call_on_update_address(0);
- break;
+TIMER_CALLBACK_MEMBER(mc6845_device::hsync_on)
+{
+ uint8_t hsync_width = ( m_sync_width & 0x0f ) ? ( m_sync_width & 0x0f ) : 0x10;
- case TIMER_UPD_TRANS:
- {
- int addr = (param >> 8);
- int strobe = (param & 0xff);
+ m_hsync_width_counter = 0;
+ set_hsync( true );
- /* call the callback function -- we know it exists */
- m_on_update_addr_changed_cb(addr, strobe);
+ /* Schedule HSYNC off signal */
+ m_hsync_off_timer->adjust(cclks_to_attotime(hsync_width));
+}
- if(!m_update_ready_bit && MODE_TRANSPARENT_BLANK)
- {
- m_update_addr++;
- m_update_addr &= 0x3fff;
- m_update_ready_bit = true;
- }
- }
- break;
+TIMER_CALLBACK_MEMBER(mc6845_device::hsync_off)
+{
+ set_hsync( false );
+}
- }
+TIMER_CALLBACK_MEMBER(mc6845_device::latch_light_pen)
+{
+ m_light_pen_addr = get_ma();
+ m_light_pen_latched = true;
}
+TIMER_CALLBACK_MEMBER(mc6845_device::adr_update_tick)
+{
+ /* fire a update address strobe */
+ call_on_update_address(MODE_UPDATE_STROBE);
+}
-void mos8563_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(mc6845_device::transparent_update_tick)
{
- switch (id)
- {
- case TIMER_BLOCK_COPY:
- {
- uint8_t data = VSS_COPY ? read_videoram(m_block_addr++) : m_data;
+ int addr = (param >> 8);
+ int strobe = (param & 0xff);
- write_videoram(m_update_addr++, data);
+ /* call the callback function -- we know it exists */
+ m_on_update_addr_changed_cb(addr, strobe);
- if (--m_word_count)
- {
- m_block_copy_timer->adjust(cclks_to_attotime(1));
- }
- else
- {
- m_update_ready_bit = 1;
- }
- break;
- }
- default:
- mc6845_device::device_timer(timer, id, param, ptr);
- break;
+ if(!m_update_ready_bit && MODE_TRANSPARENT_BLANK)
+ {
+ m_update_addr++;
+ m_update_addr &= 0x3fff;
+ m_update_ready_bit = true;
}
}
@@ -1004,6 +863,14 @@ void mc6845_device::assert_light_pen_input()
}
+// Microbee requires precise supplied light-pen address
+void mc6845_device::assert_light_pen_input(u16 ma)
+{
+ m_light_pen_addr = ma;
+ m_light_pen_latched = true;
+}
+
+
void mc6845_device::set_hpixels_per_column(int hpixels_per_column)
{
/* validate arguments */
@@ -1060,7 +927,7 @@ uint8_t mc6845_device::draw_scanline(int y, bitmap_rgb32 &bitmap, const rectangl
// is in units of characters and is relative to the start of the
// displayable area, not relative to the screen bitmap origin.
int8_t cursor_x = cursor_visible ? (m_cursor_addr - m_current_disp_addr) : -1;
- int de = (y < m_max_visible_y) ? 1 : 0;
+ int de = (y <= m_max_visible_y) ? 1 : 0;
int vbp = m_vert_pix_total - m_vsync_off_pos;
if (vbp < 0) vbp = 0;
int hbp = m_horiz_pix_total - m_hsync_off_pos;
@@ -1088,14 +955,32 @@ uint8_t mc6845_device::draw_scanline(int y, bitmap_rgb32 &bitmap, const rectangl
}
+uint8_t hd6345_device::draw_scanline(int y, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ uint8_t ra = hd6845s_device::draw_scanline(y, bitmap, cliprect);
+
+ /* update MA for screen split */
+ if (ra == m_max_ras_addr + (MODE_INTERLACE_AND_VIDEO ? m_interlace_adjust : m_noninterlace_adjust) - 1)
+ {
+ int y_pos = y / (m_max_ras_addr + (MODE_INTERLACE_AND_VIDEO ? m_interlace_adjust : m_noninterlace_adjust));
+ if ((m_control1 & 0x03) > 0 && y_pos == m_disp2_pos && m_disp2_pos != m_disp3_pos && m_disp2_pos != m_disp4_pos)
+ m_current_disp_addr = m_disp2_start_addr;
+ if ((m_control1 & 0x03) > 1 && y_pos == m_disp3_pos && m_disp3_pos != m_disp2_pos && m_disp3_pos != m_disp4_pos)
+ m_current_disp_addr = m_disp3_start_addr;
+ if ((m_control1 & 0x03) > 2 && y_pos == m_disp4_pos && m_disp4_pos != m_disp2_pos && m_disp4_pos != m_disp3_pos)
+ m_current_disp_addr = m_disp4_start_addr;
+ }
+
+ return ra;
+}
+
+
uint32_t mc6845_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
assert(bitmap.valid());
if (m_has_valid_parameters)
{
- assert(!m_update_row_cb.isnull());
-
if (m_display_disabled_msg_shown == true)
{
logerror("M6845: Valid screen parameters - display reenabled!!!\n");
@@ -1103,8 +988,7 @@ uint32_t mc6845_device::screen_update(screen_device &screen, bitmap_rgb32 &bitma
}
/* call the set up function if any */
- if (!m_begin_update_cb.isnull())
- m_begin_update_cb(bitmap, cliprect);
+ m_begin_update_cb(bitmap, cliprect);
if (cliprect.min_y == 0)
{
@@ -1113,14 +997,13 @@ uint32_t mc6845_device::screen_update(screen_device &screen, bitmap_rgb32 &bitma
}
/* for each row in the visible region */
- for (uint16_t y = cliprect.min_y; y <= cliprect.max_y && y <= m_max_visible_y; y++)
+ for (uint16_t y = cliprect.min_y; y <= cliprect.max_y; y++)
{
this->draw_scanline(y, bitmap, cliprect);
}
/* call the tear down function if any */
- if (!m_end_update_cb.isnull())
- m_end_update_cb(bitmap, cliprect);
+ m_end_update_cb(bitmap, cliprect);
}
else
{
@@ -1142,32 +1025,27 @@ void mc6845_device::device_start()
/* bind delegates */
m_reconfigure_cb.resolve();
- m_begin_update_cb.resolve();
- m_update_row_cb.resolve();
- m_end_update_cb.resolve();
+ m_begin_update_cb.resolve_safe();
+ m_update_row_cb.resolve_safe();
+ m_end_update_cb.resolve_safe();
m_on_update_addr_changed_cb.resolve();
- /* resolve callbacks */
- m_out_de_cb.resolve_safe();
- m_out_cur_cb.resolve_safe();
- m_out_hsync_cb.resolve_safe();
- m_out_vsync_cb.resolve_safe();
-
/* create the timers */
- m_line_timer = timer_alloc(TIMER_LINE);
- m_de_off_timer = timer_alloc(TIMER_DE_OFF);
- m_cur_on_timer = timer_alloc(TIMER_CUR_ON);
- m_cur_off_timer = timer_alloc(TIMER_CUR_OFF);
- m_hsync_on_timer = timer_alloc(TIMER_HSYNC_ON);
- m_hsync_off_timer = timer_alloc(TIMER_HSYNC_OFF);
- m_light_pen_latch_timer = timer_alloc(TIMER_LIGHT_PEN_LATCH);
- m_upd_adr_timer = timer_alloc(TIMER_UPD_ADR);
- m_upd_trans_timer = timer_alloc(TIMER_UPD_TRANS);
+ m_line_timer = timer_alloc(FUNC(mc6845_device::handle_line_timer), this);
+ m_de_off_timer = timer_alloc(FUNC(mc6845_device::de_off_tick), this);
+ m_cursor_on_timer = timer_alloc(FUNC(mc6845_device::cursor_on), this);
+ m_cursor_off_timer = timer_alloc(FUNC(mc6845_device::cursor_off), this);
+ m_hsync_on_timer = timer_alloc(FUNC(mc6845_device::hsync_on), this);
+ m_hsync_off_timer = timer_alloc(FUNC(mc6845_device::hsync_off), this);
+ m_light_pen_latch_timer = timer_alloc(FUNC(mc6845_device::latch_light_pen), this);
+ m_upd_adr_timer = timer_alloc(FUNC(mc6845_device::adr_update_tick), this);
+ m_upd_trans_timer = timer_alloc(FUNC(mc6845_device::transparent_update_tick), this);
/* Use some large startup values */
m_horiz_char_total = 0xff;
m_max_ras_addr = 0x1f;
m_vert_char_total = 0x7f;
+ m_mode_control = 0x00;
m_supports_disp_start_addr_r = false; // MC6845 can not read Display Start (double checked on datasheet)
m_supports_vert_sync_width = false;
@@ -1338,37 +1216,41 @@ void hd6345_device::device_start()
{
hd6845s_device::device_start();
- m_supports_disp_start_addr_r = true;
- m_supports_vert_sync_width = true;
- m_supports_status_reg_d5 = true;
- m_supports_status_reg_d6 = true;
- m_supports_status_reg_d7 = true;
- //m_supports_transparent = true;
+ m_disp2_pos = 0;
+ m_disp3_pos = 0;
+ m_disp4_pos = 0;
+ m_disp2_start_addr = 0;
+ m_disp3_start_addr = 0;
+ m_disp4_start_addr = 0;
+ m_vert_sync_pos_adj = 0;
+ m_smooth_scroll_ras = 0;
+ m_mem_width_offs = 0;
+ m_cursor2_start_ras = 0;
+ m_cursor2_end_ras = 0;
+ m_cursor2_addr = 0;
+ m_cursor_width = 0;
+ m_cursor2_width = 0;
+
+ save_item(NAME(m_disp2_pos));
+ save_item(NAME(m_disp2_start_addr));
+ save_item(NAME(m_disp3_pos));
+ save_item(NAME(m_disp3_start_addr));
+ save_item(NAME(m_disp4_pos));
+ save_item(NAME(m_disp4_start_addr));
+ save_item(NAME(m_vert_sync_pos_adj));
+ save_item(NAME(m_smooth_scroll_ras));
+ save_item(NAME(m_control1));
+ save_item(NAME(m_control2));
+ save_item(NAME(m_control3));
+ save_item(NAME(m_mem_width_offs));
+ save_item(NAME(m_cursor2_start_ras));
+ save_item(NAME(m_cursor2_end_ras));
+ save_item(NAME(m_cursor2_addr));
+ save_item(NAME(m_cursor_width));
+ save_item(NAME(m_cursor2_width));
}
-void ams40041_device::device_start()
-{
- mc6845_device::device_start();
-
- m_horiz_char_total = 113;
- m_horiz_disp = 80;
- m_horiz_sync_pos = 90;
- m_sync_width = 10;
- m_vert_char_total = 127;
- m_vert_total_adj = 6;
- m_vert_disp = 100;
- m_vert_sync_pos = 112;
- m_mode_control = 2;
-
- m_supports_disp_start_addr_r = false;
- m_supports_vert_sync_width = false;
- m_supports_status_reg_d5 = false;
- m_supports_status_reg_d6 = false;
- m_supports_status_reg_d7 = false;
- m_supports_transparent = false;
-}
-
void ams40489_device::device_start()
{
mc6845_device::device_start();
@@ -1382,96 +1264,6 @@ void ams40489_device::device_start()
}
-void mos8563_device::device_start()
-{
- mc6845_device::device_start();
-
- /* create the timers */
- m_block_copy_timer = timer_alloc(TIMER_BLOCK_COPY);
-
- m_supports_status_reg_d5 = true;
- m_supports_status_reg_d6 = true;
- m_supports_status_reg_d7 = true;
- m_update_ready_bit = 1;
-
- // default update_row delegate
- m_update_row_cb.set(*this, FUNC(mos8563_device::vdc_update_row));
-
- m_char_blink_state = false;
- m_char_blink_count = 0;
- m_attribute_addr = 0;
- m_horiz_char = 0;
- m_vert_char_disp = 0;
- m_vert_scroll = 0;
- m_horiz_scroll = 0;
- m_color = 0;
- m_row_addr_incr = 0;
- m_char_base_addr = 0;
- m_underline_ras = 0;
- m_word_count = 0;
- m_data = 0;
- m_block_addr = 0;
- m_de_begin = 0;
- m_dram_refresh = 0;
- m_sync_polarity = 0;
-
- m_revision = 1;
-
- // initialize video RAM
- uint8_t data = 0xff;
-
- for (offs_t offset = 0; offset < 0x10000; offset++)
- {
- write_videoram(offset, data);
- data ^= 0xff;
- }
-
- // VICE palette
- set_pen_color(0, rgb_t::black());
- set_pen_color(1, rgb_t(0x55, 0x55, 0x55));
- set_pen_color(2, rgb_t(0x00, 0x00, 0xaa));
- set_pen_color(3, rgb_t(0x55, 0x55, 0xff));
- set_pen_color(4, rgb_t(0x00, 0xaa, 0x00));
- set_pen_color(5, rgb_t(0x55, 0xff, 0x55));
- set_pen_color(6, rgb_t(0x00, 0xaa, 0xaa));
- set_pen_color(7, rgb_t(0x55, 0xff, 0xff));
- set_pen_color(8, rgb_t(0xaa, 0x00, 0x00));
- set_pen_color(9, rgb_t(0xff, 0x55, 0x55));
- set_pen_color(10, rgb_t(0xaa, 0x00, 0xaa));
- set_pen_color(11, rgb_t(0xff, 0x55, 0xff));
- set_pen_color(12, rgb_t(0xaa, 0x55, 0x00));
- set_pen_color(13, rgb_t(0xff, 0xff, 0x55));
- set_pen_color(14, rgb_t(0xaa, 0xaa, 0xaa));
- set_pen_color(15, rgb_t::white());
-
- save_item(NAME(m_char_buffer));
- save_item(NAME(m_attr_buffer));
- save_item(NAME(m_attribute_addr));
- save_item(NAME(m_horiz_char));
- save_item(NAME(m_vert_char_disp));
- save_item(NAME(m_vert_scroll));
- save_item(NAME(m_horiz_scroll));
- save_item(NAME(m_color));
- save_item(NAME(m_row_addr_incr));
- save_item(NAME(m_char_base_addr));
- save_item(NAME(m_underline_ras));
- save_item(NAME(m_word_count));
- save_item(NAME(m_data));
- save_item(NAME(m_block_addr));
- save_item(NAME(m_de_begin));
- save_item(NAME(m_dram_refresh));
- save_item(NAME(m_sync_polarity));
- save_item(NAME(m_revision));
- save_item(NAME(m_clk_scale));
-}
-
-
-void mos8568_device::device_start()
-{
- mos8563_device::device_start();
-}
-
-
void mc6845_device::device_reset()
{
/* internal registers other than status remain unchanged, all outputs go low */
@@ -1481,8 +1273,10 @@ void mc6845_device::device_reset()
m_out_vsync_cb(false);
- if (!m_line_timer->enabled())
+ if (!m_line_timer->enabled() && m_has_valid_parameters)
+ {
m_line_timer->adjust(cclks_to_attotime(m_horiz_char_total + 1));
+ }
m_light_pen_latched = false;
@@ -1503,38 +1297,17 @@ void hd6845s_device::device_reset() { mc6845_device::device_reset(); }
void c6545_1_device::device_reset() { mc6845_device::device_reset(); }
void sy6545_1_device::device_reset() { mc6845_device::device_reset(); }
void sy6845e_device::device_reset() { mc6845_device::device_reset(); }
-void hd6345_device::device_reset() { mc6845_device::device_reset(); }
-void ams40041_device::device_reset() { mc6845_device::device_reset(); }
-void ams40489_device::device_reset() { mc6845_device::device_reset(); }
-void mos8563_device::device_reset()
+void hd6345_device::device_reset()
{
- mc6845_device::device_reset();
-
- m_sync_polarity = 0xc0;
-}
+ hd6845s_device::device_reset();
-void mos8568_device::device_reset() { mos8563_device::device_reset(); }
-
-
-//-------------------------------------------------
-// memory_space_config - return a description of
-// any address spaces owned by this device
-//-------------------------------------------------
-
-device_memory_interface::space_config_vector mos8563_device::memory_space_config() const
-{
- return space_config_vector {
- std::make_pair(0, &m_videoram_space_config),
- };
+ m_control1 = 0;
+ m_control2 = 0;
+ m_control3 = 0;
}
-// default address maps
-void mos8563_device::mos8563_videoram_map(address_map &map)
-{
- if (!has_configured_map(0))
- map(0x0000, 0xffff).ram();
-}
+void ams40489_device::device_reset() { mc6845_device::device_reset(); }
r6545_1_device::r6545_1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
@@ -1585,151 +1358,7 @@ hd6345_device::hd6345_device(const machine_config &mconfig, const char *tag, dev
}
-ams40041_device::ams40041_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mc6845_device(mconfig, AMS40041, tag, owner, clock)
-{
-}
-
ams40489_device::ams40489_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: mc6845_device(mconfig, AMS40489, tag, owner, clock)
{
}
-
-
-mos8563_device::mos8563_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : mc6845_device(mconfig, type, tag, owner, clock),
- device_memory_interface(mconfig, *this),
- device_palette_interface(mconfig, *this),
- m_videoram_space_config("videoram", ENDIANNESS_LITTLE, 8, 16, 0, address_map_constructor(FUNC(mos8563_device::mos8563_videoram_map), this))
-{
- m_clk_scale = 8;
-}
-
-
-mos8563_device::mos8563_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mos8563_device(mconfig, MOS8563, tag, owner, clock)
-{
-}
-
-
-mos8568_device::mos8568_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mos8563_device(mconfig, MOS8568, tag, owner, clock)
-{
-}
-
-
-void mos8563_device::update_cursor_state()
-{
- mc6845_device::update_cursor_state();
-
- /* save and increment character blink counter */
- uint8_t last_char_blink_count = m_char_blink_count;
- m_char_blink_count++;
-
- /* switch on character blinking mode */
- if (VSS_CBRATE)
- {
- if ((last_char_blink_count & 0x20) != (m_char_blink_count & 0x20))
- m_char_blink_state = !m_char_blink_state;
- }
- else
- {
- if ((last_char_blink_count & 0x10) != (m_char_blink_count & 0x10))
- m_char_blink_state = !m_char_blink_state;
- }
-}
-
-
-uint8_t mos8563_device::draw_scanline(int y, bitmap_rgb32 &bitmap, const rectangle &cliprect)
-{
- uint8_t ra = mc6845_device::draw_scanline(y, bitmap, cliprect);
-
- if (ra == m_max_ras_addr)
- m_current_disp_addr = (m_current_disp_addr + m_row_addr_incr) & 0x3fff;
-
- return ra;
-}
-
-
-MC6845_UPDATE_ROW( mos8563_device::vdc_update_row )
-{
- ra += (m_vert_scroll & 0x0f);
- ra &= 0x0f;
-
- uint8_t cth = (m_horiz_char >> 4) + (HSS_DBL ? 0 : 1);
- uint8_t cdh = (m_horiz_char & 0x0f) + (HSS_DBL ? 0 : 1);
- uint8_t cdv = m_vert_char_disp;
-
- for (int column = 0; column < x_count; column++)
- {
- uint8_t code = read_videoram(ma + column);
- uint8_t attr = 0;
-
- int fg = m_color >> 4;
- int bg = m_color & 0x0f;
-
- if (HSS_ATTR)
- {
- offs_t attr_addr = m_attribute_addr + ma + column;
- attr = read_videoram(attr_addr);
- }
-
- if (HSS_TEXT)
- {
- if (HSS_ATTR)
- {
- fg = ATTR_FOREGROUND;
- bg = ATTR_BACKGROUND;
- }
-
- if (VSS_RVS) code ^= 0xff;
-
- for (int bit = 0; bit < cdh; bit++)
- {
- int x = (m_horiz_scroll & 0x0f) - cth + (column * cth) + bit;
- if (x < 0) x = 0;
- int color = BIT(code, 7) ? fg : bg;
-
- bitmap.pix32(vbp + y, hbp + x) = pen(de ? color : 0);
- }
- }
- else
- {
- if (HSS_ATTR)
- {
- fg = ATTR_COLOR;
- }
-
- offs_t font_addr;
-
- if (m_max_ras_addr < 16)
- {
- font_addr = ((m_char_base_addr & 0xe0) << 8) | (ATTR_ALTERNATE_CHARSET << 12) | (code << 4) | (ra & 0x0f);
- }
- else
- {
- font_addr = ((m_char_base_addr & 0xc0) << 8) | (ATTR_ALTERNATE_CHARSET << 13) | (code << 5) | (ra & 0x1f);
- }
-
- uint8_t data = read_videoram(font_addr);
-
- if (ra >= cdv) data = 0;
- if (ATTR_UNDERLINE && (ra == m_underline_ras)) data = 0xff;
- if (ATTR_BLINK && !m_char_blink_state) data = 0;
- if (ATTR_REVERSE) data ^= 0xff;
- if (column == cursor_x) data ^= 0xff;
- if (VSS_RVS) data ^= 0xff;
-
- for (int bit = 0; bit < cdh; bit++)
- {
- int x = (m_horiz_scroll & 0x0f) - cth + (column * cth) + bit;
- if (x < 0) x = 0;
- int color = BIT(data, 7) ? fg : bg;
-
- bitmap.pix32(vbp + y, hbp + x) = pen(de ? color : 0);
-
- if ((bit < 8) || !HSS_SEMI) data <<= 1;
- }
- }
- }
-}