--- nono/vm/fdd.cpp 2026/04/29 17:05:18 1.1.1.2 +++ nono/vm/fdd.cpp 2026/04/29 17:05:38 1.1.1.5 @@ -13,6 +13,9 @@ // トラックは 8~ 個のセクタで構成される。 // セクタは 128~ バイトで構成される。 +// 割り込み状態はこちらでは保持しておらず PEDEC 側で持っている。 +// PEDEC への割り込みは AssertINT() するだけで使っている。 + #include "fdd.h" #include "config.h" #include "fdc.h" @@ -83,13 +86,10 @@ FDTrack::Clear() // // コンストラクタ -FDDDevice::FDDDevice(int unit_) +FDDDevice::FDDDevice(uint unit_) : inherited(OBJ_FDD(unit_)) { unit = unit_; - - event.func = ToEventCallback(&FDDDevice::EventCallback); - event.Regist(GetName()); } // デストラクタ @@ -101,27 +101,25 @@ FDDDevice::~FDDDevice() bool FDDDevice::Init() { - if (inherited::Init() == false) { - return false; - } - fdc = GetFDCDevice(); pedec = GetPEDECDevice(); - const std::string keybody = string_format("fd%d-", unit); + const std::string keybody = string_format("fd%u-", unit); const std::string imgkey = keybody + "image"; const std::string wikey = keybody + "writeignore"; - // デバイス種別(v[0])とパス(v[1])に分解。 - // デバイス種別はすでにチェックしてあるのでここでは不要。 const ConfigItem& itemimg = gConfig->Find(imgkey); const std::string& filename = itemimg.AsString(); // UI からの通知を受け取るイベントを用意 scheduler->ConnectMessage(MessageID::FDD_LOAD(unit), this, - ToMessageCallback(&FDDDevice::LoadCallback)); + ToMessageCallback(&FDDDevice::LoadMessage)); scheduler->ConnectMessage(MessageID::FDD_UNLOAD(unit), this, - ToMessageCallback(&FDDDevice::UnloadCallback)); + ToMessageCallback(&FDDDevice::UnloadMessage)); + + event.func = ToEventCallback(&FDDDevice::EventCallback); + event.SetName(GetName()); + scheduler->RegistEvent(event); // オープン前に writeignore をチェック。 // この後パス名を処理するとすぐに UI に通知を出すため、それより前で @@ -131,14 +129,7 @@ FDDDevice::Init() // 設定時点でファイルが指定されていればオープン if (filename.empty() == false) { - std::string path; - if (filename[0] == '/') { - path = filename; - } else { - // 相対パスなら VM ディレクトリから - path = gMainApp.GetVMDir() + filename; - } - + std::string path = gMainApp.NormalizePath(filename); if (LoadDisk(path) == false) { return false; } @@ -167,7 +158,7 @@ FDDDevice::ResetHard(bool poweron) // y = 11 以降が各ドライブの状態で、このうち x = 26 以降が FDD の担当。 // y = 16 以降は FDD のアクセスマップ。 void -FDDDevice::MonitorUpdateFDD(TextScreen& screen, int hd) +FDDDevice::MonitorUpdateFDD(TextScreen& screen, uint hd) { /* 1 2 3 4 5 6 7 0123456789012345678901234567890123456789012345678901234567890123456789012345678 @@ -213,14 +204,14 @@ XX>01234567890123456 01234567890123456| if (medium_loaded) { // フォーマットと CHRN - screen.Print(ux + 20, uy, "%4s %2d %d %2d %d(%d)", + screen.Print(ux + 20, uy, "%4s %2u %u %2u %u(%u)", format_name.c_str(), ncyl, nhead, nsect, format_n, sectsize); } uy = 16 + (unit / 2) * 10; ux = (unit % 2) * 41; - screen.Print(ux, uy++, "Unit %d", unit); + screen.Print(ux, uy++, "Unit %u", unit); // 横ガイド for (int i = 0; i < 8; i++) { screen.Puts(ux + 2, uy + i, "|"); @@ -233,7 +224,7 @@ XX>01234567890123456 01234567890123456| } TA selattr = selected ? TA::Em : TA::Normal; - screen.Print(ux, uy - 1, selattr, "Unit %d: HD=%d cyl=%2d/%d pos=%5d/%d", + screen.Print(ux, uy - 1, selattr, "Unit %u: HD=%u cyl=%2u/%u pos=%5u/%u", unit, hd, cylinder, ncyl, pos, MFM_TRACK_RAW_SIZE); // ヘッドの現在位置。 @@ -253,10 +244,8 @@ XX>01234567890123456 01234567890123456| } // ヘッド位置 - screen.Print(ux, uy + heady, selattr, "%2d>", cylinder); + screen.Print(ux, uy + heady, selattr, "%2u>", cylinder); screen.Puts(ux + hd * 18 + 3 + headx, uy + heady, selattr, "#"); - // 裏のヘッド位置 - screen.Puts(ux + (1 - hd) * 18 + 3 + headx, uy + heady, selattr, "+"); } // READY 信号 @@ -407,7 +396,7 @@ FDDDevice::DoMotorOn() // 細かいことは無視して、増速に転じる motor_state = SPIN_UP; } else { - VMPANIC("DoMotorOn called on motor_state=%d", (int)motor_state); + VMPANIC("DoMotorOn called on motor_state=%u", (uint)motor_state); } scheduler->RestartEvent(event); @@ -434,7 +423,7 @@ FDDDevice::DoMotorOff() // 細かいことは無視して、減速に転じる。 motor_state = SPIN_DOWN; } else { - VMPANIC("DoMotorOff called on motor_state=%d", (int)motor_state); + VMPANIC("DoMotorOff called on motor_state=%u", (uint)motor_state); } scheduler->RestartEvent(event); @@ -653,7 +642,7 @@ FDDDevice::LoadDisk(const std::string& p { bool ejected; off_t size; - bool w_ok; + int w_ok; bool read_only; // すでにあればクローズ (ここでは通知は行わない) @@ -665,10 +654,29 @@ FDDDevice::LoadDisk(const std::string& p goto done; } - if (image.GetInfo(&size, &w_ok) == false) { + w_ok = image.IsWriteable(); + if (w_ok < 0) { goto done; } + // 書き込みモードをここで確定 + if (w_ok) { + if (write_ignore) { + write_mode = RW::WriteIgnore; + } else { + write_mode = RW::Writeable; + } + } else { + write_mode = RW::WriteProtect; + } + + // ここでオープン + read_only = (GetWriteMode() != RW::Writeable); + if (image.Open(read_only, write_ignore) == false) { + goto done; + } + + size = image.GetSize(); if (size == 1261568) { // Human68k 2HD フォーマットとみなす // 77track, 2side, 8sector, 1024bytes/sector @@ -698,23 +706,6 @@ FDDDevice::LoadDisk(const std::string& p gap4b = (MFM_TRACK_RAW_SIZE - MFM_TRACK_HEADER) - (sectsize + MFM_SECTOR_HEADER + gap3) * nsect; - // 書き込みモードをここで確定 - if (w_ok) { - if (write_ignore) { - write_mode = RW::WriteIgnore; - } else { - write_mode = RW::Writeable; - } - } else { - write_mode = RW::WriteProtect; - } - - // ここでオープン - read_only = (GetWriteMode() != RW::Writeable); - if (image.Open(read_only, write_ignore) == false) { - goto done; - } - // 書き込み無視なら一応ログ出力 if (GetWriteMode() == RW::WriteIgnore) { putmsg(0, "write is ignored"); @@ -818,7 +809,7 @@ FDDDevice::UnloadDiskUI(bool force) // メディア挿入メッセージコールバック void -FDDDevice::LoadCallback(MessageID msgid, uint32 arg) +FDDDevice::LoadMessage(MessageID msgid, uint32 arg) { if (LoadDisk(new_pathname) == false) { // 失敗したら UI に通知 @@ -828,7 +819,7 @@ FDDDevice::LoadCallback(MessageID msgid, // メディア排出メッセージコールバック void -FDDDevice::UnloadCallback(MessageID msgid, uint32 arg) +FDDDevice::UnloadMessage(MessageID msgid, uint32 arg) { bool force = arg; UnloadDisk(force);