File:  [Isaki's NoNo m68k/m88k emulator] / nono / lib / mainapp.h
Revision 1.1.1.20 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:05:57 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v027, HEAD
nono 1.7.0

//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//

//
// CLI/GUI 共通のメイン部分
//

#pragma once

#include "header.h"
#include <vector>

class Config;
class Logger;
class MonitorManager;
class Object;
class ThreadManager;
class UIMessage;
class VM;

// VM 種別
enum class VMType {
	NONE = 0,
	X68030,
	LUNA1,
	LUNA88K,
	NEWS,
	VIRT68K,
};

// VM ケーパビリティ (ビットマスク表現)
enum class VMCap : uint32 {
	NONE	= 0,
	X68030	= (1U << (int)VMType::X68030),
	LUNA1	= (1U << (int)VMType::LUNA1),
	LUNA88K	= (1U << (int)VMType::LUNA88K),
	NEWS	= (1U << (int)VMType::NEWS),
	VIRT68K	= (1U << (int)VMType::VIRT68K),

	LUNA	= VMCap::LUNA1 | VMCap::LUNA88K,
	M68K	= VMCap::X68030 | VMCap::LUNA1 | VMCap::NEWS | VMCap::VIRT68K,
	M88K	= VMCap::LUNA88K,
	ALL		= 0xffffffff,
};
inline VMCap operator|(VMCap a, VMCap b) {
	return static_cast<VMCap>(static_cast<uint32>(a) | static_cast<uint32>(b));
}

class MainApp
{
 public:
	// Init() の戻り値
	static const int PASS = -1;		// 実行を継続

	// CPU のバインド方法。
	// o Neutral は何もしない。
	// o Binding は、Heavy スレッドを高性能コアにバインドする。
	//   Light スレッドは
	//    高性能コアが 3個以上あれば、バインドしない (OS に任せる)。
	//    高性能コアが 2個以下なら、低性能コアにバインドする
	enum class AffinityPolicy {
		Neutral,
		Binding,
	};

 public:
	MainApp();
	~MainApp();

	void Dispose();

	// 初期化 (ステージ1)
	int Init1(int ac, char *av[], std::string (*conv)(const std::string&));

	// 初期化 (ステージ2)
	bool Init2();

	// VM 種別を返す。
	// (Config が持っているのは文字列)
	VMType GetVMType() const { return vmtype; }

	// VM 種別を文字列で返す。"luna" とか。
	const std::string& GetVMTypeStr() const { return vmstr; }

	// たいていは、この機種か?で調べたいことが多いので。
	bool IsX68030() const	{ return (GetVMType() == VMType::X68030); }
	bool IsLUNA1() const	{ return (GetVMType() == VMType::LUNA1); }
	bool IsLUNA88K() const	{ return (GetVMType() == VMType::LUNA88K); }
	bool IsNEWS() const		{ return (GetVMType() == VMType::NEWS); }
	bool IsVIRT68K() const	{ return (GetVMType() == VMType::VIRT68K); }

	// 現在の VM が指定のケーパビリティを持っているか?
	bool Has(VMCap cap) const;

	// VM 機種名を返す。こっちが "LUNA-I" とかで表示用。
	const char *GetVMName() const;

	// VM ディレクトリを返す
	const std::string& GetVMDir() const { return vmdir; }

	// ファイル名から適切なフルパスを検索。
	std::string SearchFile(const std::string& name) const;

	// 指定の path を正規化(展開)して返す。
	// path が絶対パスならそのまま返す。
	// path が '~' から始まっていればホームディレクトリからの相対パス、
	// それ以外なら VM ディレクトリからの相対パスとみなして展開する。
	std::string NormalizePath(const std::string& path) const;

	// オブジェクト登録
	void RegistObject(Object *obj);

	// オブジェクト削除
	void UnregistObject(Object *obj);

	// オブジェクトのリストを返す
	const std::vector<Object *>& GetObjects() const { return objects; }

	// 指定のオブジェクトを返す。こっちは、なければ NULL を返す。
	Object *FindObject(uint id) const;

	// 指定のオブジェクトを返す。こっちは、なければ assert する。
	Object *GetObject(uint id) const;

	// 指定のオブジェクトを型 T* にキャストして返す。
	// オブジェクトがないかキャストできなければ NULL を返す。
	template <typename T>
	T *FindObject(uint id) const {
		return dynamic_cast<T *>(FindObject(id));
	}

	// 指定のオブジェクトを型 T* にキャストして返す。
	// オブジェクトがないかキャストできなければ assert する。
	template <typename T>
	T *GetObject(uint id) const {
		auto dev = FindObject<T>(id);
		assert(dev);
		return dev;
	}

	// ログレベルを設定する。
	static bool SetLogopt(const std::vector<std::string>&, std::string *errmsg);

	// ログ名の一覧を表示する
	static std::vector<std::string> GetLogNames();

	// list を一覧表示をする
	static void ShowHelpList(FILE*, const std::vector<std::string>& list);

	// Logger を返す
	Logger *GetLogger() const { return logger.get(); }

	// ThreadManager を返す
	ThreadManager *GetThreadManager() const { return threadmanager.get(); }

	// UIMessage を返す
	UIMessage *GetUIMessage() const { return uimessage.get(); }

 public:
	// CLI/GUI 区別
	bool IsCLI() const { return  is_cli; }
	bool IsGUI() const { return !is_cli; }

	// -b(--b): ブレークポイント "[<cpu>,]<addr>[,<skip>]"
	std::vector<std::string> debug_breakaddr {};

	// --bi: 命令ブレークポイント "[<cpu>,]<inst>[:<mask>][,<skip>]"
	std::vector<std::string> debug_breakinst {};

	// --bv: ベクタブレークポイント "[<cpu>,]<vec1>[-<vec2>][,<skip>]"
	std::vector<std::string> debug_breakvec {};

	// --bi-exg (とりあえず)
	bool debug_breakinst_exg {};

	// --console-log: コンソールデバイスの出力ログ。
	const char *console_logfile {};

	// -d: 起動時にデバッガで停止
	bool debug_on_start {};

	// -H: 内蔵 Human68k 風を組み込む。-X による実行ファイル名が必要。
	bool human_mode {};

	// -M: モニタ名
	std::string monitor_opt {};

	// -M: 内蔵 MSX-DOS 風を組み込む。-X による実行ファイル名が必要。
	bool msxdos_mode {};

	// -X: ホスト実行ファイル名とその引数
	const char *exec_file {};
	std::string exec_arg {};

	// AVX2 を使うかどうか。ホスト CPU 調査と設定ファイル反映後の値。
	bool enable_avx2 {};

	// AVX2 をホストがサポートしているかどうか。(こっちは情報表示用)
	bool detect_avx2 {};

	// NEON を使うかどうか。ホスト CPU 調査の設定ファイル反映後の値。
	bool enable_neon {};

	// NEON をホストがサポートしているかどうか。(こっちは情報表示用)
	bool detect_neon {};

	// CPU のバインド方法。
	AffinityPolicy affinity_policy {};

	// 要素数がコア数。高性能コアのところが true。
	std::vector<bool> fastcore {};

	// ログ表示用
	std::unique_ptr<Object> hostcpu /*{}*/;

 private:
	// 初期化ステージ1 の下請け。
	int Init1a(int, char *[], std::string (*conv)(const std::string&));
	int Init1b();

	// path を絶対パスにして返す。
	// 相対パスならカレントディレクトリからのパスとする。
	static std::string AbsPath(const char *path);

	// path を正規化して返す (下請け)。
	// path が相対パスなら basedir を起点とする。
	static std::string NormalizePath(const std::string& path,
		const std::string& basedir);

	// ヘルプメッセージを表示する
	void ShowHelp(bool all) const;

	// バージョンを表示する
	void ShowVersion() const;

	// 引数を処理する
	int ParseOpt(int ac, char *av[]);

	// CPU の機能をチェックする。
	bool CheckCPU();

	// CPU のアフィニティを調べる。
	bool CheckCPUAffinity();

	// CPU 番号リスト文字列を処理する。
	std::string ParseCPUList(const std::string& input);

	// opt を logopt に追加する (-L オプション用)
	void AddLogopt(const char *opt);

	// -L オプションを処理する
	bool ParseLogopt();
	// 早期版
	void ParseLogoptEarly();

	// ログレベル1つを設定する。
	static bool SetLogopt1(const std::string&, std::string *errmsg);

	// コンパイルされている host netdriver の一覧を表示
	void ShowHostnet() const;

	// CLI/GUI 区別
	bool is_cli {};

	// ログ
	std::unique_ptr<Logger> logger /*{}*/;

	// UIMessage
	std::unique_ptr<UIMessage> uimessage /*{}*/;

	// 全オブジェクトへのポインタのリスト (所有はしていない)
	std::vector<Object*> objects {};

	// VM
	std::unique_ptr<VM> pVM /*{}*/;

	// 設定項目
	std::unique_ptr<Config> pConfig /*{}*/;

	// VM 種別
	VMType vmtype {};
	std::string vmstr {};

	// スレッドマネージャ
	std::unique_ptr<ThreadManager> threadmanager /*{}*/;

	// モニタマネージャ
	std::unique_ptr<MonitorManager> pMonitorManager /*{}*/;

	// -c: VM ディレクトリ or 設定ファイル
	std::string vmdir {};
	std::string vmfile {};

	// -C: ログをコンソールに出力
	bool log_to_console {};

	// -L: ログ指定文字列
	std::string logopt {};

	// --perf: パフォーマンス測定モード
	bool opt_perf {};

	// --show-config: 設定内容を表示 (1なら通常、2ならall)
	int show_config {};

	// -V: パラメータ指定
	std::vector<std::pair<std::string, std::string>> config_options {};
};

// グローバルインスタンス
extern MainApp gMainApp;

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.