From 4a42de4f181856f6a3357e2d2cde02330c431e18 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 20 Nov 2020 21:37:17 -0500 Subject: [PATCH] Attempts to add 5.25" drive support to the IIgs. I want to try some classic software. --- Components/DiskII/DiskIIDrive.cpp | 46 +++++++++++++++++++ Components/DiskII/DiskIIDrive.hpp | 33 +++++++++++++ .../DiskII/MacintoshDoubleDensityDrive.hpp | 2 +- Machines/Apple/AppleIIgs/AppleIIgs.cpp | 38 +++++++++------ .../Clock Signal.xcodeproj/project.pbxproj | 6 +++ 5 files changed, 110 insertions(+), 15 deletions(-) create mode 100644 Components/DiskII/DiskIIDrive.cpp create mode 100644 Components/DiskII/DiskIIDrive.hpp diff --git a/Components/DiskII/DiskIIDrive.cpp b/Components/DiskII/DiskIIDrive.cpp new file mode 100644 index 000000000..010e685c6 --- /dev/null +++ b/Components/DiskII/DiskIIDrive.cpp @@ -0,0 +1,46 @@ +// +// DiskIIDrive.cpp +// Clock Signal +// +// Created by Thomas Harte on 20/11/2020. +// Copyright © 2020 Thomas Harte. All rights reserved. +// + +#include "DiskIIDrive.hpp" + +using namespace Apple::Disk; + +DiskIIDrive::DiskIIDrive(int input_clock_rate) : + IWMDrive(input_clock_rate, 1) { + Drive::set_rotation_speed(300.0f); +} + +void DiskIIDrive::set_enabled(bool enabled) { + set_motor_on(enabled); +} + +void DiskIIDrive::set_control_lines(int lines) { + // If the stepper magnet selections have changed, and any is on, see how + // that moves the head. + if(lines ^ stepper_mask_ && lines) { + // Convert from a representation of bits set to the centre of pull. + int direction = 0; + if(lines&1) direction += (((stepper_position_ - 0) + 4)&7) - 4; + if(lines&2) direction += (((stepper_position_ - 2) + 4)&7) - 4; + if(lines&4) direction += (((stepper_position_ - 4) + 4)&7) - 4; + if(lines&8) direction += (((stepper_position_ - 6) + 4)&7) - 4; + const int bits_set = (lines&1) + ((lines >> 1)&1) + ((lines >> 2)&1) + ((lines >> 3)&1); + direction /= bits_set; + + // Compare to the stepper position to decide whether that pulls in the current cog notch, + // or grabs a later one. + step(Storage::Disk::HeadPosition(-direction, 4)); + stepper_position_ = (stepper_position_ - direction + 8) & 7; + printf("Step %0.2f\n", float(-direction) / 4.0f); + } + stepper_mask_ = lines; +} + +bool DiskIIDrive::read() { + return !!(stepper_mask_ & 2) || get_is_read_only(); +} diff --git a/Components/DiskII/DiskIIDrive.hpp b/Components/DiskII/DiskIIDrive.hpp new file mode 100644 index 000000000..e003919aa --- /dev/null +++ b/Components/DiskII/DiskIIDrive.hpp @@ -0,0 +1,33 @@ +// +// DiskIIDrive.hpp +// Clock Signal +// +// Created by Thomas Harte on 20/11/2020. +// Copyright © 2020 Thomas Harte. All rights reserved. +// + +#ifndef DiskIIDrive_hpp +#define DiskIIDrive_hpp + +#include "IWM.hpp" + +namespace Apple { +namespace Disk { + +class DiskIIDrive: public IWMDrive { + public: + DiskIIDrive(int input_clock_rate); + + private: + void set_enabled(bool) final; + void set_control_lines(int) final; + bool read() final; + + int stepper_mask_ = 0; + int stepper_position_ = 0; +}; + +} +} + +#endif /* DiskIIDrive_hpp */ diff --git a/Components/DiskII/MacintoshDoubleDensityDrive.hpp b/Components/DiskII/MacintoshDoubleDensityDrive.hpp index 4427d1a90..3c6bf5b8f 100644 --- a/Components/DiskII/MacintoshDoubleDensityDrive.hpp +++ b/Components/DiskII/MacintoshDoubleDensityDrive.hpp @@ -21,7 +21,7 @@ class DoubleDensityDrive: public IWMDrive { /*! @returns @c true if this is an 800kb drive; @c false otherwise. */ - bool is_800k() { + bool is_800k() const { return is_800k_; } diff --git a/Machines/Apple/AppleIIgs/AppleIIgs.cpp b/Machines/Apple/AppleIIgs/AppleIIgs.cpp index ef57b4de6..94855df01 100644 --- a/Machines/Apple/AppleIIgs/AppleIIgs.cpp +++ b/Machines/Apple/AppleIIgs/AppleIIgs.cpp @@ -23,6 +23,7 @@ #include "../../../Components/AudioToggle/AudioToggle.hpp" #include "../../../Components/DiskII/IWM.hpp" #include "../../../Components/DiskII/MacintoshDoubleDensityDrive.hpp" +#include "../../../Components/DiskII/DiskIIDrive.hpp" #include "../../../Outputs/Speaker/Implementation/CompoundSource.hpp" #include "../../../Outputs/Speaker/Implementation/LowpassSpeaker.hpp" @@ -56,10 +57,14 @@ class ConcreteMachine: ConcreteMachine(const Analyser::Static::AppleIIgs::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) : m65816_(*this), iwm_(CLOCK_RATE / 2), - drives_{ + drives35_{ {CLOCK_RATE / 2, true}, {CLOCK_RATE / 2, true} }, + drives525_{ + {CLOCK_RATE / 2}, + {CLOCK_RATE / 2} + }, sound_glu_(audio_queue_), audio_toggle_(audio_queue_), mixer_(sound_glu_, audio_toggle_), @@ -114,9 +119,8 @@ class ConcreteMachine: adb_glu_.set_is_rom03(target.model == Target::Model::ROM03); // Attach drives to the IWM. - // TODO: presumably attach more, some of which are 5.25"? - iwm_->set_drive(0, &drives_[0]); - iwm_->set_drive(1, &drives_[1]); + iwm_->set_drive(0, &drives35_[0]); + iwm_->set_drive(1, &drives35_[1]); // TODO: enable once machine is otherwise sane. // Memory::Fuzz(ram_); @@ -165,15 +169,22 @@ class ConcreteMachine: // MARK: MediaTarget. bool insert_media(const Analyser::Static::Media &media) final { if(!media.disks.empty()) { - drives_[0].set_disk(media.disks[0]); + const auto disk = media.disks[0]; + if(disk->get_maximum_head_position().as_int() > 35) { + drives35_[0].set_disk(media.disks[0]); + } else { + drives525_[0].set_disk(media.disks[0]); + } } return true; } // MARK: Activity::Source void set_activity_observer(Activity::Observer *observer) final { - drives_[0].set_activity_observer(observer, "First 3.5\" Drive", true); - drives_[1].set_activity_observer(observer, "Second 3.5\" Drive", true); + drives35_[0].set_activity_observer(observer, "First 3.5\" Drive", true); + drives35_[1].set_activity_observer(observer, "Second 3.5\" Drive", true); + drives525_[0].set_activity_observer(observer, "First 5.25\" Drive", true); + drives525_[1].set_activity_observer(observer, "Second 5.25\" Drive", true); } // MARK: BusHandler. @@ -514,13 +525,11 @@ class ConcreteMachine: // Presumably bit 6 selects between two 5.25" drives rather than the two 3.5"? if(*value & 0x40) { - iwm_->set_drive(0, &drives_[0]); - iwm_->set_drive(1, &drives_[1]); + iwm_->set_drive(0, &drives35_[0]); + iwm_->set_drive(1, &drives35_[1]); } else { - // TODO: add 5.25" drives. - // (and any Smartport devices?) - iwm_->set_drive(0, nullptr); - iwm_->set_drive(1, nullptr); + iwm_->set_drive(0, &drives525_[0]); + iwm_->set_drive(1, &drives525_[1]); } break; @@ -754,7 +763,8 @@ class ConcreteMachine: Zilog::SCC::z8530 scc_; JustInTimeActor iwm_; Cycles cycles_since_clock_tick_; - Apple::Macintosh::DoubleDensityDrive drives_[2]; + Apple::Macintosh::DoubleDensityDrive drives35_[2]; + Apple::Disk::DiskIIDrive drives525_[2]; // The audio parts. Concurrency::DeferringAsyncTaskQueue audio_queue_; diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index c34cd63f8..1622dc329 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -395,6 +395,7 @@ 4B7F188F2154825E00388727 /* MasterSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7F188C2154825D00388727 /* MasterSystem.cpp */; }; 4B7F1897215486A200388727 /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7F1896215486A100388727 /* StaticAnalyser.cpp */; }; 4B7F1898215486A200388727 /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7F1896215486A100388727 /* StaticAnalyser.cpp */; }; + 4B80CD6F2568A82C00176FCC /* DiskIIDrive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B80CD6D2568A82600176FCC /* DiskIIDrive.cpp */; }; 4B8318B022D3E531006DB630 /* AppleII.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BCE0050227CE8CA000CA200 /* AppleII.cpp */; }; 4B8318B122D3E53A006DB630 /* DiskIICard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BCE004E227CE8CA000CA200 /* DiskIICard.cpp */; }; 4B8318B222D3E53C006DB630 /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BCE004D227CE8CA000CA200 /* Video.cpp */; }; @@ -1303,6 +1304,8 @@ 4B7F1895215486A100388727 /* StaticAnalyser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StaticAnalyser.hpp; sourceTree = ""; }; 4B7F1896215486A100388727 /* StaticAnalyser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StaticAnalyser.cpp; sourceTree = ""; }; 4B80214322EE7C3E00068002 /* JustInTime.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = JustInTime.hpp; sourceTree = ""; }; + 4B80CD6D2568A82600176FCC /* DiskIIDrive.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DiskIIDrive.cpp; sourceTree = ""; }; + 4B80CD6E2568A82900176FCC /* DiskIIDrive.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DiskIIDrive.hpp; sourceTree = ""; }; 4B8334811F5D9FF70097E338 /* PartialMachineCycle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PartialMachineCycle.cpp; sourceTree = ""; }; 4B8334831F5DA0360097E338 /* Z80Storage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Z80Storage.cpp; sourceTree = ""; }; 4B8334851F5DA3780097E338 /* 6502Storage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = 6502Storage.cpp; sourceTree = ""; }; @@ -2330,6 +2333,8 @@ 4B302181208A550100773308 /* DiskII */ = { isa = PBXGroup; children = ( + 4B80CD6D2568A82600176FCC /* DiskIIDrive.cpp */, + 4B80CD6E2568A82900176FCC /* DiskIIDrive.hpp */, 4B302182208A550100773308 /* DiskII.hpp */, 4B302183208A550100773308 /* DiskII.cpp */, 4BEE1498227FC0EA00133682 /* IWM.cpp */, @@ -5191,6 +5196,7 @@ 4B4518A41F75FD1C00926311 /* OricMFMDSK.cpp in Sources */, 4B4B1A3C200198CA00A0F866 /* KonamiSCC.cpp in Sources */, 4BB0A65B2044FD3000FB3688 /* SN76489.cpp in Sources */, + 4B80CD6F2568A82C00176FCC /* DiskIIDrive.cpp in Sources */, 4B894532201967B4007DE474 /* 6502.cpp in Sources */, 4BDB61EC203285AE0048AF91 /* Atari2600OptionsPanel.swift in Sources */, 4BBB70A8202014E2002FE009 /* MultiProducer.cpp in Sources */,