mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-25 16:31:42 +00:00
Fill in and use some parts of mode description.
This commit is contained in:
parent
a6251f436a
commit
e66a92d6cb
@ -346,6 +346,13 @@ void TMS9918<personality>::run_for(const HalfCycles cycles) {
|
||||
this->screen_mode_ = this->template current_screen_mode<true>();
|
||||
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.
|
||||
next_line_buffer.first_pixel_output_column = Timing<personality>::FirstPixelCycle;
|
||||
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_->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);
|
||||
}
|
||||
break;
|
||||
|
@ -391,7 +391,7 @@ template <Personality personality> struct Base: public Storage<personality> {
|
||||
case CommandStep::CopySourcePixelToStatus:
|
||||
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);
|
||||
break;
|
||||
|
||||
@ -441,7 +441,7 @@ template <Personality personality> struct Base: public Storage<personality> {
|
||||
|
||||
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);
|
||||
} 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;
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
@ -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 {
|
||||
Text,
|
||||
Character,
|
||||
|
@ -139,7 +139,7 @@ struct Command {
|
||||
|
||||
/// Repopulates the fields above with the next action to take, being provided with the
|
||||
/// number of pixels per byte in the current screen mode.
|
||||
virtual void advance(int pixels_per_byte) = 0;
|
||||
virtual void advance() = 0;
|
||||
|
||||
protected:
|
||||
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];
|
||||
}
|
||||
|
||||
void advance(int) final {
|
||||
void advance() final {
|
||||
--context.size.v[0];
|
||||
cycles = 88;
|
||||
|
||||
@ -231,7 +231,7 @@ template <bool is_read> struct Point: public Command {
|
||||
return done_;
|
||||
}
|
||||
|
||||
void advance(int) final {
|
||||
void advance() final {
|
||||
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;
|
||||
/// @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) {
|
||||
bool advance_pixel() {
|
||||
if constexpr (logical) {
|
||||
advance_axis<0, include_source>();
|
||||
--context.size.v[0];
|
||||
@ -273,10 +270,10 @@ template <bool logical, bool include_source> struct Rectangle: public Command {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
advance_axis<0, include_source>(pixels_per_byte);
|
||||
context.size.v[0] -= pixels_per_byte;
|
||||
advance_axis<0, include_source>(mode_description.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;
|
||||
}
|
||||
}
|
||||
@ -312,7 +309,7 @@ template <bool logical> struct MoveFromCPU: public Rectangle<logical, false> {
|
||||
Command::access = logical ? Command::AccessType::PlotPoint : Command::AccessType::WriteByte;
|
||||
}
|
||||
|
||||
void advance(int pixels_per_byte) final {
|
||||
void advance() final {
|
||||
switch(Command::access) {
|
||||
default: break;
|
||||
|
||||
@ -325,7 +322,7 @@ template <bool logical> struct MoveFromCPU: public Rectangle<logical, false> {
|
||||
case Command::AccessType::PlotPoint:
|
||||
Command::cycles = 0;
|
||||
Command::access = Command::AccessType::WaitForColourReceipt;
|
||||
if(Rectangle<logical, false>::advance_pixel(pixels_per_byte)) {
|
||||
if(Rectangle<logical, false>::advance_pixel()) {
|
||||
Command::cycles = 64;
|
||||
// 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;
|
||||
}
|
||||
|
||||
void advance(int pixels_per_byte) final {
|
||||
void advance() final {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -369,9 +366,9 @@ struct HighSpeedFill: public Rectangle<false, false> {
|
||||
access = AccessType::WriteByte;
|
||||
}
|
||||
|
||||
void advance(int pixels_per_byte) final {
|
||||
void advance() final {
|
||||
cycles = 48;
|
||||
if(advance_pixel(pixels_per_byte)) {
|
||||
if(advance_pixel()) {
|
||||
cycles += 56;
|
||||
}
|
||||
}
|
||||
@ -383,7 +380,7 @@ struct LogicalFill: public Rectangle<false, false> {
|
||||
access = AccessType::PlotPoint;
|
||||
}
|
||||
|
||||
void advance(int) final {
|
||||
void advance() final {
|
||||
cycles = 72;
|
||||
if(advance_pixel()) {
|
||||
cycles += 64;
|
||||
|
Loading…
Reference in New Issue
Block a user