diff options
Diffstat (limited to 'src/mame/apple/apple2video.cpp')
| -rw-r--r-- | src/mame/apple/apple2video.cpp | 160 |
1 files changed, 88 insertions, 72 deletions
diff --git a/src/mame/apple/apple2video.cpp b/src/mame/apple/apple2video.cpp index 3f8487a281a..699a7c6d6a7 100644 --- a/src/mame/apple/apple2video.cpp +++ b/src/mame/apple/apple2video.cpp @@ -61,6 +61,7 @@ void a2_video_device::device_start() // initialise for device_palette_interface init_palette(); + save_item(NAME(m_hgr2)); save_item(NAME(m_page2)); save_item(NAME(m_flash)); save_item(NAME(m_mix)); @@ -80,6 +81,7 @@ void a2_video_device::device_start() save_item(NAME(m_monochrome)); save_item(NAME(m_rgbmode)); save_item(NAME(m_shr_palette)); + save_item(NAME(m_shr_scbs)); } void a2_video_device::device_reset() @@ -124,7 +126,7 @@ void a2_video_device::mix_w(int state) void a2_video_device::scr_w(int state) { // select primary or secondary page - if (!m_80col) + if (!m_80store && (m_page2 != state)) screen().update_now(); m_page2 = state; } @@ -174,6 +176,14 @@ void a2_video_device::a80col_w(bool b80Col) } } +void a2_video_device::a80store_w(bool b80Store) +{ + // select PAGE2 aux RAM (displaying PAGE1) + if (m_page2 && (m_80store != b80Store)) + screen().update_now(); + m_80store = b80Store; +} + void a2_video_device::altcharset_w(bool altch) { if (m_altcharset != altch) @@ -184,10 +194,41 @@ void a2_video_device::altcharset_w(bool altch) } } +void a2_video_device::set_GS_textcol(u8 textcol) +{ + // select foreground and background text colors + const u8 fg = textcol >> 4; + const u8 bg = textcol & 0xf; + if ((m_GSfg != fg) || (m_GSbg != bg)) + { + screen().update_now(); + m_GSfg = fg; + m_GSbg = bg; + } +} + +void a2_video_device::set_GS_border(u8 border) +{ + // select border color + if (m_GSborder != border) + { + screen().update_now(); + m_GSborder = border; + } +} + +void a2_video_device::set_newvideo(u8 newvideo) +{ + // select super hi-res and monochrome modes + if ((m_newvideo & 0xA0) != (newvideo & 0xA0)) + screen().update_now(); + m_newvideo = newvideo; +} + void a2_video_device::set_GS_langsel(u8 langsel) { // select primary language character set - if ((langsel & 0xe8) != (m_GS_langsel & 0xe8)) + if ((m_GS_langsel & 0xe8) != (langsel & 0xe8)) screen().update_now(); m_GS_langsel = langsel; } @@ -825,55 +866,42 @@ uint32_t a2_video_device::palette_entries() const noexcept uint32_t a2_video_device::screen_update_GS(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { - int const beamy = cliprect.top(); + // de-jitter clock drift; video scanner latches whole bytes + const int left = cliprect.left() & ~0xF; + const int right = (cliprect.right() + 1) & ~0xF; // inclusive bounds + const bool shr = BIT(m_newvideo, 7); - if (m_newvideo & 0x80) + const int beamy = cliprect.top(); { - // in top or bottom border? - if ((beamy < BORDER_TOP) || (beamy >= 200+BORDER_TOP)) - { - // don't draw past the bottom border - if (beamy >= 231+BORDER_TOP) - { - return 0; - } + uint32_t *const scanline = &bitmap.pix(beamy); + if ((beamy < BORDER_TOP) || (beamy >= BORDER_TOP + (shr ? 200 : 192))) + { + // in top or bottom border uint32_t *const scanline = &bitmap.pix(beamy); - for (int col = 0; col < BORDER_LEFT+BORDER_RIGHT+640; col++) - { + for (int col = left; col < right; col++) scanline[col] = m_GSborder_colors[m_GSborder]; - } } - else // regular screen area + else if (shr) { - int const shrline = beamy - BORDER_TOP; - - uint8_t scb; - if (shrline & 1) - { - scb = m_aux_ptr[0x9e80 + (shrline >> 1)]; - } - else - { - scb = m_aux_ptr[0x5e80 + (shrline >> 1)]; - } - int const palette = ((scb & 0x0f) << 4); - - uint8_t const *const vram = &m_aux_ptr[0x2000 + (shrline * 80)]; - uint8_t const *const vram2 = &m_aux_ptr[0x6000 + (shrline * 80)]; - - uint32_t *const scanline = &bitmap.pix(beamy); + const int shrline = beamy - BORDER_TOP; + const u8 scb = m_shr_scbs[shrline]; + const int palette = ((scb & 0x0f) << 4); + const uint8_t *const vram = &m_aux_ptr[0x2000 + (shrline * 80)]; + const uint8_t *const vram2 = &m_aux_ptr[0x6000 + (shrline * 80)]; // draw left and right borders - for (int col = 0; col < BORDER_LEFT; col++) - { + for (int col = left; col < (std::min)(right, BORDER_LEFT); col++) + scanline[col] = m_GSborder_colors[m_GSborder]; + for (int col = (std::max)(left, BORDER_LEFT + 640); col < right; col++) scanline[col] = m_GSborder_colors[m_GSborder]; - scanline[col+BORDER_LEFT+640] = m_GSborder_colors[m_GSborder]; - } + + const int gsleft = (std::max)((left - BORDER_LEFT), 0) / 8; + const int gsright = (std::min)((right - BORDER_LEFT), 640) / 8; if (scb & 0x80) // 640 mode { - for (int col = 0; col < 80; col++) + for (int col = gsleft; col < gsright; col++) { uint8_t b = vram[col]; scanline[col * 8 + 0 + BORDER_LEFT] = m_shr_palette[palette + 0 + ((b >> 6) & 0x03)]; @@ -888,7 +916,7 @@ uint32_t a2_video_device::screen_update_GS(screen_device &screen, bitmap_rgb32 & scanline[col * 8 + 7 + BORDER_LEFT] = m_shr_palette[palette + 12 + ((b >> 0) & 0x03)]; } } - else // 320 mode + else // 320 mode { // the low 5 bits of the SCB determine the initial fillmode color // for the scanline (hardware testing by John Brooks) @@ -899,7 +927,7 @@ uint32_t a2_video_device::screen_update_GS(screen_device &screen, bitmap_rgb32 & }; uint32_t last_pixel = fillmode_init[scb & 0x1f]; - for (int col = 0; col < 80; col++) + for (int col = gsleft; col < gsright; col++) { uint8_t b; uint32_t pixel; @@ -948,44 +976,32 @@ uint32_t a2_video_device::screen_update_GS(screen_device &screen, bitmap_rgb32 & } } } - } - else - { - if (beamy >= BORDER_TOP) - { - rectangle const new_cliprect(0, 559, cliprect.top() - BORDER_TOP, cliprect.bottom() - BORDER_TOP); - screen_update<model::IIGS, true, false>(screen, *m_8bit_graphics, new_cliprect); - } - - if ((beamy < BORDER_TOP) || (beamy >= (192 + BORDER_TOP))) - { - if (beamy >= (231+BORDER_TOP)) - { - return 0; - } - - uint32_t *const scanline = &bitmap.pix(beamy); - for (int col = 0; col < BORDER_LEFT+BORDER_RIGHT+640; col++) - { - scanline[col] = m_GSborder_colors[m_GSborder]; - } - } else { - uint32_t *const scanline = &bitmap.pix(beamy); + // scale 16 MHz cliprect to 14 MHz + const int a2left = (std::max)(((left - BORDER_LEFT) / 16 * 14), 0); + const int a2right = (std::min)(((right - BORDER_LEFT) / 16 * 14), 560); + const rectangle a2cliprect(a2left, a2right - 1, cliprect.top() - BORDER_TOP, cliprect.bottom() - BORDER_TOP); + screen_update<model::IIGS, true, false>(screen, *m_8bit_graphics, a2cliprect); // exclusive bounds + + // these stretch factors align partial updates within left and right borders + // FIXME: stretch 8-bit modes to match super hi-res, stop stretching borders + const float lbstretch = (float)(BORDER_LEFT + 40) / (BORDER_LEFT / 16); + const float rbstretch = (float)(BORDER_RIGHT + 40) / (BORDER_RIGHT / 16); + const int lbleft = left / 16 * lbstretch; + const int lbright = right / 16 * lbstretch; + const int rbleft = ((left - (BORDER_LEFT + 640)) / 16 * rbstretch) + (BORDER_LEFT + 40 + 560); + const int rbright = ((right - (BORDER_LEFT + 640)) / 16 * rbstretch) + (BORDER_LEFT + 40 + 560); // draw left and right borders - for (int col = 0; col < BORDER_LEFT + 40; col++) - { + for (int col = lbleft; col < (std::min)(lbright, BORDER_LEFT + 40); col++) + scanline[col] = m_GSborder_colors[m_GSborder]; + for (int col = (std::max)(rbleft, BORDER_LEFT + 40 + 560); col < rbright; col++) scanline[col] = m_GSborder_colors[m_GSborder]; - scanline[col+BORDER_LEFT+600] = m_GSborder_colors[m_GSborder]; - } - uint16_t *a2pixel = &m_8bit_graphics->pix(beamy - BORDER_TOP); - for (int x = 0; x < 560; x++) - { - scanline[40 + BORDER_LEFT + x] = m_GSborder_colors[*a2pixel++]; - } + const uint16_t *const a2pixel = &m_8bit_graphics->pix(beamy - BORDER_TOP); + for (int col = a2left; col < a2right; col++) + scanline[BORDER_LEFT + 40 + col] = m_GSborder_colors[a2pixel[col]]; } } return 0; |
