| 1 |
#ifndef REALDRIVE_HH |
| 2 |
#define REALDRIVE_HH |
| 3 |
|
| 4 |
#include "DiskChanger.hh" |
| 5 |
#include "DiskDrive.hh" |
| 6 |
|
| 7 |
#include "Clock.hh" |
| 8 |
#include "MSXMotherBoard.hh" |
| 9 |
#include "Schedulable.hh" |
| 10 |
#include "ThrottleManager.hh" |
| 11 |
#include "serialize_meta.hh" |
| 12 |
|
| 13 |
#include "outer.hh" |
| 14 |
|
| 15 |
#include <bitset> |
| 16 |
#include <optional> |
| 17 |
|
| 18 |
namespace openmsx { |
| 19 |
|
| 20 |
|
| 21 |
|
| 22 |
class RealDrive final : public DiskDrive, public MediaProvider |
| 23 |
{ |
| 24 |
public: |
| 25 |
static constexpr unsigned MAX_DRIVES = 26; |
| 26 |
using DrivesInUse = std::bitset<MAX_DRIVES>; |
| 27 |
static std::shared_ptr<DrivesInUse> getDrivesInUse(MSXMotherBoard& motherBoard); |
| 28 |
|
| 29 |
public: |
| 30 |
RealDrive(MSXMotherBoard& motherBoard, EmuDuration motorTimeout, |
| 31 |
bool signalsNeedMotorOn, bool doubleSided, unsigned nominalTracks, |
| 32 |
DiskDrive::TrackMode trackMode); |
| 33 |
~RealDrive() override; |
| 34 |
|
| 35 |
|
| 36 |
[[nodiscard]] bool isDiskInserted() const override; |
| 37 |
[[nodiscard]] bool isWriteProtected() const override; |
| 38 |
[[nodiscard]] bool isDoubleSided() override; |
| 39 |
[[nodiscard]] bool isTrack00() const override; |
| 40 |
void setSide(bool side) override; |
| 41 |
[[nodiscard]] bool getSide() const override; |
| 42 |
void step(bool direction, EmuTime time) override; |
| 43 |
void setMotor(bool status, EmuTime time) override; |
| 44 |
[[nodiscard]] bool getMotor() const override; |
| 45 |
[[nodiscard]] bool indexPulse(EmuTime time) override; |
| 46 |
[[nodiscard]] EmuTime getTimeTillIndexPulse(EmuTime time, int count) override; |
| 47 |
|
| 48 |
[[nodiscard]] unsigned getTrackLength() override; |
| 49 |
void writeTrackByte(int idx, uint8_t val, bool addIdam) override; |
| 50 |
[[nodiscard]] uint8_t readTrackByte(int idx) override; |
| 51 |
EmuTime getNextSector(EmuTime time, RawTrack::Sector& sector) override; |
| 52 |
void flushTrack() override; |
| 53 |
bool diskChanged() override; |
| 54 |
[[nodiscard]] bool peekDiskChanged() const override; |
| 55 |
[[nodiscard]] bool isDummyDrive() const override; |
| 56 |
|
| 57 |
void applyWd2793ReadTrackQuirk() override; |
| 58 |
void invalidateWd2793ReadTrackQuirk() override; |
| 59 |
|
| 60 |
|
| 61 |
void getMediaInfo(TclObject& result) override; |
| 62 |
void setMedia(const TclObject& info, EmuTime time) override; |
| 63 |
|
| 64 |
template<typename Archive> |
| 65 |
void serialize(Archive& ar, unsigned version); |
| 66 |
|
| 67 |
private: |
| 68 |
struct SyncLoadingTimeout final : Schedulable { |
| 69 |
friend class RealDrive; |
| 70 |
explicit SyncLoadingTimeout(Scheduler& s) : Schedulable(s) {} |
| 71 |
void executeUntil(EmuTime ) override { |
| 72 |
auto& drive = OUTER(RealDrive, syncLoadingTimeout); |
| 73 |
drive.execLoadingTimeout(); |
| 74 |
} |
| 75 |
} syncLoadingTimeout; |
| 76 |
|
| 77 |
struct SyncMotorTimeout final : Schedulable { |
| 78 |
friend class RealDrive; |
| 79 |
explicit SyncMotorTimeout(Scheduler& s) : Schedulable(s) {} |
| 80 |
void executeUntil(EmuTime time) override { |
| 81 |
auto& drive = OUTER(RealDrive, syncMotorTimeout); |
| 82 |
drive.execMotorTimeout(time); |
| 83 |
} |
| 84 |
} syncMotorTimeout; |
| 85 |
|
| 86 |
void execLoadingTimeout(); |
| 87 |
void execMotorTimeout(EmuTime time); |
| 88 |
[[nodiscard]] EmuTime getCurrentTime() const { return syncLoadingTimeout.getCurrentTime(); } |
| 89 |
|
| 90 |
void doSetMotor(bool status, EmuTime time); |
| 91 |
void setLoading(EmuTime time); |
| 92 |
[[nodiscard]] unsigned getCurrentAngle(EmuTime time) const; |
| 93 |
|
| 94 |
[[nodiscard]] unsigned getMaxTrack() const; |
| 95 |
[[nodiscard]] std::optional<unsigned> getDiskReadTrack() const; |
| 96 |
[[nodiscard]] std::optional<unsigned> getDiskWriteTrack() const; |
| 97 |
void getTrack(); |
| 98 |
void invalidateTrack(); |
| 99 |
|
| 100 |
private: |
| 101 |
static constexpr unsigned TICKS_PER_ROTATION = 200000; |
| 102 |
static constexpr unsigned INDEX_DURATION = TICKS_PER_ROTATION / 50; |
| 103 |
|
| 104 |
MSXMotherBoard& motherBoard; |
| 105 |
LoadingIndicator loadingIndicator; |
| 106 |
const EmuDuration motorTimeout; |
| 107 |
|
| 108 |
using MotorClock = Clock<TICKS_PER_ROTATION * ROTATIONS_PER_SECOND>; |
| 109 |
MotorClock motorTimer; |
| 110 |
std::optional<DiskChanger> changer; |
| 111 |
unsigned headPos = 0; |
| 112 |
unsigned side = 0; |
| 113 |
unsigned startAngle = 0; |
| 114 |
bool motorStatus = false; |
| 115 |
const bool doubleSizedDrive; |
| 116 |
const bool signalsNeedMotorOn; |
| 117 |
const DiskDrive::TrackMode trackMode; |
| 118 |
|
| 119 |
std::shared_ptr<DrivesInUse> drivesInUse; |
| 120 |
|
| 121 |
RawTrack track; |
| 122 |
bool trackValid = false; |
| 123 |
bool trackDirty = false; |
| 124 |
}; |
| 125 |
SERIALIZE_CLASS_VERSION(RealDrive, 6); |
| 126 |
|
| 127 |
} |
| 128 |
|
| 129 |
#endif |