1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 08:49:37 +00:00

Generalise rectangular operations.

This commit is contained in:
Thomas Harte 2023-02-02 21:49:05 -05:00
parent 83f6d1cda3
commit ec227ce021

View File

@ -195,44 +195,43 @@ struct PointSet: public Command {
bool done_ = false;
};
struct LogicalMoveFromCPU: public Command {
/// Useful base class for anything that does logical work in a rectangle.
template <bool logical, bool include_source> struct Rectangle: public Command {
public:
LogicalMoveFromCPU(CommandContext &context) : Command(context) {
is_cpu_transfer = true;
Rectangle(CommandContext &context) : Command(context) {
start_x_ = context.destination.v[0];
width_ = context.size.v[0];
// This command is started with the first colour ready to transfer.
cycles = 32;
access = AccessType::PlotPoint;
}
void advance(int) final {
switch(access) {
default: break;
/// Advances the current destination and, if @c include_source is @c true also the source;
/// @returns @c true if a new row was started; @c false otherwise.
///
/// @c pixels_per_byte is used for 'fast' (i.e. not logical) rectangles only, setting pace at
/// which the source and destination proceed left-to-right.
bool advance_pixel(int pixels_per_byte = 0) {
if constexpr (logical) {
advance_axis<0, include_source>();
--context.size.v[0];
case AccessType::WaitForColourReceipt:
cycles = 32;
access = AccessType::PlotPoint;
break;
if(context.size.v[0]) {
return false;
}
} else {
advance_axis<0, include_source>(pixels_per_byte);
context.size.v[0] -= pixels_per_byte;
case AccessType::PlotPoint:
cycles = 0;
access = AccessType::WaitForColourReceipt;
advance_axis<0, false>();
--context.size.v[0];
if(!context.size.v[0]) {
cycles = 64;
context.size.v[0] = width_;
context.destination.v[0] = start_x_;
advance_axis<1, false>();
--context.size.v[1];
}
break;
if(context.size.v[0] & ~(pixels_per_byte - 1)) {
return false;
}
}
context.size.v[0] = width_;
context.destination.v[0] = start_x_;
advance_axis<1, include_source>();
--context.size.v[1];
return true;
}
bool done() final {
@ -243,37 +242,48 @@ struct LogicalMoveFromCPU: public Command {
int start_x_ = 0, width_ = 0;
};
struct HighSpeedFill: public Command {
HighSpeedFill(CommandContext &context) : Command(context) {
start_x_ = context.destination.v[0];
width_ = context.size.v[0];
struct LogicalMoveFromCPU: public Rectangle<true, false> {
LogicalMoveFromCPU(CommandContext &context) : Rectangle(context) {
is_cpu_transfer = true;
// This command is started with the first colour ready to transfer.
cycles = 32;
access = AccessType::PlotPoint;
}
void advance(int) final {
switch(access) {
default: break;
case AccessType::WaitForColourReceipt:
cycles = 32;
access = AccessType::PlotPoint;
break;
case AccessType::PlotPoint:
cycles = 0;
access = AccessType::WaitForColourReceipt;
if(advance_pixel()) {
cycles = 64;
// TODO: I'm not sure this will be honoured per the outer wrapping.
}
break;
}
}
};
struct HighSpeedFill: public Rectangle<false, false> {
HighSpeedFill(CommandContext &context) : Rectangle(context) {
cycles = 56;
access = AccessType::WriteByte;
}
bool done() final {
return !context.size.v[1] || !width_;
}
void advance(int pixels_per_byte) final {
cycles = 48;
advance_axis<0, false>(pixels_per_byte);
context.size.v[0] -= pixels_per_byte;
if(!(context.size.v[0] & ~(pixels_per_byte - 1))) {
if(!advance_pixel(pixels_per_byte)) {
cycles += 56;
context.size.v[0] = width_;
context.destination.v[0] = start_x_;
advance_axis<1, false>();
--context.size.v[1];
}
}
private:
int start_x_ = 0, width_ = 0;
};
}