Skip to content

Commit

Permalink
Fix 8bpp output, all-modes cursor.
Browse files Browse the repository at this point in the history
  • Loading branch information
TomHarte committed Apr 7, 2024
1 parent 7bf831e commit ed7cd4b
Showing 1 changed file with 55 additions and 53 deletions.
108 changes: 55 additions & 53 deletions Machines/Acorn/Archimedes/Video.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,29 @@ struct Video {
crt_.set_display_type(Outputs::Display::DisplayType::RGB);
}

static constexpr uint16_t colour(uint32_t value) {
uint8_t packed[2]{};
packed[0] = value & 0xf;
packed[1] = (value & 0xf0) | ((value & 0xf00) >> 8);

#if TARGET_RT_BIG_ENDIAN
return static_cast<uint16_t>(packed[1] | (packed[0] << 8));
#else
return static_cast<uint16_t>(packed[0] | (packed[1] << 8));
#endif
};
static constexpr uint16_t high_spread[] = {
colour(0b0000'0000'0000), colour(0b0000'0000'1000), colour(0b0000'0100'0000), colour(0b0000'0100'1000),
colour(0b0000'1000'0000), colour(0b0000'1000'1000), colour(0b0000'1100'0000), colour(0b0000'1100'1000),
colour(0b1000'0000'0000), colour(0b1000'0000'1000), colour(0b1000'0100'0000), colour(0b1000'0100'1000),
colour(0b1000'1000'0000), colour(0b1000'1000'1000), colour(0b1000'1100'0000), colour(0b1000'1100'1000),
};

void write(uint32_t value) {
const auto target = (value >> 24) & 0xfc;
const auto timing_value = [](uint32_t value) -> uint32_t {
return (value >> 14) & 0x3ff;
};
const auto colour = [](uint32_t value) -> uint16_t {
uint8_t packed[2];
packed[0] = value & 0xf;
packed[1] = (value & 0xf0) | ((value & 0xf00) >> 8);

uint16_t result;
memcpy(&result, packed, 2);
return result;
};

switch(target) {
case 0x00: case 0x04: case 0x08: case 0x0c:
Expand Down Expand Up @@ -202,72 +211,61 @@ struct Video {
// 1bpp mode: output one byte every fourth tick.
switch(colour_depth_) {
case Depth::EightBPP: {
// TODO: real 8bpp mapping here.
uint8_t next = next_byte();
pixels_[0] = colours_[next & 0xf];
pixels_[0] = (colours_[next & 0xf] & colour(0b0111'0011'0111)) | high_spread[next >> 4];

next = next_byte();
pixels_[1] = colours_[next & 0xf];

pixels_ += 2;
pixels_[1] = (colours_[next & 0xf] & colour(0b0111'0011'0111)) | high_spread[next >> 4];
} break;

case Depth::FourBPP: {
const uint8_t next = next_byte();

pixels_[0] = colours_[next & 0xf];
pixels_[1] = colours_[next >> 4];

// Overlay cursor if applicable.
// TODO: have all BPP modes output only two pixels at a time, and pull this out of the loop.
// TODO: pull this so far out that the cursor can display over the border, too.
if(cursor_pixel_ < 32) {
if(cursor_pixel_ >= 0) {
const auto colour = cursor_image_[static_cast<size_t>(cursor_pixel_)];
if(colour) {
pixels_[0] = cursor_colours_[colour];
}
}
if(cursor_pixel_ < 31) {
const auto colour = cursor_image_[static_cast<size_t>(cursor_pixel_ + 1)];
if(colour) {
pixels_[1] = cursor_colours_[colour];
}
}
cursor_pixel_ += 2;
}

pixels_ += 2;
} break;

case Depth::TwoBPP: {
if(!(pixel_count_&1)) {
const uint8_t next = next_byte();

pixels_[0] = colours_[next & 3];
pixels_[1] = colours_[(next >> 2) & 3];
pixels_[2] = colours_[(next >> 4) & 3];
pixels_[3] = colours_[next >> 6];
pixels_ += 4;
pixel_data_ = next_byte();
}

pixels_[0] = colours_[pixel_data_ & 3];
pixels_[1] = colours_[(pixel_data_ >> 2) & 3];
pixel_data_ >>= 4;
} break;

case Depth::OneBPP: {
if(!(pixel_count_&3)) {
const uint8_t next = next_byte();

pixels_[0] = colours_[next & 1];
pixels_[1] = colours_[(next >> 1) & 1];
pixels_[2] = colours_[(next >> 2) & 1];
pixels_[3] = colours_[(next >> 3) & 1];
pixels_[4] = colours_[(next >> 4) & 1];
pixels_[5] = colours_[(next >> 5) & 1];
pixels_[6] = colours_[(next >> 6) & 1];
pixels_[7] = colours_[next >> 7];
pixels_ += 8;
pixel_data_ = next_byte();
}

pixels_[0] = colours_[pixel_data_ & 1];
pixels_[1] = colours_[(pixel_data_ >> 1) & 1];
pixel_data_ >>= 2;
} break;
}

// Overlay cursor if applicable.
// TODO: have all BPP modes output only two pixels at a time, and pull this out of the loop.

This comment has been minimized.

Copy link
@PatrickvL

PatrickvL Apr 7, 2024

This commit solves this to-do, so it should be removed

This comment has been minimized.

Copy link
@TomHarte

TomHarte Apr 8, 2024

Author Owner

Yes, agreed. That was some lazy editing. Thanks!

// TODO: pull this so far out that the cursor can display over the border, too.
if(cursor_pixel_ < 32) {
if(cursor_pixel_ >= 0) {
const auto pixel = cursor_image_[static_cast<size_t>(cursor_pixel_)];
if(pixel) {
pixels_[0] = cursor_colours_[pixel];
}
}
if(cursor_pixel_ < 31) {
const auto pixel = cursor_image_[static_cast<size_t>(cursor_pixel_ + 1)];
if(pixel) {
pixels_[1] = cursor_colours_[pixel];
}
}
cursor_pixel_ += 2;
}

pixels_ += 2;
} else {
// TODO: don't assume 4bpp here either.
switch(colour_depth_) {
Expand Down Expand Up @@ -435,10 +433,14 @@ struct Video {
// Ephemeral address state.
uint32_t address_ = 0;

// Horizontal cursor output state.
uint32_t cursor_address_ = 0;
int cursor_pixel_ = 0;
std::array<uint8_t, 32> cursor_image_;

// Ephemeral graphics data.
uint8_t pixel_data_ = 0;

// Colour palette, converted to internal format.
uint16_t border_colour_;
std::array<uint16_t, 16> colours_{};
Expand Down

0 comments on commit ed7cd4b

Please sign in to comment.