summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/apple/apple2video.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/apple/apple2video.cpp')
-rw-r--r--src/mame/apple/apple2video.cpp160
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;