diff options
Diffstat (limited to 'src/devices/video/i8275.cpp')
-rw-r--r-- | src/devices/video/i8275.cpp | 546 |
1 files changed, 287 insertions, 259 deletions
diff --git a/src/devices/video/i8275.cpp b/src/devices/video/i8275.cpp index ed3204b8d9f..3da93ce26e6 100644 --- a/src/devices/video/i8275.cpp +++ b/src/devices/video/i8275.cpp @@ -1,10 +1,25 @@ // license:BSD-3-Clause -// copyright-holders:Curt Coder +// copyright-holders:Curt Coder, AJR /********************************************************************** Intel 8275 Programmable CRT Controller Intel 8276 Small Systems CRT Controller + This emulation allows up to four 8275 or 8276 CRTCs connected in + parallel and reading out their row buffers simultaneously. The + secondary CRTCs are assumed to use identical timings to the + primary CRTC and run in perfect sync with each other. + + The features provided by 8276 are practically a subset of the + 8275. Light pen input, line attributes, invisible character + attributes and DMA bursts are not supported on the 8276. Also, + the DRQ and _DACK pins are renamed BRDY (Buffer Ready) and _BS + (Buffer Select), and the latter must be asserted coincident + with _WR (but not _CS). (Even in systems without a DMAC, the + processor usually does not write to the row buffer directly, + but enables some pseudo-DMA mode which causes memory read + operations to transmit data to the CRTC in the same cycle.) + **********************************************************************/ /* @@ -31,46 +46,6 @@ //************************************************************************** -static const int DMA_BURST_SPACING[] = { 0, 7, 15, 23, 31, 39, 47, 55 }; - - -#define DOUBLE_SPACED_ROWS \ - BIT(m_param[REG_SCN1], 7) - -#define CHARACTERS_PER_ROW \ - ((m_param[REG_SCN1] & 0x7f) + 1) - -#define VRTC_ROW_COUNT \ - ((m_param[REG_SCN2] >> 6) + 1) - -#define CHARACTER_ROWS_PER_FRAME \ - ((m_param[REG_SCN2] & 0x3f) + 1) - -#define UNDERLINE \ - (m_param[REG_SCN3] >> 4) - -#define SCANLINES_PER_ROW \ - ((m_param[REG_SCN3] & 0x0f) + 1) - -#define OFFSET_LINE_COUNTER \ - BIT(m_param[REG_SCN4], 7) - -#define VISIBLE_FIELD_ATTRIBUTE \ - BIT(m_param[REG_SCN4], 6) - -#define CURSOR_FORMAT \ - ((m_param[REG_SCN4] >> 4) & 0x03) - -#define HRTC_COUNT \ - (((m_param[REG_SCN4] & 0x0f) + 1) * 2) - -#define DMA_BURST_COUNT \ - (1 << (m_param[REG_DMA] & 0x03)) - -#define DMA_BURST_SPACE \ - DMA_BURST_SPACING[(m_param[REG_DMA] >> 2) & 0x07] - - const int i8275_device::character_attribute[3][16] = { { 2, 2, 4, 4, 2, 4, 4, 4, 2, 4, 4, 0, 2, 0, 0, 0 }, @@ -108,11 +83,14 @@ i8275_device::i8275_device(const machine_config &mconfig, device_type type, cons m_write_lc(*this), m_display_cb(*this), m_refresh_hack(false), + m_next_crtc(*this, finder_base::DUMMY_TAG), + m_is_crtc0(true), m_status(0), m_param_idx(0), m_param_end(0), m_buffer_idx(0), m_fifo_idx(0), + m_fifo_idx_out(0), m_dma_idx(0), m_dma_last_char(0), m_buffer_dma(0), @@ -140,27 +118,32 @@ i8276_device::i8276_device(const machine_config &mconfig, const char *tag, devic } +void i8275_device::device_resolve_objects() +{ + if (m_next_crtc.found()) + m_next_crtc->m_is_crtc0 = false; +} + + //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- void i8275_device::device_start() { - // get the screen device - screen().register_screen_bitmap(m_bitmap); - - // resolve callbacks - m_write_drq.resolve_safe(); - m_write_irq.resolve_safe(); - m_write_hrtc.resolve_safe(); - m_write_vrtc.resolve_safe(); - m_write_lc.resolve_safe(); - m_display_cb.resolve(); - - // allocate timers - m_hrtc_on_timer = timer_alloc(TIMER_HRTC_ON); - m_drq_on_timer = timer_alloc(TIMER_DRQ_ON); - m_scanline_timer = timer_alloc(TIMER_SCANLINE); + if (m_is_crtc0) + { + // get the screen device + screen().register_screen_bitmap(m_bitmap); + + // resolve delegates + m_display_cb.resolve_safe(); + + // allocate timers + m_hrtc_on_timer = timer_alloc(FUNC(i8275_device::hrtc_on), this); + m_drq_on_timer = timer_alloc(FUNC(i8275_device::drq_on), this); + m_scanline_timer = timer_alloc(FUNC(i8275_device::scanline_tick), this); + } // state saving save_item(NAME(m_status)); @@ -169,6 +152,8 @@ void i8275_device::device_start() save_item(NAME(m_param_end)); save_item(NAME(m_buffer[0])); save_item(NAME(m_buffer[1])); + save_item(NAME(m_fifo[0])); + save_item(NAME(m_fifo[1])); save_item(NAME(m_buffer_idx)); save_item(NAME(m_fifo_idx)); save_item(NAME(m_dma_idx)); @@ -210,16 +195,13 @@ void i8275_device::device_reset() void i8275_device::vrtc_start() { - //LOG("I8275 y %u x %u VRTC 1\n", y, x); - m_write_vrtc(1); - // reset field attributes m_field_attr = 0; // Intel datasheets imply DMA requests begin only after a "Start Display" command is issued. // WY-100, however, expects a BRDY cycle from the 8276 after the program first configures and stops the display. // This suggests that DMA bursts proceed as normal in this case, but any characters sent will not be displayed. - m_buffer_idx = CHARACTERS_PER_ROW; + m_buffer_idx = characters_per_row(); m_dma_stop = false; m_end_of_screen = !(m_status & ST_VE); @@ -255,214 +237,247 @@ void i8275_device::dma_start() m_dma_idx = 0; m_dma_last_char = 0; - m_drq_on_timer->adjust(clocks_to_attotime(DMA_BURST_SPACE)); + if (m_is_crtc0) + m_drq_on_timer->adjust(clocks_to_attotime(dma_burst_space())); } //------------------------------------------------- -// device_timer - handle timer events +// timer events //------------------------------------------------- -void i8275_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +TIMER_CALLBACK_MEMBER(i8275_device::hrtc_on) { - //int y = screen().vpos(); - //int x = screen().hpos(); - int rc = m_scanline / SCANLINES_PER_ROW; - int lc = m_scanline % SCANLINES_PER_ROW; + m_write_hrtc(1); +} - switch (id) - { - case TIMER_HRTC_ON: - //LOG("I8275 y %u x %u HRTC 1\n", y, x); - m_write_hrtc(1); - break; +TIMER_CALLBACK_MEMBER(i8275_device::drq_on) +{ + m_write_drq(1); +} - case TIMER_DRQ_ON: - //LOG("I8275 y %u x %u DRQ 1\n", y, x); - m_write_drq(1); - break; +TIMER_CALLBACK_MEMBER(i8275_device::scanline_tick) +{ + int rc = m_scanline / scanlines_per_row(); + int lc = m_scanline % scanlines_per_row(); - case TIMER_SCANLINE: - //LOG("I8275 y %u x %u HRTC 0\n", y, x); - int line_counter = OFFSET_LINE_COUNTER ? ((lc - 1) % SCANLINES_PER_ROW) : lc; - m_write_lc(line_counter); - m_write_hrtc(0); + int line_counter = offset_line_counter() ? ((lc - 1) % scanlines_per_row()) : lc; + m_write_lc(line_counter); + m_write_hrtc(0); - if (m_scanline == 0) - vrtc_end(); + if (m_scanline == 0) + vrtc_end(); - if (lc == 0 && m_scanline < m_vrtc_scanline) + if (lc == 0 && m_scanline < m_vrtc_scanline) + { + for (i8275_device *crtc = this; crtc != nullptr; crtc = crtc->m_next_crtc) { - if (!m_dma_stop && m_buffer_idx < CHARACTERS_PER_ROW) + if (!crtc->m_dma_stop && crtc->m_buffer_idx < characters_per_row()) { - m_status |= ST_DU; - m_dma_stop = true; + crtc->m_status |= ST_DU; + crtc->m_dma_stop = true; // blank screen until after VRTC - m_end_of_screen = true; + crtc->m_end_of_screen = true; - //LOG("I8275 y %u x %u DMA Underrun\n", y, x); - - m_write_drq(0); + crtc->m_write_drq(0); } - if (!m_dma_stop) + if (!crtc->m_dma_stop) { // swap line buffers - m_buffer_dma = !m_buffer_dma; + crtc->m_buffer_dma = !crtc->m_buffer_dma; - if (m_scanline < (m_vrtc_scanline - SCANLINES_PER_ROW)) - dma_start(); + if (m_scanline < (m_vrtc_scanline - scanlines_per_row())) + crtc->dma_start(); } } + } - if ((m_status & ST_IE) && !(m_status & ST_IR) && m_scanline == m_irq_scanline) + if (m_scanline == m_irq_scanline) + { + for (i8275_device *crtc = this; crtc != nullptr; crtc = crtc->m_next_crtc) { - //LOG("I8275 y %u x %u IRQ 1\n", y, x); - m_status |= ST_IR; - m_write_irq(ASSERT_LINE); + if ((crtc->m_status & ST_IE) && !(crtc->m_status & ST_IR)) + { + crtc->m_status |= ST_IR; + crtc->m_write_irq(ASSERT_LINE); + } } + } - if (m_scanline == m_vrtc_scanline) - vrtc_start(); + if (m_scanline == m_vrtc_scanline) + { + //LOG("I8275 y %u x %u VRTC 1\n", y, x); + m_write_vrtc(1); - if (!m_dma_stop && m_scanline == m_vrtc_drq_scanline) + for (i8275_device *crtc = this; crtc != nullptr; crtc = crtc->m_next_crtc) + crtc->vrtc_start(); + } + + if (m_scanline == m_vrtc_drq_scanline) + { + for (i8275_device *crtc = this; crtc != nullptr; crtc = crtc->m_next_crtc) { - // swap line buffers - m_buffer_dma = !m_buffer_dma; + if (!crtc->m_dma_stop) + { + // swap line buffers + crtc->m_buffer_dma = !crtc->m_buffer_dma; - // start DMA burst - dma_start(); + // start DMA burst + crtc->dma_start(); + } + } + } + + if (m_scanline < m_vrtc_scanline) + { + int end_of_row = 0; + int blank_row = 0; + { + int n = 0; + for (i8275_device *crtc = this; crtc != nullptr; crtc = crtc->m_next_crtc, n++) + { + if (crtc->m_end_of_screen || !(m_status & ST_VE)) + end_of_row |= 1 << n; + if ((crtc->underline() >= 8) && ((lc == 0) || (lc == scanlines_per_row() - 1))) + blank_row |= 1 << n; + crtc->m_fifo_idx_out = 0; + crtc->m_field_attr = crtc->m_stored_attr; + } } - if ((m_status & ST_VE) && m_scanline < m_vrtc_scanline) + for (int sx = 0; sx < characters_per_row(); sx++) { - bool end_of_row = false; - bool blank_row = (UNDERLINE >= 8) && ((lc == 0) || (lc == SCANLINES_PER_ROW - 1)); - int fifo_idx = 0; - m_field_attr = m_stored_attr; + int n = 0; + uint32_t charcode = 0; + uint32_t attrcode = 0; - for (int sx = 0; sx < CHARACTERS_PER_ROW; sx++) + for (i8275_device *crtc = this; crtc != nullptr; crtc = crtc->m_next_crtc, n++) { - int lineattr = 0; - - uint8_t data = (end_of_row || m_end_of_screen) ? 0 : m_buffer[!m_buffer_dma][sx]; - uint8_t attr = m_field_attr; - - if ((data & 0xc0) == 0x80) - { - // field attribute code - m_field_attr = data & (FAC_H | FAC_B | FAC_GG | FAC_R | FAC_U); - - if (!VISIBLE_FIELD_ATTRIBUTE) - { - attr = m_field_attr; - data = m_fifo[!m_buffer_dma][fifo_idx]; - - fifo_idx++; - fifo_idx &= 0xf; - - if (blank_row) - attr |= FAC_B; - else if (!(m_char_blink < 32)) - attr &= ~FAC_B; - if (lc != UNDERLINE) - attr &= ~FAC_U; - } - else - { - // simply blank the attribute character itself - attr = FAC_B; - } - } - else if (data >= 0xf0 || end_of_row || m_end_of_screen) - { - // special control character - switch (data) - { - case SCC_END_OF_ROW: - case SCC_END_OF_ROW_DMA: - end_of_row = true; - break; - - case SCC_END_OF_SCREEN: - case SCC_END_OF_SCREEN_DMA: - m_end_of_screen = true; - break; - } - attr = FAC_B; - } - else if (data >= 0xc0) - { - // character attribute code - attr = data & (m_char_blink < 32 ? (CA_H | CA_B) : CA_H); - - uint8_t ca; - int cccc = (data >> 2) & 0x0f; - - if (lc < UNDERLINE) - { - ca = character_attribute[0][cccc]; - } - else if (lc == UNDERLINE) - { - ca = character_attribute[1][cccc]; - } - else - { - ca = character_attribute[2][cccc]; - } - - if (ca & CA_LTEN) - attr |= FAC_U; - if (ca & CA_VSP) - attr |= FAC_B; - lineattr = ca >> 2; - } - else - { - if (blank_row) - attr |= FAC_B; - else if (!(m_char_blink < 32)) - attr &= ~FAC_B; - if (lc != UNDERLINE) - attr &= ~FAC_U; - } - - if ((rc == m_param[REG_CUR_ROW]) && (sx == m_param[REG_CUR_COL])) - { - if ((CURSOR_FORMAT & 0x02) || (m_cursor_blink < 16)) - { - if (CURSOR_FORMAT & 0x01) - attr |= (lc == UNDERLINE) ? FAC_U : 0; - else - attr ^= FAC_R; - } - } - - if (!m_display_cb.isnull()) - m_display_cb(m_bitmap, + auto [data, attr] = crtc->char_from_buffer(n, sx, rc, lc, end_of_row, blank_row); + charcode |= uint32_t(data) << (n * 8); + attrcode |= uint32_t(attr) << (n * 8); + } + + m_display_cb(m_bitmap, sx * m_hpixels_per_column, // x position on screen of starting point m_scanline, // y position on screen line_counter, // current line of char - (data & 0x7f), // char code to be displayed - lineattr, // line attribute code - (attr & FAC_U) ? 1 : 0, // light enable signal - (attr & FAC_R) ? 1 : 0, // reverse video signal - (attr & FAC_B) ? 1 : 0, // video suppression - (attr & FAC_GG) >> 2, // general purpose attribute code - (attr & FAC_H) ? 1 : 0 // highlight - ); - } + charcode, // char code to be displayed + attrcode); + } + + if ((scanlines_per_row() - lc) == 1) + { + for (i8275_device *crtc = this; crtc != nullptr; crtc = crtc->m_next_crtc) + crtc->m_stored_attr = crtc->m_field_attr; + } + } + + m_scanline++; + m_scanline %= ((character_rows_per_frame() + vrtc_row_count()) * scanlines_per_row()); +} + + +std::pair<uint8_t, uint8_t> i8275_device::char_from_buffer(int n, int sx, int rc, int lc, int &end_of_row, int blank_row) +{ + uint8_t data = BIT(end_of_row, n) ? 0 : m_buffer[!m_buffer_dma][sx]; + uint8_t attr = m_field_attr; + int lineattr = 0; - if ((SCANLINES_PER_ROW - lc) == 1) - m_stored_attr = m_field_attr; + if ((data & 0xc0) == 0x80) + { + // field attribute code + m_field_attr = data & (FAC_H | FAC_B | FAC_GG | FAC_R | FAC_U); + + if (!visible_field_attribute()) + { + attr = m_field_attr; + data = m_fifo[!m_buffer_dma][m_fifo_idx_out]; + + m_fifo_idx_out++; + m_fifo_idx_out &= 0xf; + + if (BIT(blank_row, n)) + attr |= FAC_B; + else if (!(m_char_blink < 32)) + attr &= ~FAC_B; + if (lc != underline()) + attr &= ~FAC_U; } + else + { + // simply blank the attribute character itself + attr = FAC_B; + } + } + else if (data >= 0xf0 || BIT(end_of_row, n)) + { + // special control character + switch (data) + { + case SCC_END_OF_ROW: + case SCC_END_OF_ROW_DMA: + end_of_row |= 1 << n; + break; - m_scanline++; - m_scanline %= ((CHARACTER_ROWS_PER_FRAME + VRTC_ROW_COUNT) * SCANLINES_PER_ROW); - break; + case SCC_END_OF_SCREEN: + case SCC_END_OF_SCREEN_DMA: + m_end_of_screen = true; + break; + } + attr = FAC_B; + } + else if (data >= 0xc0) + { + // character attribute code + attr = data & (m_char_blink < 32 ? (CA_H | CA_B) : CA_H); + + uint8_t ca; + int cccc = (data >> 2) & 0x0f; + + if (lc < underline()) + { + ca = character_attribute[0][cccc]; + } + else if (lc == underline()) + { + ca = character_attribute[1][cccc]; + } + else + { + ca = character_attribute[2][cccc]; + } + + if (ca & CA_LTEN) + attr |= FAC_U; + if (ca & CA_VSP) + attr |= FAC_B; + lineattr = ca >> 2; } + else + { + if (BIT(blank_row, n)) + attr |= FAC_B; + else if (!(m_char_blink < 32)) + attr &= ~FAC_B; + if (lc != underline()) + attr &= ~FAC_U; + } + + if ((rc == m_param[REG_CUR_ROW]) && (sx == m_param[REG_CUR_COL])) + { + if ((cursor_format() & 0x02) || (m_cursor_blink < 16)) + { + if (cursor_format() & 0x01) + attr |= (lc == underline()) ? FAC_U : 0; + else + attr ^= FAC_R; + } + } + + return std::make_pair(data & 0x7f, attr | lineattr << 6); } @@ -525,12 +540,15 @@ void i8275_device::write(offs_t offset, uint8_t data) */ if (m_preset) { - int hrtc_on_pos = CHARACTERS_PER_ROW * m_hpixels_per_column; + int hrtc_on_pos = characters_per_row() * m_hpixels_per_column; m_preset = false; - m_hrtc_on_timer->adjust(screen().time_until_pos(screen().vpos(), hrtc_on_pos), 0, screen().scan_period()); m_scanline = m_vrtc_drq_scanline; - m_scanline_timer->adjust(screen().time_until_pos(m_vrtc_drq_scanline, 0), 0, screen().scan_period()); + if (m_is_crtc0) + { + m_hrtc_on_timer->adjust(screen().time_until_pos(screen().vpos(), hrtc_on_pos), 0, screen().scan_period()); + m_scanline_timer->adjust(screen().time_until_pos(m_vrtc_drq_scanline, 0), 0, screen().scan_period()); + } } switch (data >> 5) @@ -549,7 +567,8 @@ void i8275_device::write(offs_t offset, uint8_t data) LOG("I8275 IRQ 0\n"); m_write_irq(CLEAR_LINE); m_write_drq(0); - m_drq_on_timer->adjust(attotime::never); + if (m_is_crtc0) + m_drq_on_timer->adjust(attotime::never); m_dma_stop = true; m_param_idx = REG_SCN1; @@ -563,7 +582,7 @@ void i8275_device::write(offs_t offset, uint8_t data) */ case CMD_START_DISPLAY: m_param[REG_DMA] = data; - LOG("I8275 Start Display %u %u\n", DMA_BURST_COUNT, DMA_BURST_SPACE); + LOG("I8275 Start Display %u %u\n", dma_burst_count(), dma_burst_space()); m_dma_stop = false; m_status |= (ST_IE | ST_VE); break; @@ -602,8 +621,11 @@ void i8275_device::write(offs_t offset, uint8_t data) case CMD_PRESET_COUNTERS: LOG("I8275 Preset Counters\n"); m_preset = true; - m_scanline_timer->adjust(attotime::never); - m_hrtc_on_timer->adjust(attotime::never); + if (m_is_crtc0) + { + m_scanline_timer->adjust(attotime::never); + m_hrtc_on_timer->adjust(attotime::never); + } break; } } @@ -631,7 +653,7 @@ void i8275_device::dack_w(uint8_t data) m_write_drq(0); - if (!VISIBLE_FIELD_ATTRIBUTE && ((m_dma_last_char & 0xc0) == 0x80)) + if (!visible_field_attribute() && ((m_dma_last_char & 0xc0) == 0x80)) { if (m_fifo_idx == 16) { @@ -644,7 +666,7 @@ void i8275_device::dack_w(uint8_t data) data = 0; } - else if (m_buffer_idx < CHARACTERS_PER_ROW) + else if (m_buffer_idx < characters_per_row()) { m_buffer[m_buffer_dma][m_buffer_idx++] = data; } @@ -655,27 +677,30 @@ void i8275_device::dack_w(uint8_t data) { case SCC_END_OF_ROW_DMA: // stop DMA - m_buffer_idx = CHARACTERS_PER_ROW; + m_buffer_idx = characters_per_row(); break; case SCC_END_OF_SCREEN_DMA: m_dma_stop = true; - m_buffer_idx = CHARACTERS_PER_ROW; + m_buffer_idx = characters_per_row(); break; default: - if (m_buffer_idx == CHARACTERS_PER_ROW) - { - // stop DMA - m_drq_on_timer->adjust(attotime::never); - } - else if (!(m_dma_idx % DMA_BURST_COUNT)) - { - m_drq_on_timer->adjust(clocks_to_attotime(DMA_BURST_SPACE)); - } - else + if (m_is_crtc0) { - m_drq_on_timer->adjust(attotime::zero); + if (m_buffer_idx == characters_per_row()) + { + // stop DMA + m_drq_on_timer->adjust(attotime::never); + } + else if (!(m_dma_idx % dma_burst_count())) + { + m_drq_on_timer->adjust(clocks_to_attotime(dma_burst_space())); + } + else + { + m_drq_on_timer->adjust(attotime::zero); + } } } @@ -687,12 +712,12 @@ void i8275_device::dack_w(uint8_t data) // lpen_w - //------------------------------------------------- -WRITE_LINE_MEMBER( i8275_device::lpen_w ) +void i8275_device::lpen_w(int state) { if (!m_lpen && state) { m_param[REG_LPEN_COL] = screen().hpos() / m_hpixels_per_column; - m_param[REG_LPEN_ROW] = screen().vpos() / SCANLINES_PER_ROW; + m_param[REG_LPEN_ROW] = screen().vpos() / scanlines_per_row(); m_status |= ST_LP; } @@ -724,30 +749,33 @@ uint32_t i8275_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap void i8275_device::recompute_parameters() { + if (!m_is_crtc0) + return; + int y = screen().vpos(); - int horiz_pix_total = (CHARACTERS_PER_ROW + HRTC_COUNT) * m_hpixels_per_column; - int vert_pix_total = (CHARACTER_ROWS_PER_FRAME + VRTC_ROW_COUNT) * SCANLINES_PER_ROW; - attotime refresh = clocks_to_attotime((CHARACTERS_PER_ROW + HRTC_COUNT) * vert_pix_total); - int max_visible_x = (CHARACTERS_PER_ROW * m_hpixels_per_column) - 1; - int max_visible_y = (CHARACTER_ROWS_PER_FRAME * SCANLINES_PER_ROW) - 1; + int horiz_pix_total = (characters_per_row() + hrtc_count()) * m_hpixels_per_column; + int vert_pix_total = (character_rows_per_frame() + vrtc_row_count()) * scanlines_per_row(); + attotime refresh = clocks_to_attotime((characters_per_row() + hrtc_count()) * vert_pix_total); + int max_visible_x = (characters_per_row() * m_hpixels_per_column) - 1; + int max_visible_y = (character_rows_per_frame() * scanlines_per_row()) - 1; LOG("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, refresh.as_hz()); rectangle visarea(0, max_visible_x, 0, max_visible_y); screen().configure(horiz_pix_total, vert_pix_total, visarea, (m_refresh_hack ? screen().frame_period() : refresh).as_attoseconds()); - int hrtc_on_pos = CHARACTERS_PER_ROW * m_hpixels_per_column; + int hrtc_on_pos = characters_per_row() * m_hpixels_per_column; m_hrtc_on_timer->adjust(screen().time_until_pos(y, hrtc_on_pos), 0, screen().scan_period()); - m_irq_scanline = (CHARACTER_ROWS_PER_FRAME - 1) * SCANLINES_PER_ROW; - m_vrtc_scanline = CHARACTER_ROWS_PER_FRAME * SCANLINES_PER_ROW; - m_vrtc_drq_scanline = vert_pix_total - SCANLINES_PER_ROW; + m_irq_scanline = (character_rows_per_frame() - 1) * scanlines_per_row(); + m_vrtc_scanline = character_rows_per_frame() * scanlines_per_row(); + m_vrtc_drq_scanline = vert_pix_total - scanlines_per_row(); LOG("irq_y %u vrtc_y %u drq_y %u\n", m_irq_scanline, m_vrtc_scanline, m_vrtc_drq_scanline); m_scanline = y; m_scanline_timer->adjust(screen().time_until_pos((y + 1) % vert_pix_total, 0), 0, screen().scan_period()); - if (DOUBLE_SPACED_ROWS) fatalerror("Double spaced rows not supported!"); + if (double_spaced_rows()) fatalerror("Double spaced rows not supported!"); } |