1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-23 20:29:42 +00:00

Adds some semblance of an AY.

This commit is contained in:
Thomas Harte 2019-10-06 22:30:48 -04:00
parent 87a6d22894
commit 3bb0bf9e14

View File

@ -12,8 +12,13 @@
#include "../../Processors/68000/68000.hpp"
#include "../../Components/AY38910/AY38910.hpp"
#include "Video.hpp"
#include "../../ClockReceiver/JustInTime.hpp"
#include "../../ClockReceiver/ForceInline.hpp"
#include "../../Outputs/Speaker/Implementation/LowpassSpeaker.hpp"
#include "../Utility/MemoryPacker.hpp"
#include "../Utility/MemoryFuzzer.hpp"
@ -31,8 +36,11 @@ class ConcreteMachine:
public CRTMachine::Machine {
public:
ConcreteMachine(const Target &target, const ROMMachine::ROMFetcher &rom_fetcher) :
mc68000_(*this) {
mc68000_(*this),
ay_(audio_queue_),
speaker_(ay_) {
set_clock_rate(CLOCK_RATE);
speaker_.set_input_rate(CLOCK_RATE / 4);
ram_.resize(512 * 512);
Memory::Fuzz(ram_);
@ -58,13 +66,17 @@ class ConcreteMachine:
memory_map_[0xff] = BusDevice::IO;
}
~ConcreteMachine() {
audio_queue_.flush();
}
// MARK: CRTMachine::Machine
void set_scan_target(Outputs::Display::ScanTarget *scan_target) final {
video_->set_scan_target(scan_target);
}
Outputs::Speaker::Speaker *get_speaker() final {
return nullptr;
return &speaker_;
}
void run_for(const Cycles cycles) final {
@ -75,7 +87,7 @@ class ConcreteMachine:
using Microcycle = CPU::MC68000::Microcycle;
HalfCycles perform_bus_operation(const CPU::MC68000::Microcycle &cycle, int is_supervisor) {
// Advance time.
video_ += cycle.length;
advance_time(cycle.length);
// A null cycle leaves nothing else to do.
if(!(cycle.operation & (Microcycle::NewAddress | Microcycle::SameAddress))) return HalfCycles(0);
@ -83,6 +95,7 @@ class ConcreteMachine:
/* TODO: DTack, bus error, VPA. */
auto address = cycle.word_address();
if(cycle.data_select_active()) printf("%c %06x\n", (cycle.operation & Microcycle::Read) ? 'r' : 'w', *cycle.address & 0xffffff);
uint16_t *memory;
switch(memory_map_[address >> 15]) {
case BusDevice::MostlyRAM:
@ -118,11 +131,51 @@ class ConcreteMachine:
return HalfCycles(0);
case BusDevice::Unassigned:
assert(false);
return HalfCycles(0);
case BusDevice::IO:
assert(false);
break;
switch(address) {
default:
assert(false);
case 0x7fc000:
/* Memory controller configuration:
b0, b1: bank 1
b2, b3: bank 0
00 = 128k
01 = 512k
10 = 2mb
11 = reserved
*/
break;
case 0x7fc400: /* PSG: write to select register, read to read register. */
case 0x7fc401: /* PSG: write to write register. */
if(!cycle.data_select_active()) return HalfCycles(0);
// TODO: byte accesses to the odd addresses shouldn't obey logic below.
advance_time(HalfCycles(2));
update_audio();
if(cycle.operation & Microcycle::Read) {
ay_.set_control_lines(GI::AY38910::ControlLines(GI::AY38910::BC2 | GI::AY38910::BC1));
cycle.value->halves.low = ay_.get_data_output();
ay_.set_control_lines(GI::AY38910::ControlLines(0));
} else {
if(address == 0x7fc400) {
ay_.set_control_lines(GI::AY38910::BC1);
ay_.set_data_input(cycle.value->halves.low);
ay_.set_control_lines(GI::AY38910::ControlLines(0));
} else {
ay_.set_control_lines(GI::AY38910::ControlLines(GI::AY38910::BC2 | GI::AY38910::BDIR));
ay_.set_data_input(cycle.value->halves.low);
ay_.set_control_lines(GI::AY38910::ControlLines(0));
}
}
return HalfCycles(2);
}
return HalfCycles(0);
}
// If control has fallen through to here, the access is either a read from ROM, or a read or write to RAM.
@ -150,10 +203,28 @@ class ConcreteMachine:
return HalfCycles(0);
}
void flush() {
audio_queue_.perform();
}
private:
forceinline void advance_time(HalfCycles length) {
video_ += length;
cycles_since_audio_update_ += length;
}
void update_audio() {
speaker_.run_for(audio_queue_, cycles_since_audio_update_.divide_cycles(Cycles(4)));
}
CPU::MC68000::Processor<ConcreteMachine, true> mc68000_;
JustInTimeActor<Video, HalfCycles> video_;
Concurrency::DeferringAsyncTaskQueue audio_queue_;
GI::AY38910::AY38910 ay_;
Outputs::Speaker::LowpassSpeaker<GI::AY38910::AY38910> speaker_;
HalfCycles cycles_since_audio_update_;
std::vector<uint16_t> ram_;
std::vector<uint16_t> rom_;