From a315384e30d093dcfc18beab751ab08c7689da6c Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Tue, 31 Jan 2023 21:29:55 -0500 Subject: [PATCH] Provide context for byte-by-byte commands. --- Components/9918/Implementation/9918.cpp | 2 +- Components/9918/Implementation/9918Base.hpp | 6 ++-- .../9918/Implementation/AccessEnums.hpp | 17 ++++++++++ .../9918/Implementation/YamahaCommands.hpp | 33 ++++++++++++++----- 4 files changed, 44 insertions(+), 14 deletions(-) diff --git a/Components/9918/Implementation/9918.cpp b/Components/9918/Implementation/9918.cpp index 178e45d60..510b5ed1c 100644 --- a/Components/9918/Implementation/9918.cpp +++ b/Components/9918/Implementation/9918.cpp @@ -871,7 +871,7 @@ void Base::commit_register(int reg, uint8_t value) { Storage::command_ && Storage::command_->access == Command::AccessType::WaitForColourReceipt ) { - Storage::command_->advance(); + Storage::command_->advance(pixels_per_byte(this->screen_mode_)); Storage::update_command_step(fetch_pointer_.column); } break; diff --git a/Components/9918/Implementation/9918Base.hpp b/Components/9918/Implementation/9918Base.hpp index 3ec608949..8d5b36309 100644 --- a/Components/9918/Implementation/9918Base.hpp +++ b/Components/9918/Implementation/9918Base.hpp @@ -365,8 +365,6 @@ template struct Storage struct Base: public Storage { ram_[address] = Storage::command_latch_; - Storage::command_->advance(); + Storage::command_->advance(pixels_per_byte(this->screen_mode_)); Storage::update_command_step(access_column); } break; case CommandStep::WriteByte: ram_[command_address()] = Storage::command_context_.colour; - Storage::command_->advance(); + Storage::command_->advance(pixels_per_byte(this->screen_mode_)); Storage::update_command_step(access_column); break; } diff --git a/Components/9918/Implementation/AccessEnums.hpp b/Components/9918/Implementation/AccessEnums.hpp index 66a80ec1e..a2a079b64 100644 --- a/Components/9918/Implementation/AccessEnums.hpp +++ b/Components/9918/Implementation/AccessEnums.hpp @@ -39,6 +39,23 @@ enum class ScreenMode { YamahaGraphics2 = Graphics, }; +constexpr int pixels_per_byte(ScreenMode mode) { + switch(mode) { + case ScreenMode::Blank: return 0; + case ScreenMode::Text: return 6; + case ScreenMode::MultiColour: return 2; + case ScreenMode::ColouredText: return 8; + case ScreenMode::Graphics: return 8; + case ScreenMode::SMSMode4: return 2; + case ScreenMode::YamahaText80: return 6; + case ScreenMode::YamahaGraphics3: return 8; + case ScreenMode::YamahaGraphics4: return 2; + case ScreenMode::YamahaGraphics5: return 4; + case ScreenMode::YamahaGraphics6: return 2; + case ScreenMode::YamahaGraphics7: return 1; + } +} + enum class FetchMode { Text, Character, diff --git a/Components/9918/Implementation/YamahaCommands.hpp b/Components/9918/Implementation/YamahaCommands.hpp index 291066ea1..6eb9fa13d 100644 --- a/Components/9918/Implementation/YamahaCommands.hpp +++ b/Components/9918/Implementation/YamahaCommands.hpp @@ -95,14 +95,14 @@ struct Command { /// @returns @c true if all output from this command is done; @c false otherwise. virtual bool done() = 0; - /// Repopulates the fields above with the next action to take. - virtual void advance() = 0; + /// 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; protected: - template void advance_axis() { - context.destination.add(context.arguments & (0x4 << axis) ? -1 : 1); + template void advance_axis(int offset = 1) { + context.destination.add(context.arguments & (0x4 << axis) ? -offset : offset); } - }; // MARK: - Line drawing. @@ -136,7 +136,7 @@ struct Line: public Command { return !context.size.v[0]; } - void advance() final { + void advance(int) final { --context.size.v[0]; cycles = 88; @@ -186,7 +186,7 @@ struct PointSet: public Command { return done_; } - void advance() final { + void advance(int) final { done_ = true; } @@ -208,7 +208,7 @@ struct LogicalMoveFromCPU: public Command { location = context.destination; } - void advance() final { + void advance(int) final { switch(access) { default: break; @@ -258,8 +258,23 @@ struct HighSpeedFill: public Command { return true; } - void advance() final { + void advance(int pixels_per_byte) final { cycles = 48; + + // TODO: step at byte speed, not pixel speed. + advance_axis<0>(pixels_per_byte); + --context.size.v[0]; + + if(!context.size.v[0]) { + cycles += 56; + context.size.v[0] = width_; + context.destination.v[0] = start_x_; + + advance_axis<1>(); + --context.size.v[1]; + } + + location = context.destination; } private: