--- nono/vm/vm.cpp 2026/04/29 17:05:10 1.1.1.8 +++ nono/vm/vm.cpp 2026/04/29 17:05:46 1.1.1.14 @@ -9,43 +9,34 @@ // #include "vm.h" -#include "debugger_private.h" +#include "debugger.h" #include "mainapp.h" -#include "mpu.h" -#include "power.h" -#include "ram.h" +#include "mainbus.h" #include "scheduler.h" #include "signalthread.h" -#include "sync.h" - -// グローバル参照用 -VM *gVM; +#include "syncer.h" // コンストラクタ -VM::VM() +VM::VM(const char *vmname_) { + vmname = vmname_; + assert(vmname); + // SignalThread は他のスレッドより先に起動する必要があるので、先頭。 // Scheduler は以降の他のデバイスからのイベント登録を受け付ける必要が // あるためその次。 + // Debugger は HostCOM と stdio ドライバが競合した場合に優先したいため + // もあって必ず先に配置する必要がある。 NEWDV(SignalThread, new SignalThread()); NEWDV(Scheduler, new Scheduler()); - NEWDV(Sync, new Sync()); - NEWDV(Power, new PowerDevice()); + NEWDV(Syncer, new Syncer()); NEWDV(Debugger, new Debugger()); - - // バスエラーデバイスをここで作成して全域をバスエラーで初期化。 - // この後継承先で必要に応じて上書きする。 - NEWDV(BusErr, new BusErrDevice()); - for (int i = 0; i < countof(::devtable); i++) { - ::devtable[i] = gBusErr; - } } // デストラクタ VM::~VM() { Dispose(); - gVM = NULL; } // 終了 @@ -55,10 +46,10 @@ VM::Dispose() // まずスレッドを止める。 // デバッガスレッドがスケジューラスレッドにアクセスするのでデバッガが先。 if ((bool)pDebugger) { - gDebugger->TerminateThread(); + GetDebugger()->TerminateThread(); } if ((bool)pScheduler) { - gScheduler->TerminateThread(); + GetScheduler()->TerminateThread(); } // 残りのスレッドを停止 @@ -82,22 +73,37 @@ VM::Dispose() // だめだったらまた考える。 } -// コンストラクタ後の初期化 +// 動的コンストラクション。 bool -VM::Create() +VM::Create(VM::CreationPhase phase) { // d->Create() は Object を追加する場合があるため、ここで - // ranged for は使えない。また追加されたデバイスの Create() も(念のため) + // ranged for は使えない。また追加されたデバイスの Create()/Create2() も // 実行したいため、ループ終了条件で毎回 size() を取り出して比較する。 for (int i = 0; i < gMainApp.GetObjects().size(); i++) { auto dev = dynamic_cast(gMainApp.GetObjects()[i]); if (dev) { - if (!dev->Create()) { - return false; + if (phase == CreationPhase::First) { + if (!dev->Create()) { + return false; + } + } else { + if (!dev->Create2()) { + return false; + } } } } + // ログのためのメンバ変数初期化。 + // 同じオブジェクトに対して複数回呼んでも副作用はない。 + for (auto obj : gMainApp.GetObjects()) { + auto dev = dynamic_cast(obj); + if (dev) { + dev->EarlyInit(); + } + } + return true; } @@ -114,6 +120,18 @@ VM::Init() } } + // デバイスの初期化が全部出来たのでメインバスの初期化。 + auto mainbus = dynamic_cast(pMainbus.get()); + if (mainbus->InitMainbus() == false) { + return false; + } + + // イベントが出揃ったのでスケジューラモニタの行数を確定。 + auto scheduler = dynamic_cast(pScheduler.get()); + if (scheduler->Init2() == false) { + return false; + } + return true; } @@ -148,25 +166,3 @@ VM::Apply() return true; } - -// ブートページを切り替える (共通処理) -// 派生クラスから呼ぶこと。 -void -VM::SwitchBootPage(Device *parent, bool isrom) -{ - // ログ表示 - if (isrom) { - parent->putlogf(1, lstr("SwitchBootPage ROM (Boot)")); - } else { - parent->putlogf(1, lstr("SwitchBootPage RAM (Normal)")); - } - - // 同期モード指示 - gSync->RequestBootPageMode(isrom); -} - -// MPU の RESET 命令によるリセット -void -VM::ResetByMPU() -{ -}