From 47f36f08fb13ad36a30f17848b9ae78ea1e302fc Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 13 Nov 2021 15:53:41 -0500 Subject: [PATCH] Switches to a synchronous audio state machine; renames advance -> advance_dma. I can worry about how to just-in-time things once I better understand the hardware in general. --- Machines/Amiga/Audio.cpp | 4 ++-- Machines/Amiga/Audio.hpp | 8 ++++---- Machines/Amiga/Blitter.cpp | 2 +- Machines/Amiga/Blitter.hpp | 2 +- Machines/Amiga/Chipset.cpp | 37 ++++++++++++++++++------------------- Machines/Amiga/Chipset.hpp | 8 ++++---- Machines/Amiga/Copper.cpp | 2 +- Machines/Amiga/Copper.hpp | 2 +- Machines/Amiga/Disk.cpp | 2 +- 9 files changed, 33 insertions(+), 34 deletions(-) diff --git a/Machines/Amiga/Audio.cpp b/Machines/Amiga/Audio.cpp index 3cb36159b..302bec962 100644 --- a/Machines/Amiga/Audio.cpp +++ b/Machines/Amiga/Audio.cpp @@ -17,7 +17,7 @@ using namespace Amiga; -bool Audio::advance(int channel) { +bool Audio::advance_dma(int channel) { if(channels_[channel].has_data || !channels_[channel].length) { return false; } @@ -70,7 +70,7 @@ void Audio::set_interrupt_requests(uint16_t requests) { channels_[3].interrupt_pending = requests & uint16_t(InterruptFlag::AudioChannel3); } -void Audio::run_for([[maybe_unused]] Cycles duration) { +void Audio::output() { // TODO: // // Check whether any channel's period counter is exhausted and, if diff --git a/Machines/Amiga/Audio.hpp b/Machines/Amiga/Audio.hpp index 867be81df..f998843dc 100644 --- a/Machines/Amiga/Audio.hpp +++ b/Machines/Amiga/Audio.hpp @@ -24,11 +24,11 @@ class Audio: public DMADevice<4> { /// Idiomatic call-in for DMA scheduling; indicates that this class may /// perform a DMA access for the stated channel now. - bool advance(int channel); + bool advance_dma(int channel); - /// Standard JustInTimeActor item; allows this class to track the - /// amount of time between other events. - void run_for(Cycles); + /// Advances output by one DMA window, which is implicitly two cycles + /// at the output rate that was specified to the constructor. + void output(); /// Sets the total number of words to fetch for the given channel. void set_length(int channel, uint16_t); diff --git a/Machines/Amiga/Blitter.cpp b/Machines/Amiga/Blitter.cpp index 66e7ed71f..f5196d119 100644 --- a/Machines/Amiga/Blitter.cpp +++ b/Machines/Amiga/Blitter.cpp @@ -95,7 +95,7 @@ uint16_t Blitter::get_status() { return result; } -bool Blitter::advance() { +bool Blitter::advance_dma() { if(!height_) return false; not_zero_flag_ = false; diff --git a/Machines/Amiga/Blitter.hpp b/Machines/Amiga/Blitter.hpp index 2ece312db..334ade11f 100644 --- a/Machines/Amiga/Blitter.hpp +++ b/Machines/Amiga/Blitter.hpp @@ -37,7 +37,7 @@ class Blitter: public DMADevice<4, 4> { uint16_t get_status(); - bool advance(); + bool advance_dma(); private: int width_ = 0, height_ = 0; diff --git a/Machines/Amiga/Chipset.cpp b/Machines/Amiga/Chipset.cpp index 8972d529e..bc5517211 100644 --- a/Machines/Amiga/Chipset.cpp +++ b/Machines/Amiga/Chipset.cpp @@ -141,7 +141,7 @@ template void Chipset::output() { static_assert(blank3 == 43); // Advance audio. - audio_ += Cycles(1); + audio_.output(); // Trigger any sprite loads encountered. constexpr auto dcycle = cycle << 1; @@ -347,7 +347,7 @@ template bool Chipset::perform_cycle() { if((dma_control_ & BitplaneFlag) == BitplaneFlag) { // TODO: offer a cycle for bitplane collection. // Probably need to indicate odd or even? - if(fetch_vertical_ && fetch_horizontal_ && bitplanes_.advance(cycle)) { + if(fetch_vertical_ && fetch_horizontal_ && bitplanes_.advance_dma(cycle)) { did_fetch_ = true; return false; } @@ -362,7 +362,7 @@ template bool Chipset::perform_cycle() { // Blitter and CPU priority is dealt with below. if constexpr (cycle >= 0x07 && cycle < 0x0d) { if((dma_control_ & DiskFlag) == DiskFlag) { - if(disk_.advance()) { + if(disk_.advance_dma()) { return false; } } @@ -371,7 +371,7 @@ template bool Chipset::perform_cycle() { if constexpr (cycle >= 0xd && cycle < 0x14) { constexpr auto channel = (cycle - 0xd) >> 1; if((dma_control_ & AudioFlags[channel]) == AudioFlags[channel]) { - if(audio_->advance(channel)) { + if(audio_.advance_dma(channel)) { return false; } } @@ -380,7 +380,7 @@ template bool Chipset::perform_cycle() { if constexpr (cycle >= 0x15 && cycle < 0x35) { if((dma_control_ & SpritesFlag) == SpritesFlag) { constexpr auto sprite_id = (cycle - 0x15) >> 2; - if(sprites_[sprite_id].advance(y_)) { + if(sprites_[sprite_id].advance_dma(y_)) { return false; } } @@ -391,7 +391,7 @@ template bool Chipset::perform_cycle() { // // The Blitter and CPU are dealt with outside of the odd/even test. if((dma_control_ & CopperFlag) == CopperFlag) { - if(copper_.advance(uint16_t(((y_ & 0xff) << 8) | (cycle & 0xfe)))) { + if(copper_.advance_dma(uint16_t(((y_ & 0xff) << 8) | (cycle & 0xfe)))) { return false; } } else { @@ -401,7 +401,7 @@ template bool Chipset::perform_cycle() { // Down here: give first refusal to the Blitter, otherwise // pass on to the CPU. - return (dma_control_ & BlitterFlag) != BlitterFlag || !blitter_.advance(); + return (dma_control_ & BlitterFlag) != BlitterFlag || !blitter_.advance_dma(); } /// Performs all slots starting with @c first_slot and ending just before @c last_slot. @@ -696,7 +696,7 @@ void Chipset::perform(const CPU::MC68000::Microcycle &cycle) { disk_controller_.set_control(paula_disk_control_); disk_.set_control(paula_disk_control_); - audio_->set_modulation_flags(paula_disk_control_); + audio_.set_modulation_flags(paula_disk_control_); break; case Read(0x010): // ADKCONR LOG("Read disk control"); @@ -735,7 +735,7 @@ void Chipset::perform(const CPU::MC68000::Microcycle &cycle) { break; case Write(0x096): // DMACON ApplySetClear(dma_control_, 0x1fff); - audio_->set_channel_enables(dma_control_); + audio_.set_channel_enables(dma_control_); break; // Interrupts. @@ -750,7 +750,7 @@ void Chipset::perform(const CPU::MC68000::Microcycle &cycle) { case Write(0x09c): // INTREQ ApplySetClear(interrupt_requests_, 0x7fff); update_interrupts(); - audio_->set_interrupt_requests(interrupt_requests_); + audio_.set_interrupt_requests(interrupt_requests_); break; case Read(0x01e): // INTREQR cycle.set_value16(interrupt_requests_); @@ -873,12 +873,12 @@ void Chipset::perform(const CPU::MC68000::Microcycle &cycle) { // Audio. #define Audio(index, pointer) \ - case Write(pointer + 0): audio_->set_pointer(cycle.value16()); break; \ - case Write(pointer + 2): audio_->set_pointer(cycle.value16()); break; \ - case Write(pointer + 4): audio_->set_length(index, cycle.value16()); break; \ - case Write(pointer + 6): audio_->set_period(index, cycle.value16()); break; \ - case Write(pointer + 8): audio_->set_volume(index, cycle.value16()); break; \ - case Write(pointer + 10): audio_->set_data(index, cycle.value16()); break; \ + case Write(pointer + 0): audio_.set_pointer(cycle.value16()); break; \ + case Write(pointer + 2): audio_.set_pointer(cycle.value16()); break; \ + case Write(pointer + 4): audio_.set_length(index, cycle.value16()); break; \ + case Write(pointer + 6): audio_.set_period(index, cycle.value16()); break; \ + case Write(pointer + 8): audio_.set_volume(index, cycle.value16()); break; \ + case Write(pointer + 10): audio_.set_data(index, cycle.value16()); break; \ Audio(0, 0x0a0); Audio(1, 0x0b0); @@ -966,7 +966,7 @@ void Chipset::perform(const CPU::MC68000::Microcycle &cycle) { // MARK: - Bitplanes. -bool Chipset::Bitplanes::advance(int cycle) { +bool Chipset::Bitplanes::advance_dma(int cycle) { #define BIND_CYCLE(offset, plane) \ case offset: \ if(plane_count_ > plane) { \ @@ -1049,7 +1049,7 @@ void Chipset::Sprite::set_image_data(int slot, uint16_t value) { active |= slot == 0; } -bool Chipset::Sprite::advance(int y) { +bool Chipset::Sprite::advance_dma(int y) { switch(dma_state_) { // i.e. stopped. default: return false; @@ -1290,5 +1290,4 @@ uint16_t Chipset::Mouse::get_position() { } void Chipset::flush() { - audio_.flush(); } diff --git a/Machines/Amiga/Chipset.hpp b/Machines/Amiga/Chipset.hpp index d9bc70493..aba4e3d25 100644 --- a/Machines/Amiga/Chipset.hpp +++ b/Machines/Amiga/Chipset.hpp @@ -143,7 +143,7 @@ class Chipset: private ClockingHint::Observer { void set_stop_and_control(uint16_t value); void set_image_data(int slot, uint16_t value); - bool advance(int y); + bool advance_dma(int y); void reset_dma(); uint16_t data[2]{}; @@ -244,7 +244,7 @@ class Chipset: private ClockingHint::Observer { public: using DMADevice::DMADevice; - bool advance(int cycle); + bool advance_dma(int cycle); void do_end_of_line(); void set_control(uint16_t); @@ -311,7 +311,7 @@ class Chipset: private ClockingHint::Observer { // MARK: - Audio. - JustInTimeActor audio_; + Audio audio_; // MARK: - Serial port. @@ -399,7 +399,7 @@ class Chipset: private ClockingHint::Observer { void set_length(uint16_t); void set_control(uint16_t); - bool advance(); + bool advance_dma(); void enqueue(uint16_t value, bool matches_sync); diff --git a/Machines/Amiga/Copper.cpp b/Machines/Amiga/Copper.cpp index 61777ddd6..516783c2d 100644 --- a/Machines/Amiga/Copper.cpp +++ b/Machines/Amiga/Copper.cpp @@ -18,7 +18,7 @@ using namespace Amiga; -bool Copper::advance(uint16_t position) { +bool Copper::advance_dma(uint16_t position) { switch(state_) { default: return false; diff --git a/Machines/Amiga/Copper.hpp b/Machines/Amiga/Copper.hpp index 8afee3efa..473cd00cb 100644 --- a/Machines/Amiga/Copper.hpp +++ b/Machines/Amiga/Copper.hpp @@ -20,7 +20,7 @@ class Copper: public DMADevice<2> { /// Offers a DMA slot to the Copper, specifying the current beam position. /// /// @returns @c true if the slot was used; @c false otherwise. - bool advance(uint16_t position); + bool advance_dma(uint16_t position); /// Forces a reload of address @c id (i.e. 0 or 1) and restarts the Copper. template void reload() { diff --git a/Machines/Amiga/Disk.cpp b/Machines/Amiga/Disk.cpp index 7e18ff580..be1c278f7 100644 --- a/Machines/Amiga/Disk.cpp +++ b/Machines/Amiga/Disk.cpp @@ -51,7 +51,7 @@ void Chipset::DiskDMA::set_length(uint16_t value) { last_set_length_ = value; } -bool Chipset::DiskDMA::advance() { +bool Chipset::DiskDMA::advance_dma() { if(!dma_enable_) return false; if(!write_) {