--- nono/vm/vm.cpp 2026/04/29 17:04:32 1.1.1.3 +++ nono/vm/vm.cpp 2026/04/29 17:04:53 1.1.1.7 @@ -1,14 +1,17 @@ // // nono -// Copyright (C) 2017 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // #include "vm.h" #include "bus.h" #include "mainapp.h" #include "mpu.h" +#include "mythread.h" #include "ram.h" #include "renderer.h" +#include "rtc.h" #include "scheduler.h" std::unique_ptr gVM; @@ -18,35 +21,47 @@ VM::VM() { // どこでやるのがいいかわからんけど、このコンストラクタはメインスレッドで // 作られるので、ここでメインスレッドの名前を設定。 - pthread_setname_np("Main"); + PTHREAD_SETNAME("Main"); - // Scheduler は必ず先頭。(Scheduler::Init のコメント参照) - gScheduler.reset(new Scheduler()); - buserr.reset(new BusErrDevice()); + // バスエラーデバイスだけここで作成。 + gBusErr.reset(new BusErrDevice()); // まず全域をバスエラーで初期化。 // この後継承先で必要に応じて上書きする。 for (int i = 0; i < countof(::devtable); i++) { - ::devtable[i] = buserr.get(); + ::devtable[i] = gBusErr.get(); } } // デストラクタ VM::~VM() { - // スケジューラを停止。 - // スケジューラ(VMスレッド)からのアクセスさえなくなれば - // 後の有象無象はグローバルデストラクタにお任せでもいいか。 - // だめだったらもっと頑張る。 - gScheduler->Terminate(); - gScheduler.reset(); + Dispose(); +} + +// 終了 +void +VM::Dispose() +{ + if ((bool)gScheduler) { + // スケジューラを停止。 + // スケジューラ(VMスレッド)からのアクセスさえなくなれば + // 後の有象無象はグローバルデストラクタにお任せでもいいか。 + // だめだったらもっと頑張る。 + gScheduler->Terminate(); + gScheduler.reset(); + } } // コンストラクタ後の初期化 bool VM::Create() { - for (const auto& d : gDevices) { + // d->Create() は gDevices に要素を追加する場合があるため、ここで + // ranged for は使えない。また追加されたデバイスの Create() も(念のため) + // 実行したいため、ループ終了条件で毎回 size() を取り出して比較する。 + for (int i = 0; i < gDevices.size(); i++) { + Device *d = gDevices[i]; if (!d->Create()) { return false; } @@ -81,64 +96,18 @@ VM::Apply() return true; } -// VM の全デバイスの電源をオン -bool -VM::DevicePowerOn() -{ - for (const auto& d : gDevices) { - if (!d->PowerOn()) { - return false; - } - } - - // ハードウェアリセット - ResetHard(); - - // スケジューラを開始 - // (MPU の ResetHard() より後で起動時に1回だけ呼び出す) - gScheduler->Run(); - - return true; -} - -// VM の全デバイスの電源をオフ -// (Scheduler から呼ばれる) -bool -VM::DevicePowerOff() -{ - for (const auto& d : gDevices) { - if (!d->PowerOff()) { - return false; - } - } - // GUI に通知 - if (poweroff_callback) { - poweroff_callback(); - } - return true; -} - -// VM 電源オフ時のコールバックを設定する +// ブートページを切り替える (共通処理) +// 派生クラスから呼ぶこと。 void -VM::SetPowerOffCallback(void (*callback)()) +VM::SwitchBootPage(Device *parent, bool isrom) { - poweroff_callback = callback; -} - -// ハードウェアリセット -void -VM::ResetHard() -{ - for (const auto& d : gDevices) { - d->ResetHard(); + // ログ表示 + if (isrom) { + parent->putlogf(1, lstr("SwitchBootPage ROM (Boot)")); + } else { + parent->putlogf(1, lstr("SwitchBootPage RAM (Normal)")); } -} -// MPU の RESET 命令によるリセット -void -VM::ResetSoft() -{ - for (const auto& d : gDevices) { - d->ResetSoft(); - } + // スケジューラに指示 + gScheduler->RequestBootPageMode(isrom); }