mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-20 14:29:11 +00:00
Prepare for source/destination operations.
This commit is contained in:
parent
6d315b4660
commit
83f6d1cda3
@ -629,32 +629,32 @@ template <Personality personality> struct Base: public Storage<personality> {
|
|||||||
return ScreenMode::Blank;
|
return ScreenMode::Blank;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddressT command_address() const {
|
AddressT command_address(Vector location) const {
|
||||||
if constexpr (is_yamaha_vdp(personality)) {
|
if constexpr (is_yamaha_vdp(personality)) {
|
||||||
switch(this->screen_mode_) {
|
switch(this->screen_mode_) {
|
||||||
default:
|
default:
|
||||||
case ScreenMode::YamahaGraphics4: // 256 pixels @ 4bpp
|
case ScreenMode::YamahaGraphics4: // 256 pixels @ 4bpp
|
||||||
return AddressT(
|
return AddressT(
|
||||||
(Storage<personality>::command_->location.v[0] >> 1) +
|
(location.v[0] >> 1) +
|
||||||
(Storage<personality>::command_->location.v[1] << 7)
|
(location.v[1] << 7)
|
||||||
);
|
);
|
||||||
|
|
||||||
case ScreenMode::YamahaGraphics5: // 512 pixels @ 2bpp
|
case ScreenMode::YamahaGraphics5: // 512 pixels @ 2bpp
|
||||||
return AddressT(
|
return AddressT(
|
||||||
(Storage<personality>::command_->location.v[0] >> 2) +
|
(location.v[0] >> 2) +
|
||||||
(Storage<personality>::command_->location.v[1] << 7)
|
(location.v[1] << 7)
|
||||||
);
|
);
|
||||||
|
|
||||||
case ScreenMode::YamahaGraphics6: // 512 pixels @ 4bpp
|
case ScreenMode::YamahaGraphics6: // 512 pixels @ 4bpp
|
||||||
return AddressT(
|
return AddressT(
|
||||||
(Storage<personality>::command_->location.v[0] >> 1) +
|
(location.v[0] >> 1) +
|
||||||
(Storage<personality>::command_->location.v[1] << 8)
|
(location.v[1] << 8)
|
||||||
);
|
);
|
||||||
|
|
||||||
case ScreenMode::YamahaGraphics7: // 256 pixels @ 8bpp
|
case ScreenMode::YamahaGraphics7: // 256 pixels @ 8bpp
|
||||||
return AddressT(
|
return AddressT(
|
||||||
(Storage<personality>::command_->location.v[0] >> 0) +
|
(location.v[0] >> 0) +
|
||||||
(Storage<personality>::command_->location.v[1] << 8)
|
(location.v[1] << 8)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -662,7 +662,7 @@ template <Personality personality> struct Base: public Storage<personality> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<uint8_t, uint8_t> command_colour_mask() const {
|
std::pair<uint8_t, uint8_t> command_colour_mask(Vector location) const {
|
||||||
if constexpr (is_yamaha_vdp(personality)) {
|
if constexpr (is_yamaha_vdp(personality)) {
|
||||||
switch(this->screen_mode_) {
|
switch(this->screen_mode_) {
|
||||||
default:
|
default:
|
||||||
@ -670,14 +670,14 @@ template <Personality personality> struct Base: public Storage<personality> {
|
|||||||
case ScreenMode::YamahaGraphics6: // 512 pixels @ 4bpp
|
case ScreenMode::YamahaGraphics6: // 512 pixels @ 4bpp
|
||||||
return
|
return
|
||||||
std::make_pair(
|
std::make_pair(
|
||||||
0xf0 >> ((Storage<personality>::command_->location.v[0] & 1) << 2),
|
0xf0 >> ((location.v[0] & 1) << 2),
|
||||||
Storage<personality>::command_context_.colour4bpp
|
Storage<personality>::command_context_.colour4bpp
|
||||||
);
|
);
|
||||||
|
|
||||||
case ScreenMode::YamahaGraphics5: // 512 pixels @ 2bpp
|
case ScreenMode::YamahaGraphics5: // 512 pixels @ 2bpp
|
||||||
return
|
return
|
||||||
std::make_pair(
|
std::make_pair(
|
||||||
0xc0 >> ((Storage<personality>::command_->location.v[0] & 3) << 1),
|
0xc0 >> ((location.v[0] & 3) << 1),
|
||||||
Storage<personality>::command_context_.colour2bpp
|
Storage<personality>::command_context_.colour2bpp
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -707,26 +707,27 @@ template <Personality personality> struct Base: public Storage<personality> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto &context = Storage<personality>::command_context_;
|
||||||
switch(Storage<personality>::next_command_step_) {
|
switch(Storage<personality>::next_command_step_) {
|
||||||
// Duplicative, but keeps the compiler happy.
|
// Duplicative, but keeps the compiler happy.
|
||||||
case CommandStep::None:
|
case CommandStep::None:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CommandStep::ReadPixel:
|
case CommandStep::ReadPixel:
|
||||||
Storage<personality>::command_latch_ = ram_[command_address()];
|
Storage<personality>::command_latch_ = ram_[command_address(context.destination)];
|
||||||
|
|
||||||
Storage<personality>::minimum_command_column_ = access_column + 24;
|
Storage<personality>::minimum_command_column_ = access_column + 24;
|
||||||
Storage<personality>::next_command_step_ = CommandStep::WritePixel;
|
Storage<personality>::next_command_step_ = CommandStep::WritePixel;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CommandStep::WritePixel: {
|
case CommandStep::WritePixel: {
|
||||||
const auto [mask, unmasked_colour] = command_colour_mask();
|
const auto [mask, unmasked_colour] = command_colour_mask(context.destination);
|
||||||
const auto address = command_address();
|
const auto address = command_address(context.destination);
|
||||||
const uint8_t colour = unmasked_colour & mask;
|
const uint8_t colour = unmasked_colour & mask;
|
||||||
|
|
||||||
using LogicalOperation = CommandContext::LogicalOperation;
|
using LogicalOperation = CommandContext::LogicalOperation;
|
||||||
if(!Storage<personality>::command_context_.test_source || colour) {
|
if(!context.test_source || colour) {
|
||||||
switch(Storage<personality>::command_context_.pixel_operation) {
|
switch(context.pixel_operation) {
|
||||||
default:
|
default:
|
||||||
case LogicalOperation::Copy:
|
case LogicalOperation::Copy:
|
||||||
Storage<personality>::command_latch_ &= ~mask;
|
Storage<personality>::command_latch_ &= ~mask;
|
||||||
@ -755,7 +756,7 @@ template <Personality personality> struct Base: public Storage<personality> {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case CommandStep::WriteByte:
|
case CommandStep::WriteByte:
|
||||||
ram_[command_address()] = Storage<personality>::command_context_.colour;
|
ram_[command_address(context.destination)] = context.colour;
|
||||||
Storage<personality>::command_->advance(pixels_per_byte(this->underlying_mode_));
|
Storage<personality>::command_->advance(pixels_per_byte(this->underlying_mode_));
|
||||||
Storage<personality>::update_command_step(access_column);
|
Storage<personality>::update_command_step(access_column);
|
||||||
break;
|
break;
|
||||||
|
@ -86,7 +86,6 @@ struct Command {
|
|||||||
AccessType access = AccessType::PlotPoint;
|
AccessType access = AccessType::PlotPoint;
|
||||||
int cycles = 0;
|
int cycles = 0;
|
||||||
bool is_cpu_transfer = false;
|
bool is_cpu_transfer = false;
|
||||||
Vector location;
|
|
||||||
|
|
||||||
/// Current command parameters.
|
/// Current command parameters.
|
||||||
CommandContext &context;
|
CommandContext &context;
|
||||||
@ -101,8 +100,11 @@ struct Command {
|
|||||||
virtual void advance(int pixels_per_byte) = 0;
|
virtual void advance(int pixels_per_byte) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
template <int axis> void advance_axis(int offset = 1) {
|
template <int axis, bool include_source> void advance_axis(int offset = 1) {
|
||||||
context.destination.add<axis>(context.arguments & (0x4 << axis) ? -offset : offset);
|
context.destination.add<axis>(context.arguments & (0x4 << axis) ? -offset : offset);
|
||||||
|
if constexpr (include_source) {
|
||||||
|
context.source.add<axis>(context.arguments & (0x4 << axis) ? -offset : offset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -124,7 +126,6 @@ struct Line: public Command {
|
|||||||
// context.size.v[1] = short side dots;
|
// context.size.v[1] = short side dots;
|
||||||
// context.arguments => direction
|
// context.arguments => direction
|
||||||
|
|
||||||
location = context.destination;
|
|
||||||
position_ = context.size.v[1];
|
position_ = context.size.v[1];
|
||||||
numerator_ = position_ << 1;
|
numerator_ = position_ << 1;
|
||||||
denominator_ = context.size.v[0] << 1;
|
denominator_ = context.size.v[0] << 1;
|
||||||
@ -150,9 +151,9 @@ struct Line: public Command {
|
|||||||
// b3: 1 => y direction is up;
|
// b3: 1 => y direction is up;
|
||||||
// 0 => y direction is down.
|
// 0 => y direction is down.
|
||||||
if(context.arguments & 0x1) {
|
if(context.arguments & 0x1) {
|
||||||
advance_axis<1>();
|
advance_axis<1, false>();
|
||||||
} else {
|
} else {
|
||||||
advance_axis<0>();
|
advance_axis<0, false>();
|
||||||
}
|
}
|
||||||
|
|
||||||
position_ -= numerator_;
|
position_ -= numerator_;
|
||||||
@ -161,13 +162,11 @@ struct Line: public Command {
|
|||||||
cycles += 32;
|
cycles += 32;
|
||||||
|
|
||||||
if(context.arguments & 0x1) {
|
if(context.arguments & 0x1) {
|
||||||
advance_axis<0>();
|
advance_axis<0, false>();
|
||||||
} else {
|
} else {
|
||||||
advance_axis<1>();
|
advance_axis<1, false>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
location = context.destination;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -180,9 +179,8 @@ struct Line: public Command {
|
|||||||
struct PointSet: public Command {
|
struct PointSet: public Command {
|
||||||
public:
|
public:
|
||||||
PointSet(CommandContext &context) : Command(context) {
|
PointSet(CommandContext &context) : Command(context) {
|
||||||
cycles = 0;
|
cycles = 0; // TODO.
|
||||||
access = AccessType::PlotPoint;
|
access = AccessType::PlotPoint;
|
||||||
location = context.destination;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool done() final {
|
bool done() final {
|
||||||
@ -208,7 +206,6 @@ struct LogicalMoveFromCPU: public Command {
|
|||||||
// This command is started with the first colour ready to transfer.
|
// This command is started with the first colour ready to transfer.
|
||||||
cycles = 32;
|
cycles = 32;
|
||||||
access = AccessType::PlotPoint;
|
access = AccessType::PlotPoint;
|
||||||
location = context.destination;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void advance(int) final {
|
void advance(int) final {
|
||||||
@ -217,14 +214,13 @@ struct LogicalMoveFromCPU: public Command {
|
|||||||
|
|
||||||
case AccessType::WaitForColourReceipt:
|
case AccessType::WaitForColourReceipt:
|
||||||
cycles = 32;
|
cycles = 32;
|
||||||
location = context.destination;
|
|
||||||
access = AccessType::PlotPoint;
|
access = AccessType::PlotPoint;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AccessType::PlotPoint:
|
case AccessType::PlotPoint:
|
||||||
cycles = 0;
|
cycles = 0;
|
||||||
access = AccessType::WaitForColourReceipt;
|
access = AccessType::WaitForColourReceipt;
|
||||||
advance_axis<0>();
|
advance_axis<0, false>();
|
||||||
--context.size.v[0];
|
--context.size.v[0];
|
||||||
|
|
||||||
if(!context.size.v[0]) {
|
if(!context.size.v[0]) {
|
||||||
@ -232,7 +228,7 @@ struct LogicalMoveFromCPU: public Command {
|
|||||||
context.size.v[0] = width_;
|
context.size.v[0] = width_;
|
||||||
context.destination.v[0] = start_x_;
|
context.destination.v[0] = start_x_;
|
||||||
|
|
||||||
advance_axis<1>();
|
advance_axis<1, false>();
|
||||||
--context.size.v[1];
|
--context.size.v[1];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -254,7 +250,6 @@ struct HighSpeedFill: public Command {
|
|||||||
|
|
||||||
cycles = 56;
|
cycles = 56;
|
||||||
access = AccessType::WriteByte;
|
access = AccessType::WriteByte;
|
||||||
location = context.destination;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool done() final {
|
bool done() final {
|
||||||
@ -264,7 +259,7 @@ struct HighSpeedFill: public Command {
|
|||||||
void advance(int pixels_per_byte) final {
|
void advance(int pixels_per_byte) final {
|
||||||
cycles = 48;
|
cycles = 48;
|
||||||
|
|
||||||
advance_axis<0>(pixels_per_byte);
|
advance_axis<0, false>(pixels_per_byte);
|
||||||
context.size.v[0] -= pixels_per_byte;
|
context.size.v[0] -= pixels_per_byte;
|
||||||
|
|
||||||
if(!(context.size.v[0] & ~(pixels_per_byte - 1))) {
|
if(!(context.size.v[0] & ~(pixels_per_byte - 1))) {
|
||||||
@ -272,11 +267,9 @@ struct HighSpeedFill: public Command {
|
|||||||
context.size.v[0] = width_;
|
context.size.v[0] = width_;
|
||||||
context.destination.v[0] = start_x_;
|
context.destination.v[0] = start_x_;
|
||||||
|
|
||||||
advance_axis<1>();
|
advance_axis<1, false>();
|
||||||
--context.size.v[1];
|
--context.size.v[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
location = context.destination;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user