1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-01 11:49:58 +00:00

Fill in and use some parts of mode description.

This commit is contained in:
Thomas Harte 2023-03-18 23:07:33 -04:00
parent a6251f436a
commit e66a92d6cb
4 changed files with 48 additions and 21 deletions

View File

@ -346,6 +346,13 @@ void TMS9918<personality>::run_for(const HalfCycles cycles) {
this->screen_mode_ = this->template current_screen_mode<true>(); this->screen_mode_ = this->template current_screen_mode<true>();
this->underlying_mode_ = this->template current_screen_mode<false>(); this->underlying_mode_ = this->template current_screen_mode<false>();
if constexpr (is_yamaha_vdp(personality)) {
auto &desc = Storage<personality>::mode_description_;
desc.pixels_per_byte = pixels_per_byte(this->underlying_mode_);
desc.width = width(this->underlying_mode_);
desc.rotate_address = interleaves_banks(this->underlying_mode_);
}
// Based on the output mode, pick a line mode. // Based on the output mode, pick a line mode.
next_line_buffer.first_pixel_output_column = Timing<personality>::FirstPixelCycle; next_line_buffer.first_pixel_output_column = Timing<personality>::FirstPixelCycle;
next_line_buffer.next_border_column = Timing<personality>::CyclesPerLine; next_line_buffer.next_border_column = Timing<personality>::CyclesPerLine;
@ -903,7 +910,7 @@ void Base<personality>::commit_register(int reg, uint8_t value) {
Storage<personality>::command_ && Storage<personality>::command_ &&
Storage<personality>::command_->access == Command::AccessType::WaitForColourReceipt Storage<personality>::command_->access == Command::AccessType::WaitForColourReceipt
) { ) {
Storage<personality>::command_->advance(pixels_per_byte(this->underlying_mode_)); Storage<personality>::command_->advance();
Storage<personality>::update_command_step(fetch_pointer_.column); Storage<personality>::update_command_step(fetch_pointer_.column);
} }
break; break;

View File

@ -391,7 +391,7 @@ template <Personality personality> struct Base: public Storage<personality> {
case CommandStep::CopySourcePixelToStatus: case CommandStep::CopySourcePixelToStatus:
Storage<personality>::colour_status_ = extract_colour(source[command_address(context.source, context.arguments & 0x10)], context.source); Storage<personality>::colour_status_ = extract_colour(source[command_address(context.source, context.arguments & 0x10)], context.source);
Storage<personality>::command_->advance(pixels_per_byte(this->underlying_mode_)); Storage<personality>::command_->advance();
Storage<personality>::update_command_step(access_column); Storage<personality>::update_command_step(access_column);
break; break;
@ -441,7 +441,7 @@ template <Personality personality> struct Base: public Storage<personality> {
destination[address] = Storage<personality>::command_latch_; destination[address] = Storage<personality>::command_latch_;
Storage<personality>::command_->advance(pixels_per_byte(this->underlying_mode_)); Storage<personality>::command_->advance();
Storage<personality>::update_command_step(access_column); Storage<personality>::update_command_step(access_column);
} break; } break;
@ -460,7 +460,7 @@ template <Personality personality> struct Base: public Storage<personality> {
destination[command_address(context.destination, context.arguments & 0x20)] = context.latched_colour.has_value() ? context.latched_colour.colour : context.colour.colour; destination[command_address(context.destination, context.arguments & 0x20)] = context.latched_colour.has_value() ? context.latched_colour.colour : context.colour.colour;
context.latched_colour.reset(); context.latched_colour.reset();
Storage<personality>::command_->advance(pixels_per_byte(this->underlying_mode_)); Storage<personality>::command_->advance();
Storage<personality>::update_command_step(access_column); Storage<personality>::update_command_step(access_column);
break; break;
} }

View File

