|
|
nono 1.7.0
//
// nono
// Copyright (C) 2022 nono project
// Licensed under nono-license.txt
//
//
// FDD
//
#pragma once
#include "device.h"
#include "diskimage.h"
#include "message.h"
#include "textscreen.h"
// FD マーク
#define MARK_IAM (0xfc)
#define MARK_IDAM (0xfe)
#define MARK_DAM (0xfb)
#define MARK_DDAM (0xf8)
class FDCDevice;
class PEDECDevice;
// フロッピーディスクの 1 トラック
class FDTrack
{
public:
// トラック記録の開始
void Begin();
// トラック記録の終了
void End();
// トラックデータ追加(FDDDevice から呼ばれる)
void Append(uint8 data);
void Append(uint8 data, int count);
// トラックデータにマーク追加
void AppendMark(uint8 data);
void Clear();
// buf[0] はインデックスホールの位置と一致させる
std::vector<uint8> buf {}; // リングアクセスバッファ
std::vector<int> markpos {}; // アドレスマーク位置
// SYNC の次にあるIAM,IDAM,DAM/DDAM
uint32 lba {}; // バッファしているトラックの先頭セクタのLBA
};
class FDDDevice : public Device
{
using inherited = Device;
public:
// メディアへの書き込みモード
//
// Device Media Ignore
// RW RO * WriteProtect
// RW RW no Writeable
// RW RW yes WriteIgnore
enum class RW {
WriteProtect = 1, // 書き込み禁止メディア
Writeable = 0, // 書き込み可能
WriteIgnore = -1, // 書き込み可能メディアで書き込みを無視
};
// アクセス LED 状態
enum class LED {
OFF = 0,
GREEN,
RED,
BLINK, // 緑点滅 (内部のみで使用)
};
public:
explicit FDDDevice(uint unit_);
~FDDDevice() override;
bool Init() override;
void ResetHard(bool poweron) override;
// モニタ更新 (FDC の下請け)
void MonitorScreenFDD(TextScreen&, uint hd);
// ユニット番号を返す
int GetUnitNo() const { return unit; }
// ドライブコントロールレジスタへの書き込み
void SetDriveCtrl(uint8);
// ドライブセレクト入力
void SetDriveSelect(uint sel, bool is_2dd_);
// MOTOR_ON 信号入力
void SetMotorOn(bool);
bool GetReady() const;
// TRK00 信号
bool GetTrack0() const;
// WRITEPROTECT 信号
bool GetWriteProtect() const;
// 1 step シーク実行
void DoSeek(int dir_);
// インデックスホール位置なら true
bool IsIndex() const { return pos == 0; }
// トラックの現在のアクセス位置の 1 バイトを取得
uint8 ReadByte();
// トラックの現在のアクセス位置に 1 バイト書き込み
void WriteByte(uint8 data);
// 指定した相対位置のデータを取得
uint8 PeekByte(int) const;
// 次のマークまたはインデックスホールまでのバイト距離を返す。
int GetDistanceToMark() const;
// トラックバッファに現在のトラックを読み込む
void ReadTrack(int hd);
// トラックバッファをイメージに書き出す
void WriteTrack();
// メディアが入っていれば true
bool IsMediumLoaded() const { return medium_loaded; }
// メディアの書き込みモードを返す
RW GetWriteMode() const { return write_mode; }
// メディア(ディスク)イメージを開く/閉じる。(同一スレッドから呼ぶこと)
bool LoadDisk(const std::string& path_);
void UnloadDisk(bool force = false);
// メディア(ディスク)イメージを開く/閉じる。(UI スレッドから呼ぶ)
void LoadDiskUI(const std::string& path_);
void UnloadDiskUI(bool force);
// メディアの取り出し可否
bool IsEjectEnable() const { return eject_enable; }
// イメージファイルのフルパスを返す
const std::string& GetPathName() const { return pathname; }
// アクセスランプの状態取得。
LED GetAccessLED() const;
// イジェクトランプの状態取得。点灯なら true
bool GetEjectLED() const;
private:
// モータ状態変更
void DoMotorOn();
void DoMotorOff();
// モータ、LED の状態更新
void ChangeStatus();
// ディスクイメージを閉じる (内部用)
bool UnloadDisk_internal();
// ディスク状態をクリアする
void Clear();
// メディア状態変更を UI に通知する
void MediaChanged() const;
// メディア挿入/排出コールバック
void LoadMessage(MessageID, uint32);
void UnloadMessage(MessageID, uint32);
// イベントコールバック
void EventCallback(Event *);
uint unit {}; // ユニット番号(ドライブ番号)
bool selected {}; // FDD SELECT 入力信号で選択されていれば true
enum {
STOPPED = 0, // モータ停止中
SPIN_DOWN, // 停止に向けて慣性回転中
SPIN_UP, // モータ始動
READY, // 定常回転中
} motor_state {};
bool motor_on {}; // モーターオン入力信号の状態
bool IsMotorActive() const {
return (motor_state == SPIN_UP || motor_state == READY);
}
bool IsReady() const { return (motor_state == READY); }
bool is_blink {}; // LED ブリンク
uint cylinder {}; // 現在のシリンダ番号
uint pos {}; // アクセス位置
// トラックバッファ
FDTrack trackbuf {};
// メディアフォーマット
uint32 ncyl {}; // シリンダ数 (C)
uint32 nhead {}; // ヘッド数 (H)
uint32 nsect {}; // トラックあたりのセクタ数 (R)
uint8 format_n {}; // セクタ長 (N)
uint32 sectsize {}; // 1セクタあたりのバイト数
uint gap3 {}; // Gap3
uint gap4b {}; // Gap4b
std::string format_name {}; // フォーマット名
// イメージファイル
DiskImage image {};
bool write_ignore {}; // 書き込み無視オプション
bool medium_loaded {}; // メディアが挿入されていれば true
// メディアの書き込みモード
RW write_mode {};
// メディアの取り出しを許可するなら true。
bool eject_enable {};
// アクセス LED の状態
LED access_led {};
// アクセス LED の点滅開始時刻
uint64 blink_start {};
// イメージファイルのフルパス
std::string pathname {};
// 新しいイメージファイルのフルパス (UIから)
std::string new_pathname {};
FDCDevice *fdc {};
PEDECDevice *pedec {};
Event *event {};
};
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.