#!/usr/bin/env python3
# Generated by configurator/build_standalone.py. Do not edit this file directly.
from __future__ import annotations

import sys
import types

_MODULES = {'box64rc': 'from __future__ import annotations\n'
            '\n'
            'import os\n'
            'from dataclasses import dataclass\n'
            'from pathlib import Path\n'
            'from typing import Dict, Iterable, List, Optional, Tuple\n'
            '\n'
            '\n'
            '@dataclass(frozen=True)\n'
            'class SectionKey:\n'
            '    kind: str\n'
            '    name: str\n'
            '    arch: str = ""\n'
            '\n'
            '    def sort_key(self) -> Tuple[int, str, str]:\n'
            '        order = {"shared": 0, "exact": 1, "wildcard": 2, "file": 3}\n'
            '        return (order.get(self.kind, 9), self.name.lower(), self.arch.lower())\n'
            '\n'
            '\n'
            '@dataclass(frozen=True)\n'
            'class Assignment:\n'
            '    key: str\n'
            '    value: str\n'
            '    line_index: int\n'
            '\n'
            '\n'
            '@dataclass(frozen=True)\n'
            'class RcSection:\n'
            '    header: str\n'
            '    start: int\n'
            '    end: int\n'
            '    key: SectionKey\n'
            '    assignments: Tuple[Assignment, ...]\n'
            '\n'
            '    def last_value(self, key: str) -> Optional[str]:\n'
            '        return next((item.value for item in reversed(self.assignments) if item.key == key), None)\n'
            '\n'
            '\n'
            'def normalize_arch(value: Optional[str]) -> str:\n'
            '    value = (value or "").strip().strip("`")\n'
            '    if value == "<empty>":\n'
            '        return ""\n'
            '    return value.lower()\n'
            '\n'
            '\n'
            'def section_key_from_header(header: str, arch: Optional[str] = None) -> SectionKey:\n'
            '    name = header.strip()\n'
            '    arch_value = normalize_arch(arch)\n'
            '    if name == "*":\n'
            '        return SectionKey("shared", "*", arch_value)\n'
            '    if name.startswith("*") and name.endswith("*") and len(name) > 2:\n'
            '        return SectionKey("wildcard", name[1:-1].strip().lower(), arch_value)\n'
            '    if name.startswith("/"):\n'
            '        return SectionKey("file", name.lower(), arch_value)\n'
            '    return SectionKey("exact", name.lower(), arch_value)\n'
            '\n'
            '\n'
            'def header_from_key(key: SectionKey) -> str:\n'
            '    if key.kind == "shared":\n'
            '        return "*"\n'
            '    if key.kind == "wildcard":\n'
            '        return f"*{key.name}*"\n'
            '    return key.name\n'
            '\n'
            '\n'
            'def semantic_line(line: str) -> str:\n'
            '    return line.rstrip("\\n").split("#", 1)[0].strip()\n'
            '\n'
            '\n'
            'def parse_section_header(line: str) -> Optional[str]:\n'
            '    semantic = semantic_line(line)\n'
            '    return semantic[1 : semantic.find("]")].strip() if semantic.startswith("[") and "]" in semantic else '
            'None\n'
            '\n'
            '\n'
            'def parse_assignment(line: str) -> Optional[Tuple[str, str]]:\n'
            '    semantic = semantic_line(line)\n'
            '    if "=" not in semantic:\n'
            '        return None\n'
            '    key, value = semantic.split("=", 1)\n'
            '    key = key.strip()\n'
            '    return (key, value.strip()) if key else None\n'
            '\n'
            '\n'
            'def render_assignment_line(original: str, key: str, value: str) -> str:\n'
            '    text = original.rstrip("\\n")\n'
            '    newline = "\\n" if original.endswith("\\n") else ""\n'
            '    indent = text[: len(text) - len(text.lstrip())]\n'
            '    comment = ""\n'
            '    comment_start = text.find("#")\n'
            '    if comment_start >= 0:\n'
            '        comment = "  " + text[comment_start:].strip()\n'
            '    return f"{indent}{key}={value}{comment}{newline or os.linesep}"\n'
            '\n'
            '\n'
            'class RcDocument:\n'
            '    def __init__(self, path: Path) -> None:\n'
            '        self.path = path\n'
            '        self.lines: List[str] = []\n'
            '        self.sections: List[RcSection] = []\n'
            '        self.sections_by_key: Dict[SectionKey, RcSection] = {}\n'
            '        self.reload()\n'
            '\n'
            '    def reload(self) -> None:\n'
            '        self.lines = self.path.read_text(encoding="utf-8").splitlines(True) if self.path.is_file() else '
            '[]\n'
            '        self._parse()\n'
            '\n'
            '    def _parse(self) -> None:\n'
            '        builders: List[Dict[str, object]] = []\n'
            '        current: Optional[Dict[str, object]] = None\n'
            '\n'
            '        for index, line in enumerate(self.lines):\n'
            '            header = parse_section_header(line)\n'
            '            if header is not None:\n'
            '                if current is not None:\n'
            '                    current["end"] = index\n'
            '                current = {\n'
            '                    "header": header,\n'
            '                    "start": index,\n'
            '                    "end": len(self.lines),\n'
            '                    "assignments": [],\n'
            '                }\n'
            '                builders.append(current)\n'
            '                continue\n'
            '\n'
            '            if current is None:\n'
            '                continue\n'
            '\n'
            '            parsed = parse_assignment(line)\n'
            '            if parsed is None:\n'
            '                continue\n'
            '            key, value = parsed\n'
            '            current["assignments"].append(Assignment(key, value, index))\n'
            '\n'
            '        if current is not None:\n'
            '            current["end"] = len(self.lines)\n'
            '\n'
            '        sections: List[RcSection] = []\n'
            '        for builder in builders:\n'
            '            assignments = tuple(builder["assignments"])\n'
            '            arch = next((item.value for item in reversed(assignments) if item.key == "BOX64_ARCH"), '
            'None)\n'
            '            key = section_key_from_header(str(builder["header"]), arch)\n'
            '            sections.append(\n'
            '                RcSection(\n'
            '                    header=str(builder["header"]),\n'
            '                    start=int(builder["start"]),\n'
            '                    end=int(builder["end"]),\n'
            '                    key=key,\n'
            '                    assignments=assignments,\n'
            '                )\n'
            '            )\n'
            '\n'
            '        self.sections = sections\n'
            '        self.sections_by_key = {section.key: section for section in sections}\n'
            '\n'
            '    def section_for_key(self, key: SectionKey) -> Optional[RcSection]:\n'
            '        return self.sections_by_key.get(key)\n'
            '\n'
            '    def add_section(self, header: str, assignments: Optional[Dict[str, str]] = None) -> RcSection:\n'
            '        if self.lines and self.lines[-1].strip():\n'
            '            self.lines.append(os.linesep)\n'
            '        self.lines.append(f"[{header}]{os.linesep}")\n'
            '        for key, value in (assignments or {}).items():\n'
            '            self.lines.append(f"{key}={value}{os.linesep}")\n'
            '        self._parse()\n'
            '        return self.sections[-1]\n'
            '\n'
            '    def delete_section(self, key: SectionKey) -> None:\n'
            '        section = self.section_for_key(key)\n'
            '        if section is None:\n'
            '            return\n'
            '        del self.lines[section.start : section.end]\n'
            '        self._parse()\n'
            '\n'
            '    def set_assignment(self, section_key: SectionKey, key: str, value: str) -> SectionKey:\n'
            '        section = self.section_for_key(section_key)\n'
            '        if section is None:\n'
            '            raise KeyError(section_key)\n'
            '\n'
            '        matching = [assignment for assignment in section.assignments if assignment.key == key]\n'
            '        if matching:\n'
            '            line_index = matching[-1].line_index\n'
            '            self.lines[line_index] = render_assignment_line(self.lines[line_index], key, value)\n'
            '            start = section.start\n'
            '        else:\n'
            '            insert_at = section.end\n'
            '            self.lines.insert(insert_at, f"{key}={value}{os.linesep}")\n'
            '            start = section.start\n'
            '\n'
            '        self._parse()\n'
            '        for updated in self.sections:\n'
            '            if updated.start == start:\n'
            '                return updated.key\n'
            '        raise KeyError(section_key)\n'
            '\n'
            '    def remove_assignment(self, section_key: SectionKey, key: str) -> SectionKey:\n'
            '        section = self.section_for_key(section_key)\n'
            '        if section is None:\n'
            '            raise KeyError(section_key)\n'
            '\n'
            '        indexes = [assignment.line_index for assignment in section.assignments if assignment.key == key]\n'
            '        start = section.start\n'
            '        for line_index in reversed(indexes):\n'
            '            del self.lines[line_index]\n'
            '\n'
            '        self._parse()\n'
            '        for updated in self.sections:\n'
            '            if updated.start == start:\n'
            '                return updated.key\n'
            '        return section_key\n'
            '\n'
            '    def save(self) -> None:\n'
            '        self.path.parent.mkdir(parents=True, exist_ok=True)\n'
            '        data = "".join(self.lines)\n'
            '        tmp_path = self.path.with_name(f"{self.path.name}.tmp")\n'
            '        tmp_path.write_text(data, encoding="utf-8")\n'
            '        if self.path.exists():\n'
            '            mode = self.path.stat().st_mode\n'
            '            os.chmod(tmp_path, mode)\n'
            '        os.replace(tmp_path, self.path)\n'
            '\n'
            '\n'
            'def copy_assignments(section: RcSection) -> Dict[str, str]:\n'
            '    return {assignment.key: assignment.value for assignment in section.assignments}\n'
            '\n'
            '\n'
            'def direct_box64_assignments(section: Optional[RcSection]) -> Iterable[Assignment]:\n'
            '    return () if section is None else tuple(\n'
            '        assignment for assignment in section.assignments if assignment.key.startswith("BOX64_")\n'
            '    )\n',
 'configurator': '#!/usr/bin/env python3\n'
                 'from __future__ import annotations\n'
                 '\n'
                 'import argparse\n'
                 'import json\n'
                 'import locale\n'
                 'import platform\n'
                 'import sys\n'
                 'from pathlib import Path\n'
                 'from typing import Dict, List, Optional, Sequence, Tuple\n'
                 '\n'
                 'if __package__ in (None, ""):\n'
                 '    sys.path.insert(0, str(Path(__file__).resolve().parent))\n'
                 '\n'
                 'import gi\n'
                 '\n'
                 'gi.require_version("Gtk", "3.0")\n'
                 'from gi.repository import Gio, GLib, Gtk, Pango\n'
                 '\n'
                 'try:\n'
                 '    from .model import ConfigStore, EntryRecord, ValueState, box64_arch_from_machine\n'
                 '    from .usage import EnvOption, load_default_usage_catalog, load_usage_catalog\n'
                 'except ImportError:\n'
                 '    from model import ConfigStore, EntryRecord, ValueState, box64_arch_from_machine\n'
                 '    from usage import EnvOption, load_default_usage_catalog, load_usage_catalog\n'
                 '\n'
                 '\n'
                 'APP_ID = "org.box64.Configurator"\n'
                 '\n'
                 '\n'
                 '_EMBEDDED_TEXTS: Optional[Dict[str, Dict[str, str]]] = globals().get("_EMBEDDED_TEXTS")\n'
                 '_EMBEDDED_UI: Optional[str] = globals().get("_EMBEDDED_UI")\n'
                 '\n'
                 '\n'
                 'def load_texts() -> Dict[str, Dict[str, str]]:\n'
                 '    if _EMBEDDED_TEXTS is not None:\n'
                 '        return _EMBEDDED_TEXTS\n'
                 '\n'
                 '    directory = Path(__file__).resolve().parent\n'
                 '    texts: Dict[str, Dict[str, str]] = {}\n'
                 '    for language in ("en", "zh"):\n'
                 '        path = directory / f"text_{language}.json"\n'
                 '        with path.open("r", encoding="utf-8") as file:\n'
                 '            texts[language] = json.load(file)\n'
                 '    return texts\n'
                 '\n'
                 '\n'
                 'def load_ui(builder: Gtk.Builder) -> None:\n'
                 '    if _EMBEDDED_UI is not None:\n'
                 '        builder.add_from_string(_EMBEDDED_UI)\n'
                 '        return\n'
                 '    builder.add_from_file(str(Path(__file__).resolve().parent / "configurator.ui"))\n'
                 '\n'
                 '\n'
                 'TEXT = load_texts()\n'
                 '\n'
                 '\n'
                 'CSS = b"""\n'
                 '.configurator-window:backdrop,\n'
                 '.configurator-window *:backdrop {\n'
                 '    color: @theme_fg_color;\n'
                 '}\n'
                 'headerbar:backdrop {\n'
                 '    background-color: @theme_bg_color;\n'
                 '    background-image: none;\n'
                 '    color: @theme_fg_color;\n'
                 '}\n'
                 'headerbar:backdrop button,\n'
                 'headerbar:backdrop combobox,\n'
                 'headerbar:backdrop label,\n'
                 'headerbar:backdrop image {\n'
                 '    color: @theme_fg_color;\n'
                 '    opacity: 1;\n'
                 '    -gtk-icon-effect: none;\n'
                 '}\n'
                 '.sidebar {\n'
                 '    background: @theme_base_color;\n'
                 '}\n'
                 '.entry-title {\n'
                 '    font-weight: 600;\n'
                 '}\n'
                 '.entry-subtitle {\n'
                 '    opacity: 0.72;\n'
                 '    font-size: 0.88em;\n'
                 '}\n'
                 '.detail-title {\n'
                 '    font-size: 1.45em;\n'
                 '    font-weight: 700;\n'
                 '}\n'
                 '.section-heading {\n'
                 '    font-size: 1.08em;\n'
                 '    font-weight: 700;\n'
                 '    margin-top: 18px;\n'
                 '    margin-bottom: 6px;\n'
                 '}\n'
                 '.option-row {\n'
                 '    background: transparent;\n'
                 '    border-left: 3px solid transparent;\n'
                 '    border-bottom: 1px solid alpha(@theme_fg_color, 0.18);\n'
                 '}\n'
                 '.option-row:hover {\n'
                 '    background: alpha(@theme_selected_bg_color, 0.10);\n'
                 '}\n'
                 '.option-row:focus {\n'
                 '    box-shadow: inset 0 0 0 1px alpha(@theme_selected_bg_color, 0.55);\n'
                 '}\n'
                 '.option-row.selected-option {\n'
                 '    background: alpha(@theme_selected_bg_color, 0.18);\n'
                 '    border-left-color: @theme_selected_bg_color;\n'
                 '    border-bottom-color: alpha(@theme_selected_bg_color, 0.40);\n'
                 '}\n'
                 '.option-row.selected-option:hover {\n'
                 '    background: alpha(@theme_selected_bg_color, 0.24);\n'
                 '}\n'
                 '.default-row {\n'
                 '    color: alpha(@theme_fg_color, 0.62);\n'
                 '    background: alpha(@theme_fg_color, 0.035);\n'
                 '}\n'
                 '.choice-doc {\n'
                 '    opacity: 0.78;\n'
                 '    font-size: 0.9em;\n'
                 '}\n'
                 '.status-note {\n'
                 '    border-radius: 6px;\n'
                 '    padding: 8px 10px;\n'
                 '    background: alpha(@theme_selected_bg_color, 0.12);\n'
                 '}\n'
                 '.badge {\n'
                 '    border-radius: 999px;\n'
                 '    padding: 2px 8px;\n'
                 '    background: alpha(@theme_fg_color, 0.12);\n'
                 '    font-size: 0.85em;\n'
                 '}\n'
                 '.selected-option {\n'
                 '    background: alpha(@theme_selected_bg_color, 0.10);\n'
                 '}\n'
                 '"""\n'
                 '\n'
                 '\n'
                 'def tr(language: str, key: str) -> str:\n'
                 '    return TEXT[language].get(key, TEXT["en"][key])\n'
                 '\n'
                 '\n'
                 'def detect_language() -> str:\n'
                 '    code = locale.getlocale()[0] or ""\n'
                 '    return "zh" if code.lower().startswith("zh") else "en"\n'
                 '\n'
                 '\n'
                 'def add_style(widget: Gtk.Widget, *classes: str) -> Gtk.Widget:\n'
                 '    style = widget.get_style_context()\n'
                 '    for css_class in classes:\n'
                 '        style.add_class(css_class)\n'
                 '    return widget\n'
                 '\n'
                 '\n'
                 'def set_style(widget: Gtk.Widget, css_class: str, active: bool) -> None:\n'
                 '    style = widget.get_style_context()\n'
                 '    (style.add_class if active else style.remove_class)(css_class)\n'
                 '\n'
                 '\n'
                 'def make_label(\n'
                 '    text: str = "",\n'
                 '    css_class: Optional[str] = None,\n'
                 '    *,\n'
                 '    selectable: bool = False,\n'
                 '    wrap: bool = False,\n'
                 '    ellipsize: bool = False,\n'
                 ') -> Gtk.Label:\n'
                 '    label = Gtk.Label(label=text)\n'
                 '    label.set_xalign(0)\n'
                 '    label.set_selectable(selectable)\n'
                 '    label.set_line_wrap(wrap)\n'
                 '    if ellipsize:\n'
                 '        label.set_ellipsize(Pango.EllipsizeMode.END)\n'
                 '    if css_class:\n'
                 '        add_style(label, css_class)\n'
                 '    return label\n'
                 '\n'
                 '\n'
                 'def default_system_rc() -> Path:\n'
                 '    etc_path = Path("/etc/box64.box64rc")\n'
                 '    if etc_path.is_file():\n'
                 '        return etc_path\n'
                 '    repo_sample = Path(__file__).resolve().parent.parent / "system" / "box64.box64rc"\n'
                 '    return repo_sample\n'
                 '\n'
                 '\n'
                 'def default_user_rc() -> Path:\n'
                 '    return Path.home() / ".box64rc"\n'
                 '\n'
                 '\n'
                 'class EntryRow(Gtk.ListBoxRow):\n'
                 '    def __init__(self, entry: EntryRecord, language: str) -> None:\n'
                 '        super().__init__()\n'
                 '        self.entry = entry\n'
                 '        self.language = language\n'
                 '\n'
                 '        box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=3)\n'
                 '        box.set_border_width(8)\n'
                 '\n'
                 '        self.title = make_label(css_class="entry-title", ellipsize=True)\n'
                 '        box.pack_start(self.title, False, False, 0)\n'
                 '\n'
                 '        self.subtitle = make_label(css_class="entry-subtitle", ellipsize=True)\n'
                 '        box.pack_start(self.subtitle, False, False, 0)\n'
                 '\n'
                 '        self.add(box)\n'
                 '        self.update(entry, language)\n'
                 '\n'
                 '    def update(self, entry: EntryRecord, language: str) -> None:\n'
                 '        self.entry = entry\n'
                 '        self.language = language\n'
                 '        self.title.set_text(self._title())\n'
                 '        self.subtitle.set_text(self._subtitle())\n'
                 '\n'
                 '    def _title(self) -> str:\n'
                 '        if self.entry.key.kind == "shared":\n'
                 '            return "[*]"\n'
                 '        return self.entry.display_name\n'
                 '\n'
                 '    def _subtitle(self) -> str:\n'
                 '        pieces: List[str] = []\n'
                 '        if self.entry.key.kind == "wildcard":\n'
                 '            pieces.append("*pattern*")\n'
                 '        elif self.entry.key.kind == "file":\n'
                 '            pieces.append("file")\n'
                 '        if self.entry.arch:\n'
                 '            pieces.append(self.entry.arch)\n'
                 '        pieces.append(tr(self.language, f"source_{self.entry.editable_source}"))\n'
                 '        return " · ".join(pieces)\n'
                 '\n'
                 '\n'
                 'class OptionRow(Gtk.EventBox):\n'
                 '    KEY_RETURN = 65293\n'
                 '    KEY_KP_ENTER = 65421\n'
                 '    KEY_SPACE = 32\n'
                 '\n'
                 '    def __init__(self, owner: "ConfiguratorWindow", option: EnvOption) -> None:\n'
                 '        super().__init__()\n'
                 '        self.owner = owner\n'
                 '        self.option = option\n'
                 '        self.entry: Optional[EntryRecord] = None\n'
                 '        self.state: Optional[ValueState] = None\n'
                 '        self.language = ""\n'
                 '        self.is_selected = False\n'
                 '\n'
                 '        add_style(self, "option-row")\n'
                 '        self.set_visible_window(True)\n'
                 '        self.set_can_focus(True)\n'
                 '        self.connect("button-press-event", self._on_button_press)\n'
                 '        self.connect("key-press-event", self._on_key_press)\n'
                 '\n'
                 '        box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=14)\n'
                 '        box.set_border_width(14)\n'
                 '        self.add(box)\n'
                 '\n'
                 '        text_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=7)\n'
                 '        box.pack_start(text_box, True, True, 0)\n'
                 '\n'
                 '        title_line = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8)\n'
                 '        text_box.pack_start(title_line, False, False, 0)\n'
                 '\n'
                 '        self.name = make_label(option.name, "entry-title", selectable=True)\n'
                 '        title_line.pack_start(self.name, False, False, 0)\n'
                 '\n'
                 '        self.badge = make_label(css_class="badge")\n'
                 '        title_line.pack_start(self.badge, False, False, 0)\n'
                 '\n'
                 '        self.description = make_label(css_class="choice-doc", ellipsize=True)\n'
                 '        text_box.pack_start(self.description, False, False, 0)\n'
                 '\n'
                 '        self.chevron = Gtk.Image.new_from_icon_name("pan-end-symbolic", Gtk.IconSize.MENU)\n'
                 '        box.pack_end(self.chevron, False, False, 0)\n'
                 '\n'
                 '    def update(\n'
                 '        self,\n'
                 '        entry: EntryRecord,\n'
                 '        state: ValueState,\n'
                 '        default_row: bool,\n'
                 '        language: str,\n'
                 '        selected: bool,\n'
                 '    ) -> None:\n'
                 '        self.entry = entry\n'
                 '        self.state = state\n'
                 '\n'
                 '        set_style(self, "default-row", default_row)\n'
                 '\n'
                 '        source_label = tr(language, f"source_{state.source}")\n'
                 '        if state.source == "default" and not state.value:\n'
                 '            value_label = tr(language, "default_dynamic")\n'
                 '        else:\n'
                 '            value_label = state.value if state.value != "" else "<empty>"\n'
                 '        self.badge.set_text(f"{source_label}: {value_label}")\n'
                 '\n'
                 '        if language != self.language:\n'
                 '            self.language = language\n'
                 '            self.description.set_text(self.option.description(language))\n'
                 '            self.set_tooltip_text(tr(language, "edit"))\n'
                 '\n'
                 '        self.set_selected(selected)\n'
                 '\n'
                 '    def set_selected(self, selected: bool) -> None:\n'
                 '        set_style(self, "selected-option", selected)\n'
                 '        self.is_selected = selected\n'
                 '        self.chevron.set_from_icon_name(\n'
                 '            "pan-down-symbolic" if selected else "pan-end-symbolic", Gtk.IconSize.MENU\n'
                 '        )\n'
                 '\n'
                 '    def _activate(self) -> None:\n'
                 '        if self.entry is None or self.state is None:\n'
                 '            return\n'
                 '        self.owner.toggle_option(self.entry, self.state.option.name)\n'
                 '\n'
                 '    def _on_button_press(self, _widget: Gtk.Widget, event) -> bool:\n'
                 '        if event.button != 1:\n'
                 '            return False\n'
                 '        self.grab_focus()\n'
                 '        self._activate()\n'
                 '        return True\n'
                 '\n'
                 '    def _on_key_press(self, _widget: Gtk.Widget, event) -> bool:\n'
                 '        if event.keyval not in (self.KEY_RETURN, self.KEY_KP_ENTER, self.KEY_SPACE):\n'
                 '            return False\n'
                 '        self._activate()\n'
                 '        return True\n'
                 '\n'
                 '\n'
                 'class ConfiguratorWindow(Gtk.ApplicationWindow):\n'
                 '    def __init__(self, app: Gtk.Application, store: ConfigStore) -> None:\n'
                 '        super().__init__(application=app)\n'
                 '        self.store = store\n'
                 '        self.language = detect_language()\n'
                 '        self.get_style_context().add_class("configurator-window")\n'
                 '        self.current_key = None\n'
                 '        self.rows_by_key: Dict[object, EntryRow] = {}\n'
                 '        self.status_context = 0\n'
                 '        self._filter_text = ""\n'
                 '        self._entry_filter_mode = "all"\n'
                 '        self._building = False\n'
                 '        self._pending_refresh_key = None\n'
                 '        self._pending_status = ""\n'
                 '        self._pending_rebuild_entries = False\n'
                 '        self._pending_refresh_source = 0\n'
                 '        self.option_rows: Dict[str, OptionRow] = {}\n'
                 '        self.selected_option_name: Optional[str] = None\n'
                 '        self.selected_option_editor: Optional[Gtk.Widget] = None\n'
                 '\n'
                 '        self.set_default_size(1120, 740)\n'
                 '        self.set_title(tr(self.language, "title"))\n'
                 '        self.connect("delete-event", self._on_delete_event)\n'
                 '\n'
                 '        self._install_css()\n'
                 '        self._build_ui()\n'
                 '        self._refresh_view()\n'
                 '        self.show_all()\n'
                 '\n'
                 '    def _install_css(self) -> None:\n'
                 '        provider = Gtk.CssProvider()\n'
                 '        provider.load_from_data(CSS)\n'
                 '        Gtk.StyleContext.add_provider_for_screen(\n'
                 '            self.get_screen(), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION\n'
                 '        )\n'
                 '\n'
                 '    def _build_ui(self) -> None:\n'
                 '        builder = Gtk.Builder()\n'
                 '        load_ui(builder)\n'
                 '\n'
                 '        self.header = builder.get_object("header")\n'
                 '        self.set_titlebar(self.header)\n'
                 '        self.header.props.title = tr(self.language, "title")\n'
                 '\n'
                 '        root = builder.get_object("root_box")\n'
                 '        self.add(root)\n'
                 '\n'
                 '        self.new_button = builder.get_object("new_button")\n'
                 '        self.delete_button = builder.get_object("delete_button")\n'
                 '        self.reload_button = builder.get_object("reload_button")\n'
                 '        self.save_button = builder.get_object("save_button")\n'
                 '        self.language_combo = builder.get_object("language_combo")\n'
                 '        self.search = builder.get_object("search_entry")\n'
                 '        self.mode_box = builder.get_object("mode_box")\n'
                 '        self.all_button = builder.get_object("all_button")\n'
                 '        self.user_button = builder.get_object("user_button")\n'
                 '        self.status = builder.get_object("statusbar")\n'
                 '\n'
                 '        list_scroll = builder.get_object("list_scroll")\n'
                 '        list_scroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)\n'
                 '        for child in list_scroll.get_children():\n'
                 '            list_scroll.remove(child)\n'
                 '        self.entry_list = Gtk.ListBox()\n'
                 '        self.entry_list.set_selection_mode(Gtk.SelectionMode.SINGLE)\n'
                 '        list_scroll.add(self.entry_list)\n'
                 '\n'
                 '        detail_scroll = builder.get_object("detail_scroll")\n'
                 '        detail_scroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)\n'
                 '        for child in detail_scroll.get_children():\n'
                 '            detail_scroll.remove(child)\n'
                 '        self.detail_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=8)\n'
                 '        self.detail_box.set_border_width(18)\n'
                 '        self.detail_header = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)\n'
                 '        self.effective_group = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)\n'
                 '        self.unsupported_group = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)\n'
                 '        self.defaults_group = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)\n'
                 '        self.detail_box.pack_start(self.detail_header, False, False, 0)\n'
                 '        self.detail_box.pack_start(self.effective_group, False, False, 0)\n'
                 '        self.detail_box.pack_start(self.unsupported_group, False, False, 0)\n'
                 '        self.detail_box.pack_start(self.defaults_group, False, False, 0)\n'
                 '        detail_scroll.add(self.detail_box)\n'
                 '\n'
                 '        self._configure_header_button(self.new_button, "document-new-symbolic", "new", '
                 'self._on_new_entry)\n'
                 '        self._configure_header_button(self.delete_button, "user-trash-symbolic", "delete", '
                 'self._on_delete_entry)\n'
                 '        self._configure_header_button(self.reload_button, "view-refresh-symbolic", "reload", '
                 'self._on_reload)\n'
                 '        self._configure_header_button(self.save_button, "document-save-symbolic", "save", '
                 'self._on_save)\n'
                 '        save_action = Gio.SimpleAction.new("save", None)\n'
                 '        save_action.connect("activate", self._on_save_action)\n'
                 '        self.add_action(save_action)\n'
                 '        self.get_application().set_accels_for_action("win.save", ["<Primary>s"])\n'
                 '\n'
                 '        self.language_combo.append("en", "English")\n'
                 '        self.language_combo.append("zh", "中文")\n'
                 '        self.language_combo.set_active_id(self.language)\n'
                 '        self.language_combo.connect("changed", self._on_language_changed)\n'
                 '\n'
                 '        self.search.set_can_focus(True)\n'
                 '        self.search.set_placeholder_text(tr(self.language, "search"))\n'
                 '        self.search.connect("search-changed", self._on_search_changed)\n'
                 '\n'
                 '        self.all_button.set_can_focus(True)\n'
                 '        self.user_button.set_can_focus(True)\n'
                 '        self.all_button.set_label(tr(self.language, "filter_all"))\n'
                 '        self.user_button.set_label(tr(self.language, "filter_user"))\n'
                 '        self.all_button.connect("toggled", self._on_mode_toggled, "all")\n'
                 '        self.user_button.connect("toggled", self._on_mode_toggled, "user")\n'
                 '\n'
                 '        self.entry_list.set_can_focus(True)\n'
                 '        self.entry_list.set_filter_func(self._filter_entry_row)\n'
                 '        self.entry_list.connect("row-selected", self._on_entry_selected)\n'
                 '\n'
                 '        self.language_combo.set_can_focus(True)\n'
                 '\n'
                 '        self.status_context = self.status.get_context_id("main")\n'
                 '\n'
                 '    def _configure_header_button(\n'
                 '        self, button: Gtk.Button, icon: str, tooltip_key: str, callback\n'
                 '    ) -> None:\n'
                 '        button.set_image(Gtk.Image.new_from_icon_name(icon, Gtk.IconSize.BUTTON))\n'
                 '        button.set_tooltip_text(tr(self.language, tooltip_key))\n'
                 '        button.connect("clicked", callback)\n'
                 '\n'
                 '    def _filter_entry_row(self, row: EntryRow) -> bool:\n'
                 '        if self._entry_filter_mode == "user" and row.entry.user_section is None:\n'
                 '            return False\n'
                 '        text = self._filter_text\n'
                 '        if not text:\n'
                 '            return True\n'
                 '        haystack = f"{row.entry.display_name} {row.entry.key.arch}".lower()\n'
                 '        return text in haystack\n'
                 '\n'
                 '    def _refresh_entries(self, select_key=None) -> None:\n'
                 '        self._building = True\n'
                 '        selected_key = select_key if select_key is not None else self.current_key\n'
                 '        for child in self.entry_list.get_children():\n'
                 '            self.entry_list.remove(child)\n'
                 '\n'
                 '        self.rows_by_key.clear()\n'
                 '        for entry in self.store.entries():\n'
                 '            row = EntryRow(entry, self.language)\n'
                 '            self.rows_by_key[entry.key] = row\n'
                 '            self.entry_list.add(row)\n'
                 '\n'
                 '        self.entry_list.show_all()\n'
                 '        self.entry_list.invalidate_filter()\n'
                 '\n'
                 '        if selected_key in self.rows_by_key:\n'
                 '            self.entry_list.select_row(self.rows_by_key[selected_key])\n'
                 '            self.current_key = selected_key\n'
                 '        elif self.rows_by_key:\n'
                 '            first_row = next(iter(self.rows_by_key.values()))\n'
                 '            self.entry_list.select_row(first_row)\n'
                 '            self.current_key = first_row.entry.key\n'
                 '        else:\n'
                 '            self.current_key = None\n'
                 '\n'
                 '        self._building = False\n'
                 '        self._update_actions()\n'
                 '\n'
                 '    def _refresh_entry_row(self, key) -> None:\n'
                 '        row = self.rows_by_key.get(key)\n'
                 '        entry = self.store.entry_for_key(key)\n'
                 '        if row is None or entry is None:\n'
                 '            self._refresh_entries(select_key=key)\n'
                 '            return\n'
                 '\n'
                 '        row.update(entry, self.language)\n'
                 '        row.show_all()\n'
                 '        self.entry_list.invalidate_filter()\n'
                 '\n'
                 '    def _refresh_view(self, select_key=None) -> None:\n'
                 '        self._refresh_entries(select_key=select_key)\n'
                 '        self._refresh_details()\n'
                 '\n'
                 '    def _refresh_details(self) -> None:\n'
                 '        self.selected_option_editor = None\n'
                 '        self.option_rows.clear()\n'
                 '        for container in (\n'
                 '            self.detail_header,\n'
                 '            self.effective_group,\n'
                 '            self.unsupported_group,\n'
                 '            self.defaults_group,\n'
                 '        ):\n'
                 '            for child in container.get_children():\n'
                 '                child.destroy()\n'
                 '\n'
                 '        self.effective_group.hide()\n'
                 '        self.unsupported_group.hide()\n'
                 '        self.defaults_group.hide()\n'
                 '\n'
                 '        if self.current_key is None:\n'
                 '            self.detail_header.pack_start(\n'
                 '                make_label(tr(self.language, "select_entry")), False, False, 0\n'
                 '            )\n'
                 '            self.detail_header.show_all()\n'
                 '            return\n'
                 '\n'
                 '        entry = self.store.entry_for_key(self.current_key)\n'
                 '        if entry is None:\n'
                 '            return\n'
                 '\n'
                 '        self._add_entry_header(entry)\n'
                 '        active, defaults = self.store.effective_values(entry)\n'
                 '        visible_names = {state.option.name for state in (*active, *defaults)}\n'
                 '        if self.selected_option_name not in visible_names:\n'
                 '            self.selected_option_name = None\n'
                 '        self._add_option_group(\n'
                 '            self.effective_group, tr(self.language, "effective"), active, entry, default_rows=False\n'
                 '        )\n'
                 '        self._add_unsupported(entry)\n'
                 '        self._add_option_group(\n'
                 '            self.defaults_group, tr(self.language, "defaults"), defaults, entry, default_rows=True\n'
                 '        )\n'
                 '\n'
                 '        self.detail_header.show_all()\n'
                 '        self.effective_group.show_all()\n'
                 '        self.defaults_group.show_all()\n'
                 '        if self.unsupported_group.get_children():\n'
                 '            self.unsupported_group.show_all()\n'
                 '        else:\n'
                 '            self.unsupported_group.hide()\n'
                 '        self._update_actions()\n'
                 '\n'
                 '    def _add_entry_header(self, entry: EntryRecord) -> None:\n'
                 '        title = "[*]" if entry.key.kind == "shared" else entry.display_name\n'
                 '        self.detail_header.pack_start(\n'
                 '            make_label(title, "detail-title", selectable=True), False, False, 0\n'
                 '        )\n'
                 '\n'
                 '        source_text = (\n'
                 '            tr(self.language, "user_note") if entry.user_section else tr(self.language, '
                 '"system_note")\n'
                 '        )\n'
                 '        if entry.system_section is None:\n'
                 '            source_text = tr(self.language, "user_note")\n'
                 '        if entry.arch:\n'
                 '            source_text = f"{source_text}  BOX64_ARCH={entry.arch}"\n'
                 '\n'
                 '        self.detail_header.pack_start(\n'
                 '            make_label(source_text, "status-note", wrap=True), False, False, 0\n'
                 '        )\n'
                 '\n'
                 '    def _build_option_editor(self, entry: EntryRecord, state: ValueState) -> Gtk.Box:\n'
                 '        option = state.option\n'
                 '        panel = add_style(Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=8), "status-note")\n'
                 '        panel.pack_start(make_label(option.name, "entry-title"), False, False, 0)\n'
                 '        panel.pack_start(make_label(option.description(self.language), wrap=True), False, False, 0)\n'
                 '\n'
                 '        controls = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8)\n'
                 '        panel.pack_start(controls, False, False, 0)\n'
                 '\n'
                 '        if option.allows_custom_value:\n'
                 '            value_entry = Gtk.Entry()\n'
                 '            value_entry.set_text(state.value)\n'
                 '            value_entry.set_width_chars(28)\n'
                 '            controls.pack_start(value_entry, False, False, 0)\n'
                 '\n'
                 '            apply_button = Gtk.Button(label=tr(self.language, "apply"))\n'
                 '            apply_button.connect(\n'
                 '                "clicked",\n'
                 '                lambda _button: self.change_option(entry, option.name, value_entry.get_text()),\n'
                 '            )\n'
                 '            controls.pack_start(apply_button, False, False, 0)\n'
                 '        else:\n'
                 '            combo = Gtk.ComboBoxText()\n'
                 '            values: List[str] = []\n'
                 '            active_index = -1\n'
                 '            for index, choice in enumerate(option.choices):\n'
                 '                combo.append(str(index), choice.label)\n'
                 '                values.append(choice.value)\n'
                 '                if choice.value == state.value:\n'
                 '                    active_index = index\n'
                 '\n'
                 '            if active_index < 0 and state.value:\n'
                 '                active_index = len(values)\n'
                 '                values.append(state.value)\n'
                 '                combo.append(str(active_index), state.value)\n'
                 '\n'
                 '            combo.set_active(active_index)\n'
                 '            combo.connect("changed", self._on_editor_choice_changed, entry, option.name, values)\n'
                 '            controls.pack_start(combo, False, False, 0)\n'
                 '\n'
                 '        reset = Gtk.Button(label=tr(self.language, "reset"))\n'
                 '        reset.set_sensitive(entry.user_section is not None)\n'
                 '        reset.connect("clicked", lambda _button: self.reset_option(entry, option.name))\n'
                 '        controls.pack_start(reset, False, False, 0)\n'
                 '\n'
                 '        choice_lines = []\n'
                 '        for choice in option.choices:\n'
                 '            suffix = f" [{tr(self.language, \'default_marker\')}]" if choice.is_default else ""\n'
                 '            choice_lines.append(f"{choice.label}: {choice.description(self.language)}{suffix}")\n'
                 '\n'
                 '        if choice_lines:\n'
                 '            panel.pack_start(\n'
                 '                make_label("\\n".join(choice_lines), "choice-doc", wrap=True), False, False, 0\n'
                 '            )\n'
                 '\n'
                 '        return panel\n'
                 '\n'
                 '    def _add_option_group(\n'
                 '        self,\n'
                 '        container: Gtk.Box,\n'
                 '        title_text: str,\n'
                 '        states: Sequence[ValueState],\n'
                 '        entry: EntryRecord,\n'
                 '        default_rows: bool,\n'
                 '    ) -> None:\n'
                 '        container.pack_start(\n'
                 '            make_label(f"{title_text} ({len(states)})", "section-heading"), False, False, 0\n'
                 '        )\n'
                 '\n'
                 '        if not states:\n'
                 '            return\n'
                 '\n'
                 '        for state in states:\n'
                 '            selected = state.option.name == self.selected_option_name\n'
                 '            row = self._option_row_for(\n'
                 '                entry,\n'
                 '                state,\n'
                 '                default_rows,\n'
                 '                selected=selected,\n'
                 '            )\n'
                 '            container.pack_start(row, False, False, 0)\n'
                 '            if selected:\n'
                 '                self._insert_option_editor_after(container, row, entry, state)\n'
                 '\n'
                 '    def _option_row_for(\n'
                 '        self, entry: EntryRecord, state: ValueState, default_row: bool, selected: bool\n'
                 '    ) -> OptionRow:\n'
                 '        row = self.option_rows.get(state.option.name)\n'
                 '        if row is None:\n'
                 '            row = OptionRow(self, state.option)\n'
                 '            self.option_rows[state.option.name] = row\n'
                 '        row.update(entry, state, default_row, self.language, selected)\n'
                 '        return row\n'
                 '\n'
                 '    def _add_unsupported(self, entry: EntryRecord) -> None:\n'
                 '        unsupported = self.store.unsupported_assignments(entry)\n'
                 '        if not unsupported:\n'
                 '            return\n'
                 '\n'
                 '        self.unsupported_group.pack_start(\n'
                 '            make_label(\n'
                 '                f"{tr(self.language, \'unsupported\')} ({len(unsupported)})", "section-heading"\n'
                 '            ),\n'
                 '            False,\n'
                 '            False,\n'
                 '            0,\n'
                 '        )\n'
                 '        self.unsupported_group.pack_start(\n'
                 '            make_label(tr(self.language, "unsupported_help"), wrap=True), False, False, 0\n'
                 '        )\n'
                 '\n'
                 '        for assignment in unsupported:\n'
                 '            self.unsupported_group.pack_start(\n'
                 '                make_label(\n'
                 '                    f"{assignment.key}={assignment.value}", "choice-doc", selectable=True\n'
                 '                ),\n'
                 '                False,\n'
                 '                False,\n'
                 '                0,\n'
                 '            )\n'
                 '\n'
                 '    def toggle_option(self, entry: EntryRecord, option_name: str) -> None:\n'
                 '        if entry.key != self.current_key:\n'
                 '            self.current_key = entry.key\n'
                 '            self.selected_option_name = option_name\n'
                 '            self._refresh_details()\n'
                 '            return\n'
                 '\n'
                 '        row = self.option_rows.get(option_name)\n'
                 '        state = self._state_for_option(entry, option_name)\n'
                 '        if row is None or state is None:\n'
                 '            self.selected_option_name = option_name\n'
                 '            self._refresh_details()\n'
                 '            return\n'
                 '\n'
                 '        if self.selected_option_name == option_name:\n'
                 '            self.selected_option_name = None\n'
                 '            row.set_selected(False)\n'
                 '            self._remove_selected_option_editor()\n'
                 '            return\n'
                 '\n'
                 '        previous_name = self.selected_option_name\n'
                 '        if previous_name is not None:\n'
                 '            previous_row = self.option_rows.get(previous_name)\n'
                 '            if previous_row is not None:\n'
                 '                previous_row.set_selected(False)\n'
                 '        self._remove_selected_option_editor()\n'
                 '\n'
                 '        self.selected_option_name = option_name\n'
                 '        row.set_selected(True)\n'
                 '        self._insert_option_editor_after(row.get_parent(), row, entry, state)\n'
                 '\n'
                 '    def _state_for_option(self, entry: EntryRecord, option_name: str) -> Optional[ValueState]:\n'
                 '        active, defaults = self.store.effective_values(entry)\n'
                 '        for state in (*active, *defaults):\n'
                 '            if state.option.name == option_name:\n'
                 '                return state\n'
                 '        return None\n'
                 '\n'
                 '    def _remove_selected_option_editor(self) -> None:\n'
                 '        editor = self.selected_option_editor\n'
                 '        self.selected_option_editor = None\n'
                 '        if editor is None:\n'
                 '            return\n'
                 '        parent = editor.get_parent()\n'
                 '        if parent is not None:\n'
                 '            parent.remove(editor)\n'
                 '        editor.destroy()\n'
                 '\n'
                 '    def _insert_option_editor_after(\n'
                 '        self, container: Gtk.Box, row: OptionRow, entry: EntryRecord, state: ValueState\n'
                 '    ) -> None:\n'
                 '        panel = self._build_option_editor(entry, state)\n'
                 '        self.selected_option_editor = panel\n'
                 '        container.pack_start(panel, False, False, 8)\n'
                 '        try:\n'
                 '            position = container.get_children().index(row) + 1\n'
                 '        except ValueError:\n'
                 '            position = -1\n'
                 '        if position >= 0:\n'
                 '            container.reorder_child(panel, position)\n'
                 '        panel.show_all()\n'
                 '\n'
                 '    def change_option(self, entry: EntryRecord, option_name: str, value: str) -> None:\n'
                 '        self.selected_option_name = option_name\n'
                 '        try:\n'
                 '            new_key, forked = self.store.set_option(entry, option_name, value)\n'
                 '        except Exception as error:\n'
                 '            self._show_error(error)\n'
                 '            return\n'
                 '\n'
                 '        self._queue_refresh(\n'
                 '            new_key,\n'
                 '            tr(self.language, "forked" if forked else "dirty"),\n'
                 '            rebuild_entries=(new_key != entry.key),\n'
                 '        )\n'
                 '\n'
                 '    def reset_option(self, entry: EntryRecord, option_name: str) -> None:\n'
                 '        self.selected_option_name = option_name\n'
                 '        try:\n'
                 '            new_key = self.store.reset_option(entry, option_name)\n'
                 '        except Exception as error:\n'
                 '            self._show_error(error)\n'
                 '            return\n'
                 '        self._queue_refresh(new_key, tr(self.language, "dirty"), rebuild_entries=(new_key != '
                 'entry.key))\n'
                 '\n'
                 '    def _queue_refresh(self, key, status: str, rebuild_entries: bool = False) -> None:\n'
                 '        self.current_key = key\n'
                 '        self._pending_refresh_key = key\n'
                 '        self._pending_status = status\n'
                 '        self._pending_rebuild_entries = self._pending_rebuild_entries or rebuild_entries\n'
                 '        if not self._pending_refresh_source:\n'
                 '            self._pending_refresh_source = GLib.idle_add(self._flush_queued_refresh)\n'
                 '\n'
                 '    def _flush_queued_refresh(self) -> bool:\n'
                 '        key = self._pending_refresh_key\n'
                 '        status = self._pending_status\n'
                 '        rebuild_entries = self._pending_rebuild_entries\n'
                 '        self._pending_refresh_key = None\n'
                 '        self._pending_status = ""\n'
                 '        self._pending_rebuild_entries = False\n'
                 '        self._pending_refresh_source = 0\n'
                 '        if rebuild_entries:\n'
                 '            self._refresh_entries(select_key=key)\n'
                 '        else:\n'
                 '            self._refresh_entry_row(key)\n'
                 '        self._refresh_details()\n'
                 '        if status:\n'
                 '            self._push_status(status)\n'
                 '        return GLib.SOURCE_REMOVE\n'
                 '\n'
                 '    def _on_editor_choice_changed(\n'
                 '        self,\n'
                 '        combo: Gtk.ComboBoxText,\n'
                 '        entry: EntryRecord,\n'
                 '        option_name: str,\n'
                 '        values: Sequence[str],\n'
                 '    ) -> None:\n'
                 '        index = combo.get_active()\n'
                 '        if index < 0 or index >= len(values):\n'
                 '            return\n'
                 '        self.change_option(entry, option_name, values[index])\n'
                 '\n'
                 '    def _on_search_changed(self, search: Gtk.SearchEntry) -> None:\n'
                 '        self._filter_text = search.get_text().strip().lower()\n'
                 '        self.entry_list.invalidate_filter()\n'
                 '\n'
                 '    def _on_mode_toggled(self, button: Gtk.ToggleButton, mode: str) -> None:\n'
                 '        if not button.get_active():\n'
                 '            return\n'
                 '        self._entry_filter_mode = mode\n'
                 '        if mode == "all":\n'
                 '            self.user_button.set_active(False)\n'
                 '        else:\n'
                 '            self.all_button.set_active(False)\n'
                 '        self.entry_list.invalidate_filter()\n'
                 '        self._select_first_visible_entry()\n'
                 '        self._refresh_details()\n'
                 '\n'
                 '    def _select_first_visible_entry(self) -> None:\n'
                 '        if self.current_key is not None:\n'
                 '            row = self.rows_by_key.get(self.current_key)\n'
                 '            if row is not None and self._filter_entry_row(row):\n'
                 '                return\n'
                 '        for row in self.entry_list.get_children():\n'
                 '            if self._filter_entry_row(row):\n'
                 '                self.entry_list.select_row(row)\n'
                 '                return\n'
                 '        self.current_key = None\n'
                 '\n'
                 '    def _on_entry_selected(self, _listbox: Gtk.ListBox, row: Optional[EntryRow]) -> None:\n'
                 '        if self._building or row is None:\n'
                 '            return\n'
                 '        is_new_entry = row.entry.key != self.current_key\n'
                 '        self.current_key = row.entry.key\n'
                 '        if is_new_entry:\n'
                 '            self.selected_option_name = None\n'
                 '            self._clear_status()\n'
                 '        self._refresh_details()\n'
                 '\n'
                 '    def _on_language_changed(self, combo: Gtk.ComboBoxText) -> None:\n'
                 '        active = combo.get_active_id()\n'
                 '        if active not in ("en", "zh"):\n'
                 '            return\n'
                 '        self.language = active\n'
                 '        self.header.props.title = tr(self.language, "title")\n'
                 '        self.set_title(tr(self.language, "title"))\n'
                 '        self.search.set_placeholder_text(tr(self.language, "search"))\n'
                 '        self.all_button.set_label(tr(self.language, "filter_all"))\n'
                 '        self.user_button.set_label(tr(self.language, "filter_user"))\n'
                 '        self.new_button.set_tooltip_text(tr(self.language, "new"))\n'
                 '        self.delete_button.set_tooltip_text(tr(self.language, "delete"))\n'
                 '        self.reload_button.set_tooltip_text(tr(self.language, "reload"))\n'
                 '        self.save_button.set_tooltip_text(tr(self.language, "save"))\n'
                 '        self._refresh_view()\n'
                 '\n'
                 '    def _on_new_entry(self, _button: Gtk.Button) -> None:\n'
                 '        dialog = Gtk.Dialog(\n'
                 '            title=tr(self.language, "new_title"),\n'
                 '            transient_for=self,\n'
                 '            modal=True,\n'
                 '            destroy_with_parent=True,\n'
                 '        )\n'
                 '        dialog.add_button(tr(self.language, "cancel"), Gtk.ResponseType.CANCEL)\n'
                 '        dialog.add_button(tr(self.language, "create"), Gtk.ResponseType.OK)\n'
                 '        dialog.set_default_response(Gtk.ResponseType.OK)\n'
                 '\n'
                 '        content = dialog.get_content_area()\n'
                 '        content.set_spacing(8)\n'
                 '        content.set_border_width(12)\n'
                 '        content.pack_start(make_label(tr(self.language, "new_prompt")), False, False, 0)\n'
                 '        entry = Gtk.Entry()\n'
                 '        entry.set_activates_default(True)\n'
                 '        content.pack_start(entry, False, False, 0)\n'
                 '        dialog.show_all()\n'
                 '\n'
                 '        response = dialog.run()\n'
                 '        name = entry.get_text().strip()\n'
                 '        dialog.destroy()\n'
                 '        if response != Gtk.ResponseType.OK or not name:\n'
                 '            return\n'
                 '        if "\\n" in name or "]" in name:\n'
                 '            self._show_error(ValueError("Invalid section name"))\n'
                 '            return\n'
                 '\n'
                 '        new_key = self.store.create_entry(name)\n'
                 '        self.current_key = new_key\n'
                 '        self._refresh_view(new_key)\n'
                 '        self._push_status(tr(self.language, "dirty"))\n'
                 '\n'
                 '    def _on_delete_entry(self, _button: Gtk.Button) -> None:\n'
                 '        if self.current_key is None:\n'
                 '            return\n'
                 '        entry = self.store.entry_for_key(self.current_key)\n'
                 '        if entry is None or entry.user_section is None:\n'
                 '            return\n'
                 '\n'
                 '        if self._message(\n'
                 '            Gtk.MessageType.WARNING,\n'
                 '            tr(self.language, "delete_title"),\n'
                 '            tr(self.language, "delete_body"),\n'
                 '            ((tr(self.language, "cancel"), Gtk.ResponseType.CANCEL),\n'
                 '             (tr(self.language, "delete_action"), Gtk.ResponseType.OK)),\n'
                 '        ) != Gtk.ResponseType.OK:\n'
                 '            return\n'
                 '\n'
                 '        self.store.delete_user_entry(entry.key)\n'
                 '        self.current_key = entry.key if entry.system_section else None\n'
                 '        self._refresh_view(self.current_key)\n'
                 '        self._push_status(tr(self.language, "dirty"))\n'
                 '\n'
                 '    def _on_reload(self, _button: Gtk.Button) -> None:\n'
                 '        if self.store.dirty and not self._confirm_discard():\n'
                 '            return\n'
                 '        self.store.reload()\n'
                 '        self._refresh_view(self.current_key)\n'
                 '\n'
                 '    def _on_save(self, _button: Gtk.Button) -> None:\n'
                 '        try:\n'
                 '            self.store.save()\n'
                 '        except Exception as error:\n'
                 '            self._show_error(error)\n'
                 '            return\n'
                 '        self._refresh_view(self.current_key)\n'
                 '        self._push_status(tr(self.language, "saved"))\n'
                 '\n'
                 '    def _on_save_action(self, _action: Gio.SimpleAction, _parameter) -> None:\n'
                 '        if self.store.dirty:\n'
                 '            self._on_save(self.save_button)\n'
                 '\n'
                 '    def _on_delete_event(self, _widget: Gtk.Widget, _event) -> bool:\n'
                 '        if not self.store.dirty:\n'
                 '            return False\n'
                 '\n'
                 '        response = self._message(\n'
                 '            Gtk.MessageType.QUESTION,\n'
                 '            tr(self.language, "save_changes_title"),\n'
                 '            tr(self.language, "save_changes_body"),\n'
                 '            ((tr(self.language, "discard"), Gtk.ResponseType.NO),\n'
                 '             (tr(self.language, "cancel"), Gtk.ResponseType.CANCEL),\n'
                 '             (tr(self.language, "save"), Gtk.ResponseType.YES)),\n'
                 '        )\n'
                 '        if response == Gtk.ResponseType.YES:\n'
                 '            self._on_save(self.save_button)\n'
                 '            return self.store.dirty\n'
                 '        if response == Gtk.ResponseType.NO:\n'
                 '            return False\n'
                 '        return True\n'
                 '\n'
                 '    def _confirm_discard(self) -> bool:\n'
                 '        return self._message(\n'
                 '            Gtk.MessageType.QUESTION,\n'
                 '            tr(self.language, "save_changes_title"),\n'
                 '            tr(self.language, "save_changes_body"),\n'
                 '            ((tr(self.language, "cancel"), Gtk.ResponseType.CANCEL),\n'
                 '             (tr(self.language, "discard"), Gtk.ResponseType.OK)),\n'
                 '        ) == Gtk.ResponseType.OK\n'
                 '\n'
                 '    def _update_actions(self) -> None:\n'
                 '        self.save_button.set_sensitive(self.store.dirty)\n'
                 '        entry = self.store.entry_for_key(self.current_key) if self.current_key is not None else '
                 'None\n'
                 '        self.delete_button.set_sensitive(bool(entry and entry.user_section is not None))\n'
                 '\n'
                 '    def _push_status(self, text: str) -> None:\n'
                 '        self.status.pop(self.status_context)\n'
                 '        self.status.push(self.status_context, text)\n'
                 '\n'
                 '    def _clear_status(self) -> None:\n'
                 '        self.status.pop(self.status_context)\n'
                 '\n'
                 '    def _show_error(self, error: Exception) -> None:\n'
                 '        self._message(Gtk.MessageType.ERROR, tr(self.language, "error"), str(error))\n'
                 '\n'
                 '    def _message(\n'
                 '        self,\n'
                 '        message_type: Gtk.MessageType,\n'
                 '        text: str,\n'
                 '        secondary: str = "",\n'
                 '        buttons: Sequence[Tuple[str, Gtk.ResponseType]] = (),\n'
                 '    ) -> int:\n'
                 '        dialog = Gtk.MessageDialog(\n'
                 '            transient_for=self,\n'
                 '            modal=True,\n'
                 '            destroy_with_parent=True,\n'
                 '            message_type=message_type,\n'
                 '            buttons=Gtk.ButtonsType.NONE if buttons else Gtk.ButtonsType.CLOSE,\n'
                 '            text=text,\n'
                 '        )\n'
                 '        if secondary:\n'
                 '            dialog.format_secondary_text(secondary)\n'
                 '        for label, response in buttons:\n'
                 '            dialog.add_button(label, response)\n'
                 '        response = dialog.run()\n'
                 '        dialog.destroy()\n'
                 '        return response\n'
                 '\n'
                 '\n'
                 'class ConfiguratorApplication(Gtk.Application):\n'
                 '    def __init__(self, store: ConfigStore) -> None:\n'
                 '        super().__init__(application_id=APP_ID, flags=Gio.ApplicationFlags.FLAGS_NONE)\n'
                 '        self.store = store\n'
                 '        self.window: Optional[ConfiguratorWindow] = None\n'
                 '\n'
                 '    def do_activate(self) -> None:\n'
                 '        if self.window is None:\n'
                 '            self.window = ConfiguratorWindow(self, self.store)\n'
                 '        self.window.present()\n'
                 '\n'
                 '\n'
                 'def parse_args(argv: Optional[Sequence[str]]) -> argparse.Namespace:\n'
                 '    parser = argparse.ArgumentParser(description="Box64 graphical rcfile configurator")\n'
                 '    parser.add_argument("--usage", type=Path)\n'
                 '    parser.add_argument("--usage-cn", type=Path)\n'
                 '    parser.add_argument("--system-rc", type=Path, default=default_system_rc())\n'
                 '    parser.add_argument("--user-rc", type=Path, default=default_user_rc())\n'
                 '    return parser.parse_args(argv)\n'
                 '\n'
                 '\n'
                 'def main(argv: Optional[Sequence[str]] = None) -> int:\n'
                 '    args = parse_args(argv)\n'
                 '    if args.usage is not None or args.usage_cn is not None:\n'
                 '        if args.usage is None or args.usage_cn is None:\n'
                 '            raise SystemExit("--usage and --usage-cn must be used together")\n'
                 '        catalog = load_usage_catalog(args.usage, args.usage_cn)\n'
                 '    else:\n'
                 '        catalog = load_default_usage_catalog()\n'
                 '    store = ConfigStore(args.system_rc, args.user_rc, catalog, '
                 'box64_arch_from_machine(platform.machine()))\n'
                 '    app = ConfiguratorApplication(store)\n'
                 '    return app.run([sys.argv[0]])\n'
                 '\n'
                 '\n'
                 'if __name__ == "__main__":\n'
                 '    raise SystemExit(main())\n',
 'model': 'from __future__ import annotations\n'
          '\n'
          'from dataclasses import dataclass\n'
          'from pathlib import Path\n'
          'from typing import Dict, List, Optional, Tuple\n'
          '\n'
          'try:\n'
          '    from .box64rc import (\n'
          '        Assignment,\n'
          '        RcDocument,\n'
          '        RcSection,\n'
          '        SectionKey,\n'
          '        copy_assignments,\n'
          '        direct_box64_assignments,\n'
          '        header_from_key,\n'
          '    )\n'
          '    from .usage import EnvOption, UsageCatalog\n'
          'except ImportError:\n'
          '    from box64rc import (\n'
          '        Assignment,\n'
          '        RcDocument,\n'
          '        RcSection,\n'
          '        SectionKey,\n'
          '        copy_assignments,\n'
          '        direct_box64_assignments,\n'
          '        header_from_key,\n'
          '    )\n'
          '    from usage import EnvOption, UsageCatalog\n'
          '\n'
          '\n'
          'ARCH_ALIASES = {\n'
          '    "aarch64": "arm64",\n'
          '    "arm64": "arm64",\n'
          '    "amd64": "x86_64",\n'
          '    "loong64": "la64",\n'
          '    "loongarch64": "la64",\n'
          '    "powerpc64le": "ppc64le",\n'
          '    "ppc64le": "ppc64le",\n'
          '    "x86_64": "x86_64",\n'
          '}\n'
          '\n'
          '\n'
          'def box64_arch_from_machine(machine: Optional[str]) -> str:\n'
          '    value = (machine or "").strip().lower().replace("-", "_")\n'
          '    if value.startswith("riscv64"):\n'
          '        return "rv64"\n'
          '    return ARCH_ALIASES.get(value, value)\n'
          '\n'
          '\n'
          '@dataclass(frozen=True)\n'
          'class EntryRecord:\n'
          '    key: SectionKey\n'
          '    display_name: str\n'
          '    system_section: Optional[RcSection]\n'
          '    user_section: Optional[RcSection]\n'
          '\n'
          '    @property\n'
          '    def editable_source(self) -> str:\n'
          '        if self.user_section is not None:\n'
          '            return "user"\n'
          '        if self.system_section is not None:\n'
          '            return "system"\n'
          '        return "new"\n'
          '\n'
          '    @property\n'
          '    def arch(self) -> str:\n'
          '        return self.key.arch\n'
          '\n'
          '\n'
          '@dataclass(frozen=True)\n'
          'class ValueState:\n'
          '    option: EnvOption\n'
          '    value: str\n'
          '    source: str\n'
          '\n'
          '\n'
          'SectionIdentity = Tuple[str, str]\n'
          '\n'
          '\n'
          'class ConfigStore:\n'
          '    def __init__(\n'
          '        self, system_path: Path, user_path: Path, catalog: UsageCatalog, machine_arch: str = ""\n'
          '    ) -> None:\n'
          '        self.catalog = catalog\n'
          '        self.machine_arch = machine_arch\n'
          '        self.system = RcDocument(system_path)\n'
          '        self.user = RcDocument(user_path)\n'
          '        self.dirty = False\n'
          '        self._entries: Tuple[EntryRecord, ...] = ()\n'
          '        self._entries_by_key: Dict[SectionKey, EntryRecord] = {}\n'
          '        self._system_sections_by_identity: Dict[SectionIdentity, RcSection] = {}\n'
          '        self._user_sections_by_identity: Dict[SectionIdentity, RcSection] = {}\n'
          '        self._rebuild_entry_cache()\n'
          '\n'
          '    def reload(self) -> None:\n'
          '        self.system.reload()\n'
          '        self.user.reload()\n'
          '        self.dirty = False\n'
          '        self._rebuild_entry_cache()\n'
          '\n'
          '    def save(self) -> None:\n'
          '        self.user.save()\n'
          '        self.reload()\n'
          '\n'
          '    def entries(self) -> Tuple[EntryRecord, ...]:\n'
          '        return self._entries\n'
          '\n'
          '    def entry_for_key(self, key: SectionKey) -> Optional[EntryRecord]:\n'
          '        return self._entries_by_key.get(key)\n'
          '\n'
          '    def _rebuild_entry_cache(self) -> None:\n'
          '        self._system_sections_by_identity = self._effective_sections(self.system)\n'
          '        self._user_sections_by_identity = self._effective_sections(self.user)\n'
          '        identities = set(self._system_sections_by_identity)\n'
          '        identities.update(self._user_sections_by_identity)\n'
          '\n'
          '        entries: List[EntryRecord] = []\n'
          '        for identity in identities:\n'
          '            system_section = self._system_sections_by_identity.get(identity)\n'
          '            user_section = self._user_sections_by_identity.get(identity)\n'
          '            display_section = user_section or system_section\n'
          '            if display_section is None:\n'
          '                continue\n'
          '            display_name = display_section.header if display_section else '
          'header_from_key(display_section.key)\n'
          '            entries.append(EntryRecord(display_section.key, display_name, system_section, user_section))\n'
          '\n'
          '        self._entries = tuple(\n'
          '            sorted(entries, key=lambda entry: (entry.key.sort_key(), entry.display_name.lower()))\n'
          '        )\n'
          '        self._entries_by_key = {entry.key: entry for entry in self._entries}\n'
          '\n'
          '    def _effective_sections(self, document: RcDocument) -> Dict[SectionIdentity, RcSection]:\n'
          '        sections: Dict[SectionIdentity, RcSection] = {}\n'
          '        for section in document.sections:\n'
          '            if not self._section_matches_arch(section):\n'
          '                continue\n'
          '\n'
          '            identity = self._identity(section.key)\n'
          '            current = sections.get(identity)\n'
          '            if current is None or self._section_replaces(current, section):\n'
          '                sections[identity] = section\n'
          '        return sections\n'
          '\n'
          '    def _section_matches_arch(self, section: RcSection) -> bool:\n'
          '        return not section.key.arch or section.key.arch == self.machine_arch\n'
          '\n'
          '    def _section_replaces(self, current: RcSection, candidate: RcSection) -> bool:\n'
          '        if candidate.key.arch:\n'
          '            return candidate.key.arch == self.machine_arch\n'
          '        return not current.key.arch\n'
          '\n'
          '    def _identity(self, key: SectionKey) -> SectionIdentity:\n'
          '        return key.kind, key.name\n'
          '\n'
          '    def _mark_dirty(self) -> None:\n'
          '        self.dirty = True\n'
          '        self._rebuild_entry_cache()\n'
          '\n'
          '    def create_entry(self, header: str) -> SectionKey:\n'
          '        section = self.user.add_section(header.strip())\n'
          '        self._mark_dirty()\n'
          '        return section.key\n'
          '\n'
          '    def delete_user_entry(self, key: SectionKey) -> None:\n'
          '        self.user.delete_section(key)\n'
          '        self._mark_dirty()\n'
          '\n'
          '    def set_option(self, entry: EntryRecord, option_name: str, value: str) -> Tuple[SectionKey, bool]:\n'
          '        section, forked = self._ensure_user_section(entry)\n'
          '        new_key = self.user.set_assignment(section.key, option_name, value)\n'
          '        self._mark_dirty()\n'
          '        return new_key, forked\n'
          '\n'
          '    def reset_option(self, entry: EntryRecord, option_name: str) -> SectionKey:\n'
          '        user_section = entry.user_section\n'
          '        if user_section is None:\n'
          '            return entry.key\n'
          '\n'
          '        system_value = None\n'
          '        if entry.system_section is not None:\n'
          '            system_value = entry.system_section.last_value(option_name)\n'
          '\n'
          '        new_key = (\n'
          '            self.user.set_assignment(user_section.key, option_name, system_value)\n'
          '            if system_value is not None\n'
          '            else self.user.remove_assignment(user_section.key, option_name)\n'
          '        )\n'
          '        self._mark_dirty()\n'
          '        return new_key\n'
          '\n'
          '    def unsupported_assignments(self, entry: EntryRecord) -> Tuple[Assignment, ...]:\n'
          '        section = entry.user_section or entry.system_section\n'
          '        return tuple(\n'
          '            assignment for assignment in direct_box64_assignments(section) if assignment.key not in '
          'self.catalog\n'
          '        )\n'
          '\n'
          '    def effective_values(self, entry: EntryRecord) -> Tuple[List[ValueState], List[ValueState]]:\n'
          '        states: Dict[str, ValueState] = {}\n'
          '\n'
          '        if entry.key.kind != "shared":\n'
          '            self._apply_shared(states)\n'
          '            self._apply_matching_wildcards(states, entry)\n'
          '\n'
          '        self._apply_direct(states, entry)\n'
          '\n'
          '        active: List[ValueState] = []\n'
          '        defaults: List[ValueState] = []\n'
          '        for option in self.catalog.options:\n'
          '            state = states.get(option.name)\n'
          '            if state is None:\n'
          '                defaults.append(\n'
          '                    ValueState(\n'
          '                        option=option,\n'
          '                        value=option.default_value,\n'
          '                        source="default",\n'
          '                    )\n'
          '                )\n'
          '            else:\n'
          '                active.append(state)\n'
          '\n'
          '        return active, defaults\n'
          '\n'
          '    def _ensure_user_section(self, entry: EntryRecord) -> Tuple[RcSection, bool]:\n'
          '        user_section = self.user.section_for_key(entry.key)\n'
          '        if user_section is not None:\n'
          '            return user_section, False\n'
          '\n'
          '        if entry.system_section is not None:\n'
          '            assignments = copy_assignments(entry.system_section)\n'
          '            user_section = self.user.add_section(entry.system_section.header, assignments)\n'
          '            return user_section, True\n'
          '\n'
          '        user_section = self.user.add_section(entry.display_name)\n'
          '        return user_section, True\n'
          '\n'
          '    def _apply_shared(self, states: Dict[str, ValueState]) -> None:\n'
          '        for section, source in (\n'
          '            (self._system_sections_by_identity.get(("shared", "*")), "shared-system"),\n'
          '            (self._user_sections_by_identity.get(("shared", "*")), "shared-user"),\n'
          '        ):\n'
          '            if section is not None:\n'
          '                self._apply_assignments(states, section, source)\n'
          '\n'
          '    def _apply_matching_wildcards(self, states: Dict[str, ValueState], entry: EntryRecord) -> None:\n'
          '        if entry.key.kind not in ("exact", "file"):\n'
          '            return\n'
          '\n'
          '        target = entry.key.name.lower()\n'
          '        wildcard_identities = {\n'
          '            identity\n'
          '            for identity in (\n'
          '                *self._system_sections_by_identity.keys(),\n'
          '                *self._user_sections_by_identity.keys(),\n'
          '            )\n'
          '            if identity[0] == "wildcard" and identity[1] in target\n'
          '        }\n'
          '\n'
          '        for identity in sorted(wildcard_identities, key=lambda item: item[1]):\n'
          '            user_section = self._user_sections_by_identity.get(identity)\n'
          '            system_section = self._system_sections_by_identity.get(identity)\n'
          '            if user_section is not None:\n'
          '                self._apply_assignments(states, user_section, "wildcard-user")\n'
          '            elif system_section is not None:\n'
          '                self._apply_assignments(states, system_section, "wildcard-system")\n'
          '\n'
          '    def _apply_direct(self, states: Dict[str, ValueState], entry: EntryRecord) -> None:\n'
          '        if entry.user_section is not None:\n'
          '            self._apply_assignments(states, entry.user_section, "user")\n'
          '        elif entry.system_section is not None:\n'
          '            self._apply_assignments(states, entry.system_section, "system")\n'
          '\n'
          '    def _apply_assignments(\n'
          '        self, states: Dict[str, ValueState], section: RcSection, source: str\n'
          '    ) -> None:\n'
          '        for assignment in section.assignments:\n'
          '            option = self.catalog.by_name.get(assignment.key)\n'
          '            if option is None:\n'
          '                continue\n'
          '            states[assignment.key] = ValueState(\n'
          '                option=option,\n'
          '                value=assignment.value,\n'
          '                source=source,\n'
          '            )\n',
 'usage': 'from __future__ import annotations\n'
          '\n'
          'import json\n'
          'from dataclasses import dataclass\n'
          'from pathlib import Path\n'
          'from typing import Any, Dict, Iterable, List, Optional, Tuple\n'
          '\n'
          '\n'
          'PLACEHOLDER_MARKERS = (\n'
          '    "XXXX",\n'
          '    "YYYY",\n'
          '    "ZZZZ",\n'
          '    "xxx",\n'
          '    "yyy",\n'
          '    "zzz",\n'
          '    "symbolname",\n'
          ')\n'
          '\n'
          '_EMBEDDED_USAGE_DATA: Optional[List[Dict[str, Any]]] = globals().get("_EMBEDDED_USAGE_DATA")\n'
          '_EMBEDDED_USAGE_CN_DATA: Optional[Dict[str, Any]] = globals().get("_EMBEDDED_USAGE_CN_DATA")\n'
          '\n'
          '\n'
          'def clean_choice_value(raw_key: str) -> str:\n'
          '    value = str(raw_key).strip()\n'
          '    if value.startswith("`") and value.endswith("`") and len(value) >= 2:\n'
          '        value = value[1:-1]\n'
          '    return "" if value == "<empty>" else value\n'
          '\n'
          '\n'
          'def is_placeholder_value(value: str) -> bool:\n'
          '    return bool(value) and (\n'
          '        any(marker in value for marker in PLACEHOLDER_MARKERS) or value.startswith("0x") and "X" in value\n'
          '    )\n'
          '\n'
          '\n'
          'def localized(language: str, english: str, chinese: str) -> str:\n'
          '    return (chinese or english) if language == "zh" else english\n'
          '\n'
          '\n'
          '@dataclass(frozen=True)\n'
          'class Choice:\n'
          '    value: str\n'
          '    label: str\n'
          '    description_en: str\n'
          '    description_cn: str\n'
          '    is_default: bool\n'
          '    is_placeholder: bool\n'
          '\n'
          '    def description(self, language: str) -> str:\n'
          '        return localized(language, self.description_en, self.description_cn)\n'
          '\n'
          '\n'
          '@dataclass(frozen=True)\n'
          'class EnvOption:\n'
          '    name: str\n'
          '    description_en: str\n'
          '    description_cn: str\n'
          '    choices: Tuple[Choice, ...]\n'
          '\n'
          '    @property\n'
          '    def allows_custom_value(self) -> bool:\n'
          '        return any(choice.is_placeholder for choice in self.choices)\n'
          '\n'
          '    @property\n'
          '    def default_value(self) -> str:\n'
          '        return next((choice.value for choice in self.choices if choice.is_default), "")\n'
          '\n'
          '    def description(self, language: str) -> str:\n'
          '        return localized(language, self.description_en, self.description_cn)\n'
          '\n'
          '\n'
          'class UsageCatalog:\n'
          '    def __init__(self, options: Iterable[EnvOption]) -> None:\n'
          '        self.options: Tuple[EnvOption, ...] = tuple(options)\n'
          '        self.by_name: Dict[str, EnvOption] = {option.name: option for option in self.options}\n'
          '\n'
          '    def __contains__(self, name: str) -> bool:\n'
          '        return name in self.by_name\n'
          '\n'
          '\n'
          'def find_usage_paths(start: Optional[Path] = None) -> Tuple[Path, Path]:\n'
          '    here = (start or Path(__file__)).resolve()\n'
          '    for parent in (here.parent, *here.parents):\n'
          '        for directory in (parent / "docs" / "gen", parent / "share" / "box64"):\n'
          '            usage = directory / "usage.json"\n'
          '            usage_cn = directory / "usage_cn.json"\n'
          '            if usage.is_file() and usage_cn.is_file():\n'
          '                return usage, usage_cn\n'
          '\n'
          '    raise FileNotFoundError("Could not find usage.json and usage_cn.json")\n'
          '\n'
          '\n'
          'def load_default_usage_catalog() -> UsageCatalog:\n'
          '    if _EMBEDDED_USAGE_DATA is not None and _EMBEDDED_USAGE_CN_DATA is not None:\n'
          '        return load_usage_catalog_from_data(_EMBEDDED_USAGE_DATA, _EMBEDDED_USAGE_CN_DATA)\n'
          '\n'
          '    usage_path, usage_cn_path = find_usage_paths()\n'
          '    return load_usage_catalog(usage_path, usage_cn_path)\n'
          '\n'
          '\n'
          'def load_usage_catalog(usage_path: Path, usage_cn_path: Path) -> UsageCatalog:\n'
          '    with usage_path.open("r", encoding="utf-8") as file:\n'
          '        english_data = json.load(file)\n'
          '    with usage_cn_path.open("r", encoding="utf-8") as file:\n'
          '        chinese_data = json.load(file)\n'
          '    return load_usage_catalog_from_data(english_data, chinese_data)\n'
          '\n'
          '\n'
          'def load_usage_catalog_from_data(\n'
          '    english_data: Iterable[Dict[str, Any]], chinese_data: Dict[str, Any]\n'
          ') -> UsageCatalog:\n'
          '    options: List[EnvOption] = []\n'
          '    for entry in english_data:\n'
          '        if not entry.get("configurator", False):\n'
          '            continue\n'
          '\n'
          '        name = entry["name"]\n'
          '        chinese_entry = chinese_data.get(name, {})\n'
          '        chinese_choices = chinese_entry.get("options", {})\n'
          '        choices = []\n'
          '\n'
          '        for option in entry.get("options", []):\n'
          '            raw_key = str(option["key"])\n'
          '            value = clean_choice_value(raw_key)\n'
          '            choices.append(\n'
          '                Choice(\n'
          '                    value=value,\n'
          '                    label="<empty>" if value == "" else value,\n'
          '                    description_en=option.get("description", ""),\n'
          '                    description_cn=chinese_choices.get(raw_key, ""),\n'
          '                    is_default=bool(option.get("default", False)),\n'
          '                    is_placeholder=is_placeholder_value(value),\n'
          '                )\n'
          '            )\n'
          '\n'
          '        options.append(\n'
          '            EnvOption(\n'
          '                name=name,\n'
          '                description_en=entry.get("description", ""),\n'
          '                description_cn=chinese_entry.get("description", ""),\n'
          '                choices=tuple(choices),\n'
          '            )\n'
          '        )\n'
          '\n'
          '    return UsageCatalog(options)\n'}
