|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2022 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: //
8: // FDD
9: //
10:
11: #pragma once
12:
13: #include "device.h"
14: #include "diskimage.h"
15: #include "event.h"
16: #include "message.h"
17: #include "textscreen.h"
18:
19: // FD マーク
20: #define MARK_IAM (0xfc)
21: #define MARK_IDAM (0xfe)
22: #define MARK_DAM (0xfb)
23: #define MARK_DDAM (0xf8)
24:
25: // フロッピーディスクの 1 トラック
26: class FDTrack
27: {
28: public:
29: // トラック記録の開始
30: void Begin();
31: // トラック記録の終了
32: void End();
33: // トラックデータ追加(FDDDevice から呼ばれる)
34: void Append(uint8 data);
35: void Append(uint8 data, int count);
36:
37: // トラックデータにマーク追加
38: void AppendMark(uint8 data);
39:
40: void Clear();
41:
42: // buf[0] はインデックスホールの位置と一致させる
43: std::vector<uint8> buf; // リングアクセスバッファ
44: std::vector<int> markpos {}; // アドレスマーク位置
45: // SYNC の次にあるIAM,IDAM,DAM/DDAM
46: uint32 lba; // バッファしているトラックの先頭セクタのLBA
47: };
48:
49: class FDDDevice : public Device
50: {
51: using inherited = Device;
52: public:
53: // メディアへの書き込みモード
54: //
55: // Device Media Ignore
56: // RW RO * WriteProtect
57: // RW RW no Writeable
58: // RW RW yes WriteIgnore
59: enum class RW {
60: WriteProtect = 1, // 書き込み禁止メディア
61: Writeable = 0, // 書き込み可能
62: WriteIgnore = -1, // 書き込み可能メディアで書き込みを無視
63: };
64:
65: // アクセス LED 状態
66: enum class LED {
67: OFF = 0,
68: GREEN,
69: RED,
70: BLINK, // 緑点滅 (内部のみで使用)
71: };
72:
73: public:
74: FDDDevice(int unit_);
75: ~FDDDevice() override;
76:
77: bool Init() override;
78: void ResetHard(bool poweron) override;
79:
80: // モニタ更新 (FDC の下請け)
81: void MonitorUpdateFDD(TextScreen&, int hd);
82:
83: // ユニット番号を返す
84: int GetUnitNo() const { return unit; }
85:
86: // ドライブコントロールレジスタへの書き込み
87: void SetDriveCtrl(uint8);
88:
89: // ドライブセレクト入力
90: void SetDriveSelect(uint sel, bool is_2dd_);
91:
92: // MOTOR_ON 信号入力
93: void SetMotorOn(bool);
94:
95: bool GetReady() const;
96:
97: // TRK00 信号
98: bool GetTrack0() const;
99:
100: // WRITEPROTECT 信号
101: bool GetWriteProtect() const;
102:
103: // 1 step シーク実行
104: void DoSeek(int dir_);
105:
106: // インデックスホール位置なら true
107: bool IsIndex() const { return pos == 0; }
108:
109: // トラックの現在のアクセス位置の 1 バイトを取得
110: uint8 ReadByte();
111:
112: // トラックの現在のアクセス位置に 1 バイト書き込み
113: void WriteByte(uint8 data);
114:
115: // 指定した相対位置のデータを取得
116: uint8 PeekByte(int) const;
117:
118: // 次のマークまたはインデックスホールまでのバイト距離を返す。
119: int GetDistanceToMark() const;
120:
121: // トラックバッファに現在のトラックを読み込む
122: void ReadTrack(int hd);
123:
124: // トラックバッファをイメージに書き出す
125: void WriteTrack();
126:
127: // メディアが入っていれば true
128: bool IsMediumLoaded() const { return medium_loaded; }
129:
130: // メディアの書き込みモードを返す
131: RW GetWriteMode() const { return write_mode; }
132:
133: // メディア(ディスク)イメージを開く/閉じる。(同一スレッドから呼ぶこと)
134: bool LoadDisk(const std::string& path_);
135: void UnloadDisk(bool force = false);
136:
137: // メディア(ディスク)イメージを開く/閉じる。(UI スレッドから呼ぶ)
138: void LoadDiskUI(const std::string& path_);
139: void UnloadDiskUI(bool force);
140:
141: // メディアの取り出し可否
142: bool IsEjectEnable() const { return eject_enable; }
143:
144: // イメージファイルのフルパスを返す
145: const std::string& GetPathName() const { return pathname; }
146:
147: // アクセスランプの状態取得。
148: LED GetAccessLED() const;
149:
150: // イジェクトランプの状態取得。点灯なら true
151: bool GetEjectLED() const;
152:
153: private:
154: // モータ状態変更
155: void DoMotorOn();
156: void DoMotorOff();
157:
158: // モータ、LED の状態更新
159: void ChangeStatus();
160:
161: // ディスクイメージを閉じる (内部用)
162: bool UnloadDisk_internal();
163:
164: // ディスク状態をクリアする
165: void Clear();
166:
167: // メディア状態変更を UI に通知する
168: void MediaChanged() const;
169:
170: // メディア挿入/排出コールバック
171: void LoadCallback(MessageID, uint32);
172: void UnloadCallback(MessageID, uint32);
173:
174: // イベントコールバック
175: void EventCallback(Event &);
176:
177: int unit {}; // ユニット番号(ドライブ番号)
178: bool selected {}; // FDD SELECT 入力信号で選択されていれば true
179: enum {
180: STOPPED = 0, // モータ停止中
181: SPIN_DOWN, // 停止に向けて慣性回転中
182: SPIN_UP, // モータ始動
183: READY, // 定常回転中
184: } motor_state {};
185: bool motor_on {}; // モーターオン入力信号の状態
186: bool IsMotorActive() const {
187: return (motor_state == SPIN_UP || motor_state == READY);
188: }
189: bool IsReady() const { return (motor_state == READY); }
190: bool is_blink {}; // LED ブリンク
191: int cylinder {}; // 現在のシリンダ番号
192: int pos {}; // アクセス位置
193:
194: // トラックバッファ
195: FDTrack trackbuf {};
196:
197: // メディアフォーマット
198: uint32 ncyl {}; // シリンダ数 (C)
199: uint32 nhead {}; // ヘッド数 (H)
200: uint32 nsect {}; // トラックあたりのセクタ数 (R)
201: uint8 format_n {}; // セクタ長 (N)
202: uint32 sectsize {}; // 1セクタあたりのバイト数
203: uint gap3 {}; // Gap3
204: uint gap4b {}; // Gap4b
205: std::string format_name {}; // フォーマット名
206:
207: // イメージファイル
208: DiskImage image {};
209:
210: bool write_ignore {}; // 書き込み無視オプション
211: bool medium_loaded {}; // メディアが挿入されていれば true
212:
213: // メディアの書き込みモード
214: RW write_mode {};
215:
216: // メディアの取り出しを許可するなら true。
217: bool eject_enable {};
218:
219: // アクセス LED の状態
220: LED access_led {};
221: // アクセス LED の点滅開始時刻
222: uint64 blink_start {};
223:
224: // イメージファイルのフルパス
225: std::string pathname {};
226: // 新しいイメージファイルのフルパス (UIから)
227: std::string new_pathname {};
228:
229: Event event { this };
230: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.