mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Attempt the full panoply of logical pixel modes, across all graphics modes.
This commit is contained in:
parent
a91a5b8d07
commit
6d7f189ce7
@ -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).
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user