1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-29 00:29:34 +00:00

Attempts an implementation of the undocumented low res + annunciator 3 graphics mode.

This commit is contained in:
Thomas Harte 2018-09-08 20:51:15 -04:00
parent afeec09902
commit d70f5da94e
2 changed files with 49 additions and 6 deletions

View File

@ -243,6 +243,28 @@ void VideoBase::output_low_resolution(uint8_t *target, const uint8_t *const sour
} }
} }
void VideoBase::output_fat_low_resolution(uint8_t *target, const uint8_t *const source, size_t length, int column, int row) const {
const int row_shift = row&4;
for(size_t c = 0; c < length; ++c) {
// Low-resolution graphics mode shifts the colour code on a loop, but has to account for whether this
// 14-sample output window is starting at the beginning of a colour cycle or halfway through.
if((column + static_cast<int>(c))&1) {
target[0] = target[1] = target[8] = target[9] = (source[c] >> row_shift) & 4;
target[2] = target[3] = target[10] = target[11] = (source[c] >> row_shift) & 8;
target[4] = target[5] = target[12] = target[13] = (source[c] >> row_shift) & 1;
target[6] = target[7] = (source[c] >> row_shift) & 2;
graphics_carry_ = (source[c] >> row_shift) & 8;
} else {
target[0] = target[1] = target[8] = target[9] = (source[c] >> row_shift) & 1;
target[2] = target[3] = target[10] = target[11] = (source[c] >> row_shift) & 2;
target[4] = target[5] = target[12] = target[13] = (source[c] >> row_shift) & 4;
target[6] = target[7] = (source[c] >> row_shift) & 8;
graphics_carry_ = (source[c] >> row_shift) & 2;
}
target += 14;
}
}
void VideoBase::output_double_low_resolution(uint8_t *target, const uint8_t *const source, const uint8_t *const auxiliary_source, size_t length, int column, int row) const { void VideoBase::output_double_low_resolution(uint8_t *target, const uint8_t *const source, const uint8_t *const auxiliary_source, size_t length, int column, int row) const {
const int row_shift = row&4; const int row_shift = row&4;
for(size_t c = 0; c < length; ++c) { for(size_t c = 0; c < length; ++c) {

View File

@ -159,14 +159,15 @@ class VideoBase {
// Enumerates all Apple II and IIe display modes. // Enumerates all Apple II and IIe display modes.
enum class GraphicsMode { enum class GraphicsMode {
LowRes = 0, Text = 0,
DoubleLowRes, DoubleText,
HighRes, HighRes,
DoubleHighRes, DoubleHighRes,
Text, LowRes,
DoubleText, DoubleLowRes,
FatLowRes
}; };
bool is_text_mode(GraphicsMode m) { return m >= GraphicsMode::Text; } bool is_text_mode(GraphicsMode m) { return m <= GraphicsMode::DoubleText; }
bool is_double_mode(GraphicsMode m) { return !!(static_cast<int>(m)&1); } bool is_double_mode(GraphicsMode m) { return !!(static_cast<int>(m)&1); }
// Various soft-switch values. // Various soft-switch values.
@ -238,6 +239,14 @@ class VideoBase {
*/ */
void output_double_high_resolution(uint8_t *target, const uint8_t *source, const uint8_t *auxiliary_source, size_t length) const; void output_double_high_resolution(uint8_t *target, const uint8_t *source, const uint8_t *auxiliary_source, size_t length) const;
/*!
Outputs 40-column "fat low resolution" graphics to @c target, drawing @c length columns from @c source.
Fat low-resolution mode is like regular low-resolution mode except that data is shifted out on the 7M
clock rather than the 14M.
*/
void output_fat_low_resolution(uint8_t *target, const uint8_t *source, size_t length, int column, int row) const;
// Maintain a ClockDeferrer for delayed mode switches. // Maintain a ClockDeferrer for delayed mode switches.
ClockDeferrer<Cycles> deferrer_; ClockDeferrer<Cycles> deferrer_;
}; };
@ -368,6 +377,7 @@ template <class BusHandler, bool is_iie> class Video: public VideoBase {
case GraphicsMode::Text: case GraphicsMode::Text:
case GraphicsMode::DoubleText: case GraphicsMode::DoubleText:
case GraphicsMode::LowRes: case GraphicsMode::LowRes:
case GraphicsMode::FatLowRes:
case GraphicsMode::DoubleLowRes: { case GraphicsMode::DoubleLowRes: {
const uint16_t text_address = static_cast<uint16_t>(((video_page()+1) * 0x400) + row_address); const uint16_t text_address = static_cast<uint16_t>(((video_page()+1) * 0x400) + row_address);
fetch_address = static_cast<uint16_t>(text_address + column_); fetch_address = static_cast<uint16_t>(text_address + column_);
@ -441,6 +451,15 @@ template <class BusHandler, bool is_iie> class Video: public VideoBase {
pixel_row); pixel_row);
break; break;
case GraphicsMode::FatLowRes:
output_fat_low_resolution(
&pixel_pointer_[pixel_start * 14 + 7],
&base_stream_[static_cast<size_t>(pixel_start)],
static_cast<size_t>(pixel_end - pixel_start),
pixel_start,
pixel_row);
break;
case GraphicsMode::DoubleLowRes: case GraphicsMode::DoubleLowRes:
output_double_low_resolution( output_double_low_resolution(
&pixel_pointer_[pixel_start * 14], &pixel_pointer_[pixel_start * 14],
@ -548,7 +567,9 @@ template <class BusHandler, bool is_iie> class Video: public VideoBase {
if(high_resolution_) { if(high_resolution_) {
return (annunciator_3_ && columns_80_) ? GraphicsMode::DoubleHighRes : GraphicsMode::HighRes; return (annunciator_3_ && columns_80_) ? GraphicsMode::DoubleHighRes : GraphicsMode::HighRes;
} else { } else {
return annunciator_3_ ? GraphicsMode::DoubleLowRes : GraphicsMode::LowRes; if(columns_80_) return GraphicsMode::DoubleLowRes;
if(annunciator_3_) return GraphicsMode::FatLowRes;
return GraphicsMode::LowRes;
} }
} }