_EMBEDDED_TEXTS = {'en': {'apply': 'Apply',
        'cancel': 'Cancel',
        'create': 'Create',
        'default_dynamic': 'build dependent',
        'default_marker': 'Default',
        'defaults': 'Default values',
        'delete': 'Delete user entry',
        'delete_action': 'Delete',
        'delete_body': 'Only the ~/.box64rc section will be removed. The system rcfile is not changed.',
        'delete_title': 'Delete user entry?',
        'dirty': 'Unsaved changes',
        'discard': 'Discard',
        'edit': 'Edit',
        'effective': 'Effective options',
        'error': 'Error',
        'filter_all': 'All',
        'filter_user': 'User',
        'forked': 'Created a user fork; save writes it to ~/.box64rc.',
        'new': 'New entry',
        'new_prompt': 'Executable name or rcfile section',
        'new_title': 'New Box64 entry',
        'reload': 'Reload',
        'reset': 'Reset',
        'save': 'Save',
        'save_changes_body': 'Your ~/.box64rc edits have not been saved.',
        'save_changes_title': 'Save changes before closing?',
        'saved': 'Saved ~/.box64rc',
        'search': 'Search entries',
        'select_entry': 'Select an entry on the left.',
        'source_default': 'Default',
        'source_shared-system': 'System shared',
        'source_shared-user': 'User shared',
        'source_system': 'System',
        'source_user': 'User',
        'source_wildcard-system': 'System wildcard',
        'source_wildcard-user': 'User wildcard',
        'system_note': 'This entry comes from the system rcfile. Changing it creates a user fork in ~/.box64rc.',
        'title': 'Box64 Configurator',
        'unsupported': 'Other rcfile keys',
        'unsupported_help': 'These keys are preserved when a system entry is forked, but this tool does not edit them.',
        'user_note': 'This entry is stored in ~/.box64rc.'},
 'zh': {'apply': '应用',
        'cancel': '取消',
        'create': '创建',
        'default_dynamic': '随构建而定',
        'default_marker': '默认',
        'defaults': '默认值',
        'delete': '删除用户条目',
        'delete_action': '删除',
        'delete_body': '只会移除 ~/.box64rc 中的段，系统 rcfile 不会被修改。',
        'delete_title': '删除用户条目？',
        'dirty': '有未保存的修改',
        'discard': '放弃',
        'edit': '编辑',
        'effective': '生效选项',
        'error': '错误',
        'filter_all': '全部',
        'filter_user': '用户',
        'forked': '已创建用户 fork，保存后写入 ~/.box64rc。',
        'new': '新建条目',
        'new_prompt': '可执行文件名或 rcfile 段名',
        'new_title': '新建 Box64 条目',
        'reload': '重新载入',
        'reset': '重置',
        'save': '保存',
        'save_changes_body': '~/.box64rc 的修改尚未保存。',
        'save_changes_title': '关闭前保存修改？',
        'saved': '已保存 ~/.box64rc',
        'search': '搜索条目',
        'select_entry': '请在左侧选择一个条目。',
        'source_default': '默认',
        'source_shared-system': '系统共享',
        'source_shared-user': '用户共享',
        'source_system': '系统',
        'source_user': '用户',
        'source_wildcard-system': '系统通配',
        'source_wildcard-user': '用户通配',
        'system_note': '此条目来自系统 rcfile。修改它会在 ~/.box64rc 创建用户 fork。',
        'title': 'Box64 配置器',
        'unsupported': '其他 rcfile 项',
        'unsupported_help': '系统条目被 fork 时会保留这些项，但此工具不会编辑它们。',
        'user_note': '此条目保存在 ~/.box64rc。'}}
