diff options
Diffstat (limited to 'src/devices/video/mc6845.cpp')
-rw-r--r-- | src/devices/video/mc6845.cpp | 909 |
1 files changed, 290 insertions, 619 deletions
diff --git a/src/devices/video/mc6845.cpp b/src/devices/video/mc6845.cpp index 1c0862f1564..8ae471017d2 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,18 @@ #include "screen.h" -#define LOG_REGS (1 << 0U) -#define LOG_CONFIG (1 << 1U) -#define VERBOSE (0) +#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_FUNC osd_printf_info #include "logmacro.h" +#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__) +#define LOGREGS(...) LOGMASKED(LOG_REGS, __VA_ARGS__) +#define LOGCONF(...) LOGMASKED(LOG_CONF, __VA_ARGS__) DEFINE_DEVICE_TYPE(MC6845, mc6845_device, "mc6845", "Motorola MC6845 CRTC") DEFINE_DEVICE_TYPE(MC6845_1, mc6845_1_device, "mc6845_1", "Motorola MC6845-1 CRTC") @@ -59,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 */ @@ -77,39 +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_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) { } @@ -174,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 { @@ -199,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; @@ -213,7 +205,19 @@ uint8_t mc6845_device::register_r() void mc6845_device::register_w(uint8_t data) { - LOGMASKED(LOG_REGS, "%s:M6845 reg 0x%02x = 0x%02x\n", machine().describe_context(), m_register_address_latch, data); + LOGREGS("%s:M6845 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 < 0x0e && + m_register_address_latch != 0x0a && + m_register_address_latch != 0x0b) LOGSETUP(" * %02x <= %3u [%02x] %s\n", m_register_address_latch, + data, data, std::array<char const *, 16> + {{ "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 Raster", "R11 - Cursor End Raster", + "R12 - Start Address (H)", "R13 - Start Address (L)", "R14 - Cursor (H)", + "R15 - Cursor (L)" }}[(m_register_address_latch & 0x0f)]); switch (m_register_address_latch) { @@ -240,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: @@ -248,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; @@ -264,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) -{ - LOGMASKED(LOG_REGS, "%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; @@ -411,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; @@ -429,7 +311,27 @@ uint8_t hd6345_device::register_r() void hd6345_device::register_w(uint8_t data) { - LOGMASKED(LOG_REGS, "%s:HD6345 reg 0x%02x = 0x%02x\n", machine().describe_context(), m_register_address_latch, 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) { @@ -441,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; @@ -451,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; } @@ -571,8 +483,8 @@ void mc6845_device::recompute_parameters(bool postload) else visarea.set(0 + m_visarea_adjust_min_x, max_visible_x + m_visarea_adjust_max_x, 0 + m_visarea_adjust_min_y, max_visible_y + m_visarea_adjust_max_y); - LOGMASKED(LOG_CONFIG, "M6845 config screen: HTOTAL: %d VTOTAL: %d MAX_X: %d MAX_Y: %d HSYNC: %d-%d VSYNC: %d-%d Freq: %ffps\n", - horiz_pix_total, vert_pix_total, max_visible_x, max_visible_y, hsync_on_pos, hsync_off_pos - 1, vsync_on_pos, vsync_off_pos - 1, refresh.as_hz()); + LOGCONF("M6845 config screen: HTOTAL: %d VTOTAL: %d MAX_X: %d MAX_Y: %d HSYNC: %d-%d VSYNC: %d-%d Freq: %ffps\n", + horiz_pix_total, vert_pix_total, max_visible_x, max_visible_y, hsync_on_pos, hsync_off_pos - 1, vsync_on_pos, vsync_off_pos - 1, refresh.as_hz()); if (has_screen()) screen().configure(horiz_pix_total, vert_pix_total, visarea, refresh.as_attoseconds()); @@ -593,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; } @@ -757,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; @@ -846,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)); } } @@ -862,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; } } @@ -981,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 */ @@ -1037,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; @@ -1065,17 +955,40 @@ 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"); + m_display_disabled_msg_shown = false; + } /* 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) { @@ -1084,18 +997,21 @@ 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 { - LOGMASKED(LOG_CONFIG, "M6845: Invalid screen parameters - display disabled!!!\n"); + if (m_display_disabled_msg_shown == false) + { + logerror("M6845: Invalid screen parameters - display disabled!!!\n"); + m_display_disabled_msg_shown = true; + } } return 0; @@ -1107,34 +1023,29 @@ void mc6845_device::device_start() assert(clock() > 0); assert(m_hpixels_per_column > 0); - /* 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(); - /* bind delegates */ - m_reconfigure_cb.bind_relative_to(*owner()); - m_begin_update_cb.bind_relative_to(*owner()); - m_update_row_cb.bind_relative_to(*owner()); - m_end_update_cb.bind_relative_to(*owner()); - m_on_update_addr_changed_cb.bind_relative_to(*owner()); + m_reconfigure_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(); /* 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; @@ -1143,6 +1054,7 @@ void mc6845_device::device_start() m_supports_status_reg_d7 = false; m_supports_transparent = false; m_has_valid_parameters = false; + m_display_disabled_msg_shown = false; m_line_enable_ff = false; m_vsync_ff = 0; m_raster_counter = 0; @@ -1302,39 +1214,43 @@ void sy6845e_device::device_start() void hd6345_device::device_start() { - mc6845_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; + hd6845s_device::device_start(); + + 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(); @@ -1348,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 = update_row_delegate(FUNC(mos8563_device::vdc_update_row), this); - - 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 */ @@ -1447,16 +1273,20 @@ 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; + // TODO: as per the note above, none of these should reset unless otherwise proven. m_cursor_addr = 0; m_line_address = 0; - m_horiz_disp = 0; + // bml3 in particular disagrees with these two. + //m_horiz_disp = 0; + //m_mode_control = 0; m_cursor_x = 0; - m_mode_control = 0; m_register_address_latch = 0; m_update_addr = 0; m_light_pen_addr = 0; @@ -1469,38 +1299,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; -} - -void mos8568_device::device_reset() { mos8563_device::device_reset(); } + hd6845s_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) @@ -1515,6 +1324,12 @@ mc6845_1_device::mc6845_1_device(const machine_config &mconfig, const char *tag, } +hd6845s_device::hd6845s_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : mc6845_device(mconfig, type, tag, owner, clock) +{ +} + + hd6845s_device::hd6845s_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : mc6845_device(mconfig, HD6845S, tag, owner, clock) { @@ -1540,156 +1355,12 @@ sy6845e_device::sy6845e_device(const machine_config &mconfig, const char *tag, d hd6345_device::hd6345_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : mc6845_device(mconfig, HD6345, tag, owner, clock) + : hd6845s_device(mconfig, HD6345, tag, owner, clock) { } -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; - } - } - } -} |