--- nono/lib/config.cpp 2026/04/29 17:05:26 1.1.1.15 +++ nono/lib/config.cpp 2026/04/29 17:05:52 1.1.1.20 @@ -31,14 +31,12 @@ Config::Config() Add("cgrom-image", "", VMCap::X68030); // VM 内の時計を同期する時間軸。 - // [ real, virtual ] - Add("clock-sync", "real"); + // "real" か "virtual"。初期値は各 VM クラスで設定している。 + Add("clock-sync"); // デバッガコンソール Add("debugger-driver", "none"); Add("debugger-tcp-port", 0); - // デバッガコンソールの fallback は常に不可とする。hostcom.cpp 参照。 - // "debugger-fallback" // DIPSW エイリアス Add("dipsw-autoboot", "", VMCap::LUNA | VMCap::NEWS); @@ -55,6 +53,10 @@ Config::Config() // RAMDISK (--initrd) Add("exec-initrd", "", VMCap::VIRT68K); + // virt-m68k のブートパラメータ文字列。BootInfo の BI_COMMANDLINE で、 + // NetBSD/virt68k ではルートデバイスの決定に使っている。 + Add("exec-bootparam", "", VMCap::VIRT68K); + // X68030 の拡張メモリサイズ Add("extram-size", "0", VMCap::X68030); @@ -67,29 +69,37 @@ Config::Config() Add(string_format("fd%u-writeignore", id), 0, VMCap::X68030); } - // X68030 時の FPU の有無。 - Add("fpu-type", "68881", VMCap::X68030); + // 68030 の FPU の有無。 + Add("fpu-type", "68881", VMCap::VIRT68K | VMCap::X68030); // 高速モード。 Add("fast-mode", "0"); // ホスト CPU アクセラレーション。 - Add("host-avx2", "auto"); - Add("host-neon", "auto"); + // host-* の方は少しの間残しておくがそのうち消す。 + Add("hostcpu-avx2", "auto"); + Add("hostcpu-neon", "auto"); + AddObsolete("host-avx2", "hostcpu-avx2"); + AddObsolete("host-neon", "hostcpu-neon"); + + // ホスト CPU の高性能コア指定。 + Add("hostcpu-fastcore", "auto"); + // 古い隠しオプションのほうは使われたらエラーを出す。 + // こっちは単なる読み替えではないため AddObsolete() ではない。 + Add(".host-cpu-affinity", "obsolete"); + + // シリアルポートのホスト側設定。 + Add("hostcom0-driver", "none"); + Add("hostcom0-tcp-port", 9998); + + Add("hostcom1-driver", "none", VMCap::LUNA); + Add("hostcom1-tcp-port", 9997, VMCap::LUNA); + + Add("hostcom2-driver", "none", VMCap::LUNA); + Add("hostcom2-tcp-port", 9996, VMCap::LUNA); - // CPU アフィニティ (解釈が複雑すぎるので隠しオプション)。 - // "" … 指定しない - // auto … 予約。現状は "" と同じ。 - // low: … Light スレッドを の CPU に割り付ける。 - // high: … Heavy スレッドを の CPU に割り付ける。 - // perf: … Heavy スレッドを の CPU に、 - // Light スレッドをその反集合の CPU に割り付ける。 - Add(".host-cpu-affinity", "auto"); - - // シリアルポートのホスト側設定 - Add("hostcom-driver", "none"); - Add("hostcom-fallback", 0); - Add("hostcom-tcp-port", 9998); + AddAlias("hostcom-driver", "hostcom0-driver"); + AddAlias("hostcom-tcp-port", "hostcom0-tcp-port"); // キーボードの入力モード Add("hostkbd-input", "char", VMCap::LUNA | VMCap::X68030); @@ -97,22 +107,32 @@ Config::Config() // ネットワークのホスト側設定。 // (0 と 1 で -driver の初期値が違う) Add("hostnet0-driver", "auto"); - Add("hostnet0-fallback", 0); Add("hostnet0-afpacket-ifname", "auto"); Add("hostnet0-bpf-ifname", "auto"); Add("hostnet0-tap-devpath", "auto"); + Add("hostnet0-usermode-hostfwd",""); + Add("hostnet0-usermode-net", "10.8.0.0/24"); + Add("hostnet0-usermode-net6", "fd08::/64"); Add("hostnet1-driver", "none", VMCap::X68030); - Add("hostnet1-fallback", 0, VMCap::X68030); Add("hostnet1-afpacket-ifname", "auto", VMCap::X68030); Add("hostnet1-bpf-ifname", "auto", VMCap::X68030); Add("hostnet1-tap-devpath", "auto", VMCap::X68030); + Add("hostnet1-usermode-hostfwd","", VMCap::X68030); + Add("hostnet1-usermode-net", "10.8.0.0/24", VMCap::X68030); + Add("hostnet1-usermode-net6", "fd08::/64", VMCap::X68030); AddAlias("hostnet-driver", "hostnet0-driver"); - AddAlias("hostnet-fallback", "hostnet0-fallback"); AddAlias("hostnet-afpacket-ifname", "hostnet0-afpacket-ifname"); AddAlias("hostnet-bpf-ifname", "hostnet0-bpf-ifname"); AddAlias("hostnet-tap-devpath", "hostnet0-tap-devpath"); + AddAlias("hostnet-usermode-hostfwd","hostnet0-usermode-hostfwd"); + AddAlias("hostnet-usermode-net", "hostnet0-usermode-net"); + AddAlias("hostnet-usermode-net6", "hostnet0-usermode-net6"); + + Add("hostsound-driver", "auto"); + Add("hostsound-alsa-device", "default"); + Add("hostsound-netbsd-device", "/dev/sound"); // IPLROM1/2 ファイルパス。なければ内蔵 ROM。 Add("iplrom1-image", "", VMCap::X68030); @@ -157,6 +177,9 @@ Config::Config() // M88100 で疑似 STOP 状態をサポートする Add("mpu-pseudo-stop", 1, VMCap::M88K); + // MPU 種別。現状 m68k のみ。初期値は機種依存。 + Add("mpu-type", "", VMCap::M68K); + // Nereid Add("nereid0-enable", 0, VMCap::X68030); Add("nereid1-enable", 0, VMCap::X68030); @@ -206,9 +229,6 @@ Config::Config() Add(string_format("spc0-id%u-image", id), scsicap); // エミュレータ的に書き込みを禁止するか Add(string_format("spc0-id%u-writeignore", id), 0, scsicap); - // エミュレータ的に書き込みを禁止するか - // (後方互換、十分不要になった頃に削除する) - Add(string_format("spc0-id%u-writeprotect", id), 0, scsicap); // シークタイム [msec] Add(string_format("spc0-id%u-seektime", id), 0, scsicap); } @@ -217,19 +237,28 @@ Config::Config() Add("sram-sync-ramsize", 1, VMCap::X68030); // virtio 設定。 + auto viocap = VMCap::VIRT68K; for (int id = 0; id < 8; id++) { - auto viocap = VMCap::VIRT68K; // イメージパス Add(string_format("virtio-block%u-image", id), viocap); // エミュレータ的に書き込みを禁止するか Add(string_format("virtio-block%u-writeignore", id), 0, viocap); } + for (int id = 0; id < 8; id++) { + // 種別とイメージパス + Add(string_format("virtio-scsi-id%u-image", id), viocap); + // エミュレータ的に書き込みを禁止するか + Add(string_format("virtio-scsi-id%u-writeignore", id), 0, viocap); + } // Windrv パス。 Add("windrv-path", "", VMCap::X68030); // X68030 で FC2 ピンを切るか。 Add("x68k-cut-fc2", 1, VMCap::X68030); + + // XP プロセッサのクロック (MHz 単位の実数、小数点以下は3桁まで)。 + Add("xp-clock", "6.144", VMCap::LUNA); } // デストラクタ @@ -278,6 +307,17 @@ Config::AddAlias(const std::string& alia return true; } +// 廃止項目を追加 +void +Config::AddObsolete(const std::string& old, const std::string& alter) +{ + // すでに追加済みなら、プログラムミス。 + if (IsObsolete(old)) { + PANIC("obsolete already has %s !", old.c_str()); + } + obsolete[old] = alter; +} + // 項目を削除 // key が見付からなくても何もしない。key は複数登録されていることはないはず。 void @@ -355,32 +395,65 @@ Config::Update(const std::string& line, UpdateLinePerf("virtio-block4-writeignore=1"); UpdateLinePerf("virtio-block5-writeignore=1"); UpdateLinePerf("virtio-block6-writeignore=1"); + UpdateLinePerf("virtio-block7-writeignore=1"); + UpdateLinePerf("virtio-scsi-id0-writeignore=1"); + UpdateLinePerf("virtio-scsi-id1-writeignore=1"); + UpdateLinePerf("virtio-scsi-id2-writeignore=1"); + UpdateLinePerf("virtio-scsi-id3-writeignore=1"); + UpdateLinePerf("virtio-scsi-id4-writeignore=1"); + UpdateLinePerf("virtio-scsi-id5-writeignore=1"); + UpdateLinePerf("virtio-scsi-id6-writeignore=1"); + UpdateLinePerf("virtio-scsi-id7-writeignore=1"); return true; } else { return UpdateLine(line, ConfigItem::FromOption, optname); } } +// 実行中に動的に変更する。 +bool +Config::UpdateRunning(const std::string& line) +{ + return UpdateLine(line, ConfigItem::FromRunning, ""); +} + // 更新1行分の共通処理。 -// キーが見付からない場合、コマンドラインからならエラーとし、 -// それ以外からの場合は警告のみで無視する。 -// エラーが起きたらエラーメッセージを表示して false を返す。 +// キーが見付からない場合は from によって動作が異なる。 +// o 共通設定ファイルでなら、何もせず true を返す。 +// o VM 設定ファイルでなら、エラーメッセージを表示するが true を返す。 +// o コマンドラインでなら、エラーメッセージを表示して false を返す。 +// 起動前のこれらでは、false は実行中止を示す。 +// また +// o 実行中の変更なら、何もせず false を返す。 +// この場合の false はキーが見付からなかったことを意味する。 +// (文法エラーの場合にも false が返るが、それはプログラムエラー) bool Config::UpdateLine(const std::string& line, ConfigItem::from_t from, const std::string& where) { std::string key; std::string val; + std::string head; // キーと値に分解 if (SplitKeyVal(&key, &val, line) == false) { - ConfigItem::PrintErr(from, where, "", line, "Syntax error"); + head = ConfigItem::ErrFrom(from, where, "", line); + warnx("%s: Syntax error", head.c_str()); return false; } + head = ConfigItem::ErrFrom(from, where, key, val); + // キーが別名なら正規名に置換 key = GetCanonKey(key); + // このキーが廃止予定なら警告は出すがそのまま使う。 + if (IsObsolete(key)) { + warnx("Warning: %s: '%s' is obsolete. Please use '%s' instead.", + head.c_str(), key.c_str(), obsolete[key].c_str()); + key = obsolete[key]; + } + // キーで検索 ConfigItem *itemptr = FindItem(key); if (itemptr == NULL) { @@ -397,13 +470,17 @@ Config::UpdateLine(const std::string& li // VM 設定ファイルなら警告のみで無視する。 // このファイルに他機種向けの設定があるのはおかしいが // 止めるほどではない。 - ConfigItem::PrintErr(from, where, key, val, "Unknown key, ignored"); + warnx("%s: Unknown key, ignored", head.c_str()); return true; case ConfigItem::FromOption: // コマンドラインからの場合はエラーにする。 - ConfigItem::PrintErr(from, where, key, val, "Unknown key"); + warnx("%s: Unknown key", head.c_str()); return false; + + case ConfigItem::FromRunning: + // 実行中なら、黙って無視する。 + return true; } } @@ -564,7 +641,7 @@ Config::Fix() assert(fixed == false); // ここで、この機種に不要な変数を削除する。 - // が、その前にその変数がユーザから指定されていればエラーにする。 + // その変数がユーザから指定されていればエラーにする。 for (auto it = list.begin(); it != list.end(); ) { ConfigItem& item = *it; VMCap vmcap = item.GetVMCap(); @@ -633,27 +710,21 @@ ConfigItem::TryDouble(double *val) const return true; } -// b ^ e -static inline int ipow(int b, int e) +// b を e 乗した整数を返す。 +static inline int +ipow(int b, int e) { int rv = 1; -#if 1 + for (int i = 0; i < e; i++) { rv *= b; } -#else - // e <= 3 とかだと上のほうが速そう。 - for (; e != 0; e >>= 1) { - if ((e & 1)) { - rv *= b; - } - b *= b; - } -#endif return rv; } // 値を固定小数点値として取得してみる。 +// digit は小数点以下の桁数で、それ以下は四捨五入する。 +// 値が "1.2345" で digit=3 なら *val = 1235 を返す。 bool ConfigItem::TryFixedDecimal(int *val, int digit) const { @@ -701,6 +772,33 @@ ConfigItem::SetDefault(const std::string } } +std::string +ConfigItem::ErrMsg() const +{ + // 定型文 + return ErrMsg("Invalid argument"); +} + +std::string +ConfigItem::ErrMsg(const char *fmt, ...) const +{ + char buf[1024]; + va_list ap; + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + + std::string msg(buf); + return ErrMsg(msg); +} + +std::string +ConfigItem::ErrMsg(const std::string& msg) const +{ + return ErrFrom(from, where, key, value) + ": " + msg; +} + void ConfigItem::Err() const { @@ -725,14 +823,14 @@ ConfigItem::Err(const char *fmt, ...) co void ConfigItem::Err(const std::string& msg) const { - PrintErr(from, where, key, value, msg); + warnx("%s", ErrMsg(msg).c_str()); } -// この item についてエラーを表示する。 +// この item のエラーメッセージのヘッダ部分を返す。 // key=val の '=' がない場合のみ key を空、value を行全体として呼ぶ。 -/*static*/ void -ConfigItem::PrintErr(ConfigItem::from_t from, const std::string& where, - const std::string& key, const std::string& value, const std::string& msg) +/*static*/ std::string +ConfigItem::ErrFrom(ConfigItem::from_t from, const std::string& where, + const std::string& key, const std::string& value) { std::string fromstr; @@ -776,7 +874,7 @@ ConfigItem::PrintErr(ConfigItem::from_t break; } - warnx("%s: %s", fromstr.c_str(), msg.c_str()); + return fromstr; }