_EMBEDDED_UI = ('<?xml version="1.0" encoding="UTF-8"?>\n'
 '<!-- Generated with glade 3.40.0 -->\n'
 '<interface>\n'
 '  <requires lib="gtk+" version="3.20"/>\n'
 '  <object class="GtkHeaderBar" id="header">\n'
 '    <property name="visible">True</property>\n'
 '    <property name="can-focus">False</property>\n'
 '    <property name="show-close-button">True</property>\n'
 '    <child>\n'
 '      <object class="GtkButton" id="new_button">\n'
 '        <property name="visible">True</property>\n'
 '        <property name="can-focus">False</property>\n'
 '        <property name="receives-default">False</property>\n'
 '      </object>\n'
 '    </child>\n'
 '    <child>\n'
 '      <object class="GtkButton" id="delete_button">\n'
 '        <property name="visible">True</property>\n'
 '        <property name="can-focus">False</property>\n'
 '        <property name="receives-default">False</property>\n'
 '      </object>\n'
 '      <packing>\n'
 '        <property name="position">1</property>\n'
 '      </packing>\n'
 '    </child>\n'
 '    <child>\n'
 '      <object class="GtkButton" id="reload_button">\n'
 '        <property name="visible">True</property>\n'
 '        <property name="can-focus">False</property>\n'
 '        <property name="receives-default">False</property>\n'
 '      </object>\n'
 '      <packing>\n'
 '        <property name="pack-type">end</property>\n'
 '        <property name="position">2</property>\n'
 '      </packing>\n'
 '    </child>\n'
 '    <child>\n'
 '      <object class="GtkButton" id="save_button">\n'
 '        <property name="visible">True</property>\n'
 '        <property name="can-focus">False</property>\n'
 '        <property name="receives-default">False</property>\n'
 '      </object>\n'
 '      <packing>\n'
 '        <property name="pack-type">end</property>\n'
 '        <property name="position">3</property>\n'
 '      </packing>\n'
 '    </child>\n'
 '    <child>\n'
 '      <object class="GtkComboBoxText" id="language_combo">\n'
 '        <property name="visible">True</property>\n'
 '        <property name="can-focus">False</property>\n'
 '      </object>\n'
 '      <packing>\n'
 '        <property name="pack-type">end</property>\n'
 '        <property name="position">4</property>\n'
 '      </packing>\n'
 '    </child>\n'
 '  </object>\n'
 '  <object class="GtkBox" id="root_box">\n'
 '    <property name="visible">True</property>\n'
 '    <property name="can-focus">False</property>\n'
 '    <property name="orientation">vertical</property>\n'
 '    <child>\n'
 '      <object class="GtkPaned" id="main_paned">\n'
 '        <property name="visible">True</property>\n'
 '        <property name="can-focus">False</property>\n'
 '        <child>\n'
 '          <object class="GtkBox" id="sidebar">\n'
 '            <property name="width-request">285</property>\n'
 '            <property name="visible">True</property>\n'
 '            <property name="can-focus">False</property>\n'
 '            <property name="orientation">vertical</property>\n'
 '            <child>\n'
 '              <object class="GtkSearchEntry" id="search_entry">\n'
 '                <property name="visible">True</property>\n'
 '                <property name="can-focus">True</property>\n'
 '                <property name="margin-start">14</property>\n'
 '                <property name="margin-end">14</property>\n'
 '                <property name="margin-top">10</property>\n'
 '                <property name="margin-bottom">6</property>\n'
 '              </object>\n'
 '              <packing>\n'
 '                <property name="expand">False</property>\n'
 '                <property name="fill">False</property>\n'
 '                <property name="position">0</property>\n'
 '              </packing>\n'
 '            </child>\n'
 '            <child>\n'
 '              <object class="GtkBox" id="mode_box">\n'
 '                <property name="visible">True</property>\n'
 '                <property name="can-focus">False</property>\n'
 '                <property name="margin-start">14</property>\n'
 '                <property name="margin-end">14</property>\n'
 '                <property name="margin-bottom">8</property>\n'
 '                <child>\n'
 '                  <object class="GtkToggleButton" id="all_button">\n'
 '                    <property name="visible">True</property>\n'
 '                    <property name="can-focus">False</property>\n'
 '                    <property name="receives-default">False</property>\n'
 '                    <property name="active">True</property>\n'
 '                  </object>\n'
 '                  <packing>\n'
 '                    <property name="expand">True</property>\n'
 '                    <property name="fill">True</property>\n'
 '                    <property name="position">0</property>\n'
 '                  </packing>\n'
 '                </child>\n'
 '                <child>\n'
 '                  <object class="GtkToggleButton" id="user_button">\n'
 '                    <property name="visible">True</property>\n'
 '                    <property name="can-focus">False</property>\n'
 '                    <property name="receives-default">False</property>\n'
 '                  </object>\n'
 '                  <packing>\n'
 '                    <property name="expand">True</property>\n'
 '                    <property name="fill">True</property>\n'
 '                    <property name="position">1</property>\n'
 '                  </packing>\n'
 '                </child>\n'
 '                <style>\n'
 '                  <class name="linked"/>\n'
 '                </style>\n'
 '              </object>\n'
 '              <packing>\n'
 '                <property name="expand">False</property>\n'
 '                <property name="fill">False</property>\n'
 '                <property name="position">1</property>\n'
 '              </packing>\n'
 '            </child>\n'
 '            <child>\n'
 '              <object class="GtkScrolledWindow" id="list_scroll">\n'
 '                <property name="visible">True</property>\n'
 '                <property name="can-focus">False</property>\n'
 '                <property name="hscrollbar-policy">never</property>\n'
 '              </object>\n'
 '              <packing>\n'
 '                <property name="expand">True</property>\n'
 '                <property name="fill">True</property>\n'
 '                <property name="position">2</property>\n'
 '              </packing>\n'
 '            </child>\n'
 '            <style>\n'
 '              <class name="sidebar"/>\n'
 '            </style>\n'
 '          </object>\n'
 '          <packing>\n'
 '            <property name="resize">False</property>\n'
 '            <property name="shrink">False</property>\n'
 '          </packing>\n'
 '        </child>\n'
 '        <child>\n'
 '          <object class="GtkScrolledWindow" id="detail_scroll">\n'
 '            <property name="visible">True</property>\n'
 '            <property name="can-focus">False</property>\n'
 '            <property name="hscrollbar-policy">never</property>\n'
 '          </object>\n'
 '          <packing>\n'
 '            <property name="resize">True</property>\n'
 '            <property name="shrink">False</property>\n'
 '          </packing>\n'
 '        </child>\n'
 '      </object>\n'
 '      <packing>\n'
 '        <property name="expand">True</property>\n'
 '        <property name="fill">True</property>\n'
 '        <property name="position">0</property>\n'
 '      </packing>\n'
 '    </child>\n'
 '    <child>\n'
 '      <object class="GtkStatusbar" id="statusbar">\n'
 '        <property name="visible">True</property>\n'
 '        <property name="can-focus">False</property>\n'
 '      </object>\n'
 '      <packing>\n'
 '        <property name="expand">False</property>\n'
 '        <property name="fill">False</property>\n'
 '        <property name="position">1</property>\n'
 '      </packing>\n'
 '    </child>\n'
 '  </object>\n'
 '</interface>\n')
