diff --git a/src/devices/video/scn2674.cpp b/src/devices/video/scn2674.cpp index 67a5fe19f94..7cf956e87a0 100644 --- a/src/devices/video/scn2674.cpp +++ b/src/devices/video/scn2674.cpp @@ -14,7 +14,7 @@ #define LOG_COMMAND (1 << 1) #define LOG_INTR (1 << 2) #define LOG_READ (1 << 3) -#define VERBOSE (0) +#define VERBOSE (1) #include "logmacro.h" @@ -43,6 +43,7 @@ scn2674_device::scn2674_device(const machine_config &mconfig, device_type type, , device_video_interface(mconfig, *this) , device_memory_interface(mconfig, *this) , m_intr_cb(*this) + , m_breq_cb(*this) , m_IR_pointer(0) , m_screen1_address(0), m_screen2_address(0) , m_cursor_address(0) @@ -103,6 +104,7 @@ void scn2674_device::device_start() // resolve callbacks m_display_cb.bind_relative_to(*owner()); m_intr_cb.resolve_safe(); + m_breq_cb.resolve_safe(); m_scanline_timer = timer_alloc(TIMER_SCANLINE); screen().register_screen_bitmap(m_bitmap); @@ -221,9 +223,12 @@ void scn2672_device::write_init_regs(uint8_t data) { //LOGMASKED(LOG_COMMAND, "scn2674_write_init_regs %02x %02x\n",m_IR_pointer,data); + bool parameters_changed = false; switch (m_IR_pointer) { case 0: + parameters_changed = m_scanline_per_char_row != ((data & 0x78) >> 3) + 1; + m_double_ht_wd = BIT(data, 7); m_scanline_per_char_row = ((data & 0x78) >> 3) + 1; m_csync_select = BIT(data, 2); @@ -252,6 +257,8 @@ void scn2672_device::write_init_regs(uint8_t data) break; case 1: + parameters_changed = m_equalizing_constant != (data & 0x7f) + 1; + m_interlace_enable = BIT(data, 7); m_equalizing_constant = (data & 0x7f) + 1; @@ -260,6 +267,8 @@ void scn2672_device::write_init_regs(uint8_t data) break; case 2: + parameters_changed = m_horz_sync_width != (((data & 0x78) >> 3) * 2) + 2; + m_horz_sync_width = (((data & 0x78) >> 3) * 2) + 2; m_horz_back_porch = ((data & 0x07) * 4) + 1; @@ -268,6 +277,9 @@ void scn2672_device::write_init_regs(uint8_t data) break; case 3: + parameters_changed = m_vert_front_porch != (((data & 0xe0) >> 5) * 4) + 4 + || m_vert_back_porch != ((data & 0x1f) * 2) + 4; + m_vert_front_porch = (((data & 0xe0) >> 5) * 4) + 4; m_vert_back_porch = ((data & 0x1f) * 2) + 4; @@ -276,6 +288,8 @@ void scn2672_device::write_init_regs(uint8_t data) break; case 4: + parameters_changed = m_rows_per_screen != (data & 0x7f) + 1; + m_rows_per_screen = (data & 0x7f) + 1; m_character_blink_rate_divisor = BIT(data, 7) ? 32 : 16; @@ -284,6 +298,8 @@ void scn2672_device::write_init_regs(uint8_t data) break; case 5: + parameters_changed = m_character_per_row != data + 1; + m_character_per_row = data + 1; LOGMASKED(LOG_IR, "IR5 - Active Characters Per Row %02i\n", m_character_per_row); break; @@ -333,8 +349,7 @@ void scn2672_device::write_init_regs(uint8_t data) break; } - // Don't reconfigure if the display isn't turned on (incomplete configurations may generate invalid screen parameters) - if (m_display_enabled) + if (parameters_changed) recompute_parameters(); m_IR_pointer = std::min(m_IR_pointer + 1, 10); @@ -345,9 +360,12 @@ void scn2674_device::write_init_regs(uint8_t data) { //LOGMASKED(LOG_COMMAND, "scn2674_write_init_regs %02x %02x\n",m_IR_pointer,data); + bool parameters_changed = false; switch (m_IR_pointer) { case 0: + parameters_changed = m_scanline_per_char_row != ((data & 0x78) >> 3) + 1; + m_double_ht_wd = BIT(data, 7); m_scanline_per_char_row = ((data & 0x78) >> 3) + 1; m_csync_select = BIT(data, 2); @@ -377,6 +395,8 @@ void scn2674_device::write_init_regs(uint8_t data) break; case 1: + parameters_changed = m_equalizing_constant != (data & 0x7f) + 1; + m_interlace_enable = BIT(data, 7); m_equalizing_constant = (data & 0x7f) + 1; @@ -385,6 +405,8 @@ void scn2674_device::write_init_regs(uint8_t data) break; case 2: + parameters_changed = m_horz_sync_width != (((data & 0x78) >> 3) * 2) + 2; + m_use_row_table = BIT(data, 7); m_horz_sync_width = (((data & 0x78) >> 3) * 2) + 2; m_horz_back_porch = ((data & 0x07) * 4) - 1; @@ -395,6 +417,9 @@ void scn2674_device::write_init_regs(uint8_t data) break; case 3: + parameters_changed = m_vert_front_porch != (((data & 0xe0) >> 5) * 4) + 4 + || m_vert_back_porch != ((data & 0x1f) * 2) + 4; + m_vert_front_porch = (((data & 0xe0) >> 5) * 4) + 4; m_vert_back_porch = ((data & 0x1f) * 2) + 4; @@ -403,6 +428,8 @@ void scn2674_device::write_init_regs(uint8_t data) break; case 4: + parameters_changed = m_rows_per_screen != (data & 0x7f) + 1; + m_rows_per_screen = (data & 0x7f) + 1; m_character_blink_rate_divisor = BIT(data, 7) ? 128 : 64; @@ -411,6 +438,8 @@ void scn2674_device::write_init_regs(uint8_t data) break; case 5: + parameters_changed = m_character_per_row != data + 1; + m_character_per_row = data + 1; LOGMASKED(LOG_IR, "IR5 - Active Characters Per Row %02i\n", m_character_per_row); break; @@ -429,6 +458,7 @@ void scn2674_device::write_init_regs(uint8_t data) m_cursor_rate_divisor = BIT(data, 4) ? 64 : 32; m_cursor_blink = BIT(data, 5); + parameters_changed = m_vsync_width != vsync_table[(data & 0xc0) >> 6]; m_vsync_width = vsync_table[(data & 0xc0) >> 6]; LOGMASKED(LOG_IR, "IR7 - Underline Position %02i\n", m_cursor_underline_position); @@ -499,8 +529,7 @@ void scn2674_device::write_init_regs(uint8_t data) break; } - // Don't reconfigure if the display isn't turned on (incomplete configurations may generate invalid screen parameters) - if (m_display_enabled) + if (parameters_changed) recompute_parameters(); m_IR_pointer = std::min(m_IR_pointer + 1, 14); @@ -601,13 +630,7 @@ void scn2674_device::write_interrupt_mask(bool enabled, uint8_t bits) if (BIT(changed_bits, 3)) LOGMASKED(LOG_INTR, "Line Zero IRQ %s\n", enabled ? "enabled" : "disabled"); if (BIT(changed_bits, 4)) - { LOGMASKED(LOG_INTR, "V-Blank IRQ %s\n", enabled ? "enabled" : "disabled"); - - // hack to allow PC-X to get its first interrupt - if (BIT(bits, 4) && !m_display_enabled) - recompute_parameters(); - } } void scn2674_device::write_delayed_command(uint8_t data) @@ -925,6 +948,12 @@ WRITE8_MEMBER( scn2674_device::write ) void scn2674_device::recompute_parameters() { + if (!m_equalizing_constant || !m_character_per_row || !m_rows_per_screen) + { + m_scanline_timer->adjust(attotime::never); + return; + } + int horiz_chars_total = (m_equalizing_constant + (m_horz_sync_width << 1)) << 1; int horiz_pix_total = horiz_chars_total * m_hpixels_per_column; int vert_pix_total = m_rows_per_screen * m_scanline_per_char_row + m_vert_front_porch + m_vert_back_porch + m_vsync_width; @@ -932,12 +961,6 @@ void scn2674_device::recompute_parameters() int max_visible_x = (m_character_per_row * m_hpixels_per_column) - 1; int max_visible_y = (m_rows_per_screen * m_scanline_per_char_row) - 1; - if (!horiz_pix_total || !vert_pix_total) - { - m_scanline_timer->adjust(attotime::never); - return; - } - //attoseconds_t refresh = clocks_to_attotime(horiz_chars_total * vert_pix_total).as_attoseconds(); LOGMASKED(LOG_IR, "width %u height %u max_x %u max_y %u refresh %f\n", horiz_pix_total, vert_pix_total, max_visible_x, max_visible_y, ATTOSECONDS_TO_HZ(refresh)); @@ -996,7 +1019,11 @@ void scn2674_device::device_timer(emu_timer &timer, device_timer_id id, int para m_irq_register |= 0x08; m_intr_cb(ASSERT_LINE); } + if (m_buffer_mode_select == 3) + m_breq_cb(ASSERT_LINE); } + else if (m_buffer_mode_select == 3) + m_breq_cb(CLEAR_LINE); // Handle screen splits for (int s = 0; s < 2; s++) diff --git a/src/devices/video/scn2674.h b/src/devices/video/scn2674.h index b594f0dcb52..c3dd8503c32 100644 --- a/src/devices/video/scn2674.h +++ b/src/devices/video/scn2674.h @@ -22,7 +22,9 @@ public: // static configuration auto intr_callback() { return m_intr_cb.bind(); } + auto breq_callback() { return m_breq_cb.bind(); } void set_character_width(int value) { m_hpixels_per_column = value; } + template void set_display_callback(void (FunctionClass::*callback)(bitmap_rgb32 &, int, int, uint8_t, uint8_t, uint8_t, uint16_t, bool, bool, bool, bool, bool), const char *name) { @@ -59,6 +61,7 @@ protected: //protected: bitmap_rgb32 m_bitmap; devcb_write_line m_intr_cb; + devcb_write_line m_breq_cb; uint8_t m_IR_pointer; uint16_t m_screen1_address; diff --git a/src/mame/drivers/qvt201.cpp b/src/mame/drivers/qvt201.cpp index 81cf016c7fc..13c232924db 100644 --- a/src/mame/drivers/qvt201.cpp +++ b/src/mame/drivers/qvt201.cpp @@ -21,6 +21,7 @@ public: qvt201_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag) , m_maincpu(*this, "maincpu") + , m_mainnmi(*this, "mainnmi") , m_eia(*this, "eia") , m_screen(*this, "screen") , m_p_chargen(*this, "chargen") @@ -40,6 +41,7 @@ private: void mem_map(address_map &map); required_device m_maincpu; + required_device m_mainnmi; required_device m_eia; required_device m_screen; required_region_ptr m_p_chargen; @@ -73,11 +75,12 @@ WRITE8_MEMBER(qvt201_state::duart_out_w) // OP3 = 132/_80 // OP4 = SRV // OP5 = BLOCK/_UL - // OP6 = preset NMI flipflop + // OP6 = preset MBC NMI flipflop // OP7 = _DATA/TALK (EIA pin 14) m_eia->write_rts(BIT(data, 0)); m_eia->write_dtr(BIT(data, 1)); + m_mainnmi->in_w<1>(!BIT(data, 6)); } void qvt201_state::mem_map(address_map &map) @@ -100,8 +103,11 @@ MACHINE_CONFIG_START(qvt201_state::qvt201) MCFG_DEVICE_ADD("maincpu", Z80, 3.6864_MHz_XTAL) MCFG_DEVICE_PROGRAM_MAP(mem_map) // IORQ is not used at all - MCFG_INPUT_MERGER_ANY_HIGH("mainint") // open collector - MCFG_INPUT_MERGER_OUTPUT_HANDLER(INPUTLINE("maincpu", 0)) + input_merger_device &mainint(INPUT_MERGER_ANY_HIGH(config, "mainint")); // open collector + mainint.output_handler().set_inputline("maincpu", INPUT_LINE_IRQ0); + + input_merger_device &mainnmi(INPUT_MERGER_ALL_HIGH(config, "mainnmi")); + mainnmi.output_handler().set_inputline("maincpu", INPUT_LINE_NMI); MCFG_DEVICE_ADD("duart", SCN2681, 3.6864_MHz_XTAL) // XTAL not directly connected MCFG_MC68681_IRQ_CALLBACK(WRITELINE("mainint", input_merger_device, in_w<1>)) @@ -126,6 +132,7 @@ MACHINE_CONFIG_START(qvt201_state::qvt201) scn2672_device &crtc(SCN2672(config, "crtc", 48.654_MHz_XTAL / 30)); crtc.set_character_width(10); // 9 in 132-column mode crtc.intr_callback().set("mainint", FUNC(input_merger_device::in_w<0>)); + crtc.breq_callback().set("mainnmi", FUNC(input_merger_device::in_w<0>)); crtc.set_screen("screen"); MACHINE_CONFIG_END