1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-26 10:29:31 +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 {
const int row_shift = row&4;
for(size_t c = 0; c < length; ++c) {

View File

@ -159,14 +159,15 @@ class VideoBase {
// Enumerates all Apple II and IIe display modes.
enum class GraphicsMode {
LowRes = 0,
DoubleLowRes,
Text = 0,
DoubleText,
HighRes,
DoubleHighRes,
Text,
DoubleText,
LowRes,
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); }
// 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;
/*!
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.
ClockDeferrer<Cycles> deferrer_;
};
@ -368,6 +377,7 @@ template <class BusHandler, bool is_iie> class Video: public VideoBase {
case GraphicsMode::Text:
case GraphicsMode::DoubleText:
case GraphicsMode::LowRes:
case GraphicsMode::FatLowRes:
case GraphicsMode::DoubleLowRes: {
const uint16_t text_address = static_cast<uint16_t>(((video_page()+1) * 0x400) + row_address);
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);
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:
output_double_low_resolution(
&pixel_pointer_[pixel_start * 14],
@ -548,7 +567,9 @@ template <class BusHandler, bool is_iie> class Video: public VideoBase {
if(high_resolution_) {
return (annunciator_3_ && columns_80_) ? GraphicsMode::DoubleHighRes : GraphicsMode::HighRes;
} else {
return annunciator_3_ ? GraphicsMode::DoubleLowRes : GraphicsMode::LowRes;
if(columns_80_) return GraphicsMode::DoubleLowRes;
if(annunciator_3_) return GraphicsMode::FatLowRes;
return GraphicsMode::LowRes;
}
}