@ -57,6 +57,29 @@ constexpr int pixels_per_byte(ScreenMode mode) {
} }
} }
constexpr int width(ScreenMode mode) {
switch(mode) {
default:
case ScreenMode::Blank: return 0;
case ScreenMode::Text: return 240;
case ScreenMode::MultiColour: return 256;
case ScreenMode::ColouredText: return 256;
case ScreenMode::Graphics: return 256;
case ScreenMode::SMSMode4: return 256;
case ScreenMode::YamahaText80: return 480;
case ScreenMode::YamahaGraphics3: return 256;
case ScreenMode::YamahaGraphics4: return 256;
case ScreenMode::YamahaGraphics5: return 512;
case ScreenMode::YamahaGraphics6: return 512;
case ScreenMode::YamahaGraphics7: return 256;
}
}
constexpr bool interleaves_banks(ScreenMode mode) {
return mode == ScreenMode::YamahaGraphics6 || mode == ScreenMode::YamahaGraphics7;
}
enum class FetchMode { enum class FetchMode {
Text, Text,
Character, Character,

View File

@ -139,7 +139,7 @@ struct Command {
/// Repopulates the fields above with the next action to take, being provided with the /// Repopulates the fields above with the next action to take, being provided with the
/// number of pixels per byte in the current screen mode. /// number of pixels per byte in the current screen mode.
virtual void advance(int pixels_per_byte) = 0; virtual void advance() = 0;
protected: protected:
template <int axis, bool include_source> void advance_axis(int offset = 1) { template <int axis, bool include_source> void advance_axis(int offset = 1) {
@ -180,7 +180,7 @@ struct Line: public Command {
return !context.size.v[0]; return !context.size.v[0];
} }
void advance(int) final { void advance() final {
--context.size.v[0]; --context.size.v[0];
cycles = 88; cycles = 88;
@ -231,7 +231,7 @@ template <bool is_read> struct Point: public Command {
return done_; return done_;
} }
void advance(int) final { void advance() final {
done_ = true; done_ = true;
} }
@ -261,10 +261,7 @@ template <bool logical, bool include_source> struct Rectangle: public Command {
/// Advances the current destination and, if @c include_source is @c true also the source; /// 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. /// @returns @c true if a new row was started; @c false otherwise.
/// bool advance_pixel() {
/// @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) { if constexpr (logical) {
advance_axis<0, include_source>(); advance_axis<0, include_source>();
--context.size.v[0]; --context.size.v[0];
@ -273,10 +270,10 @@ template <bool logical, bool include_source> struct Rectangle: public Command {
return false; return false;
} }
} else { } else {
advance_axis<0, include_source>(pixels_per_byte); advance_axis<0, include_source>(mode_description.pixels_per_byte);
context.size.v[0] -= pixels_per_byte; context.size.v[0] -= mode_description.pixels_per_byte;
if(context.size.v[0] & ~(pixels_per_byte - 1)) { if(context.size.v[0] & ~(mode_description.pixels_per_byte - 1)) {
return false; return false;
} }
} }
@ -312,7 +309,7 @@ template <bool logical> struct MoveFromCPU: public Rectangle<logical, false> {
Command::access = logical ? Command::AccessType::PlotPoint : Command::AccessType::WriteByte; Command::access = logical ? Command::AccessType::PlotPoint : Command::AccessType::WriteByte;
} }
void advance(int pixels_per_byte) final { void advance() final {
switch(Command::access) { switch(Command::access) {
default: break; default: break;
@ -325,7 +322,7 @@ template <bool logical> struct MoveFromCPU: public Rectangle<logical, false> {
case Command::AccessType::PlotPoint: case Command::AccessType::PlotPoint:
Command::cycles = 0; Command::cycles = 0;
Command::access = Command::AccessType::WaitForColourReceipt; Command::access = Command::AccessType::WaitForColourReceipt;
if(Rectangle<logical, false>::advance_pixel(pixels_per_byte)) { if(Rectangle<logical, false>::advance_pixel()) {
Command::cycles = 64; Command::cycles = 64;
// TODO: I'm not sure this will be honoured per the outer wrapping. // TODO: I'm not sure this will be honoured per the outer wrapping.
} }
@ -353,9 +350,9 @@ template <MoveType type> struct Move: public Rectangle<type == MoveType::Logical
Command::y_only = is_y_only; Command::y_only = is_y_only;
} }
void advance(int pixels_per_byte) final { void advance() final {
Command::cycles = is_y_only ? 40 : 64; Command::cycles = is_y_only ? 40 : 64;
if(RectangleBase::advance_pixel(pixels_per_byte)) { if(RectangleBase::advance_pixel()) {
Command::cycles += is_y_only ? 0 : 64; Command::cycles += is_y_only ? 0 : 64;
} }
} }
@ -369,9 +366,9 @@ struct HighSpeedFill: public Rectangle<false, false> {
access = AccessType::WriteByte; access = AccessType::WriteByte;
} }
void advance(int pixels_per_byte) final { void advance() final {
cycles = 48; cycles = 48;
if(advance_pixel(pixels_per_byte)) { if(advance_pixel()) {
cycles += 56; cycles += 56;
} }
} }
@ -383,7 +380,7 @@ struct LogicalFill: public Rectangle<false, false> {
access = AccessType::PlotPoint; access = AccessType::PlotPoint;
} }
void advance(int) final { void advance() final {
cycles = 72; cycles = 72;
if(advance_pixel()) { if(advance_pixel()) {
cycles += 64; cycles += 64;