1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-25 18:30:07 +00:00

Attempt the full panoply of logical pixel modes, across all graphics modes.

This commit is contained in:
Thomas Harte 2023-01-29 18:28:49 -05:00
parent a91a5b8d07
commit 6d7f189ce7
3 changed files with 95 additions and 48 deletions

View File

@ -852,8 +852,8 @@ void Base<personality>::commit_register(int reg, uint8_t value) {
case 44:
Storage<personality>::command_context_.colour = value;
Storage<personality>::command_context_.colour4pp = (value & 0xf) | (value << 4);
Storage<personality>::command_context_.colour2pp = (value & 0x3) | ((value & 0x3) << 2) | ((value & 0x3) << 4) | ((value & 0x3) << 6);
Storage<personality>::command_context_.colour4bpp = (value & 0xf) | (value << 4);
Storage<personality>::command_context_.colour2bpp = (value & 0x3) | ((value & 0x3) << 2) | ((value & 0x3) << 4) | ((value & 0x3) << 6);
// Check whether a command was blocked on this.
if(
@ -911,7 +911,8 @@ void Base<personality>::commit_register(int reg, uint8_t value) {
}
#undef Begin
Storage<personality>::command_context_.pixel_operation = CommandContext::LogicalOperation(value & 0xf);
Storage<personality>::command_context_.pixel_operation = CommandContext::LogicalOperation(value & 7);
Storage<personality>::command_context_.test_source = value & 8;
// Kill the command immediately if it's done in zero operations
// (e.g. a line of length 0).

View File

@ -579,6 +579,66 @@ template <Personality personality> struct Base: public Storage<personality> {
return ScreenMode::Blank;
}
uint32_t command_address() const {
if constexpr (is_yamaha_vdp(personality)) {
switch(this->screen_mode_) {
default:
case ScreenMode::YamahaGraphics4: // 256 pixels @ 4bpp
return
(Storage<personality>::command_->location.v[0] >> 1) +
(Storage<personality>::command_->location.v[1] << 7);
case ScreenMode::YamahaGraphics5: // 512 pixels @ 2bpp
return
(Storage<personality>::command_->location.v[0] >> 2) +
(Storage<personality>::command_->location.v[1] << 7);
case ScreenMode::YamahaGraphics6: // 512 pixels @ 4bpp
return
(Storage<personality>::command_->location.v[0] >> 1) +
(Storage<personality>::command_->location.v[1] << 8);
case ScreenMode::YamahaGraphics7: // 256 pixels @ 8bpp
return
(Storage<personality>::command_->location.v[0] >> 0) +
(Storage<personality>::command_->location.v[1] << 8);
}
} else {
return 0;
}
}
std::pair<uint8_t, uint8_t> command_colour_mask() const {
if constexpr (is_yamaha_vdp(personality)) {
switch(this->screen_mode_) {
default:
case ScreenMode::YamahaGraphics4: // 256 pixels @ 4bpp
case ScreenMode::YamahaGraphics6: // 512 pixels @ 4bpp
return
std::make_pair(
0xf0 >> ((Storage<personality>::command_->location.v[0] & 1) << 2),
Storage<personality>::command_context_.colour4bpp
);
case ScreenMode::YamahaGraphics5: // 512 pixels @ 2bpp
return
std::make_pair(
0xc0 >> ((Storage<personality>::command_->location.v[0] & 3) << 1),
Storage<personality>::command_context_.colour2bpp
);
case ScreenMode::YamahaGraphics7: // 256 pixels @ 8bpp
return
std::make_pair(
0xff,
Storage<personality>::command_context_.colour
);
}
} else {
return std::make_pair(0, 0);
}
}
void do_external_slot(int access_column) {
// Don't do anything if the required time for the access to become executable
// has yet to pass.
@ -593,56 +653,47 @@ template <Personality personality> struct Base: public Storage<personality> {
return;
}
// Compute the affected address and pixel
unsigned address;
uint8_t mask;
switch(this->screen_mode_) {
default:
case ScreenMode::YamahaGraphics4: // 256 pixels @ 4bpp
address =
(Storage<personality>::command_->location.v[0] >> 1) +
(Storage<personality>::command_->location.v[1] << 7);
mask = 0xf0 >> ((Storage<personality>::command_->location.v[0] & 1) << 2);
break;
case ScreenMode::YamahaGraphics5: // 512 pixels @ 2bpp
address =
(Storage<personality>::command_->location.v[0] >> 2) +
(Storage<personality>::command_->location.v[1] << 7);
mask = 0xc0 >> ((Storage<personality>::command_->location.v[0] & 3) << 1);
break;
case ScreenMode::YamahaGraphics6: // 512 pixels @ 4bpp
address =
(Storage<personality>::command_->location.v[0] >> 1) +
(Storage<personality>::command_->location.v[1] << 8);
mask = 0xf0 >> ((Storage<personality>::command_->location.v[0] & 1) << 2);
break;
case ScreenMode::YamahaGraphics7: // 256 pixels @ 8bpp
address =
(Storage<personality>::command_->location.v[0] >> 0) +
(Storage<personality>::command_->location.v[1] << 8);
mask = 0xff;
break;
}
switch(Storage<personality>::next_command_step_) {
// Duplicative, but keeps the compiler happy.
case CommandStep::None:
break;
case CommandStep::ReadPixel:
Storage<personality>::command_latch_ = ram_[address];
Storage<personality>::command_latch_ = ram_[command_address()];
Storage<personality>::minimum_command_column_ = access_column + 24;
Storage<personality>::next_command_step_ = CommandStep::WritePixel;
break;
case CommandStep::WritePixel: {
uint8_t packed_colour = Storage<personality>::command_context_.colour & 3;
packed_colour |= packed_colour << 2;
packed_colour |= packed_colour << 4;
const auto [mask, unmasked_colour] = command_colour_mask();
const auto address = command_address();
const uint8_t colour = unmasked_colour & mask;
using LogicalOperation = CommandContext::LogicalOperation;
if(!Storage<personality>::command_context_.test_source || colour) {
switch(Storage<personality>::command_context_.pixel_operation) {
default:
case LogicalOperation::Copy:
Storage<personality>::command_latch_ &= ~mask;
Storage<personality>::command_latch_ |= colour;
break;
case LogicalOperation::And:
Storage<personality>::command_latch_ &= ~mask | colour;
break;
case LogicalOperation::Or:
Storage<personality>::command_latch_ |= colour;
break;
case LogicalOperation::Xor:
Storage<personality>::command_latch_ ^= colour;
break;
case LogicalOperation::Not:
Storage<personality>::command_latch_ &= ~mask;
Storage<personality>::command_latch_ |= colour ^ mask;
break;
}
}
Storage<personality>::command_latch_ &= ~mask;
Storage<personality>::command_latch_ |= packed_colour & mask;
ram_[address] = Storage<personality>::command_latch_;
Storage<personality>::command_->advance();

View File

@ -51,9 +51,9 @@ struct CommandContext {
/// Colour as written by the CPU.
uint8_t colour = 0;
/// The low four bits of the CPU-written colour, repeated twice.
uint8_t colour4pp = 0;
uint8_t colour4bpp = 0;
/// The low two bits of the CPU-written colour, repeated four times.
uint8_t colour2pp = 0;
uint8_t colour2bpp = 0;
enum class LogicalOperation {
Copy = 0b0000,
@ -61,14 +61,9 @@ struct CommandContext {
Or = 0b0010,
Xor = 0b0011,
Not = 0b0100,
ConditionalCopy = 0b1000,
ConditionalAnd = 0b1001,
ConditionalOr = 0b1010,
ConditionalXor = 0b1011,
ConditionalNot = 0b1100,
};
LogicalOperation pixel_operation;
bool test_source;
};
struct Command {