diff --git a/Machines/Acorn/Archimedes/MemoryController.hpp b/Machines/Acorn/Archimedes/MemoryController.hpp index 2e43da591..3a1614a0d 100644 --- a/Machines/Acorn/Archimedes/MemoryController.hpp +++ b/Machines/Acorn/Archimedes/MemoryController.hpp @@ -106,8 +106,9 @@ struct MemoryController { case 0b111: os_mode_ = address & (1 << 12); sound_dma_enable_ = address & (1 << 11); - ioc_.sound().set_dma_enabled(sound_dma_enable_); video_dma_enable_ = address & (1 << 10); + ioc_.sound().set_dma_enabled(sound_dma_enable_); + ioc_.video().set_dma_enabled(video_dma_enable_); switch((address >> 8) & 3) { default: dynamic_ram_refresh_ = DynamicRAMRefresh::None; diff --git a/Machines/Acorn/Archimedes/Video.hpp b/Machines/Acorn/Archimedes/Video.hpp index 607f82c0d..282a38836 100644 --- a/Machines/Acorn/Archimedes/Video.hpp +++ b/Machines/Acorn/Archimedes/Video.hpp @@ -15,6 +15,7 @@ #include #include #include +#include namespace Archimedes { @@ -243,6 +244,30 @@ struct Video { return overages_; } + void set_dma_enabled(bool dma_enabled) { + dma_enabled_ = dma_enabled; + } + + // + // The following is provided for input automation; + // it does not correlate with real hardware functionality. + // + std::optional> cursor_location() { + if( + !dma_enabled_ || + vertical_timing_.cursor_end <= vertical_timing_.cursor_start || + horizontal_timing_.cursor_start >= (horizontal_timing_.period * 2) + + ) { + return std::nullopt; + } + + const auto horizontal_start = horizontal_timing_.display_start + horizontal_state_.output_latency(colour_depth_); + return std::make_pair( + horizontal_timing_.cursor_start + 6 - (horizontal_start * 2), + vertical_timing_.cursor_start - vertical_timing_.display_start); + } + private: Log::Logger logger; InterruptObserverT &interrupt_observer_; @@ -253,6 +278,7 @@ private: // being deferred to the component itself. const uint8_t *ram_ = nullptr; Outputs::CRT::CRT crt_; + bool dma_enabled_ = false; // Horizontal and vertical timing. struct Timing { @@ -330,11 +356,12 @@ private: } bool is_outputting(Depth depth) const { - return position >= display_start + output_latencies[static_cast(depth)] && position < display_end + output_latencies[static_cast(depth)]; + const auto latency = output_latency(depth); + return position >= display_start + latency && position < display_end + latency; } uint32_t output_cycle(Depth depth) const { - return position - display_start - output_latencies[static_cast(depth)]; + return position - display_start - output_latency(depth); } static constexpr uint32_t output_latencies[] = { @@ -343,6 +370,9 @@ private: 7 >> 1, // 4 bpp. 5 >> 1 // 8 bpp. }; + uint32_t output_latency(Depth depth) const { + return output_latencies[static_cast(depth)]; + } static constexpr uint8_t SyncEnded = 0x1; static constexpr uint8_t BorderStarted = 0x2;