diff --git a/Machines/Tandy/CoCo/CoCo.cpp b/Machines/Tandy/CoCo/CoCo.cpp index f9fa7e0ab..f1e6e30b7 100644 --- a/Machines/Tandy/CoCo/CoCo.cpp +++ b/Machines/Tandy/CoCo/CoCo.cpp @@ -482,11 +482,9 @@ public: bus_phase_ &= 1; if constexpr (has_disk_drive) { - // Piggy-back off the existing bus_phase_ counter to multiply the clock by 4.5, - // giving very close to the standard 8Mhz. Unless and until a real clock speed emerges. - disk_controller_.run_for( - duration * 4 + bus_phase_ - ); + // Multiply by 4.5 to get very close to 8Mhz for the controller. + cycles_16mhz_ += duration * 9; + disk_controller_.run_for(cycles_16mhz_.divide(2)); } if(m6847_ += duration) { @@ -1012,11 +1010,18 @@ private: tape_player_.set_tape(media.tapes.front(), TargetPlatform::ThomsonMO); } + if(has_disk_drive && !media.disks.empty()) { + for(size_t c = 0; c < media.disks.size() && c < 4; c++) { + disk_controller_.set_disk(media.disks[c], c); + } + } + const bool had_cartridge = + !has_disk_drive && !media.cartridges.empty() && sam_.insert_cartridge(media.cartridges.front()->segments().front().data); - return !media.tapes.empty() || had_cartridge; + return !media.tapes.empty() || had_cartridge || (has_disk_drive && !media.disks.empty()); } ChangeEffect effect_for_file_did_change(const std::string &) const override { @@ -1042,6 +1047,9 @@ private: void set_activity_observer(Activity::Observer *const observer) override { tape_player_.set_activity_observer(observer); + if(has_disk_drive) { + disk_controller_.set_activity_observer(observer); + } } // MARK: - Joysticks. @@ -1100,6 +1108,7 @@ private: // MARK: - Disk. DiskController disk_controller_; + Cycles cycles_16mhz_; }; } diff --git a/Machines/Tandy/CoCo/DiskController.cpp b/Machines/Tandy/CoCo/DiskController.cpp index d0deec977..08ac739cc 100644 --- a/Machines/Tandy/CoCo/DiskController.cpp +++ b/Machines/Tandy/CoCo/DiskController.cpp @@ -11,10 +11,10 @@ using namespace Tandy::CoCo; DiskController::DiskController() : WD::WD1770(P1773) { - emplace_drives(2, 8'000'000, 300, 2); + emplace_drives(4, 8'000'000, 300, 2); } -void DiskController::set_control(uint8_t) { +void DiskController::set_control(const uint8_t value) { // TODO: // // b7: halt flag, 1 = enabled @@ -23,4 +23,33 @@ void DiskController::set_control(uint8_t) { // b4: write precompensation, 1 = enable // b3: drive motors, 1 = on // b0–b2: drive selects + + set_is_double_density(value & 0x20); + for_all_drives([&] (Storage::Disk::Drive &drive, size_t) { + drive.set_motor_on(value & 0x8); + }); + set_drive((value & 7) | ((value >> 3) & 8)); + + // TODO: HALT connection. +} + +void DiskController::set_disk(std::shared_ptr disk, const size_t drive) { + get_drive(drive).set_disk(disk); +} + +void DiskController::set_activity_observer(Activity::Observer *const observer) { + for_all_drives([observer] (Storage::Disk::Drive &drive, size_t index) { + drive.set_activity_observer(observer, "Drive " + std::to_string(index+1), true); + }); +} + +const Storage::Disk::Disk *DiskController::disk(const std::string &name) { + const Storage::Disk::Disk *result = nullptr; + for_all_drives( [&](Storage::Disk::Drive &drive, size_t) { + const auto disk = drive.disk(); + if(disk && disk->represents(name)) { + result = disk; + } + }); + return result; } diff --git a/Machines/Tandy/CoCo/DiskController.hpp b/Machines/Tandy/CoCo/DiskController.hpp index 615ad230c..423443c8c 100644 --- a/Machines/Tandy/CoCo/DiskController.hpp +++ b/Machines/Tandy/CoCo/DiskController.hpp @@ -9,6 +9,9 @@ #pragma once #include "Components/1770/1770.hpp" +#include "Activity/Observer.hpp" + +#include namespace Tandy::CoCo { @@ -35,6 +38,10 @@ public: set_control(value); } } + + void set_activity_observer(Activity::Observer *); + void set_disk(std::shared_ptr, size_t drive); + const Storage::Disk::Disk *disk(const std::string &); }; }