1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-25 16:31:42 +00:00

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.
This commit is contained in:
Thomas Harte 2021-11-13 15:53:41 -05:00
parent f906bab1a5
commit 47f36f08fb
9 changed files with 33 additions and 34 deletions

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -141,7 +141,7 @@ template <int cycle> 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 <int cycle, bool stop_if_cpu> 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 <int cycle, bool stop_if_cpu> 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 <int cycle, bool stop_if_cpu> 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 <int cycle, bool stop_if_cpu> 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 <int cycle, bool stop_if_cpu> 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 <int cycle, bool stop_if_cpu> 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<index, 16>(cycle.value16()); break; \
case Write(pointer + 2): audio_->set_pointer<index, 0>(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<index, 16>(cycle.value16()); break; \
case Write(pointer + 2): audio_.set_pointer<index, 0>(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();
}

View File

@ -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, Cycles> 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);

View File

@ -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;

View File

@ -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 <int id> void reload() {

View File

@ -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_) {