--- nono/vm/fdc.cpp 2026/04/29 17:05:33 1.1.1.14 +++ nono/vm/fdc.cpp 2026/04/29 17:05:43 1.1.1.16 @@ -75,6 +75,11 @@ // OP.SEL.x でドライブごとに有効になる信号 // EJECT, EJECT MASK, LED BLINK, DISK IN, ERR DISK +// ドライブセレクトイネーブルがネゲートされていて、 +// どのドライブも選択されていない状態になったとき、 +// 各入力信号はプルアップされているため、 +// 負論理の信号はすべてネゲート状態となる。 + #include "fdc.h" #include "bitops.h" #include "config.h" @@ -128,7 +133,13 @@ FDCDevice::Create() // vector は面倒なので一旦 unique_ptr[] に確保して // 生ポインタの vector を作る。うーん。 for (int i = 0; i < ndrive; i++) { - fdd_list[i].reset(new FDDDevice(i)); + try { + fdd_list[i].reset(new FDDDevice(i)); + } catch (...) { } + if ((bool)fdd_list[i] == false) { + warnx("Failed to initialize FDDDevice(%u) at %s", i, __method__); + return false; + } } for (int i = 0; i < ndrive; i++) { if ((bool)fdd_list[i]) { @@ -145,10 +156,6 @@ FDCDevice::Create() bool FDCDevice::Init() { - if (inherited::Init() == false) { - return false; - } - dmac = GetDMACDevice(); pedec = GetPEDECDevice(); @@ -277,13 +284,15 @@ FDCDevice::WritePort(uint32 offset, uint // ドライブコントロールレジスタ putlog(1, "Drive Control <- $%02x", data); - // FDD 割り込みクリア(要実機確認) - pedec->NegateINT(fdd_vector[0]); - uint8 bit = 0x01; for (const auto f : fdd_vector) { + // ドライブセレクタのビットが %1 -> %0 になると動作する。 if (f && bit_falling(drivectrl, data, bit)) { f->SetDriveCtrl(data & 0xe0); + + // FDD 割り込みのクリアは詳細不明だが、とりあえず + // 同じタイミングで動作するようにしておく。 + pedec->NegateINT(f); } bit <<= 1; } @@ -896,11 +905,8 @@ FDCDevice::ReadyChanged(int unit, bool i // ことの通知を受けてポーリングループを起動し、どのユニットも変化が // なくなったらポーリングを止めるようにしておく。 // uPD765 マニュアル POLLING FEATURE OF THE uPD765 (p.433) + StartPoll(); - // SPECIFY コマンドで有効になる - if (initialized) { - StartPoll(); - } // 転送の同期を取るために、READY になった時刻を覚えておく if (is_ready) { unitinfo[unit].ready_time = scheduler->GetVirtTime(); @@ -911,6 +917,10 @@ FDCDevice::ReadyChanged(int unit, bool i void FDCDevice::StartPoll() { + // SPECIFY コマンドで有効になる + if (initialized == false) { + return; + } if (poll_event.IsRunning() == false) { putlog(3, "Start polling"); scheduler->StartEvent(poll_event); @@ -1042,9 +1052,7 @@ FDCDevice::SetForceReady(bool force_read { force_ready = force_ready_; putlog(2, "Force Ready %s", force_ready ? "On" : "Off"); - if (initialized) { - StartPoll(); - } + StartPoll(); } // DACK 信号をアサートする (DMAC から呼ばれる) @@ -1135,6 +1143,10 @@ FDCDevice::DriveSelect(uint8 drive) fdd = NULL; } + // ドライブセレクト信号線が変わったら READY が変わるかもしれないので + // ポーリングを再開する必要がある。 + StartPoll(); + // いまのところ LUNA のことは忘れる }