_EMBEDDED_USAGE_DATA = [{'category': 'Libraries',
  'configurator': False,
  'description': 'Add extras to the needed libraries list, rarely needed.',
  'name': 'BOX64_ADDLIBS',
  'options': [{'default': False, 'description': 'Add library XXXX to the needed libraries list.', 'key': 'XXXX'},
              {'default': False,
               'description': 'Add library XXXX, YYYY and ZZZZ to the needed libraries list.',
               'key': 'XXXX:YYYY:ZZZZ'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': True,
  'description': 'Expose AES capabilities.',
  'name': 'BOX64_AES',
  'options': [{'default': False, 'description': 'Do not expose AES capabilities.', 'key': '0'},
              {'default': True, 'description': 'Expose AES capabilities.', 'key': '1'}],
  'wine': True},
 {'category': 'Libraries',
  'configurator': False,
  'description': 'Allow missing libraries to be ignored.',
  'name': 'BOX64_ALLOWMISSINGLIBS',
  'options': [{'default': True, 'description': 'Do not allow missing libraries.', 'key': '0'},
              {'default': False, 'description': 'Allow missing libraries.', 'key': '1'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Specify the architecture in rcfiles to which the current entry applies. This option only takes '
                 'effect when used inside rcfiles.',
  'name': 'BOX64_ARCH',
  'options': [{'default': False, 'description': 'Only apply current entry for AArch64.', 'key': '`arm64`'},
              {'default': False, 'description': 'Only apply current entry for LoongArch64.', 'key': '`la64`'},
              {'default': False, 'description': 'Only apply current entry for RISC-V.', 'key': '`rv64`'},
              {'default': True,
               'description': 'Apply current entry for all architectures, will be replaced by more specific entries.',
               'key': '`<empty>`'}],
  'wine': False},
 {'category': 'Arguments',
  'configurator': False,
  'description': 'Arguments to pass to the guest program, only valid if there is no existing arguments.',
  'name': 'BOX64_ARGS',
  'options': [{'default': False, 'description': 'Pass argument XXXX to the program.', 'key': 'XXXX'},
              {'default': False,
               'description': 'Pass arguments XXXX, YYYY and ZZZZ to the guest program.',
               'key': 'XXXX YYYY ZZZZ'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': True,
  'description': 'Expose AVX extension to CPUID and cpuinfo file. Default value is 2 on Arm64 and LoongArch64 because '
                 "it's fully implemented in DynaRec, 0 otherwise.",
  'name': 'BOX64_AVX',
  'options': [{'default': False, 'description': 'Do not expose AVX capabilities.', 'key': '0'},
              {'default': False,
               'description': 'Expose AVX, BMI1, F16C and VAES extensions to CPUID and cpuinfo file.',
               'key': '1'},
              {'default': False,
               'description': 'All in 1, plus AVX2, BMI2, FMA, ADX,VPCLMULQDQ and RDRAND extensions.',
               'key': '2'}],
  'wine': True},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Path to the bash executable.',
  'name': 'BOX64_BASH',
  'options': [{'default': False, 'description': 'Use bash executable at path XXXX.', 'key': 'XXXX'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Specify the CPU type to emulate.',
  'name': 'BOX64_CPUTYPE',
  'options': [{'default': True, 'description': 'Emulate a Intel CPU Model.', 'key': '0'},
              {'default': False, 'description': 'Emulate a AMD CPU Model.', 'key': '1'}],
  'wine': True},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Use a dummy crash handler or not.',
  'name': 'BOX64_CRASHHANDLER',
  'options': [{'default': False, 'description': 'Use emulated crashhandler.so library if needed.', 'key': '0'},
              {'default': True, 'description': 'Use an internal dummy (empty) crashhandler.so library.', 'key': '1'}],
  'wine': False},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Enable or disable the logging of dlsym errors.',
  'name': 'BOX64_DLSYM_ERROR',
  'options': [{'default': True, 'description': 'Disable the logging of dlsym errors.', 'key': '0'},
              {'default': False, 'description': 'Enable the logging of dlsym errors.', 'key': '1'}],
  'wine': False},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Dump elfloader debug information.',
  'name': 'BOX64_DUMP',
  'options': [{'default': True, 'description': 'Do not dump elfloader debug information.', 'key': '0'},
              {'default': False, 'description': 'Dump elfloader debug information.', 'key': '1'}],
  'wine': True},
 {'category': 'Performance',
  'configurator': True,
  'description': "Enable/disable the Dynamic Recompiler (a.k.a DynaRec). This option defaults to 1 if it's enabled in "
                 'the build options for a supported architecture.',
  'name': 'BOX64_DYNAREC',
  'options': [{'default': False, 'description': 'Disable DynaRec.', 'key': '0'},
              {'default': False, 'description': 'Enable DynaRec.', 'key': '1'}],
  'wine': True},
 {'category': 'Performance',
  'configurator': False,
  'description': 'Generate aligned atomics only (only available on Arm64 for now).',
  'name': 'BOX64_DYNAREC_ALIGNED_ATOMICS',
  'options': [{'default': True, 'description': 'Generate unaligned atomics handling code.', 'key': '0'},
              {'default': False,
               'description': 'Generate aligned atomics only, which is faster and smaller code size, but will cause '
                              'SIGBUS for LOCK prefixed opcodes operating on unaligned data addresses.',
               'key': '1'}],
  'wine': True},
 {'category': 'Performance',
  'configurator': True,
  'description': 'Enable building bigger DynaRec code blocks for better performance.',
  'name': 'BOX64_DYNAREC_BIGBLOCK',
  'options': [{'default': False,
               'description': 'Do not try to build block as big as possible, suitable for programs using lots of '
                              'threads and JIT, like Unity.',
               'key': '0'},
              {'default': False, 'description': 'Build DynaRec block as big as possible.', 'key': '1'},
              {'default': True,
               'description': 'Build DynaRec block bigger, do not stop when block overlaps, but only for blocks in elf '
                              'memory.',
               'key': '2'},
              {'default': False,
               'description': 'Build DynaRec block bigger, do not stop when block overlaps, for all type of memory, '
                              'useful for wine programs.',
               'key': '3'}],
  'wine': True},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Detect MonoBleedingEdge and apply conservative settings (Linux only).',
  'name': 'BOX64_DYNAREC_BLEEDING_EDGE',
  'options': [{'default': False, 'description': 'Do not detect MonoBleedingEdge.', 'key': '0'},
              {'default': True,
               'description': 'Detect MonoBleedingEdge and apply BOX64_DYNAREC_BIGBLOCK=0 BOX64_DYNAREC_STRONGMEM=1 '
                              'when detected.',
               'key': '1'}],
  'wine': False},
 {'category': 'Performance',
  'configurator': True,
  'description': 'Optimize CALL/RET opcodes.',
  'name': 'BOX64_DYNAREC_CALLRET',
  'options': [{'default': True, 'description': 'Do not optimize CALL/RET, use jump table.', 'key': '0'},
              {'default': False,
               'description': 'Try to optimize CALL/RET, skipping the jump table when possible.',
               'key': '1'},
              {'default': False,
               'description': 'Try to optimize CALL/RET, skipping the jump table when possible, adding code to handle '
                              'return to dirty/modified block. Does not work on WowBox64.',
               'key': '2'}],
  'wine': True},
 {'category': 'Performance',
  'configurator': True,
  'description': 'Optimize CALL/RET further with Secondary Entry Points (SEP). Has no effect if CALLRET is not enabled',
  'name': 'BOX64_DYNAREC_SEP',
  'options': [{'default': False, 'description': 'Do not add SEP at CALLRET return', 'key': '0'},
              {'default': True,
               'description': 'Add SEP at CALLRET return, on memory that are from known binary files',
               'key': '1'},
              {'default': False, 'description': 'Add SEP at CALLRET return for all type of memory.', 'key': '2'}],
  'wine': True},
 {'category': 'Performance',
  'configurator': False,
  'description': 'Enable or disable the use of deferred flags.',
  'name': 'BOX64_DYNAREC_DF',
  'options': [{'default': False, 'description': 'Disable the use of deferred flags.', 'key': '0'},
              {'default': True, 'description': 'Enable the use of deferred flags.', 'key': '1'}],
  'wine': True},
 {'category': 'Performance',
  'configurator': True,
  'description': 'Allow continue running a block that is unprotected and potentially dirty.',
  'name': 'BOX64_DYNAREC_DIRTY',
  'options': [{'default': True,
               'description': 'Do not allow continue running a block that is unprotected and potentially dirty.',
               'key': '0'},
              {'default': False,
               'description': 'Allow continue to run a DynaBlock that write data in the same page as code. It can gets '
                              'faster in loading time of some game but can also get unexpected crashes.',
               'key': '1'},
              {'default': False,
               'description': 'Will also, when it detects a HotPage, flag that page as NEVERCLEAN, and so it will not '
                              'be write protected but blocks built from that page will always be tested. It can be '
                              'faster that way (but some SMC case might not be trapped).',
               'key': '2'}],
  'wine': False},
 {'category': 'Performance',
  'configurator': True,
  'description': 'Disable detection of hot page (where code is executed and data written at the same time).',
  'name': 'BOX64_DYNAREC_NOHOTPAGE',
  'options': [{'default': True, 'description': 'Detect hot page', 'key': '0'},
              {'default': False, 'description': 'Do not detect hot page', 'key': '1'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': True,
  'description': 'Enable or disable the generation of division-by-zero exception.',
  'name': 'BOX64_DYNAREC_DIV0',
  'options': [{'default': True, 'description': 'Do not generate the division-by-zero exception.', 'key': '0'},
              {'default': False, 'description': 'Generate the division-by-zero exception.', 'key': '1'}],
  'wine': True},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Enable DynaRec dump.',
  'name': 'BOX64_DYNAREC_DUMP',
  'options': [{'default': True, 'description': 'Do not dump DynaRec blocks.', 'key': '0'},
              {'default': False, 'description': 'Dump DynaRec blocks.', 'key': '1'},
              {'default': False, 'description': 'Dump DynaRec blocks with some colors.', 'key': '2'}],
  'wine': True},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Dump DynaRec blocks in the specified range.',
  'name': 'BOX64_DYNAREC_DUMP_RANGE',
  'options': [{'default': False,
               'description': 'Define the range where DynaBlock gets dumped (inclusive-exclusive).',
               'key': '0xXXXXXXXX-0xYYYYYYYY'}],
  'wine': True},
 {'category': 'Performance',
  'configurator': True,
  'description': 'Enable or disable fast NaN handling.',
  'name': 'BOX64_DYNAREC_FASTNAN',
  'options': [{'default': False, 'description': 'Precisely emulate the -NaN generation like on x86.', 'key': '0'},
              {'default': True, 'description': 'Do not do anything special with -NAN generation, faster.', 'key': '1'}],
  'wine': True},
 {'category': 'Performance',
  'configurator': True,
  'description': 'Enable or disable fast rounding.',
  'name': 'BOX64_DYNAREC_FASTROUND',
  'options': [{'default': False,
               'description': 'Generate float/double -> int rounding and use current rounding mode for float/double '
                              'computation like on x86.',
               'key': '0'},
              {'default': True,
               'description': 'Do not do anything special with edge case rounding, faster.',
               'key': '1'},
              {'default': False,
               'description': 'Generate float/double -> int rounding using current rounding mode for float/double '
                              'computation like on x86, but use fast int -> float/double conversion.',
               'key': '2'}],
  'wine': True},
 {'category': 'Performance',
  'configurator': True,
  'description': 'Define max allowed forward value when building block. Only 0, 128, 256, 512 and 1024 are valid; '
                 'other values fall back to 128.',
  'name': 'BOX64_DYNAREC_FORWARD',
  'options': [{'default': False,
               'description': 'No forward value. When current block ends, do not try to go further even if there are '
                              'previous forward jumps.',
               'key': '0'},
              {'default': True,
               'description': 'Allow up to 128 bytes of gap between end of the block and the next forward jump.',
               'key': '128'},
              {'default': False,
               'description': 'Allow up to 256 bytes of gap between end of the block and the next forward jump.',
               'key': '256'},
              {'default': False,
               'description': 'Allow up to 512 bytes of gap between end of the block and the next forward jump.',
               'key': '512'},
              {'default': False,
               'description': 'Allow up to 1024 bytes of gap between end of the block and the next forward jump.',
               'key': '1024'}],
  'wine': True},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'The GDBJIT debugging support, only available on build with `-DGDBJIT=ON`, enable it with gdb '
                 'command: jit-reader-load /usr/local/lib/libbox64gdbjitreader.so.',
  'name': 'BOX64_DYNAREC_GDBJIT',
  'options': [{'default': True, 'description': 'DynaRec will not generate GDBJIT debuginfo.', 'key': '0'},
              {'default': False, 'description': 'DynaRec will generate GDBJIT debuginfo.', 'key': '1'},
              {'default': False,
               'description': 'DynaRec will generate detailed GDBJIT debuginfo with internal state.',
               'key': '2'},
              {'default': False,
               'description': 'DynaRec will register detailed GDBJIT debuginfo only for DynaBlocks that the guest '
                              'program trap into, greatly improving performance.',
               'key': '3'},
              {'default': False,
               'description': 'Define the range where DynaRec will generate detailed GDBJIT debuginfo with internal '
                              'state.',
               'key': '0xXXXXXXX-0xYYYYYYY'}],
  'wine': False},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Disable or enable DynaRec logs.',
  'name': 'BOX64_DYNAREC_LOG',
  'options': [{'default': True, 'description': 'Disable DynaRec logs.', 'key': '0'},
              {'default': False, 'description': 'Enable minimal DynaRec logs.', 'key': '1'},
              {'default': False, 'description': 'Enable debug level DynaRec logs.', 'key': '2'},
              {'default': False, 'description': 'Enable verbose level DynaRec logs.', 'key': '3'}],
  'wine': True},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Print missing opcodes.',
  'name': 'BOX64_DYNAREC_MISSING',
  'options': [{'default': True, 'description': 'Do not print the missing opcode.', 'key': '0'},
              {'default': False, 'description': 'Print missing opcodes.', 'key': '1'},
              {'default': False,
               'description': 'Print the fallback to scalar opcodes, only valid on RISC-V.',
               'key': '2'}],
  'wine': True},
 {'category': 'Performance',
  'configurator': True,
  'description': 'Enable or disable the use of native flags.',
  'name': 'BOX64_DYNAREC_NATIVEFLAGS',
  'options': [{'default': False, 'description': 'Do not use native flags.', 'key': '0'},
              {'default': True, 'description': 'Use native flags when possible.', 'key': '1'}],
  'wine': True},
 {'category': 'Debugging',
  'configurator': True,
  'description': 'Disable optional host extensions.',
  'name': 'BOX64_DYNAREC_NOHOSTEXT',
  'options': [{'default': True, 'description': 'Disable nothing.', 'key': '0'},
              {'default': False, 'description': 'Disable all the optional extensions.', 'key': '1'},
              {'default': False,
               'description': 'Disable selected optional extensions, choices are Arm: '
                              '`crc32,pmull,aes,atomics,sha1,sha2,uscat,flagm,flagm2,frintts,afp,rndr`, LoongArch: '
                              '`lasx,lbt,frecipe,lam_bh,lamcas,scq`, and RISC-V: '
                              '`zba,zbb,zbc,zbs,vector,xtheadba,xtheadbb,xtheadbs,xtheadmemidx,xtheadmempair,xtheadcondmov`.',
               'key': 'xxx,yyy,zzz'}],
  'wine': False},
 {'category': 'Performance',
  'configurator': False,
  'description': 'Enable x86 PAUSE emulation, may help the performance of spinlocks.',
  'name': 'BOX64_DYNAREC_PAUSE',
  'options': [{'default': True, 'description': 'Ignore x86 PAUSE instruction.', 'key': '0'},
              {'default': False, 'description': 'Use YIELD to emulate x86 PAUSE instruction.', 'key': '1'},
              {'default': False, 'description': 'Use WFI to emulate x86 PAUSE instruction.', 'key': '2'},
              {'default': False, 'description': 'Use SEVL+WFE to emulate x86 PAUSE instruction.', 'key': '3'}],
  'wine': True},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Generate map file for Linux perf tool.',
  'name': 'BOX64_DYNAREC_PERFMAP',
  'options': [{'default': True, 'description': 'DynaRec will not generate perf map.', 'key': '0'},
              {'default': False, 'description': 'DynaRec will generate perf map.', 'key': '1'}],
  'wine': False},
 {'category': 'Fragile or Legacy',
  'configurator': False,
  'description': "Purge DynaBlocks that haven't been executed recently, based on tick age threshold "
                 '(BOX64_DYNAREC_PURGE_AGE).',
  'name': 'BOX64_DYNAREC_PURGE',
  'options': [{'default': True, 'description': 'DynaRec will not purge old unused DynaBlocks.', 'key': '0'},
              {'default': False,
               'description': 'DynaRec will purge old unused DynaBlocks based on tick age.',
               'key': '1'}],
  'wine': False},
 {'category': 'Fragile or Legacy',
  'configurator': False,
  'description': 'Tick age threshold for DynaBlock purging (requires BOX64_DYNAREC_PURGE=1).',
  'name': 'BOX64_DYNAREC_PURGE_AGE',
  'options': [{'default': True, 'description': 'Default age threshold.', 'key': '4096'},
              {'default': False, 'description': 'Custom age threshold (range: 10-65536).', 'key': 'XXXX'}],
  'wine': False},
 {'category': 'Performance',
  'configurator': True,
  'description': 'Behaviour of flags emulation on CALL/RET opcodes and other edge cases.',
  'name': 'BOX64_DYNAREC_SAFEFLAGS',
  'options': [{'default': False, 'description': 'Treat CALL/RET as if it never needs any flags.', 'key': '0'},
              {'default': True, 'description': 'Most of RETs will need flags, most of CALLs will not.', 'key': '1'},
              {'default': False,
               'description': 'All CALL/RET will need flags. All edge cases are also handled.',
               'key': '2'}],
  'wine': True},
 {'category': 'Performance',
  'configurator': True,
  'description': 'Enable the emulation of x86 strong memory model.',
  'name': 'BOX64_DYNAREC_STRONGMEM',
  'options': [{'default': True, 'description': 'Do not try anything special.', 'key': '0'},
              {'default': False,
               'description': 'Enable some memory barriers when writing to memory to emulate the x86 strong memory '
                              'model in a limited way.',
               'key': '1'},
              {'default': False, 'description': 'All in 1, plus memory barriers on SIMD instructions.', 'key': '2'},
              {'default': False, 'description': 'All in 2, plus more memory barriers on a regular basis.', 'key': '3'},
              {'default': False,
               'description': "Mimic x86 TSO similarly to QEMU's approach, for evaluation purposes.",
               'key': '4'}],
  'wine': True},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Enable or disable libtbb detection.',
  'name': 'BOX64_DYNAREC_TBB',
  'options': [{'default': False, 'description': 'Do not detect libtbb.', 'key': '0'},
              {'default': True, 'description': 'Detect libtbb and apply conservative settings.', 'key': '1'}],
  'wine': False},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Enable DynaRec execution comparison with the interpreter, very slow, only for testing.',
  'name': 'BOX64_DYNAREC_TEST',
  'options': [{'default': True, 'description': 'No comparison.', 'key': '0'},
              {'default': False,
               'description': 'Each opcode runs on interpreter and on DynaRec, regs and memory are compared and '
                              'printed when they differ.',
               'key': '1'},
              {'default': False,
               'description': 'Define the range where DynaRec is tested (inclusive-exclusive).',
               'key': '0xXXXXXXXX-0xYYYYYYYY'}],
  'wine': True},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Enable deduplication of IP address where COSIM find a difference.',
  'name': 'BOX64_DYNAREC_TEST_NODUP',
  'options': [{'default': True, 'description': 'Show all addresses in error.', 'key': '0'},
              {'default': False,
               'description': 'Show address in error only 1 time, even if dump might differs.',
               'key': '1'}],
  'wine': True},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Do not dump test code when BOX64_DYNAREC_DUMP is enabled.',
  'name': 'BOX64_DYNAREC_TEST_NODUMP',
  'options': [{'default': False, 'description': 'Dump test code.', 'key': '0'},
              {'default': True, 'description': 'Do not dump test code.', 'key': '1'}],
  'wine': True},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Enable or disable DynaRec trace.',
  'name': 'BOX64_DYNAREC_TRACE',
  'options': [{'default': True, 'description': 'Do not trace DynaRec blocks.', 'key': '0'},
              {'default': False,
               'description': 'Trace DynaRec blocks, will slow down the program a lot and generates huge logs.',
               'key': '1'}],
  'wine': False},
 {'category': 'Performance',
  'configurator': False,
  'description': 'Use volatile metadata parsed from PE files, only valid for 64bit Windows games.',
  'name': 'BOX64_DYNAREC_VOLATILE_METADATA',
  'options': [{'default': False, 'description': 'Do not use volatile metadata.', 'key': '0'},
              {'default': True,
               'description': 'Use volatile metadata, which will guide Box64 for better strong memory emulation.',
               'key': '1'}],
  'wine': False},
 {'category': 'Fragile or Legacy',
  'configurator': False,
  'description': 'Wait or not for the building of a DynaRec code block to be ready.',
  'name': 'BOX64_DYNAREC_WAIT',
  'options': [{'default': False,
               'description': 'Do not wait and use interpreter instead, might speedup a bit on massive multithread or '
                              'JIT programs.',
               'key': '0'},
              {'default': True, 'description': 'Wait for a DynaRec code block to be ready.', 'key': '1'}],
  'wine': True},
 {'category': 'Fragile or Legacy',
  'configurator': False,
  'description': 'Tweak the memory barriers to reduce the performance impact by strong memory emulation.',
  'name': 'BOX64_DYNAREC_WEAKBARRIER',
  'options': [{'default': False, 'description': 'Use regular safe barrier.', 'key': '0'},
              {'default': True, 'description': 'Use weak barriers to have more performance boost.', 'key': '1'},
              {'default': False, 'description': 'All in 1, plus disable the last write barriers.', 'key': '2'}],
  'wine': True},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Force the use of float/double for x87 emulation.',
  'name': 'BOX64_DYNAREC_X87DOUBLE',
  'options': [{'default': True, 'description': 'Try to use float when possible for x87 emulation.', 'key': '0'},
              {'default': False, 'description': 'Only use Double for x87 emulation.', 'key': '1'},
              {'default': False, 'description': 'Check Precision Control low precision on x87 emulation.', 'key': '2'}],
  'wine': True},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Allow the use of DynaRec in Signal Handlers.',
  'name': 'BOX64_DYNAREC_INTERP_SIGNAL',
  'options': [{'default': True, 'description': 'Allow the use of DynaRec in signal handlers.', 'key': '0'},
              {'default': False,
               'description': 'Only use the Interpreter for signal handlers (as it was in v0.3.8 and earlier).',
               'key': '1'}],
  'wine': False},
 {'category': 'Performance',
  'configurator': True,
  'description': 'Enable/disable the Dynamic Recompiler Cache (a.k.a DynaCache). This option defaults to 2 (to read '
                 'cache if present but not generate any). DynaCache writes files to the home folder by default, and '
                 'keeps its folder below BOX64_DYNACACHE_LIMIT when generating new cache files.',
  'name': 'BOX64_DYNACACHE',
  'options': [{'default': False, 'description': 'Disable DynaCache.', 'key': '0'},
              {'default': True, 'description': 'Enable DynaCache.', 'key': '1'},
              {'default': False,
               'description': 'Use DynaCache files if present, but do not generate new one.',
               'key': '2'}],
  'wine': False},
 {'category': 'Performance',
  'configurator': True,
  'description': 'Set the folder for DynaCache files. Default is $XDG_CACHE_HOME/box64 or $HOME/.cache/box64 if '
                 '$XDG_CACHE_HOME is not set.',
  'name': 'BOX64_DYNACACHE_FOLDER',
  'options': [{'default': False, 'description': 'Use folder XXXX for DynaCache files.', 'key': 'XXXX'}],
  'wine': False},
 {'category': 'Performance',
  'configurator': True,
  'description': 'Maximum size, in MiB, for the DynaCache folder. When the limit is exceeded, invalid DynaCache files '
                 'are removed first, then the oldest valid files are removed if needed. Default size is 2048MiB.',
  'name': 'BOX64_DYNACACHE_LIMIT',
  'options': [{'default': False, 'description': 'Do not limit the DynaCache folder size.', 'key': '0'},
              {'default': False,
               'description': 'Keep the DynaCache folder below XXXX MiB by removing invalid cache files first, then '
                              'the oldest valid cache files.',
               'key': 'XXXX'},
              {'default': True, 'description': 'A size of 2048 MiB is the default value.', 'key': '2048'}],
  'wine': False},
 {'category': 'Performance',
  'configurator': True,
  'description': 'Compress or not DynaCache files on disk',
  'name': 'BOX64_DYNACACHE_COMPRESS',
  'options': [{'default': False, 'description': 'Do not compress dynacache files', 'key': '0'},
              {'default': True,
               'description': 'Compress dynacache files using Zlib with fastest compression.',
               'key': '1'},
              {'default': False,
               'description': 'Compress dynacache files using ZLib with default compression.',
               'key': '2'}],
  'wine': False},
 {'category': 'Performance',
  'configurator': True,
  'description': 'Minimum size, in KB, for a DynaCache to be written to disk. Default size is 30KB',
  'name': 'BOX64_DYNACACHE_MIN',
  'options': [{'default': False,
               'description': 'Set a minimum size of XXXX KB of DynaRec code to write the dynacache to disk. Will not '
                              'be saved to disk else.',
               'key': 'XXXX'},
              {'default': True, 'description': 'A size of 30 KB is the default value.', 'key': '30'}],
  'wine': False},
 {'category': 'Libraries',
  'configurator': True,
  'description': 'Force the use of emulated libraries.',
  'name': 'BOX64_EMULATED_LIBS',
  'options': [{'default': False, 'description': 'Force the use of emulated library XXXX.', 'key': 'XXXX'},
              {'default': False,
               'description': 'Force the use of emulated libraries XXXX, YYYY and ZZZZ.',
               'key': 'XXXX:YYYY:ZZZZ'}],
  'wine': False},
 {'category': 'Environment',
  'configurator': False,
  'description': 'Add an environment variable.',
  'name': 'BOX64_ENV',
  'options': [{'default': False, 'description': 'Add environment variable XXXX with value yyyy.', 'key': 'XXXX=yyyy'}],
  'wine': False},
 {'category': 'Environment',
  'configurator': False,
  'description': 'Add an environment variable.',
  'name': 'BOX64_ENV[1-5]',
  'options': [{'default': False, 'description': 'Add environment variable XXXX with value yyyy.', 'key': 'XXXX=yyyy'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Just exit, do not try to run the program.',
  'name': 'BOX64_EXIT',
  'options': [{'default': True, 'description': 'Does nothing.', 'key': '0'},
              {'default': False, 'description': 'Just exit.', 'key': '1'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Fix 64bit inodes.',
  'name': 'BOX64_FIX_64BIT_INODES',
  'options': [{'default': True, 'description': 'Do not fix 64bit inodes.', 'key': '0'},
              {'default': False, 'description': 'Fix 64bit inodes.', 'key': '1'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Force symbols from BOX64_LD_PRELOAD libraries to be resolved by RTLD_NEXT.',
  'name': 'BOX64_FORCE_LD_PRELOAD',
  'options': [{'default': True, 'description': 'Do nothing.', 'key': '0'},
              {'default': False,
               'description': 'Force symbols from BOX64_LD_PRELOAD libraries to be resolved by RTLD_NEXT.',
               'key': '1'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Ignore INT3 instructions.',
  'name': 'BOX64_IGNOREINT3',
  'options': [{'default': True, 'description': 'Trigger a TRAP signal if a handler is present.', 'key': '0'},
              {'default': False, 'description': 'Skip the opcode silently.', 'key': '1'}],
  'wine': False},
 {'category': 'Arguments',
  'configurator': False,
  'description': 'Prepend arguments to the command line.',
  'name': 'BOX64_INSERT_ARGS',
  'options': [{'default': False, 'description': 'Prepend argument XXXX to the program.', 'key': 'XXXX'},
              {'default': False,
               'description': 'Prepend arguments XXXX, YYYY and ZZZZ to the guest program.',
               'key': 'XXXX YYYY ZZZZ'}],
  'wine': False},
 {'category': 'Arguments',
  'configurator': False,
  'description': 'Add --in-process-gpu argument to the guest program.',
  'name': 'BOX64_INPROCESSGPU',
  'options': [{'default': True, 'description': 'Does nothing.', 'key': '0'},
              {'default': False, 'description': 'Add --in-process-gpu argument to the guest program.', 'key': '1'}],
  'wine': False},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Launch gdb or not for SIGSEGV, SIGILL, and SIGBUS.',
  'name': 'BOX64_JITGDB',
  'options': [{'default': True, 'description': 'Just print the message when the signal is caught.', 'key': '0'},
              {'default': False,
               'description': 'Launch gdb when a SIGSEGV, SIGILL or SIGBUS signal is trapped, attached to the '
                              'offending process and go in an endless loop, waiting. Inside gdb, you need to find the '
                              'correct thread yourself (the one with `my_box64signalhandler` in its stack), then '
                              "probably need to `finish` 1 or 2 functions (inside `usleep(..)`) and then you'll be in "
                              '`my_box64signalhandler`, just before the printf of the Segfault message. Then `set '
                              'waiting=0` to exit the infinite loop.',
               'key': '1'},
              {'default': False,
               'description': 'Launch gdbserver when a SIGSEGV, SIGILL or SIGBUS signal is trapped, attached to the '
                              'offending process, and go in an endless loop, waiting. Use `gdb /PATH/TO/box64` and '
                              'then `target remote 127.0.0.1: 1234` to connect to the gdbserver (or use actual IP if '
                              'not on the machine). After that, the procedure is the same as with `BOX64_JITGDB=1`.',
               'key': '2'},
              {'default': False,
               'description': 'Launch lldb when a SIGSEGV, SIGILL or SIGBUS signal is trapped, attached to the '
                              'offending process and go in an endless loop, waiting.',
               'key': '3'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Detect libjvm and apply conservative settings.',
  'name': 'BOX64_JVM',
  'options': [{'default': False, 'description': 'Does nothing.', 'key': '0'},
              {'default': True,
               'description': 'Detect libjvm, and apply BOX64_DYNAREC_BIGBLOCK=0 BOX64_DYNAREC_STRONGMEM=1 '
                              'BOX64_SSE42=0 when detected.',
               'key': '1'}],
  'wine': False},
 {'category': 'Libraries',
  'configurator': False,
  'description': 'Path to look for x86_64 libraries.',
  'name': 'BOX64_LD_LIBRARY_PATH',
  'options': [{'default': False, 'description': 'Add path XXXX to the library path.', 'key': 'XXXX'}],
  'wine': False},
 {'category': 'Libraries',
  'configurator': False,
  'description': 'Force loading libraries with the binary.',
  'name': 'BOX64_LD_PRELOAD',
  'options': [{'default': False, 'description': 'Force the loading of library XXXX.', 'key': 'XXXX'},
              {'default': False, 'description': 'Force the loading of libraries XXXX and YYYY.', 'key': 'XXXX:YYYY'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Detect libcef and apply BOX64_MALLOC_HACK settings.',
  'name': 'BOX64_LIBCEF',
  'options': [{'default': True, 'description': 'Does nothing.', 'key': '0'},
              {'default': False,
               'description': 'Detect libcef, and apply BOX64_MALLOC_HACK=2 if detected.',
               'key': '1'}],
  'wine': False},
 {'category': 'Libraries',
  'configurator': False,
  'description': 'Set the name for libGL.',
  'name': 'BOX64_LIBGL',
  'options': [{'default': False, 'description': 'Set the name for libGL to libXXXX.', 'key': 'libXXXX'},
              {'default': False,
               'description': 'Set the name and path for libGL to /path/to/libXXXX, you can also use '
                              'SDL_VIDEO_GL_DRIVER.',
               'key': '/path/to/libXXXX'}],
  'wine': False},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Set the address where the program is loaded, only active for PIE guest programs.',
  'name': 'BOX64_LOAD_ADDR',
  'options': [{'default': False, 'description': 'Set the address where the program is loaded.', 'key': '0xXXXXXXXX'}],
  'wine': False},
 {'category': 'Debugging',
  'configurator': True,
  'description': 'Enable or disable Box64 logs, default value is 0 if stdout is not terminal, 1 otherwise.',
  'name': 'BOX64_LOG',
  'options': [{'default': False, 'description': 'Disable Box64 logs.', 'key': '0'},
              {'default': False, 'description': 'Enable minimal Box64 logs.', 'key': '1'},
              {'default': False, 'description': 'Enable debug level Box64 logs.', 'key': '2'},
              {'default': False, 'description': 'Enable verbose level Box64 logs.', 'key': '3'}],
  'wine': True},
 {'category': 'Compatibility',
  'configurator': True,
  'description': 'Behaviour when hooking malloc operators.',
  'name': 'BOX64_MALLOC_HACK',
  'options': [{'default': True,
               'description': "Don't allow malloc operator to be redirected, rewriting code to use regular function.",
               'key': '0'},
              {'default': False, 'description': 'Allow malloc operator to be redirected.', 'key': '1'},
              {'default': False,
               'description': 'Like 0, but track special mmap/free (some redirected functions are inlined and cannot '
                              'be redirected).',
               'key': '2'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': True,
  'description': 'Maximum CPU cores exposed.',
  'name': 'BOX64_MAXCPU',
  'options': [{'default': True, 'description': 'Use the actual number of CPU cores.', 'key': '0'},
              {'default': False, 'description': 'Use XXXX CPU cores.', 'key': 'XXXX'}],
  'wine': True},
 {'category': 'Performance',
  'configurator': False,
  'description': 'Force 32-bit compatible memory mappings on 64-bit programs that run 32-bit code (like Wine WOW64), '
                 'can improve performance.',
  'name': 'BOX64_MMAP32',
  'options': [{'default': False, 'description': 'Do not force 32-bit memory mappings.', 'key': '0'},
              {'default': True, 'description': 'Force 32-bit memory mappings.', 'key': '1'}],
  'wine': False},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Disable the Box64 banner.',
  'name': 'BOX64_NOBANNER',
  'options': [{'default': False, 'description': 'Show the Box64 banner.', 'key': '0'},
              {'default': False, 'description': 'Do not show the Box64 banner.', 'key': '1'}],
  'wine': True},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Forbid DynaBlock creation in the address range specified, helpful for debugging behaviour difference '
                 'between DynaRec and Interpreter.',
  'name': 'BOX64_NODYNAREC',
  'options': [{'default': False,
               'description': 'Define the range where DynaBlock creation is forbidden (inclusive-exclusive).',
               'key': '0xXXXXXXXX-0xYYYYYYYY'}],
  'wine': True},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Remove NoDynaRec range after a delay.',
  'name': 'BOX64_NODYNAREC_DELAY',
  'options': [{'default': True, 'description': 'Do not remove NoDynaRec range.', 'key': '0'},
              {'default': False,
               'description': 'Remove the NoDynaRec range once 2 threads have been created.',
               'key': '1'}],
  'wine': True},
 {'category': 'Performance',
  'configurator': False,
  'description': 'Remove Architecture metadata from DynaRec blocks (used on signal).',
  'name': 'BOX64_DYNAREC_NOARCH',
  'options': [{'default': True,
               'description': 'Generate all architecture metadata for each blocks, including x87/mmx/SSE/AVX regs '
                              'tracking. Will use some more memory.',
               'key': '0'},
              {'default': False,
               'description': 'Generate only essential metadata for each blocks (flags, alignments), saving some '
                              'memory, but some encrypted software might fail.',
               'key': '1'},
              {'default': False,
               'description': 'Do not generate metadata for blocks. Saving a bit more memory but might fail on signal '
                              'handling.',
               'key': '2'}],
  'wine': True},
 {'category': 'Libraries',
  'configurator': True,
  'description': 'Do not load wrapped GTK libraries.',
  'name': 'BOX64_NOGTK',
  'options': [{'default': True, 'description': 'Load wrapped GTK libraries.', 'key': '0'},
              {'default': False, 'description': 'Do not load wrapped GTK libraries.', 'key': '1'}],
  'wine': False},
 {'category': 'Libraries',
  'configurator': False,
  'description': 'Do not load PulseAudio libraries (both native and x86_64).',
  'name': 'BOX64_NOPULSE',
  'options': [{'default': True, 'description': 'Load PulseAudio libraries.', 'key': '0'},
              {'default': False, 'description': 'Do not load PulseAudio libraries.', 'key': '1'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Do not load any rc files.',
  'name': 'BOX64_NORCFILES',
  'options': [{'default': True, 'description': 'Load rc files.', 'key': '0'},
              {'default': False, 'description': 'Do not load any rc files.', 'key': '1'}],
  'wine': False},
 {'category': 'Arguments',
  'configurator': True,
  'description': 'Add --no-sandbox argument to the guest program.',
  'name': 'BOX64_NOSANDBOX',
  'options': [{'default': True, 'description': 'Does nothing.', 'key': '0'},
              {'default': False, 'description': 'Add --no-sandbox argument to the guest program.', 'key': '1'}],
  'wine': False},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Disable the handling of SIGSEGV.',
  'name': 'BOX64_NOSIGSEGV',
  'options': [{'default': True, 'description': 'Let the x86 program set sighandler for SIGSEGV.', 'key': '0'},
              {'default': False, 'description': 'Disable the handling of SIGSEGV.', 'key': '1'}],
  'wine': False},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Disable the handling of SIGILL.',
  'name': 'BOX64_NOSIGILL',
  'options': [{'default': True, 'description': 'Let the x86 program set sighandler for SIGILL.', 'key': '0'},
              {'default': False, 'description': 'Disable the handling of SIGILL.', 'key': '1'}],
  'wine': False},
 {'category': 'Libraries',
  'configurator': False,
  'description': 'Do not load Vulkan libraries.',
  'name': 'BOX64_NOVULKAN',
  'options': [{'default': True, 'description': 'Load Vulkan libraries.', 'key': '0'},
              {'default': False, 'description': 'Do not load Vulkan libraries, both native and x86_64.', 'key': '1'}],
  'wine': False},
 {'category': 'Libraries',
  'configurator': False,
  'description': 'Do not load x64 Vulkan overlay.',
  'name': 'BOX64_NOVULKANOVERLAY',
  'options': [{'default': True, 'description': 'Try to load x64 Vulkan overlay.', 'key': '0'},
              {'default': False, 'description': 'Do not load x64 Vulkan overlay.', 'key': '1'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Path to look for x86_64 binaries.',
  'name': 'BOX64_PATH',
  'options': [{'default': False, 'description': 'Add path XXXX to the binary path.', 'key': 'XXXX'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': True,
  'description': 'Expose PCLMULQDQ capabilities.',
  'name': 'BOX64_PCLMULQDQ',
  'options': [{'default': False, 'description': 'Do not expose PCLMULQDQ capabilities.', 'key': '0'},
              {'default': True, 'description': 'Expose PCLMULQDQ capabilities.', 'key': '1'}],
  'wine': True},
 {'category': 'Libraries',
  'configurator': True,
  'description': 'Prefer emulated libraries over native ones.',
  'name': 'BOX64_PREFER_EMULATED',
  'options': [{'default': True, 'description': 'Prefer native libraries over emulated ones.', 'key': '0'},
              {'default': False, 'description': 'Prefer emulated libraries over native ones.', 'key': '1'}],
  'wine': False},
 {'category': 'Libraries',
  'configurator': False,
  'description': 'Prefer wrapped libs first even if the lib is specified with absolute path.',
  'name': 'BOX64_PREFER_WRAPPED',
  'options': [{'default': True, 'description': 'Prefer libs with absolute path over wrapped ones.', 'key': '0'},
              {'default': False,
               'description': 'Prefer wrapped libs first even if the lib is specified with absolute path.',
               'key': '1'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Predefined sets of environment variables with compatibility or performance in mind.',
  'name': 'BOX64_PROFILE',
  'options': [{'default': False,
               'description': 'Profile with all the unsafe DynaRec optimizations disabled.',
               'key': 'safest'},
              {'default': False, 'description': 'Well, less safer than safest.', 'key': 'safe'},
              {'default': True,
               'description': 'The default settings that most programs runs fine with a handy performance.',
               'key': 'default'},
              {'default': False,
               'description': 'Enable many unsafe optimizations, but also enable strongmem emulation.',
               'key': 'fast'},
              {'default': False,
               'description': 'Enable many unsafe optimizations to have a better performance.',
               'key': 'fastest'}],
  'wine': True},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Path to a python3 executable.',
  'name': 'BOX64_PYTHON3',
  'options': [{'default': False, 'description': 'Use python3 executable at path XXXX.', 'key': 'XXXX'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Path to the rc file to load.',
  'name': 'BOX64_RCFILE',
  'options': [{'default': False,
               'description': 'Load the rc file XXXX, default rc files will not be loaded.',
               'key': 'XXXX'}],
  'wine': False},
 {'category': 'Performance',
  'configurator': False,
  'description': 'Use hardware counter for rdtsc if available.',
  'name': 'BOX64_RDTSC_1GHZ',
  'options': [{'default': True, 'description': 'Use hardware counter for rdtsc opcode if available.', 'key': '0'},
              {'default': False,
               'description': 'Use hardware counter for rdtsc if and only if precision is at least 1GHz.',
               'key': '1'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Report Invariant TSC bit in CPUID for Intel CPU type.',
  'name': 'BOX64_RDTSC_INV',
  'options': [{'default': True, 'description': 'Do not report Invariant TSC for Intel CPU type (default).', 'key': '0'},
              {'default': False,
               'description': 'Report Invariant TSC bit in CPUID leaf 0x80000007 for Intel CPU type.',
               'key': '1'}],
  'wine': True},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Reserve high memory area for the program, always enabled on Box32.',
  'name': 'BOX64_RESERVE_HIGH',
  'options': [{'default': True, 'description': 'Do not reserve high memory area for the program.', 'key': '0'},
              {'default': False, 'description': 'Reserve high memory area for the program.', 'key': '1'}],
  'wine': False},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Show last few wrapped function call when a signal is caught.',
  'name': 'BOX64_ROLLING_LOG',
  'options': [{'default': True, 'description': 'Does nothing.', 'key': '0'},
              {'default': False,
               'description': 'Show last 16 wrapped function call when a signal is caught.',
               'key': '1'},
              {'default': False,
               'description': 'Show last XXXX wrapped function call when a signal is caught.',
               'key': 'XXXX'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Use a workaround for SDL_GetJoystickGUIDInfo function for wrapped SDL2.',
  'name': 'BOX64_SDL2_JGUID',
  'options': [{'default': True, 'description': 'Does nothing.', 'key': '0'},
              {'default': False,
               'description': 'Use a workaround for SDL_GetJoystickGUIDInfo function for wrapped SDL2.',
               'key': '1'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': True,
  'description': 'Expose SHAEXT (a.k.a. SHA_NI) capabilities.',
  'name': 'BOX64_SHAEXT',
  'options': [{'default': False, 'description': 'Do not expose SHAEXT capabilities.', 'key': '0'},
              {'default': True, 'description': 'Expose SHAEXT capabilities.', 'key': '1'}],
  'wine': True},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Show native and emulated backtrace when a signal is caught.',
  'name': 'BOX64_SHOWBT',
  'options': [{'default': True, 'description': 'Does nothing.', 'key': '0'},
              {'default': False,
               'description': 'Show native and emulated backtrace when a signal is caught.',
               'key': '1'}],
  'wine': False},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Always show SIGSEGV signal details.',
  'name': 'BOX64_SHOWSEGV',
  'options': [{'default': True, 'description': 'Does nothing.', 'key': '0'},
              {'default': False, 'description': 'Always show SIGSEGV signal details.', 'key': '1'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': True,
  'description': 'Behaviour of SSE Flush to 0 flags. Also tracking SSE exception flags.',
  'name': 'BOX64_SSE_FLUSHTO0',
  'options': [{'default': True, 'description': 'Just track the flag.', 'key': '0'},
              {'default': False,
               'description': 'Apply SSE Flush to 0 flag directly. Also reflect SSE exception flags in DynaRec (if '
                              'available)',
               'key': '1'}],
  'wine': True},
 {'category': 'Compatibility',
  'configurator': True,
  'description': 'Expose SSE4.2 capabilities.',
  'name': 'BOX64_SSE42',
  'options': [{'default': False, 'description': 'Do not expose SSE4.2 capabilities.', 'key': '0'},
              {'default': True, 'description': 'Expose SSE4.2 capabilities.', 'key': '1'}],
  'wine': True},
 {'category': 'Compatibility',
  'configurator': True,
  'description': 'Force Vulkan for Linux Steam UI.',
  'name': 'BOX64_STEAM_VULKAN',
  'options': [{'default': True, 'description': 'Do nothing.', 'key': '0'},
              {'default': False, 'description': 'Force Vulkan for Linux Steam UI.', 'key': '1'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Synchronize rounding mode between x86 and native.',
  'name': 'BOX64_SYNC_ROUNDING',
  'options': [{'default': True, 'description': 'Do not synchronize rounding mode.', 'key': '0'},
              {'default': False, 'description': 'Synchronize rounding mode between x86 and native.', 'key': '1'}],
  'wine': False},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Enable or disable colored trace output.',
  'name': 'BOX64_TRACE_COLOR',
  'options': [{'default': True, 'description': 'Disable colored trace output.', 'key': '0'},
              {'default': False, 'description': 'Enable colored trace output.', 'key': '1'}],
  'wine': False},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Enable or disable EMM (i.e. MMX) trace output.',
  'name': 'BOX64_TRACE_EMM',
  'options': [{'default': True, 'description': 'Disable EMM trace output.', 'key': '0'},
              {'default': False, 'description': 'Enable EMM trace output.', 'key': '1'}],
  'wine': False},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Send all log and trace to a file instead of `stdout`.',
  'name': 'BOX64_TRACE_FILE',
  'options': [{'default': False, 'description': 'Send all log and trace to file XXXX.', 'key': 'XXXX'},
              {'default': False,
               'description': 'Send all log and trace to file XXXX with pid appended.',
               'key': 'XXXX%pid'},
              {'default': True, 'description': 'Send all log and trace to `stderr`.', 'key': 'stderr'},
              {'default': False, 'description': 'Send all log and trace to `stdout`.', 'key': 'stdout'}],
  'wine': False},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Same as BOX64_TRACE but starts the trace immediately.',
  'name': 'BOX64_TRACE_INIT',
  'options': [{'default': True, 'description': 'Disable trace output.', 'key': '0'},
              {'default': False,
               'description': 'Enable trace output. Trace starts before the initialization of dependencies.',
               'key': '1'},
              {'default': False,
               'description': 'Enable trace output for `symbolname` only. Trace starts before the initialization of '
                              'dependencies.',
               'key': 'symbolname'},
              {'default': False,
               'description': 'Enable trace output for the range of address (inclusive-exclusive). Trace starts before '
                              'the initialization of dependencies.',
               'key': '0xXXXXXXX-0xYYYYYYY'}],
  'wine': False},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Start trace after N opcodes executed.',
  'name': 'BOX64_TRACE_START',
  'options': [{'default': True, 'description': 'Start trace immediately.', 'key': '0'},
              {'default': False, 'description': 'Start trace after 1 opcode executed.', 'key': '1'},
              {'default': False, 'description': 'Start trace after XXXX opcodes executed.', 'key': 'XXXX'}],
  'wine': False},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Enable or disable XMM (i.e. SSE) trace output.',
  'name': 'BOX64_TRACE_XMM',
  'options': [{'default': True, 'description': 'Disable XMM trace output.', 'key': '0'},
              {'default': False, 'description': 'Enable XMM trace output.', 'key': '1'}],
  'wine': False},
 {'category': 'Debugging',
  'configurator': False,
  'description': 'Only available on box64 build with trace. Adds trace of all instructions executed, along with a '
                 'register dump.',
  'name': 'BOX64_TRACE',
  'options': [{'default': True, 'description': 'Disable trace output.', 'key': '0'},
              {'default': False, 'description': 'Enable trace output.', 'key': '1'},
              {'default': False, 'description': 'Enable trace output for `symbolname` only.', 'key': 'symbolname'},
              {'default': False,
               'description': 'Enable trace output for the range of address (inclusive-exclusive).',
               'key': '0xXXXXXXX-0xYYYYYYY'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': True,
  'description': 'Detect UnityPlayer and apply conservative settings.',
  'name': 'BOX64_UNITYPLAYER',
  'options': [{'default': False, 'description': 'Does nothing.', 'key': '0'},
              {'default': True,
               'description': 'Detect UnityPlayer (Windows or Linux), and apply BOX64_UNITY=1 when detected.',
               'key': '1'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': True,
  'description': 'Games is a Unity one.',
  'name': 'BOX64_UNITY',
  'options': [{'default': False, 'description': 'Does nothing.', 'key': '0'},
              {'default': True,
               'description': 'Unity Game, use special detecting code for Windows, apply BOX64_DYNAREC_STRONGMEM=1 for '
                              'Linux.',
               'key': '1'}],
  'wine': False},
 {'category': 'Libraries',
  'configurator': False,
  'description': 'Prefer wrapped libs for EGL and GLESv2.',
  'name': 'BOX64_WRAP_EGL',
  'options': [{'default': True, 'description': 'Prefer emulated libs for EGL and GLESv2.', 'key': '0'},
              {'default': False, 'description': 'Prefer wrapped libs for EGL and GLESv2.', 'key': '1'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Force Xorg GLX extension to be present.',
  'name': 'BOX64_X11GLX',
  'options': [{'default': True, 'description': 'Do not force Xorg GLX extension to be present.', 'key': '0'},
              {'default': False, 'description': 'Require Xorg GLX extension when using XQueryExtension.', 'key': '1'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Force synchronized operation on X11 display.',
  'name': 'BOX64_X11SYNC',
  'options': [{'default': True, 'description': 'Do not force synchronized operation on X11 display.', 'key': '0'},
              {'default': False, 'description': 'Force synchronized operation on X11 display.', 'key': '1'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Call XInitThreads when loading X11. This is mostly for old Loki games with the Loki_Compat library.',
  'name': 'BOX64_X11THREADS',
  'options': [{'default': True, 'description': 'Do not call XInitThreads.', 'key': '0'},
              {'default': False, 'description': 'Call XInitThreads as soon as libX11 is loaded.', 'key': '1'}],
  'wine': False},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Behaviour of x87 80bits long double.',
  'name': 'BOX64_X87_NO80BITS',
  'options': [{'default': True, 'description': 'Try to handle 80bits long double as precise as possible.', 'key': '0'},
              {'default': False, 'description': 'Use 64bits double for x87.', 'key': '1'}],
  'wine': True},
 {'category': 'Compatibility',
  'configurator': False,
  'description': 'Disable the automatic switch of personality for 32-bit binaries (always enabled on Box32).',
  'name': 'BOX64_NOPERSONA32BITS',
  'options': [{'default': True,
               'description': 'Switch personality for 32-bit binaries (if not already tried).',
               'key': '0'},
              {'default': False, 'description': 'Do not switch personality for 32-bit binaries.', 'key': '1'}],
  'wine': False}]
_EMBEDDED_USAGE_CN_DATA = {'BOX64_ADDLIBS': {'description': '添加额外需要的共享库（这个选项不太常用）。',
                   'options': {'XXXX': '将 XXXX 共享库添加到所需库列表。', 'XXXX:YYYY:ZZZZ': '将 XXXX、YYYY 和 ZZZZ 共享库添加到所需库列表。'}},
 'BOX64_AES': {'description': '是否暴露 AES 能力。', 'options': {'0': '不暴露 AES 能力。', '1': '暴露 AES 能力。'}},
 'BOX64_ALLOWMISSINGLIBS': {'description': '是否允许忽略缺失的共享库。', 'options': {'0': '不允许忽略缺失的共享库。', '1': '允许忽略缺失的共享库。'}},
 'BOX64_ARCH': {'description': '在 rcfile 中指定当前条目适用的架构。此选项仅在 rcfile 中使用时生效。',
                'options': {'`<empty>`': '对所有架构应用当前条目，但如果存在更具体的条目，当前条目将被替换。',
                            '`arm64`': '仅对 AArch64 应用当前条目。',
                            '`la64`': '仅对 LoongArch64 应用当前条目。',
                            '`rv64`': '仅对 RISC-V 应用当前条目。'}},
 'BOX64_ARGS': {'description': '传递给目标程序的参数，仅在没有任何已有参数时有效。',
                'options': {'XXXX': '将 XXXX 参数传递给目标程序。', 'XXXX YYYY ZZZZ': '将 XXXX、YYYY 和 ZZZZ 参数传递给目标程序。'}},
 'BOX64_AVX': {'description': '向 CPUID 和 cpuinfo 文件暴露 AVX 扩展。在 Arm64 和龙架构上默认值为 2，因为 DynaRec 已完全实现，其他架构默认为 0。',
               'options': {'0': '不暴露 AVX 能力。',
                           '1': '向 CPUID 和 cpuinfo 文件暴露 AVX、BMI1、F16C 和 VAES 扩展。',
                           '2': '包含 1 的全部内容，外加 AVX2、BMI2、FMA、ADX、VPCLMULQDQ 和 RDRAND 扩展。'}},
 'BOX64_BASH': {'description': '用于指定 bash 可执行文件的路径。', 'options': {'XXXX': '使用路径为 XXXX 的 bash 可执行文件。'}},
 'BOX64_CPUTYPE': {'description': '指定要模拟的 CPU 类型。', 'options': {'0': '模拟某个 Intel CPU 型号。', '1': '模拟某个 AMD CPU 型号。'}},
 'BOX64_CRASHHANDLER': {'description': '是否使用模拟的 crashhandler.so 库。',
                        'options': {'0': '在需要时使用模拟的 crashhandler.so 库。', '1': '使用内部定义的空 crashhandler.so 库。'}},
 'BOX64_DLSYM_ERROR': {'description': '启用或禁用 dlsym 错误的日志记录。',
                       'options': {'0': '禁用 dlsym 错误的日志记录。', '1': '启用 dlsym 错误的日志记录。'}},
 'BOX64_DUMP': {'description': '是否输出 elfloader 调试信息。',
                'options': {'0': '不输出 elfloader 调试信息。', '1': '输出 elfloader 调试信息。'}},
 'BOX64_DYNACACHE': {'description': '启用或禁用动态重编译器缓存（DynaCache）。此选项默认为 2（读取已有缓存但不生成新的）。DynaCache 默认将文件写入 home '
                                    '文件夹，生成新缓存文件时会根据 BOX64_DYNACACHE_LIMIT 控制文件夹大小。',
                     'options': {'0': '禁用 DynaCache。', '1': '启用 DynaCache。', '2': '使用已有的 DynaCache 文件，但不生成新的。'}},
 'BOX64_DYNACACHE_COMPRESS': {'description': '设置是否压缩磁盘上的 DynaCache 文件。',
                              'options': {'0': '不压缩 DynaCache 文件。',
                                          '1': '使用 Zlib 最快压缩级别压缩 DynaCache 文件。',
                                          '2': '使用 Zlib 默认压缩级别压缩 DynaCache 文件。'}},
 'BOX64_DYNACACHE_FOLDER': {'description': '设置 DynaCache 文件的文件夹。默认为 $XDG_CACHE_HOME/box64，如果 $XDG_CACHE_HOME 未设置则为 '
                                           '$HOME/.cache/box64。',
                            'options': {'XXXX': '使用文件夹 XXXX 存储 DynaCache 文件。'}},
 'BOX64_DYNACACHE_LIMIT': {'description': 'DynaCache 文件夹的最大大小（MiB）。超过限制时，会先删除无效的 DynaCache 文件，如仍超限再删除最旧的有效文件。默认大小为 '
                                          '2048MiB。',
                           'options': {'0': '不限制 DynaCache 文件夹大小。',
                                       '2048': '默认值为 2048 MiB。',
                                       'XXXX': '先删除无效缓存文件，如仍超限再删除最旧的有效缓存文件，将 DynaCache 文件夹保持在 XXXX MiB 以下。'}},
 'BOX64_DYNACACHE_MIN': {'description': 'DynaCache 写入磁盘的最小大小（KB）。默认大小为 30KB。',
                         'options': {'30': '默认值为 30 KB。', 'XXXX': '设置将缓存写入磁盘的最小 DynaRec 代码大小（XXXX KB），小于此值将不会保存到磁盘。'}},
 'BOX64_DYNAREC': {'description': '启用或禁用动态重编译器（DynaRec）。如果在支持的架构上构建时开启了 DynaRec 支持，则默认为 1。',
                   'options': {'0': '禁用 DynaRec。', '1': '启用 DynaRec。'}},
 'BOX64_DYNAREC_ALIGNED_ATOMICS': {'description': '仅生成对齐的原子操作（目前仅在 Arm64 上可用）。',
                                   'options': {'0': '生成非对齐原子操作处理代码。',
                                               '1': '仅生成对齐的原子操作，代码更快更小，但在非对齐数据地址上执行 LOCK 前缀指令时会导致 SIGBUS。'}},
 'BOX64_DYNAREC_BIGBLOCK': {'description': '尝试构建更大的代码块以提高性能。',
                            'options': {'0': '不尝试构建尽可能大的代码块，适用于使用大量线程和 JIT 的程序（如 Unity）。',
                                        '1': '尽可能构建大的代码块。',
                                        '2': '构建更大的代码块，代码块重叠时不停止，但仅针对 elf 内存中的代码块。',
                                        '3': '构建更大的代码块，代码块重叠时不停止，适用于所有类型的内存，因此也对 wine 程序有用。'}},
 'BOX64_DYNAREC_BLEEDING_EDGE': {'description': '检测 MonoBleedingEdge 并应用保守设置（仅 Linux）。',
                                 'options': {'0': '不检测 MonoBleedingEdge。',
                                             '1': '检测 MonoBleedingEdge，并在检测到时应用 BOX64_DYNAREC_BIGBLOCK=0 和 '
                                                  'BOX64_DYNAREC_强内存模型=1。'}},
 'BOX64_DYNAREC_CALLRET': {'description': '优化 CALL/RET 指令。',
                           'options': {'0': '不优化 CALL/RET，使用跳转表。',
                                       '1': '尝试优化 CALL/RET，在可能的情况下跳过跳转表。',
                                       '2': '尝试优化 CALL/RET，在可能的情况下跳过跳转表，同时增加对返回到脏/已修改代码块的代码的处理。在 WowBox64 上不可用。'}},
 'BOX64_DYNAREC_DF': {'description': '启用或禁用延迟 FLAGS 的使用。', 'options': {'0': '禁用延迟 FLAGS 的使用。', '1': '启用延迟 FLAGS 的使用。'}},
 'BOX64_DYNAREC_DIRTY': {'description': '是否允许继续运行未受保护且可能已脏的代码块。',
                         'options': {'0': '不允许继续运行未受保护且可能已脏的代码块。',
                                     '1': '允许继续运行在与代码相同页面中写入数据的代码块，可以加快某些游戏的加载时间，但也可能导致意外崩溃。',
                                     '2': '除了 1 之外，当检测到热页时，将该页面标记为永不写保护，但基于该页面构建的代码块将始终被测试。这样可以更快（但某些 SMC 情况可能无法捕获）。'}},
 'BOX64_DYNAREC_DIV0': {'description': '启用或禁用除零异常的生成。', 'options': {'0': '不生成除零异常。', '1': '生成除零异常。'}},
 'BOX64_DYNAREC_DUMP': {'description': '启用 DynaRec 转储。',
                        'options': {'0': '不转储代码块。', '1': '转储代码块。', '2': '转储代码块并带有颜色。'}},
 'BOX64_DYNAREC_DUMP_RANGE': {'description': '转储指定范围内的代码块。',
                              'options': {'0xXXXXXXXX-0xYYYYYYYY': '定义代码块 被转储的范围（左闭右开）。'}},
 'BOX64_DYNAREC_FASTNAN': {'description': '启用或禁用快速 NaN 处理。',
                           'options': {'0': '精确模拟 x86 上的 -NaN 生成。', '1': '不对 -NaN 生成做任何特殊处理，速度更快。'}},
 'BOX64_DYNAREC_FASTROUND': {'description': '启用或禁用快速舍入。',
                             'options': {'0': '生成 float/double -> int 舍入，并使用当前舍入模式进行 float/double 计算，类似 x86。',
                                         '1': '不对边缘情况的舍入做任何特殊处理，速度更快。',
                                         '2': '使用当前舍入模式生成 float/double -> int 舍入（类似 x86），但使用快速的 int -> float/double '
                                              '转换。'}},
 'BOX64_DYNAREC_FORWARD': {'description': '定义构建代码块时允许的最大前向跳转值。仅接受 0、128、256、512 和 1024；其他值将回退为 128。',
                           'options': {'0': '无前向跳转值。当前代码块结束时，即使存在之前的前向跳转也不尝试继续前进。',
                                       '1024': '允许代码块结束与下一个前向跳转之间最多 1024 字节的间隙。',
                                       '128': '允许代码块结束与下一个前向跳转之间最多 128 字节的间隙。',
                                       '256': '允许代码块结束与下一个前向跳转之间最多 256 字节的间隙。',
                                       '512': '允许代码块结束与下一个前向跳转之间最多 512 字节的间隙。'}},
 'BOX64_DYNAREC_GDBJIT': {'description': 'GDBJIT 调试支持，仅在使用 `-DGDBJIT=ON` 构建时可用，通过 gdb 命令启用：jit-reader-load '
                                         '/usr/local/lib/libbox64gdbjitreader.so。',
                          'options': {'0': 'DynaRec 不会生成 GDBJIT 调试信息。',
                                      '0xXXXXXXX-0xYYYYYYY': '定义 DynaRec 将生成包含内部状态的详细 GDBJIT 调试信息的范围。',
                                      '1': 'DynaRec 将生成 GDBJIT 调试信息。',
                                      '2': 'DynaRec 将生成包含内部状态的详细 GDBJIT 调试信息。',
                                      '3': 'DynaRec 将仅对目标程序陷入的代码块 注册详细的 GDBJIT 调试信息，大幅提升性能。'}},
 'BOX64_DYNAREC_INTERP_SIGNAL': {'description': '允许在信号处理器中使用 DynaRec。',
                                 'options': {'0': '允许在信号处理器中使用 DynaRec。', '1': '仅在信号处理器中使用解释器（与 v0.3.8 及更早版本相同）。'}},
 'BOX64_DYNAREC_LOG': {'description': '禁用或启用 DynaRec 日志。',
                       'options': {'0': '禁用 DynaRec 日志。',
                                   '1': '启用最小级别的 DynaRec 日志。',
                                   '2': '启用调试级别的 DynaRec 日志。',
                                   '3': '启用详细级别的 DynaRec 日志。'}},
 'BOX64_DYNAREC_MISSING': {'description': '打印缺失的指令。',
                           'options': {'0': '不打印缺失的指令。', '1': '打印缺失的指令。', '2': '打印回退到标量指令的信息，仅对 RISC-V 有效。'}},
 'BOX64_DYNAREC_NATIVEFLAGS': {'description': '启用或禁用原生FLAGS的使用。',
                               'options': {'0': '不使用原生FLAGS。', '1': '在可能的情况下使用原生FLAGS。'}},
 'BOX64_DYNAREC_NOARCH': {'description': '从代码块中移除架构元数据（在信号处理时使用）。',
                          'options': {'0': '为每个代码块生成所有架构元数据，包括 x87/mmx/SSE/AVX 寄存器追踪。会使用更多内存。',
                                      '1': '仅生成每个代码块的必要元数据（FLAGS、对齐），节省一些内存，但某些加密软件可能会失败。',
                                      '2': '不为代码块生成元数据，进一步节省内存，但在信号处理时可能会失败。'}},
 'BOX64_DYNAREC_NOHOSTEXT': {'description': '禁用可选的主机扩展。',
                             'options': {'0': '不禁用任何扩展。',
                                         '1': '禁用所有可选扩展。',
                                         'xxx,yyy,zzz': '禁用指定的可选扩展，可选项包括 '
                                                        'Arm：`crc32,pmull,aes,atomics,sha1,sha2,uscat,flagm,flagm2,frintts,afp,rndr`，LoongArch：`lasx,lbt,frecipe,lam_bh,lamcas,scq`，以及 '
                                                        'RISC-V：`zba,zbb,zbc,zbs,vector,xtheadba,xtheadbb,xtheadbs,xtheadmemidx,xtheadmempair,xtheadcondmov`。'}},
 'BOX64_DYNAREC_NOHOTPAGE': {'description': '是否禁用热页检测（即代码执行和数据写入同时发生的页面）。', 'options': {'0': '检测热页。', '1': '不检测热页。'}},
 'BOX64_DYNAREC_PAUSE': {'description': '启用 x86 PAUSE 模拟，可能有助于自旋锁的性能。',
                         'options': {'0': '忽略 x86 PAUSE 指令。',
                                     '1': '使用 YIELD 模拟 x86 PAUSE 指令。',
                                     '2': '使用 WFI 模拟 x86 PAUSE 指令。',
                                     '3': '使用 SEVL+WFE 模拟 x86 PAUSE 指令。'}},
 'BOX64_DYNAREC_PERFMAP': {'description': '为 Linux perf 工具生成映射文件。',
                           'options': {'0': 'DynaRec 不会生成 perf 映射。', '1': 'DynaRec 将生成 perf 映射。'}},
 'BOX64_DYNAREC_PURGE': {'description': '根据年龄阈值（BOX64_DYNAREC_PURGE_AGE）清除最近未执行的代码块。',
                         'options': {'0': 'DynaRec 不会清除旧的未使用代码块。', '1': 'DynaRec 将根据年龄阈值清除旧的未使用代码块。'}},
 'BOX64_DYNAREC_PURGE_AGE': {'description': '代码块清除的年龄阈值（需要 BOX64_DYNAREC_PURGE=1）。',
                             'options': {'4096': '默认年龄阈值。', 'XXXX': '自定义年龄阈值（范围：10-65536）。'}},
 'BOX64_DYNAREC_SAFEFLAGS': {'description': '在 CALL/RET 指令和其他边缘情况下 FLAGS 模拟的行为。',
                             'options': {'0': '将 CALL/RET 标记为从不需要任何 FLAGS。',
                                         '1': '将大多数 RET 标记为需要 FLAGS，将大多数 CALL 标记为不需要。',
                                         '2': '将所有 CALL/RET 都标记为需要 FLAGS。同时也处理所有边缘情况。'}},
 'BOX64_DYNAREC_SEP': {'description': '使用二级入口点（SEP）进一步优化 CALL/RET。如果 CALLRET 未启用则无效。',
                       'options': {'0': '不在 CALLRET 返回时添加 SEP。',
                                   '1': '在 CALLRET 返回时添加 SEP，仅针对来自已知二进制文件的内存。',
                                   '2': '在 CALLRET 返回时添加 SEP，适用于所有类型的内存。'}},
 'BOX64_DYNAREC_STRONGMEM': {'description': '开启或关闭 x86 强内存模型的模拟。',
                             'options': {'0': '不做任何特殊处理。',
                                         '1': '在写入内存时启用以有限方式模拟 x86 强内存模型的内存屏障。',
                                         '2': '包含 1 的全部内容，外加 SIMD 指令的内存屏障。',
                                         '3': '包含 2 的全部内容，外加定期添加更多内存屏障。',
                                         '4': '模仿 x86 TSO，类似 QEMU 的方法，可用于评估目的。'}},
 'BOX64_DYNAREC_TBB': {'description': '启用或禁用 libtbb 检测。', 'options': {'0': '不检测 libtbb。', '1': '检测 libtbb 并应用保守设置。'}},
 'BOX64_DYNAREC_TEST': {'description': '启用 DynaRec 与解释器的执行对比，非常慢，仅用于测试。',
                        'options': {'0': '不进行对比。',
                                    '0xXXXXXXXX-0xYYYYYYYY': '定义 DynaRec 测试的范围（左闭右开）。',
                                    '1': '每个指令都在解释器和 DynaRec 上运行，当寄存器或内存不同时进行对比并打印。'}},
 'BOX64_DYNAREC_TEST_NODUMP': {'description': '当 BOX64_DYNAREC_DUMP 启用时不转储测试代码。',
                               'options': {'0': '转储测试代码。', '1': '不转储测试代码。'}},
 'BOX64_DYNAREC_TEST_NODUP': {'description': '启用 COSIM 发现差异的 IP 地址去重。',
                              'options': {'0': '显示所有出错的地址。', '1': '每个出错地址仅显示一次，即使转储可能不同。'}},
 'BOX64_DYNAREC_TRACE': {'description': '启用或禁用 DynaRec 追踪。',
                         'options': {'0': '不追踪代码块。', '1': '追踪代码块，会大幅降低程序速度并生成大量日志。'}},
 'BOX64_DYNAREC_VOLATILE_METADATA': {'description': '使用从 PE 文件解析的 volatile 元数据，仅对 64 位 Windows 游戏有效。',
                                     'options': {'0': '不使用 volatile 元数据。',
                                                 '1': '使用 volatile 元数据，将指导 Box64 进行更好的强内存模拟。'}},
 'BOX64_DYNAREC_WAIT': {'description': '是否等待代码块构建完成。',
                        'options': {'0': '不等待，改用解释器，可能在大量多线程或 JIT 程序上略微加速。', '1': '等待代码块构建完成。'}},
 'BOX64_DYNAREC_WEAKBARRIER': {'description': '调整内存屏障以减少强内存模拟的性能影响。',
                               'options': {'0': '使用常规安全屏障。', '1': '使用弱屏障以获得更多性能提升。', '2': '包含 1 的全部内容，外加禁用最后的写屏障。'}},
 'BOX64_DYNAREC_X87DOUBLE': {'description': '强制使用 float/double 进行 x87 模拟。',
                             'options': {'0': '尝试在可能的情况下对 x87 模拟使用 float。',
                                         '1': '仅对 x87 模拟使用 Double。',
                                         '2': '在 x87 模拟中检查精度控制的低精度。'}},
 'BOX64_EMULATED_LIBS': {'description': '强制使用模拟库。',
                         'options': {'XXXX': '强制使用模拟库 XXXX。', 'XXXX:YYYY:ZZZZ': '强制使用模拟库 XXXX、YYYY 和 ZZZZ。'}},
 'BOX64_ENV': {'description': '添加环境变量。', 'options': {'XXXX=yyyy': '添加值为 yyyy 的环境变量 XXXX。'}},
 'BOX64_ENV[1-5]': {'description': '添加环境变量。', 'options': {'XXXX=yyyy': '添加值为 yyyy 的环境变量 XXXX。'}},
 'BOX64_EXIT': {'description': '直接退出，不运行程序。', 'options': {'0': '不执行任何操作。', '1': '直接退出。'}},
 'BOX64_FIX_64BIT_INODES': {'description': '修复 64 位 inode。',
                            'options': {'0': '不修复 64 位 inode。', '1': '修复 64 位 inode。'}},
 'BOX64_FORCE_LD_PRELOAD': {'description': '是否强制 BOX64_LD_PRELOAD 库中的符号通过 RTLD_NEXT 解析。',
                            'options': {'0': '不执行任何操作。', '1': '强制 BOX64_LD_PRELOAD 库中的符号通过 RTLD_NEXT 解析。'}},
 'BOX64_IGNOREINT3': {'description': '忽略 INT3 指令。', 'options': {'0': '如果存在处理器则触发 TRAP 信号。', '1': '静默跳过该指令。'}},
 'BOX64_INPROCESSGPU': {'description': '向目标程序添加 --in-process-gpu 参数。',
                        'options': {'0': '不执行任何操作。', '1': '向目标程序添加 --in-process-gpu 参数。'}},
 'BOX64_INSERT_ARGS': {'description': '在命令行前添加参数。',
                       'options': {'XXXX': '在程序前添加参数 XXXX。', 'XXXX YYYY ZZZZ': '在目标程序前添加参数 XXXX、YYYY 和 ZZZZ。'}},
 'BOX64_JITGDB': {'description': '发生 SIGSEGV、SIGILL 和 SIGBUS 时是否启动 gdb。',
                  'options': {'0': '捕获信号时仅打印消息。',
                              '1': '当捕获到 SIGSEGV、SIGILL 或 SIGBUS 信号时启动 gdb，附加到有问题的进程并进入无限循环等待。在 gdb '
                                   '中，你需要自己找到正确的线程（在其堆栈中有 `my_box64signalhandler` 的线程），然后可能需要 `finish` 1 或 2 个函数（在 '
                                   '`usleep(..)` 内部），之后你将进入 `my_box64signalhandler`，就在 Segfault 消息的 printf 之前。然后 `set '
                                   'waiting=0` 退出无限循环。',
                              '2': '当捕获到 SIGSEGV、SIGILL 或 SIGBUS 信号时启动 gdbserver，附加到有问题的进程，并进入无限循环等待。使用 `gdb '
                                   '/PATH/TO/box64` 然后 `target remote 127.0.0.1:1234` 连接到 gdbserver（如果不在本机，则使用实际 '
                                   'IP）。之后的操作步骤与 `BOX64_JITGDB=1` 相同。',
                              '3': '当捕获到 SIGSEGV、SIGILL 或 SIGBUS 信号时启动 lldb，附加到有问题的进程并进入无限循环等待。'}},
 'BOX64_JVM': {'description': '检测 libjvm 并应用保守设置。',
               'options': {'0': '不执行任何操作。',
                           '1': '检测 libjvm，并在检测到时应用 BOX64_DYNAREC_BIGBLOCK=0 BOX64_DYNAREC_强内存模型=1 BOX64_SSE42=0。'}},
 'BOX64_LD_LIBRARY_PATH': {'description': '查找 x86_64 库的路径。', 'options': {'XXXX': '将路径 XXXX 添加到库搜索路径。'}},
 'BOX64_LD_PRELOAD': {'description': '强制随二进制文件加载库。',
                      'options': {'XXXX': '强制加载库 XXXX。', 'XXXX:YYYY': '强制加载库 XXXX 和 YYYY。'}},
 'BOX64_LIBCEF': {'description': '检测 libcef 并应用 BOX64_MALLOC_HACK 设置。',
                  'options': {'0': '不执行任何操作。', '1': '检测 libcef，并在检测到时应用 BOX64_MALLOC_HACK=2。'}},
 'BOX64_LIBGL': {'description': '设置 libGL 的名称。',
                 'options': {'/path/to/libXXXX': '将 libGL 的名称和路径设置为 /path/to/libXXXX，你也可以使用 SDL_VIDEO_GL_DRIVER。',
                             'libXXXX': '将 libGL 的名称设置为 libXXXX。'}},
 'BOX64_LOAD_ADDR': {'description': '设置程序加载的地址，仅对 PIE 目标程序有效。', 'options': {'0xXXXXXXXX': '设置程序加载的地址。'}},
 'BOX64_LOG': {'description': '启用或禁用 Box64 日志，如果 stdout 不是终端则默认为 0，否则为 1。',
               'options': {'0': '禁用 Box64 日志。',
                           '1': '启用最小级别的 Box64 日志。',
                           '2': '启用调试级别的 Box64 日志。',
                           '3': '启用详细级别的 Box64 日志。'}},
 'BOX64_MALLOC_HACK': {'description': '挂钩 malloc 操作符时的行为。',
                       'options': {'0': '不允许重定向 malloc 操作符，重写代码使用常规函数。',
                                   '1': '允许重定向 malloc 操作符。',
                                   '2': '与 0 类似，但追踪特殊的 mmap/free（某些内联的重定向函数无法被重定向）。'}},
 'BOX64_MAXCPU': {'description': '暴露的最大 CPU 核心数。', 'options': {'0': '使用实际的 CPU 核心数。', 'XXXX': '使用 XXXX 个 CPU 核心。'}},
 'BOX64_MMAP32': {'description': '在运行 32 位代码的 64 位程序（如 Wine WOW64）上强制使用 32 位兼容的内存映射，可提高性能。',
                  'options': {'0': '不强制使用 32 位内存映射。', '1': '强制使用 32 位内存映射。'}},
 'BOX64_NOBANNER': {'description': '禁用 Box64 横幅。', 'options': {'0': '显示 Box64 横幅。', '1': '不显示 Box64 横幅。'}},
 'BOX64_NODYNAREC': {'description': '在指定的地址范围内禁止创建代码块，有助于调试 DynaRec 和解释器之间的行为差异。',
                     'options': {'0xXXXXXXXX-0xYYYYYYYY': '定义禁止创建代码块 的范围（左闭右开）。'}},
 'BOX64_NODYNAREC_DELAY': {'description': '延迟后移除 NoDynaRec 范围。',
                           'options': {'0': '不移除 NoDynaRec 范围。', '1': '创建 2 个线程后移除 NoDynaRec 范围。'}},
 'BOX64_NOGTK': {'description': '不加载包装的 GTK 库。', 'options': {'0': '加载包装的 GTK 库。', '1': '不加载包装的 GTK 库。'}},
 'BOX64_NOPERSONA32BITS': {'description': '禁用 32 位二进制文件的自动 personality 切换（在 Box32 上始终启用）。',
                           'options': {'0': '为 32 位二进制文件切换 personality（如果尚未尝试）。', '1': '不为 32 位二进制文件切换 personality。'}},
 'BOX64_NOPULSE': {'description': '不加载 PulseAudio 库（原生库和模拟库均不加载）。',
                   'options': {'0': '加载 PulseAudio 库。', '1': '不加载 PulseAudio 库。'}},
 'BOX64_NORCFILES': {'description': '不加载任何 rc 文件。', 'options': {'0': '加载 rc 文件。', '1': '不加载任何 rc 文件。'}},
 'BOX64_NOSANDBOX': {'description': '向目标程序添加 --no-sandbox 参数。',
                     'options': {'0': '不执行任何操作。', '1': '向目标程序添加 --no-sandbox 参数。'}},
 'BOX64_NOSIGILL': {'description': '禁用 SIGILL 的处理。',
                    'options': {'0': '允许 x86 程序为 SIGILL 设置信号处理器。', '1': '禁用 SIGILL 的处理。'}},
 'BOX64_NOSIGSEGV': {'description': '禁用 SIGSEGV 的处理。',
                     'options': {'0': '允许 x86 程序为 SIGSEGV 设置信号处理器。', '1': '禁用 SIGSEGV 的处理。'}},
 'BOX64_NOVULKAN': {'description': '不加载 Vulkan 库。', 'options': {'0': '加载 Vulkan 库。', '1': '不加载 Vulkan 库，原生库和模拟库均不加载。'}},
 'BOX64_NOVULKANOVERLAY': {'description': '不加载 x64 Vulkan 覆盖层。',
                           'options': {'0': '尝试加载 x64 Vulkan 覆盖层。', '1': '不加载 x64 Vulkan 覆盖层。'}},
 'BOX64_PATH': {'description': '查找 x86_64 二进制文件的路径。', 'options': {'XXXX': '将路径 XXXX 添加到二进制搜索路径。'}},
 'BOX64_PCLMULQDQ': {'description': '暴露 PCLMULQDQ 能力。', 'options': {'0': '不暴露 PCLMULQDQ 能力。', '1': '暴露 PCLMULQDQ 能力。'}},
 'BOX64_PREFER_EMULATED': {'description': '优先使用模拟库而非原生库。', 'options': {'0': '优先使用原生库而非模拟库。', '1': '优先使用模拟库而非原生库。'}},
 'BOX64_PREFER_WRAPPED': {'description': '即使库使用绝对路径指定，也优先使用包装库。',
                          'options': {'0': '优先使用绝对路径指定的库而非包装库。', '1': '即使库使用绝对路径指定，也优先使用包装库。'}},
 'BOX64_PROFILE': {'description': '预定义的环境变量集合，以兼容性或性能为导向。',
                   'options': {'default': '大多数程序都能正常运行且性能适中的默认设置。',
                               'fast': '启用许多不安全的优化，但同时启用 强内存模型 模拟。',
                               'fastest': '启用许多不安全的优化以获得更好的性能。',
                               'safe': '比 safest 略不安全。',
                               'safest': '禁用所有不安全的 DynaRec 优化的配置文件。'}},
 'BOX64_PYTHON3': {'description': 'python3 可执行文件的路径。', 'options': {'XXXX': '使用路径为 XXXX 的 python3 可执行文件。'}},
 'BOX64_RCFILE': {'description': '要加载的 rc 文件路径。', 'options': {'XXXX': '加载 rc 文件 XXXX，不会加载默认的 rc 文件。'}},
 'BOX64_RDTSC_1GHZ': {'description': '如果可用，使用硬件计数器实现 rdtsc。',
                      'options': {'0': '如果可用，使用硬件计数器实现 rdtsc 指令。', '1': '仅当精度至少为 1GHz 时，使用硬件计数器实现 rdtsc。'}},
 'BOX64_RDTSC_INV': {'description': '在 Intel CPU 类型的 CPUID 中报告 Invariant TSC 位。',
                     'options': {'0': '不为 Intel CPU 类型报告 Invariant TSC（默认）。',
                                 '1': '在 Intel CPU 类型的 CPUID leaf 0x80000007 中报告 Invariant TSC 位。'}},
 'BOX64_RESERVE_HIGH': {'description': '为程序保留高内存区域，在 Box32 上始终启用。',
                        'options': {'0': '不为程序保留高内存区域。', '1': '为程序保留高内存区域。'}},
 'BOX64_ROLLING_LOG': {'description': '当捕获信号时显示最近几个包装函数调用。',
                       'options': {'0': '不执行任何操作。', '1': '捕获信号时显示最近 16 个包装函数调用。', 'XXXX': '捕获信号时显示最近 XXXX 个包装函数调用。'}},
 'BOX64_SDL2_JGUID': {'description': '对包装的 SDL2 使用 SDL_GetJoystickGUIDInfo 函数的变通方案。',
                      'options': {'0': '不执行任何操作。', '1': '对包装的 SDL2 使用 SDL_GetJoystickGUIDInfo 函数的变通方案。'}},
 'BOX64_SHAEXT': {'description': '暴露 SHAEXT（即 SHA_NI）能力。', 'options': {'0': '不暴露 SHAEXT 能力。', '1': '暴露 SHAEXT 能力。'}},
 'BOX64_SHOWBT': {'description': '捕获信号时显示原生和模拟的回溯。', 'options': {'0': '不执行任何操作。', '1': '捕获信号时显示原生和模拟的回溯。'}},
 'BOX64_SHOWSEGV': {'description': '始终显示 SIGSEGV 信号详情。', 'options': {'0': '不执行任何操作。', '1': '始终显示 SIGSEGV 信号详情。'}},
 'BOX64_SSE42': {'description': '暴露 SSE4.2 能力。', 'options': {'0': '不暴露 SSE4.2 能力。', '1': '暴露 SSE4.2 能力。'}},
 'BOX64_SSE_FLUSHTO0': {'description': 'SSE Flush to 0 FLAGS的行为，同时追踪 SSE 异常FLAGS。',
                        'options': {'0': '仅追踪FLAGS。',
                                    '1': '直接应用 SSE Flush to 0 FLAGS。同时在 DynaRec 中反映 SSE 异常FLAGS（如果可用）。'}},
 'BOX64_STEAM_VULKAN': {'description': '为 Linux Steam UI 强制使用 Vulkan。',
                        'options': {'0': '不执行任何操作。', '1': '为 Linux Steam UI 强制使用 Vulkan。'}},
 'BOX64_SYNC_ROUNDING': {'description': '在 x86 和原生之间同步舍入模式。', 'options': {'0': '不同步舍入模式。', '1': '在 x86 和原生之间同步舍入模式。'}},
 'BOX64_TRACE': {'description': '仅在带追踪功能的 box64 构建中可用。添加所有执行指令的追踪以及寄存器转储。',
                 'options': {'0': '禁用追踪输出。',
                             '0xXXXXXXX-0xYYYYYYY': '对指定地址范围（左闭右开）启用追踪输出。',
                             '1': '启用追踪输出。',
                             'symbolname': '仅对 `symbolname` 启用追踪输出。'}},
 'BOX64_TRACE_COLOR': {'description': '启用或禁用彩色追踪输出。', 'options': {'0': '禁用彩色追踪输出。', '1': '启用彩色追踪输出。'}},
 'BOX64_TRACE_EMM': {'description': '启用或禁用 EMM（即 MMX）追踪输出。', 'options': {'0': '禁用 EMM 追踪输出。', '1': '启用 EMM 追踪输出。'}},
 'BOX64_TRACE_FILE': {'description': '将所有日志和追踪发送到文件而非 `stdout`。',
                      'options': {'XXXX': '将所有日志和追踪发送到文件 XXXX。',
                                  'XXXX%pid': '将所有日志和追踪发送到文件 XXXX，文件名中附加 pid。',
                                  'stderr': '将所有日志和追踪发送到 `stderr`。',
                                  'stdout': '将所有日志和追踪发送到 `stdout`。'}},
 'BOX64_TRACE_INIT': {'description': '与 BOX64_TRACE 相同，但立即开始追踪。',
                      'options': {'0': '禁用追踪输出。',
                                  '0xXXXXXXX-0xYYYYYYY': '对指定地址范围（左闭右开）启用追踪输出。追踪在依赖项初始化之前开始。',
                                  '1': '启用追踪输出。追踪在依赖项初始化之前开始。',
                                  'symbolname': '仅对 `symbolname` 启用追踪输出。追踪在依赖项初始化之前开始。'}},
 'BOX64_TRACE_START': {'description': '在 N 个指令执行后开始追踪。',
                       'options': {'0': '立即开始追踪。', '1': '执行 1 个指令后开始追踪。', 'XXXX': '执行 XXXX 个指令后开始追踪。'}},
 'BOX64_TRACE_XMM': {'description': '启用或禁用 XMM（即 SSE）追踪输出。', 'options': {'0': '禁用 XMM 追踪输出。', '1': '启用 XMM 追踪输出。'}},
 'BOX64_UNITY': {'description': '告诉 Box64 这是一个 Unity 游戏。',
                 'options': {'0': '不执行任何操作。',
                             '1': '这是 Unity 游戏，对 Windows 使用特殊的检测代码，对 Linux 应用 BOX64_DYNAREC_强内存模型=1。'}},
 'BOX64_UNITYPLAYER': {'description': '检测 UnityPlayer 并应用保守设置。',
                       'options': {'0': '不执行任何操作。', '1': '检测 UnityPlayer（Windows 或 Linux），并在检测到时应用 BOX64_UNITY=1。'}},
 'BOX64_WRAP_EGL': {'description': '优先使用包装库处理 EGL 和 GLESv2。',
                    'options': {'0': '优先使用模拟库处理 EGL 和 GLESv2。', '1': '优先使用包装库处理 EGL 和 GLESv2。'}},
 'BOX64_X11GLX': {'description': '是否强制 Xorg GLX 扩展存在。',
                  'options': {'0': '不强制 Xorg GLX 扩展存在。', '1': '在使用 XQueryExtension 时要求 Xorg GLX 扩展存在。'}},
 'BOX64_X11SYNC': {'description': '是否强制 X11 显示同步操作。', 'options': {'0': '不强制 X11 显示同步操作。', '1': '强制 X11 显示同步操作。'}},
 'BOX64_X11THREADS': {'description': '加载 X11 时调用 XInitThreads。这主要用于使用 Loki_Compat 库的旧 Loki 游戏。',
                      'options': {'0': '不调用 XInitThreads。', '1': '一旦加载 libX11 就调用 XInitThreads。'}},
 'BOX64_X87_NO80BITS': {'description': 'x87 80 位 long double 的行为。',
                        'options': {'0': '尝试尽可能精确地处理 80 位 long double。', '1': '对 x87 使用 64 位 double。'}}}


def _load_module(name: str) -> types.ModuleType:
    module = types.ModuleType(name)
    module.__file__ = f"<box64-configurator:{name}>"
    module.__package__ = ""
    if name == "usage":
        module._EMBEDDED_USAGE_DATA = _EMBEDDED_USAGE_DATA
        module._EMBEDDED_USAGE_CN_DATA = _EMBEDDED_USAGE_CN_DATA
    sys.modules[name] = module
    exec(compile(_MODULES[name], module.__file__, "exec"), module.__dict__)
    return module


for _name in ("box64rc", "usage", "model"):
    _load_module(_name)

_app = types.ModuleType("box64_configurator_app")
_app.__file__ = __file__
_app.__package__ = ""
_app._EMBEDDED_TEXTS = _EMBEDDED_TEXTS
_app._EMBEDDED_UI = _EMBEDDED_UI
sys.modules["box64_configurator_app"] = _app
exec(compile(_MODULES["configurator"], __file__, "exec"), _app.__dict__)

if __name__ == "__main__":
    raise SystemExit(_app.main())
