|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2023 nono project ! 4: // Licensed under nono-license.txt ! 5: // ! 6: ! 7: // ! 8: // Windrv (相当) ! 9: // ! 10: ! 11: #pragma once ! 12: ! 13: #include "device.h" ! 14: #include <array> ! 15: #include <deque> ! 16: #include <map> ! 17: ! 18: class HostWindrv; ! 19: class MainbusDevice; ! 20: class MPU680x0Device; ! 21: class WindrvDevice; ! 22: ! 23: // Human68k の定数とか構造体とか。 ! 24: class Human68k ! 25: { ! 26: public: ! 27: static const int MAX_PATH = 96; ! 28: ! 29: static const uint8 ATTR_RDONLY = 0x01; ! 30: static const uint8 ATTR_HIDDEN = 0x02; ! 31: static const uint8 ATTR_SYSTEM = 0x04; ! 32: static const uint8 ATTR_VOLUME = 0x08; ! 33: static const uint8 ATTR_DIR = 0x10; ! 34: static const uint8 ATTR_ARCHIVE = 0x20; ! 35: ! 36: // 標準(<fcntl.h>) の O_RDONLY とかは #define なので、 ! 37: // ここで別の名前空間で同名の定数を定義するとかが出来ない。 ! 38: static const int OPEN_RDONLY = 0; ! 39: static const int OPEN_WRONLY = 1; ! 40: static const int OPEN_RDWR = 2; ! 41: ! 42: #define DEF static const uint32 ! 43: // エラーコード(下位バイト) ! 44: DEF ERR_INVALID_UNIT = 0x0001; // 無効なユニット番号 ! 45: DEF ERR_INVALID_COMMAND = 0x0003; // 無効なコマンド ! 46: DEF ERR_WRITE = 0x000a; // 書き込みエラー ! 47: DEF ERR_READ = 0x000b; // 読み込みエラー ! 48: DEF ERR_MISC = 0x000c; // エラーが発生しました ! 49: DEF ERR_WRITE_PROTECT = 0x000e; // 書き込み保護されている ! 50: // エラーコード(上位バイト) ! 51: DEF ERR_IGNORE = 0x4000; // 無視(I) ! 52: DEF ERR_RETRY = 0x2000; // 再実行(R) ! 53: DEF ERR_ABORT = 0x1000; // 中止(A) ! 54: // 合成したもの ! 55: DEF ERR_INVALID_UNIT_IA = ERR_INVALID_UNIT | ERR_IGNORE | ERR_ABORT; ! 56: DEF ERR_INVALID_COMMAND_IA = ERR_INVALID_COMMAND | ERR_IGNORE | ERR_ABORT; ! 57: ! 58: // ステータスコード ! 59: DEF RES_INVALID_FUNC = -1; // 無効なファンクションコード ! 60: DEF RES_FILE_NOT_FOUND = -2; // ファイルが見付からない ! 61: DEF RES_DIR_NOT_FOUND = -3; // ディレクトリが見付からない ! 62: DEF RES_TOO_MANY_HANDLE = -4; // オープンしているハンドルが多い ! 63: DEF RES_NOT_A_FILE = -5; // ディレクトリ・ボリュームは不可 ! 64: DEF RES_NOT_OPENED = -6; // ハンドルはオープンされていない ! 65: DEF RES_INVALID_MEM = -7; // メモリ管理領域が不正 ! 66: DEF RES_NO_MEMORY = -8; // メモリが足りない ! 67: DEF RES_INVALID_PTR = -9; // ポインタが無効 ! 68: DEF RES_INVALID_ENV = -10; // 環境が不正 ! 69: DEF RES_ILLEGAL_FORMAT = -11; // 実行ファイルのフォーマットが不正 ! 70: DEF RES_INVALID_MODE = -12; // オープンのアクセスモードが不正 ! 71: DEF RES_INVALID_PATH = -13; // ファイル名が不正 ! 72: DEF RES_INVALID_PARAM = -14; // パラメータが不正 ! 73: DEF RES_INVALID_DRIVE = -15; // ドライブ指定が不正 ! 74: DEF RES_CURRENT_DIR = -16; // カレントディレクトリは削除出来ない ! 75: DEF RES_NO_IOCTRL = -17; // IOCTRL 出来ないデバイス ! 76: DEF RES_LAST_FILE = -18; // これ以上ファイルが見付からない ! 77: DEF RES_CANNOT_WRITE = -19; // ファイルは書き込み出来ない ! 78: DEF RES_DIR_EXISTS = -20; // ディレクトリはすでに存在する ! 79: DEF RES_CANNOT_DELETE = -21; // ファイルがあるので削除出来ない ! 80: DEF RES_CANNOT_RENAME = -22; // ファイルがあるのでリネーム出来ない ! 81: DEF RES_DISK_FULL = -23; // ディスクが一杯 ! 82: DEF RES_DIR_FULL = -24; // ディレクトリが一杯 ! 83: DEF RES_CANNOT_SEEK = -25; // シーク出来ない ! 84: DEF RES_SUPERVISOR = -26; // スーパバイザ状態でスーパバイザ指定 ! 85: DEF RES_THREAD_EXISTS = -27; // スレッド名が存在する ! 86: DEF RES_PROCESS_BUF = -28; // プロセス間通信バッファが書き込み禁止 ! 87: DEF RES_BACKGROUND = -29; // バックグラウンドプロセスを起動出来ない ! 88: DEF RES_NO_LOCKBUF = -32; // ロック領域が足りない ! 89: DEF RES_LOCKED = -33; // ロックされている ! 90: DEF RES_DRIVE_OPENED = -34; // ドライブのハンドルはオープンされている ! 91: DEF RES_TOO_MANY_LINKS = -35; // シンボリックリンクのネストが多い ! 92: DEF RES_FILE_EXISTS = -80; // ファイルが存在する ! 93: #undef DEF ! 94: ! 95: struct FILES { ! 96: uint8 sattr; // $00: 検索する属性 ! 97: uint8 drive; // $01: ドライブ番号 ! 98: uint32 sector; // $02: ディレクトリのセクタ番号 ! 99: // (DOS _FILES の先頭アドレスで代用) ! 100: //uint16 sector2; // $06: 詳細不明、未使用 ! 101: uint16 offset; // $08: ディレクトリの位置、詳細不明 ! 102: //char[8] name1; // $0a: 作業用ファイル名、未使用 ! 103: //char[3] ext; // $12: 作業用拡張子、未使用 ! 104: uint8 attr; // $15: ファイル属性 ! 105: uint16 time; // $16: 最終更新時刻 ! 106: uint16 date; // $18: 最終更新日付 ! 107: uint32 size; // $1a: ファイルサイズ ! 108: //char[23] name; // $1e: ファイル名(フル) ! 109: ! 110: // ファイル名。 ! 111: // マルチバイト文字をサポートした場合はここはホスト文字コードの ! 112: // ファイル名なので、ゲスト文字コード(Shift_JIS)で23バイトに ! 113: // 収まってもホスト文字コードで23バイトで収まるとは限らない。 ! 114: std::string name; ! 115: ! 116: // (parent を通じて) 必要なフィールドだけを VM メモリに書き出す。 ! 117: void WriteToMem(WindrvDevice *parent, uint32 addr) const; ! 118: }; ! 119: ! 120: class FCB ! 121: { ! 122: // +$00, 6.B: (内部使用) ! 123: // +$06, 1.L: ファイルポインタ ! 124: // +$0a, 1.L: (内部使用) ! 125: // +$0e, 1.B: オープンモード ! 126: // +$0f, 21.B: (内部使用) ! 127: // +$24, 8.B: ファイル名1 ! 128: // +$2c, 3.B: 拡張子 ! 129: // +$2f, 1.B: ファイル属性 ! 130: // +$30, 10.B: ファイル名2 ! 131: // +$3a, 1.W: 最終更新時刻 ! 132: // +$3c, 1.W: 最終更新日付 ! 133: // +$3e, 1.W: (内部使用) ! 134: // +$40, 1.L: ファイルサイズ ! 135: // +$44, 7.L: (内部使用) ! 136: public: ! 137: FCB(WindrvDevice *parent_, uint32 addr_); ! 138: ! 139: // ここにコピーは持たず、都度 VM メモリを参照/更新する。 ! 140: // FCB はフィールドが多いわりに Open、Read などの各コマンドの ! 141: // フィールドアクセスはまばらななので。 ! 142: uint32 GetPos() const; // 現在位置取得 ! 143: void SetPos(uint32); // 現在位置設定 ! 144: void AddPos(uint32); // 現在位置を加算 ! 145: uint8 GetMode() const; // オープンモード取得 ! 146: void SetDateTime(uint32); // 日付時刻を設定 ! 147: uint32 GetSize() const; // サイズ取得 ! 148: void SetSize(uint32); // サイズ設定 ! 149: void SetName(const std::string& name1, const std::string& name2, ! 150: const std::string& ext); // ファイル名を設定 ! 151: ! 152: uint32 GetAddr() const { return addr; } ! 153: ! 154: protected: ! 155: WindrvDevice *parent {}; ! 156: ! 157: private: ! 158: uint32 addr {}; // FCB アドレス(検索キー) ! 159: }; ! 160: ! 161: struct capacity { ! 162: uint16 avail_clusters; // 空きクラスタ数 ! 163: uint16 total_clusters; // 総クラスタ数 ! 164: uint16 sectors_per_cluster; ! 165: uint16 bytes_per_sector; ! 166: ! 167: // (parent を通じて) VM メモリに書き出す。 ! 168: void WriteToMem(WindrvDevice *parent, uint32 addr) const; ! 169: }; ! 170: ! 171: struct DPB { ! 172: uint16 sector_size; // 1セクタあたりのバイト数 ! 173: uint8 cluster_size; // 1クラスタあたりのセクタ数 - 1 ! 174: uint8 shift; // クラスタからセクタへのシフト数 ! 175: // (bit7=%1 なら 16bit FAT ?) ! 176: uint16 fat_sector; // FAT の先頭セクタ番号 ! 177: uint8 fat_max; // FAT 領域の個数 ! 178: uint8 fat_size; // 1つの FAT 領域のセクタ数 ! 179: uint16 file_max; // ルートディレクトリの最大ファイル数 ! 180: uint16 data_sector; // データ領域の先頭セクタ ! 181: uint16 cluster_max; // 総クラスタ数 ! 182: uint16 root_sector; // ルートディレクトリの先頭セクタ番号 ! 183: uint8 media; // メディア ID ! 184: ! 185: // (parent を通じて) VM メモリに書き出す。 ! 186: void WriteToMem(WindrvDevice *parent, uint32 addr) const; ! 187: }; ! 188: ! 189: // 属性をデバッグ表示用文字列にする。 ! 190: static std::string AttrStr(uint8 attr); ! 191: ! 192: // オープンモードを表示用文字列にする。 ! 193: static std::string OpenModeStr(uint8 mode); ! 194: ! 195: // ステータスコード/エラーコードに対応するメッセージを返す。 ! 196: static const char *GetResultMsg(uint32 result); ! 197: ! 198: // UNIX 時刻から MS-DOS 形式の日付時刻を取得。 ! 199: // uint32 の上位が日付、下位が時刻で返す。 ! 200: static uint32 Unixtime2DateTime(time_t); ! 201: ! 202: // MS-DOS 形式の日付時刻から UNIX 時刻を取得。 ! 203: static time_t DateTime2Unixtime(uint32); ! 204: ! 205: private: ! 206: static const char * const result_msg[]; ! 207: static const char * const err_msg[]; ! 208: }; ! 209: ! 210: // 仮想ディレクトリエントリ ! 211: class VDirent ! 212: { ! 213: public: ! 214: VDirent(const std::string& name_, bool isdir_); ! 215: ! 216: // ここの属性は Valid かどうかと Dir/Archive(Regular) のみを使う。 ! 217: // Files/NFiles で拾う時は (タイムスタンプやサイズとともに) ! 218: // 属性も改めてファイルシステムから拾う。 ! 219: bool IsValid() const { return isvalid; } ! 220: bool IsDir() const { return isdir; } ! 221: bool IsArchive() const { return !isdir; } ! 222: ! 223: // このエントリを Human68k に見せないようにする。 ! 224: void Invalidate() { isvalid = false; } ! 225: ! 226: std::string name {}; // ホストファイル名。 ! 227: bool isdir {}; // ディレクトリなら true、ファイルなら false。 ! 228: bool isvalid {}; // エントリが有効なら true。 ! 229: }; ! 230: ! 231: // 仮想ディレクトリ構造 ! 232: class VDir ! 233: { ! 234: public: ! 235: VDir(); ! 236: VDir(HostWindrv *host_, const std::string& path_); ! 237: ! 238: // ホスト相対パスを返す。 ! 239: const std::string& GetPath() const { return path; } ! 240: ! 241: // このディレクトリから name にマッチするエントリを返す。 ! 242: // 見付からなければ NULL を返す。 ! 243: const VDirent *MatchName(const std::string& name, bool want_exist) const; ! 244: ! 245: void Acquire(); ! 246: void Release(); ! 247: ! 248: // 参照カウントを返す。 ! 249: int Refcount() const { return refcount; } ! 250: ! 251: // この VDir 構成時の mtime [nsec] を返す。 ! 252: uint64 GetMTime() const { return mtime; } ! 253: ! 254: // mtime を更新する。 ! 255: void SetMTime(uint64 mtime_) { mtime = mtime_; } ! 256: ! 257: // この VDir の参照時刻 [usec] を返す。 ! 258: uint64 GetATime() const { return atime; } ! 259: ! 260: // 参照時刻を更新する。 ! 261: void UpdateATime(); ! 262: ! 263: // このディレクトリ内のエントリ。 ! 264: std::vector<VDirent> list {}; ! 265: ! 266: private: ! 267: // ホストでの相対パス。 ! 268: std::string path {}; ! 269: ! 270: // ホストの対応ディレクトリの更新日時。 ! 271: // (st_mtimespec がある場合のみ使用する) ! 272: uint64 mtime {}; ! 273: ! 274: // この VDir を参照した実時刻 [usec]。 ! 275: // こっちは、キャッシュから追い出す人を決定するために使うので uint64。 ! 276: uint64 atime {}; ! 277: ! 278: // 参照中のディレクトリを消さないようにするため。 ! 279: int refcount {}; ! 280: ! 281: HostWindrv *host {}; ! 282: }; ! 283: ! 284: // VDir を自動変数みたいに勝手にクローズしてほしい。 ! 285: class AutoVDir ! 286: { ! 287: public: ! 288: AutoVDir(HostWindrv *host_, VDir *vdir_) { ! 289: host = host_; ! 290: vdir = vdir_; ! 291: } ! 292: ~AutoVDir(); ! 293: ! 294: // vdir-> で VDir* をアクセスすることで透過っぽく見せる。 ! 295: VDir *operator->() const noexcept { ! 296: return vdir; ! 297: } ! 298: ! 299: // unique_ptr と同様に (bool) で有効かどうかを返す。 ! 300: explicit operator bool() const noexcept { ! 301: return (vdir != NULL); ! 302: } ! 303: ! 304: private: ! 305: HostWindrv *host {}; ! 306: VDir *vdir {}; ! 307: }; ! 308: ! 309: // FILES のこちら側のバッファ。 ! 310: class FilesBuf ! 311: { ! 312: public: ! 313: FilesBuf(uint32 key_, HostWindrv *host_); ! 314: void Init(uint32 key_, HostWindrv *host_); ! 315: ! 316: uint64 GetATime() const { return atime; } ! 317: void UpdateATime(); ! 318: ! 319: public: ! 320: uint32 key {}; // FILES バッファアドレス ! 321: HostWindrv *host {}; // ホスト (ドライブ) ! 322: std::string path {}; // ホスト相対パス ! 323: ! 324: // マッチしたファイル名一覧。 ! 325: // Files/NFiles で取得するたびに先頭から削除していく方式。 ! 326: std::deque<std::string> list {}; ! 327: ! 328: // 直近にマッチしたファイル名(ログ出力用) ! 329: std::string fname {}; ! 330: ! 331: private: ! 332: uint64 atime {}; ! 333: }; ! 334: ! 335: class Windrv ! 336: { ! 337: public: ! 338: // Human68k の FCB 構造体とホスト側で必要なメンバを集約したクラス。 ! 339: // ハンドルのように使う。 ! 340: class FCB : public Human68k::FCB ! 341: { ! 342: using inherited = Human68k::FCB; ! 343: public: ! 344: FCB(WindrvDevice *, uint32 addr_, HostWindrv *host_); ! 345: ! 346: void Close(); ! 347: ! 348: // 対応するホストドライバ ! 349: HostWindrv *host {}; ! 350: // ファイルディスクリプタ ! 351: int fd {}; ! 352: }; ! 353: ! 354: // いずれオプションになるかも知れないが。 ! 355: static const bool option_case_sensitive = false; ! 356: }; ! 357: ! 358: class WindrvDevice : public IODevice, Windrv ! 359: { ! 360: using inherited = IODevice; ! 361: friend class Human68k; ! 362: friend class Windrv; ! 363: ! 364: // Human68k の NAMESTS 構造体を読み込んだもの。 ! 365: // windrv.sys では、Windrv デバイスから windrv.sys にこの構造体を返す ! 366: // ケースはなく、すべて windrv.sys から Windrv デバイスへの方向なので、 ! 367: // 受け取った時点でホスト側に都合のいいように加工して保持する。 ! 368: class NAMESTS ! 369: { ! 370: // +$00, 1.B: ワイルドカード文字数 ! 371: // +$01, 1.B: ドライブ番号 (A:=0、B:=1、…) ! 372: // +$02,65.B: パス ! 373: // +$43, 8.B: ファイル名1 (余りは ' ' で埋める) ! 374: // +$4b, 3.B: 拡張子 (余りは ' ' で埋める) ! 375: // +$4e,10.B: ファイル名2 (余りは '\0' で埋める) ! 376: // ! 377: // NAMESTS 内のパスは '\' 区切り、最後にも '\' が付いて '\0' で終端、 ! 378: // らしいが、観測してると '\t'(\x09) 区切りで最後にも '\t' が付いて ! 379: // '\0' で終端する文字列が来てる。なんだべ。 ! 380: public: ! 381: static const int Size = 0x58; // 構造体の大きさ ! 382: private: ! 383: std::string path; // '/' 区切り ! 384: std::string name1; // パディングの ' ' を除いたもの ! 385: std::string ext; // パディングの ' ' を除いたもの ! 386: std::string name2; // パディングの '\0' を除いたもの ! 387: public: ! 388: int wildcard; ! 389: int drive; ! 390: ! 391: public: ! 392: // コンストラクタ ! 393: NAMESTS(WindrvDevice *, uint32 addr); ! 394: ! 395: // drive, path を '/' 区切りで返す。 ! 396: std::string GetDrivePath() const; ! 397: ! 398: // path のみ('/' 区切り)を返す。 ! 399: const std::string& GetPath() const { return path; } ! 400: ! 401: // ファイル名(8+10.3)を返す。 ! 402: std::string GetName() const; ! 403: ! 404: const std::string& GetName1() const { return name1; } ! 405: const std::string& GetName2() const { return name2; } ! 406: const std::string& GetExt() const { return ext; } ! 407: ! 408: // ドライブ、パス、ファイル名を返す。 ! 409: std::string GetFull() const; ! 410: ! 411: // ログ表示用のドライブ、パス文字列を返す。 ! 412: std::string PrintDrivePath() const; ! 413: }; ! 414: ! 415: // 最大ドライブ数 ! 416: static const int MaxDrives = 1; ! 417: ! 418: // FilesBuf の最大数 ! 419: static const int MaxFilesBuf = 32; // (適当) ! 420: ! 421: public: ! 422: WindrvDevice(); ! 423: ~WindrvDevice() override; ! 424: ! 425: bool Create() override; ! 426: void SetLogLevel(int) override; ! 427: bool Init() override; ! 428: void ResetHard(bool poweron) override; ! 429: ! 430: busdata Read8(uint32 addr) override; ! 431: busdata Write8(uint32 addr, uint32 data) override; ! 432: busdata Peek8(uint32 addr) override; ! 433: ! 434: // Windrv を組み込むなら true を返す。 ! 435: static bool IsWindrv(); ! 436: ! 437: private: ! 438: uint32 GetIdent() const; ! 439: void Execute(); ! 440: uint32 DispatchCommand(); ! 441: ! 442: uint32 CmdInitialize(); ! 443: uint32 CmdCheckDir(HostWindrv *); ! 444: uint32 CmdMakeDir(HostWindrv *); ! 445: uint32 CmdRemoveDir(HostWindrv *); ! 446: uint32 CmdRename(HostWindrv *); ! 447: uint32 CmdDelete(HostWindrv *); ! 448: uint32 CmdAttribute(HostWindrv *); ! 449: uint32 CmdFiles(HostWindrv *); ! 450: uint32 CmdNFiles(HostWindrv *); ! 451: uint32 CmdCreate(HostWindrv *); ! 452: uint32 CmdOpen(HostWindrv *); ! 453: uint32 CmdClose(HostWindrv *); ! 454: uint32 CmdRead(HostWindrv *); ! 455: uint32 CmdWrite(HostWindrv *); ! 456: uint32 CmdSeek(HostWindrv *); ! 457: uint32 CmdFileTime(HostWindrv *); ! 458: uint32 CmdGetCapacity(HostWindrv *); ! 459: uint32 CmdCtrlDrive(HostWindrv *); ! 460: uint32 CmdGetDPB(HostWindrv *); ! 461: uint32 CmdDiskRead(HostWindrv *); ! 462: uint32 CmdDiskWrite(HostWindrv *); ! 463: uint32 CmdIoControl(HostWindrv *); ! 464: uint32 CmdFlush(HostWindrv *); ! 465: uint32 CmdCheckMedia(HostWindrv *); ! 466: uint32 CmdLock(HostWindrv *); ! 467: ! 468: void SetResult(uint32); ! 469: ! 470: // result を表示用に整形して返す ! 471: static std::string ResultStr(uint32 result); ! 472: ! 473: // メモリアクセス ! 474: uint32 ReadMem8(uint32 addr) const; ! 475: void WriteMem8(uint32 addr, uint32 data); ! 476: uint32 ReadMem16(uint32 addr) const; ! 477: void WriteMem16(uint32 addr, uint32 data); ! 478: uint32 ReadMem32(uint32 addr) const; ! 479: void WriteMem32(uint32 addr, uint32 data); ! 480: uint32 ReadMemAddr(uint32 addr) const; ! 481: void WriteMemAddr(uint32 addr, uint32 data); ! 482: void ReadMem(void *dst, uint32 srcaddr, int len) const; ! 483: void WriteMem(uint32 dstaddr, const void *src, int len); ! 484: ! 485: uint32 FilesCommon(FilesBuf *, uint32 addr); ! 486: bool MatchFilename(const std::string& fname, const NAMESTS& ns) const; ! 487: static bool MatchWildcard(const std::string& fn, const std::string& pn); ! 488: ! 489: // addr に対応する FILES バッファを探す。 ! 490: FilesBuf *SearchFilesBuf(uint32 addr) const; ! 491: // addr に対応する FILES バッファを作成して返す。 ! 492: FilesBuf *AllocFilesBuf(uint32 addr, HostWindrv *); ! 493: ! 494: // addr に対応する FCB を探す。 ! 495: Windrv::FCB *SearchFCB(uint32 addr) const; ! 496: // FCB を登録する。 ! 497: uint32 AddFCB(const Windrv::FCB&); ! 498: // FCB を解放して削除する。 ! 499: void FreeFCB(Windrv::FCB *); ! 500: ! 501: uint32 a5 {}; ! 502: uint32 command {}; ! 503: ! 504: // ログ表示用 ! 505: std::string cmdname {}; ! 506: ! 507: std::array<std::unique_ptr<HostWindrv>, MaxDrives> hosts /*{}*/; ! 508: ! 509: std::map<uint32, FilesBuf*> filesmap {}; ! 510: ! 511: std::map<uint32, FCB*> fcbmap {}; ! 512: ! 513: MainbusDevice *mainbus {}; ! 514: MPU680x0Device *mpu680x0 {}; ! 515: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.