--- nono/lib/mainapp.cpp 2026/04/29 17:04:30 1.1.1.2 +++ nono/lib/mainapp.cpp 2026/04/29 17:04:37 1.1.1.4 @@ -1,9 +1,9 @@ // // nono -// Copyright (C) 2018 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // -#include "header.h" #include "mainapp.h" #include "mystring.h" #include @@ -25,7 +25,7 @@ MainApp::ShowHelp(bool all) const p("-c vm directory"); p("-f fast mode"); if (IsGUI()) - p("--fontsize fontsize in monitors {12,16,24} (default:12)"); + p("--fontsize fontsize in monitors {12,16} (default:12)"); p("-h show brief help message"); p("--help show all help message including for developers"); if (IsGUI()) @@ -36,7 +36,7 @@ MainApp::ShowHelp(bool all) const if (all) { printf("\n(options for developers)\n"); - p("-b breakpoint"); + p("-b [,] set breakpoint"); p("-B benchmark mode"); p("-C output log to console"); p("-d debugger prompt on startup"); @@ -54,11 +54,14 @@ enum { OPT_fontsize = 0x80, OPT_help, OPT_show_config, + OPT_show_config_all, }; static struct option longopts[] = { { "fontsize", required_argument, NULL, OPT_fontsize }, { "help", no_argument, NULL, OPT_help }, { "show-config", no_argument, NULL, OPT_show_config }, + // --show-config-all は開発用なのでヘルプには載せない + { "show-config-all",no_argument, NULL, OPT_show_config_all }, { NULL, 0, NULL, 0 }, }; @@ -76,7 +79,7 @@ MainApp::Init(bool is_cli_, int ac, char // ログ機構は引数処理後なるはや // CLI ならログは常に標準出力へ(も)出力。 // GUI なら -C で指定。 - gLogger->UseStdout(IsCLI() ? true : log_to_console); + gLogger.UseStdout(IsCLI() ? true : log_to_console); // 設定を作成。コンストラクタで初期値を用意 gConfig.reset(new Config()); @@ -99,12 +102,12 @@ MainApp::Init(bool is_cli_, int ac, char vmtype = VMTYPE_RXZ; } else { // VM 種別文字列から vmtype を決定 - const ConfigItem& item = gConfig->Get("vmtype"); + const ConfigItem& item = gConfig->Find("vmtype"); std::string vmstr = string_tolower(item.AsString()); if (vmstr == "x68030") { vmtype = VMTYPE_X68030; } else if (vmstr == "luna") { - vmtype = VMTYPE_LUNA; + vmtype = VMTYPE_LUNA1; } else if (vmstr == "luna88k") { vmtype = VMTYPE_LUNA88K; } else { @@ -125,7 +128,7 @@ MainApp::Init(bool is_cli_, int ac, char gVM.reset(new VM_X68030()); break; - case VMTYPE_LUNA: + case VMTYPE_LUNA1: gVM.reset(new VM_LUNA()); break; @@ -143,8 +146,9 @@ MainApp::Init(bool is_cli_, int ac, char // 設定内容表示 // (MPU コンストラクタでクロック数の初期値を決めるため、その後で表示) + gConfig->Fix(); if (show_config) { - gConfig->Show(); + gConfig->Show(show_config - 1); } // 動的なコンストラクション @@ -197,7 +201,6 @@ MainApp::ParseOpt(int ac, char *av[]) fontsize = 12; screen_scale = 1.0; - debug_breakaddr = 0xffffffff; while ((c = getopt_long(ac, av, "A:b:B:c:CdDfhL:M:s:vV:X:", longopts, NULL)) != -1) { @@ -207,7 +210,7 @@ MainApp::ParseOpt(int ac, char *av[]) break; case 'b': - debug_breakaddr = (uint32)strtoul(optarg, NULL, 16); + debug_breakaddr.push_back(optarg); break; case 'B': @@ -298,7 +301,11 @@ MainApp::ParseOpt(int ac, char *av[]) return false; case OPT_show_config: - show_config = true; + show_config = 1; + break; + + case OPT_show_config_all: + show_config = 2; break; case 'h': @@ -364,7 +371,7 @@ MainApp::ParseLogopt() } // エイリアスとか printf("sch -> scheduler\n"); - if (vmtype == VMTYPE_LUNA) { + if (gMainApp.HasVMFeature(VMF_LUNA)) { printf("scc -> sio\n"); } printf("all\n"); @@ -400,7 +407,7 @@ MainApp::ParseLogopt() // 短縮形とかエイリアスとか if (strcmp(name, "sch") == 0) name = "scheduler"; - if (vmtype == VMTYPE_LUNA) { + if (gMainApp.HasVMFeature(VMF_LUNA)) { if (strcmp(name, "scc") == 0) name = "sio"; } @@ -412,14 +419,14 @@ MainApp::ParseLogopt() obj->loglevel = val; } } else { - // それ以外は一致するキーを探してセット + // それ以外は一致するキーを探してセット。 + // 複数のオブジェクトが同じ logname を持ってもよい (CMMUとか)。 std::string sname = name; bool found = false; for (auto& obj : gObjects) { if (obj->logname == sname) { obj->loglevel = val; found = true; - break; } } // 見つからない場合はエラー @@ -437,27 +444,59 @@ MainApp::ParseLogopt() } // 関連するファイルのパスを取得。 +// 1. name がファイル名のみなら、VM ディレクトリとその親ディレクトリを検索。 +// ファイルが存在すればその時点で戻り値とする。ファイルが存在したけど +// 何らか不都合があったとしても (例えばファイルサイズが 0 だとか +// パーミッションが足りないとか) 次を試すとかはしない。 +// 2. name が '~' から始まっていればホームディレクトリに展開。 +// 3. name が相対パスなら VM ディレクトリからの相対パスとする。 +// 4. name は絶対パスのはずなので、そのまま使用する。 std::string MainApp::SearchFile(const std::string& name) const { std::string path; struct stat st; - // ファイルがあるかどうかを調べるだけで、存在したけどそれに何らか - // 不都合があったら次を試すとかはしない。 + // 1. パス区切りを含んでなければ、ファイル名のみ + if (name.find('/') == std::string::npos) { + // 1a. VM ディレクトリ + path = GetVMDir() + name; + if (stat(path.c_str(), &st) == 0) { + return path; + } + + // 2. 親ディレクトリ + path = GetVMDir() + "../" + name; + if (stat(path.c_str(), &st) == 0) { + return path; + } + + // どちらもなければエラー + return ""; + } - // 1. 設定ファイルディレクトリ - path = GetVMDir() + name; - if (stat(path.c_str(), &st) == 0) { - return path; + // 2. 先頭の '~' を $HOME に展開 + path = name; + if (path[0] == '~' && path[1] == '/') { + const char *home = getenv("HOME"); + if (home == NULL) { + home = ""; + } + path = string_format("%s%s", home, path.c_str() + 1); } - // 2. 共通ディレクトリ(?) - // XXX 共通ディレクトリを返す関数を用意したほうがいいか - path = GetVMDir() + "../" + name; - if (stat(path.c_str(), &st) == 0) { - return path; + // 3. 相対パスなら、VM ディレクトリからの相対 + if (path[0] != '/') { + path = GetVMDir() + path; } - return ""; + return path; +} + +// 現在の VM が指定の feature を持っているか? +bool +MainApp::HasVMFeature(vmf_t feature) const +{ + uint32 vmf = 1 << GetVMType(); + return (vmf & feature) != 0; }