File:  [Isaki's NoNo m68k/m88k emulator] / nono / vm / fdd.h
Revision 1.1.1.6 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:05:59 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v027, HEAD
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 {};
};

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.