--- nono/cli/cli_app.cpp 2026/04/29 17:04:28 1.1 +++ nono/cli/cli_app.cpp 2026/04/29 17:05:27 1.1.1.13 @@ -1,161 +1,138 @@ // // nono -// Copyright (C) 2018 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // -#include "header.h" +// +// CLI アプリケーションのエントリポイント +// + +#include "nono.h" +#include "cuimessage.h" +#include "kevent.h" #include "mainapp.h" -#include "mpu.h" -#include "pluto.h" -#include "rtc.h" -#include "vm.h" +#include "monitor.h" +#include "power.h" // wxApp と相似にするためのクラス class CLIApp { public: - bool OnInit(); + int OnInit(); bool Parse(); - void OnCreate(); - - int ac; - char **av; -}; + int OnCreate(); + void OnHalt(); + void OnAppExit(); -// コマンドラインオプションとか -const char *human68k_file = NULL; -char human68k_arg[256]; + int ac {}; + char **av {}; -void -usage() -{ - printf("%s []\n", getprogname()); - printf(" -b break point\n"); - printf(" -B benchmark mode\n"); - printf(" -c vm directory\n"); - printf(" -d debugger prompt on startup\n"); - printf(" -f fast mode\n"); - printf(" -L = loglevel (-L help displays names)\n"); - printf(" -X human68k console emulation\n"); - printf(" -v version\n"); -} + autofd kq {}; + bool exit_request {}; +}; int main(int ac, char *av[]) { - CLIApp *app = new CLIApp(); + std::unique_ptr app(new CLIApp()); // wxApp とよく似せるため app->ac = ac; app->av = av; - if (app->OnInit()) { - return 1; - } - return 0; + return app->OnInit(); } // ここがエントリポイント(のつもり) -bool +int CLIApp::OnInit() { - debug_breakaddr = 0xffffffff; - vmdir = "."; + int rv; - if (!Parse()) { - return false; + // CLI 側では関係ないが wx 側で必要なので初期化は2ステージに分かれている + rv = gMainApp.Init1(true, ac, av); + if (rv != MainApp::PASS) { + return rv; + } + // UIMessage の初期化はなんとなくスレッド開始前のほうがよかろう + kq = CUIMessage::Init(); + if (kq < 0) { + return EXIT_FAILURE; } - // CLI 版では常にコンソールに(も)ログを出力 - if (!main_init(true)) { - return false; + // モニタ登録締切。CLI ではあまり関係ないけど揃えておく。 + gMonitorManager->Fix(); + + // スレッド作成を伴う初期化。 + if (!gMainApp.Init2()) { + return EXIT_FAILURE; } // メインウィンドウに相当するところ OnCreate(); - return true; -} + // 戻ってきたので、VM を解放。 + gMainApp.Dispose(); -// 引数をパースする。 -// 知らない引数とかがあればこちらで usage を表示して false を返す。 -bool -CLIApp::Parse() -{ - int b; - int c; - - while ((c = getopt(ac, av, "b:B:c:dfL:X:v")) != -1) { - switch (c) { - case 'b': - debug_breakaddr = (uint32)strtoul(optarg, NULL, 16); - break; - - case 'B': - b = atoi(optarg); - if (b < 2 || b > 6) { - fprintf(stderr, "-B : 2..6\n"); - return false; - } - PlutoDevice::benchmark_mode = b; - break; + return EXIT_SUCCESS; +} - case 'c': - vmdir = std::string(optarg); - break; - - case 'd': - debug_on_start = true; - break; - - case 'f': - fast_mode = true; - break; - - case 'L': - if (logopt[0] != '\0') { - strlcat(logopt, ",", sizeof(logopt)); - } - strlcat(logopt, optarg, sizeof(logopt)); - break; +// メインウィンドウ作成後のイベントに相当するところ +int +CLIApp::OnCreate() +{ + CUIMessage::Connect(UIMessage::APPEXIT, + [&](const UIMessage&) { OnAppExit(); }); + if (gMainApp.Has(VMCap::M68K)) { + CUIMessage::Connect(UIMessage::HALT, + [&](const UIMessage&) { OnHalt(); }); + } + // UIMessage の処理を開始する。 + UIMessage::Attach(&CUIMessage::Process); - case 'X': - human68k_file = optarg; - for (int i = optind; i < ac; i++) { - if (i != optind) { - strlcat(human68k_arg, " ", sizeof(human68k_arg)); - } - strlcat(human68k_arg, av[i], sizeof(human68k_arg)); + // 電源投入 + auto power = GetPowerDevice(); + power->PushPowerButton(); + + // メッセージを待つ + while (exit_request == false) { + struct kevent kev; + + if (kevent_poll(kq, &kev, 1, NULL) < 0) { + if (errno == EINTR) { + continue; } - optind = ac; - break; + warn("CLIApp::OnCreate: kevent_poll"); + // XXX どうする? + continue; + } - case 'v': - fprintf(stderr, "nono-cli version %d.%d.%d\n", - NONO_MAJOR_VER, NONO_MINOR_VER, NONO_PATCH_VER); - exit(0); - - default: - usage(); - return false; + // パイプから1メッセージ分読み出す + UIMessage m; + if (read((int)kev.ident, &m, sizeof(m)) < 0) { + warn("CLIApp::OnCreate: read"); + // XXX どうする? + continue; } + + // ディスパッチ + CUIMessage::Dispatch(m); } - return true; + return 0; } -// メインウィンドウ作成後のイベントに相当するところ +// m680x0 ダブルバスフォールト時に呼ばれるコールバック。 void -CLIApp::OnCreate() +CLIApp::OnHalt() { - // 時刻開始? - // なるべく VM が開始する直前にしたい。 - gRTC->InitRTC(); - - // VM 実行開始 - gVM->PowerButton(); - - // ? - for (;;) { - sleep(1); - } + // どうする? + warnx("Double bus fault has occurred in VM"); +} + +// アプリケーションの終了要求で呼ばれるコールバック。 +void +CLIApp::OnAppExit() +{ + exit_request = true; }