--- nono/lib/config.cpp 2026/04/29 17:05:22 1.1.1.14 +++ nono/lib/config.cpp 2026/04/29 17:05:30 1.1.1.16 @@ -55,6 +55,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); @@ -62,19 +66,29 @@ Config::Config() Add("fd-drive", 2, VMCap::X68030); for (int id = 0; id < FDCDevice::MAX_DRIVE; id++) { // 種別とイメージパス - Add(string_format("fd%d-image", id), VMCap::X68030); + Add(string_format("fd%u-image", id), VMCap::X68030); // エミュレータ的に書き込みを禁止するか - Add(string_format("fd%d-writeignore", id), 0, VMCap::X68030); + 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"); + + // CPU アフィニティ (解釈が複雑すぎるので隠しオプション)。 + // "" … 指定しない + // auto … 予約。現状は "" と同じ。 + // low: … Light スレッドを の CPU に割り付ける。 + // high: … Heavy スレッドを の CPU に割り付ける。 + // perf: … Heavy スレッドを の CPU に、 + // Light スレッドをその反集合の CPU に割り付ける。 + Add(".host-cpu-affinity", "auto"); // シリアルポートのホスト側設定 Add("hostcom-driver", "none"); @@ -126,6 +140,11 @@ Config::Config() // m88100 の別名ニーモニックを併記する。 Add(".m88k-altname", 0, VMCap::M88K); + // m88100/88200 のバージョン。 + // 初期値はコンストラクタ側で用意している。 + Add("m88100-version", 0, VMCap::M88K); + Add("m88200-version", 0, VMCap::M88K); + // 画面サイズ。 Add("mainview-scale", "1"); @@ -142,6 +161,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); @@ -188,14 +210,14 @@ Config::Config() for (int id = 0; id < 8; id++) { auto scsicap = VMCap::LUNA | VMCap::X68030; // 種別とイメージパス - Add(string_format("spc0-id%d-image", id), scsicap); + Add(string_format("spc0-id%u-image", id), scsicap); // エミュレータ的に書き込みを禁止するか - Add(string_format("spc0-id%d-writeignore", id), 0, scsicap); + Add(string_format("spc0-id%u-writeignore", id), 0, scsicap); // エミュレータ的に書き込みを禁止するか // (後方互換、十分不要になった頃に削除する) - Add(string_format("spc0-id%d-writeprotect", id), 0, scsicap); + Add(string_format("spc0-id%u-writeprotect", id), 0, scsicap); // シークタイム [msec] - Add(string_format("spc0-id%d-seektime", id), 0, scsicap); + Add(string_format("spc0-id%u-seektime", id), 0, scsicap); } // SRAM の RAM 容量を同期するか。 @@ -205,9 +227,9 @@ Config::Config() for (int id = 0; id < 8; id++) { auto viocap = VMCap::VIRT68K; // イメージパス - Add(string_format("virtio-block%d-image", id), viocap); + Add(string_format("virtio-block%u-image", id), viocap); // エミュレータ的に書き込みを禁止するか - Add(string_format("virtio-block%d-writeignore", id), 0, viocap); + Add(string_format("virtio-block%u-writeignore", id), 0, viocap); } // Windrv パス。 @@ -215,6 +237,9 @@ Config::Config() // X68030 で FC2 ピンを切るか。 Add("x68k-cut-fc2", 1, VMCap::X68030); + + // XP プロセッサのクロック (MHz 単位の実数、小数点以下は3桁まで)。 + Add("xp-clock", "6.144", VMCap::LUNA); } // デストラクタ @@ -286,9 +311,9 @@ Config::Update(const ConfigFile& file) for (const auto& pair : file.lines) { const std::string& line = pair.first; - int lineno = pair.second; + uint lineno = pair.second; - auto where = string_format("%s:%d", file.filepath.c_str(), lineno); + auto where = string_format("%s:%u", file.filepath.c_str(), lineno); if (UpdateLine(line, file.from, where) == false) { return false; } @@ -297,13 +322,53 @@ Config::Update(const ConfigFile& file) return true; } +#define UpdateLinePerf(str) do { \ + if (UpdateLine(str, ConfigItem::FromPerf, where) == false) \ + return false; \ +} while (0) + // コマンドラインオプションで更新 bool Config::Update(const std::string& line, const std::string& optname) { assert(fixed == false); - return UpdateLine(line, ConfigItem::FromOption, optname); + // パフォーマンス測定用オプション --perf が指定されたら + // line="--perf" という非正規の書式で呼ばれるので、ここで展開する。 + if (line == "--perf") { + // -V prom-image=PROM.DAT はパスの問題があるので、各自で追加指定 + // する必要がある。 + std::string where = "--perf -V"; + UpdateLinePerf(".rtc-force-fixed=1"); + UpdateLinePerf("clock-sync=virtual"); + UpdateLinePerf("fast-mode=1"); + UpdateLinePerf("fd0-writeignore=1"); + UpdateLinePerf("fd1-writeignore=1"); + UpdateLinePerf("fd2-writeignore=1"); + UpdateLinePerf("fd3-writeignore=1"); + UpdateLinePerf("ethernet-macaddr=02:00:00:00:00:01"); + UpdateLinePerf("hostcom-driver=none"); + UpdateLinePerf("hostnet-driver=none"); + UpdateLinePerf("luna-dipsw1=11110111"); + UpdateLinePerf("luna-video-plane=4"); + UpdateLinePerf("spc0-id0-writeignore=1"); + UpdateLinePerf("spc0-id1-writeignore=1"); + UpdateLinePerf("spc0-id2-writeignore=1"); + UpdateLinePerf("spc0-id3-writeignore=1"); + UpdateLinePerf("spc0-id4-writeignore=1"); + UpdateLinePerf("spc0-id5-writeignore=1"); + UpdateLinePerf("spc0-id6-writeignore=1"); + UpdateLinePerf("virtio-block0-writeignore=1"); + UpdateLinePerf("virtio-block1-writeignore=1"); + UpdateLinePerf("virtio-block2-writeignore=1"); + UpdateLinePerf("virtio-block3-writeignore=1"); + UpdateLinePerf("virtio-block4-writeignore=1"); + UpdateLinePerf("virtio-block5-writeignore=1"); + UpdateLinePerf("virtio-block6-writeignore=1"); + return true; + } else { + return UpdateLine(line, ConfigItem::FromOption, optname); + } } // 更新1行分の共通処理。 @@ -332,6 +397,7 @@ Config::UpdateLine(const std::string& li switch (from) { default: case ConfigItem::FromHome: + case ConfigItem::FromPerf: // 共通設定ファイルなら黙って無視する。 // このファイルには他機種向けの設定も並んでいる可能性があるため // 無視してくれないと困る。 @@ -422,7 +488,7 @@ Config::Show(bool all) const std::string buf = string_format("%s=\"%s\"", item.key.c_str(), item.value.c_str()); if (buf.size() < 40) { - int n = ((40 - buf.size()) + 7) / 8; + uint n = ((40 - buf.size()) + 7) / 8; buf.append(n, '\t'); } else { buf.push_back('\t'); @@ -440,9 +506,12 @@ Config::Show(bool all) const case ConfigItem::FromOption: fromstr = "option " + item.where; break; + case ConfigItem::FromPerf: + fromstr = "option --perf"; + break; default: - fromstr = string_format("corrupted item.from=%d for key=%s", - (int)item.from, item.key.c_str()); + fromstr = string_format("corrupted item.from=%u for key=%s", + (uint)item.from, item.key.c_str()); break; } @@ -574,6 +643,59 @@ ConfigItem::TryDouble(double *val) const return true; } +// b を e 乗した整数を返す。 +static inline int +ipow(int b, int e) +{ + int rv = 1; + + for (int i = 0; i < e; i++) { + rv *= b; + } + return rv; +} + +// 値を固定小数点値として取得してみる。 +// digit は小数点以下の桁数で、それ以下は四捨五入する。 +// 値が "1.2345" で digit=3 なら *val = 1235 を返す。 +bool +ConfigItem::TryFixedDecimal(int *val, int digit) const +{ + char *endp; + bool neg = false; + + if (value.empty()) { + return false; + } + + errno = 0; + int r = strtol(value.c_str(), &endp, 10); + if (errno == ERANGE || !(*endp == '\0' || *endp == '.')) { + return false; + } + if (r < 0) { + r = -r; + neg = true; + } + r *= ipow(10, digit); + if (*endp == '.') { + char *p = endp + 1; + errno = 0; + int f = strtol(p, &endp, 10); + if (errno == ERANGE || *endp != '\0') { + return false; + } + int n = endp - p; + if (n <= digit) { + r += f * ipow(10, digit - n); + } else { + r += f / ipow(10, n - digit) + (p[digit] >= '5'); + } + } + *val = neg ? -r : r; + return true; +} + // デフォルト値を差し替える void ConfigItem::SetDefault(const std::string& val) @@ -637,6 +759,7 @@ ConfigItem::PrintErr(ConfigItem::from_t break; case FromOption: + case FromPerf: // コマンドラインオプションの場合は where は // "--fontsize" とか "-V" なので、 // "-V" なら (key =) value を追加し、 @@ -652,8 +775,8 @@ ConfigItem::PrintErr(ConfigItem::from_t break; default: - fromstr = string_format("corrupted item.from=%d for key=%s", - (int)from, key.c_str()); + fromstr = string_format("corrupted item.from=%u for key=%s", + (uint)from, key.c_str()); break; } @@ -687,6 +810,10 @@ ConfigFile::Load() char buf[1024]; FILE *fp; + if (filepath.empty()) { + return true; + } + fp = fopen(filepath.c_str(), "r"); if (fp == NULL) { if (errno == ENOENT) {