mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-27 01:31:42 +00:00
Attempts a full audio wiring.
This commit is contained in:
parent
4a4da90d56
commit
17f551e89d
@ -49,6 +49,7 @@ template<Model model> class ConcreteMachine:
|
|||||||
speaker_(mixer_)
|
speaker_(mixer_)
|
||||||
{
|
{
|
||||||
set_clock_rate(ClockRate);
|
set_clock_rate(ClockRate);
|
||||||
|
speaker_.set_input_rate(float(ClockRate) / 2.0f);
|
||||||
|
|
||||||
// With only the +2a and +3 currently supported, the +3 ROM is always
|
// With only the +2a and +3 currently supported, the +3 ROM is always
|
||||||
// the one required.
|
// the one required.
|
||||||
@ -64,12 +65,21 @@ template<Model model> class ConcreteMachine:
|
|||||||
(void)target;
|
(void)target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~ConcreteMachine() {
|
||||||
|
audio_queue_.flush();
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - TimedMachine
|
// MARK: - TimedMachine
|
||||||
|
|
||||||
void run_for(const Cycles cycles) override {
|
void run_for(const Cycles cycles) override {
|
||||||
z80_.run_for(cycles);
|
z80_.run_for(cycles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void flush() {
|
||||||
|
update_audio();
|
||||||
|
audio_queue_.perform();
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - ScanProducer
|
// MARK: - ScanProducer
|
||||||
|
|
||||||
void set_scan_target(Outputs::Display::ScanTarget *scan_target) final {
|
void set_scan_target(Outputs::Display::ScanTarget *scan_target) final {
|
||||||
@ -84,6 +94,8 @@ template<Model model> class ConcreteMachine:
|
|||||||
// MARK: - BusHandler
|
// MARK: - BusHandler
|
||||||
|
|
||||||
forceinline HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) {
|
forceinline HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) {
|
||||||
|
time_since_audio_update_ += cycle.length;
|
||||||
|
|
||||||
// Ignore all but terminal cycles.
|
// Ignore all but terminal cycles.
|
||||||
// TODO: I doubt this is correct for timing.
|
// TODO: I doubt this is correct for timing.
|
||||||
if(!cycle.is_terminal()) return HalfCycles(0);
|
if(!cycle.is_terminal()) return HalfCycles(0);
|
||||||
@ -103,22 +115,42 @@ template<Model model> class ConcreteMachine:
|
|||||||
|
|
||||||
case PartialMachineCycle::Output:
|
case PartialMachineCycle::Output:
|
||||||
if(!(address&1)) {
|
if(!(address&1)) {
|
||||||
// TODO: port FE.
|
// TODO: rest of port FE.
|
||||||
|
update_audio();
|
||||||
|
audio_toggle_.set_output(*cycle.value & 0x10);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(address) {
|
switch(address) {
|
||||||
default: break;
|
default: break;
|
||||||
|
|
||||||
case 0x1ffd:
|
case 0x1ffd:
|
||||||
|
// Write to +2a/+3 paging register.
|
||||||
port1ffd_ = *cycle.value;
|
port1ffd_ = *cycle.value;
|
||||||
update_memory_map();
|
update_memory_map();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x7ffd:
|
case 0x7ffd:
|
||||||
|
// Write to classic 128kb paging register.
|
||||||
disable_paging_ |= *cycle.value & 0x20;
|
disable_paging_ |= *cycle.value & 0x20;
|
||||||
port7ffd_ = *cycle.value;
|
port7ffd_ = *cycle.value;
|
||||||
update_memory_map();
|
update_memory_map();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 0xfffd:
|
||||||
|
// Select AY register.
|
||||||
|
update_audio();
|
||||||
|
ay_.set_control_lines(GI::AY38910::ControlLines(GI::AY38910::BDIR | GI::AY38910::BC2 | GI::AY38910::BC1));
|
||||||
|
ay_.set_data_input(*cycle.value);
|
||||||
|
ay_.set_control_lines(GI::AY38910::ControlLines(0));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xbffd:
|
||||||
|
// Write to AY register.
|
||||||
|
update_audio();
|
||||||
|
ay_.set_control_lines(GI::AY38910::ControlLines(GI::AY38910::BDIR | GI::AY38910::BC2));
|
||||||
|
ay_.set_data_input(*cycle.value);
|
||||||
|
ay_.set_control_lines(GI::AY38910::ControlLines(0));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -126,6 +158,18 @@ template<Model model> class ConcreteMachine:
|
|||||||
if(!(address&1)) {
|
if(!(address&1)) {
|
||||||
// TODO: port FE.
|
// TODO: port FE.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch(address) {
|
||||||
|
default: break;
|
||||||
|
|
||||||
|
case 0xfffd:
|
||||||
|
// Read from AY register.
|
||||||
|
update_audio();
|
||||||
|
ay_.set_control_lines(GI::AY38910::ControlLines(GI::AY38910::BC2 | GI::AY38910::BC1));
|
||||||
|
*cycle.value &= ay_.get_data_output();
|
||||||
|
ay_.set_control_lines(GI::AY38910::ControlLines(0));
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,6 +257,11 @@ template<Model model> class ConcreteMachine:
|
|||||||
Audio::Toggle audio_toggle_;
|
Audio::Toggle audio_toggle_;
|
||||||
Outputs::Speaker::CompoundSource<GI::AY38910::AY38910<false>, Audio::Toggle> mixer_;
|
Outputs::Speaker::CompoundSource<GI::AY38910::AY38910<false>, Audio::Toggle> mixer_;
|
||||||
Outputs::Speaker::LowpassSpeaker<Outputs::Speaker::CompoundSource<GI::AY38910::AY38910<false>, Audio::Toggle>> speaker_;
|
Outputs::Speaker::LowpassSpeaker<Outputs::Speaker::CompoundSource<GI::AY38910::AY38910<false>, Audio::Toggle>> speaker_;
|
||||||
|
|
||||||
|
HalfCycles time_since_audio_update_;
|
||||||
|
void update_audio() {
|
||||||
|
speaker_.run_for(audio_queue_, time_since_audio_update_.divide_cycles(Cycles(2)));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user