Skip to content

Instantly share code, notes, and snippets.

@zx0r
Last active June 2, 2025 17:31
Show Gist options
  • Save zx0r/e0f8c7c8a178163a8c62cdd554101ec3 to your computer and use it in GitHub Desktop.
Save zx0r/e0f8c7c8a178163a8c62cdd554101ec3 to your computer and use it in GitHub Desktop.
DSDT Analyser dor Hackintosh
license_text = """
License for Free Use with No Commercial Use
Copyright (c) 2025 spakk
Permission is hereby granted to any person obtaining a copy of this software and associated documentation files
to use the software free of charge and without restriction, including the rights to use, copy, modify, and
distribute the software, but strictly for non-commercial purposes only.
Restrictions:
The software may not be used for commercial purposes, meaning not for direct or indirect financial gain.
Any use aimed at commercial exploitation is prohibited without the express written consent of the copyright holder.
Disclaimer:
The software is provided "as is," without any express or implied warranty, including but not limited to the
warranties of merchantability or fitness for a particular purpose. In no event shall the authors or copyright
holders be liable for any damages arising from the use or inability to use the software.
"""
# -*- coding: utf-8 -*-
import os
import re
import shutil
import subprocess
from pathlib import Path
import tkinter as tk
from tkinter import filedialog, messagebox, scrolledtext
import locale
import gettext
# Einfache Übersetzungen (du kannst beliebig viele Sprachen ergänzen)
translations = {
"en": {
"OC & Clover DSDT Analyzer & SSDT-Force Generator": "OC & Clover DSDT Analyzer & SSDT-Force Generator",
"DSDT.aml auswählen": "Select DSDT.aml",
"Decompile DSDT.aml (iasl)": "Decompile DSDT.aml (iasl)",
"Analyse (If & Device)": "Analyze (If & Device)",
"SSDT-Force erstellen": "Generate SSDT-Force",
"OpenCore Patch erstellen": "Generate OpenCore Patch",
"Alle Critical Devices prüfen": "Check All Critical Devices",
"Individuelle SSDTs erzeugen": "Generate Individual SSDTs",
"✔ Decompilation erfolgreich.": "✔ Decompilation successful.",
"✘ Fehler: iasl.exe nicht gefunden. Bitte im Skriptordner oder System-PATH ablegen.": "✘ Error: iasl.exe not found. Please place it in the script folder or add it to the system PATH.",
}
# Sprache des Systems ermitteln
lang = locale.getdefaultlocale()[0]
lang = lang.split("_")[0] if lang else "en"
if lang not in translations:
lang = "en" # Fallback
# Übersetzungsfunktion
def _(text):
return translations.get(lang, {}).get(text, text)
# --- Internationalisierung (i18n) vorbereiten ---
localedir = Path(__file__).parent / "locales"
lang, _ = locale.getdefaultlocale()
if lang:
lang = lang.split('_')[0]
else:
lang = "en"
try:
t = gettext.translation("messages", localedir=localedir, languages=[lang])
t.install()
_ = t.gettext
except FileNotFoundError:
_ = gettext.gettext
# --- Konfiguration ---
iasl_exe = "iasl.exe" # iasl.exe muss im Systempfad oder Skriptordner liegen
download_dir = Path.home() / "Downloads" / "DSDT-Analysis-Tool_dsdt"
download_dir.mkdir(parents=True, exist_ok=True)
critical_devices = {"HDEF", "HDAS", "GFX0", "IGPU", "VGA", "SAT0", "GLAN", "SBUS", "XHC", "XDCI"}
# --- Hilfsfunktionen ---
def evaluate_condition(cond_str):
# Placeholder für komplexe Evaluation (zurzeit nur Markierung)
return _("✔ {cond} (nicht evaluiert)").format(cond=cond_str)
def analyze_conditionals(dsdt_dsl_path):
conditional_info = []
devices_found = []
seen_devices = set()
with open(dsdt_dsl_path, "r", encoding="utf-8") as f:
lines = f.readlines()
pattern_if = re.compile(r"^\s*If\s*\((.+)\)")
pattern_device = re.compile(r"^\s*Device\s+\((\w+)\)")
for i, line in enumerate(lines):
m_if = pattern_if.search(line)
if m_if:
condition = m_if.group(1).strip()
# Max 15 Zeilen nach Device durchsuchen
for j in range(i + 1, min(i + 16, len(lines))):
m_dev = pattern_device.search(lines[j])
if m_dev:
dev = m_dev.group(1)
if dev not in seen_devices:
eval_result = evaluate_condition(condition)
conditional_info.append((i + 1, condition, eval_result, dev))
devices_found.append(dev)
seen_devices.add(dev)
break
return conditional_info, devices_found
def generate_ssdt_force(devices, output_path):
lines = [
'DefinitionBlock ("", "SSDT", 2, "HACK", "Force", 0x00000001)',
'{',
' External (_SB_, DeviceObj)',
]
for dev in devices:
lines.append(f" External (_SB.{dev}, DeviceObj)")
for dev in devices:
lines.append(f"""
Scope (_SB)
{{
Device ({dev})
{{
Name (_HID, "{dev}0000") // Dummy HID to force
}}
}}
""")
lines.append("}")
with open(output_path, "w", encoding="utf-8") as f:
f.write("\n".join(lines))
def generate_oc_patches(devices, output_path):
patch_lines = [
"# OpenCore ACPI Patch Template",
"# Automatically generated\n"
]
for dev in devices:
patch_lines.append(f"Patch for device label {dev}: set_label X{dev}")
with open(output_path, "w", encoding="utf-8") as f:
f.write("\n".join(patch_lines))
def generate_conditional_devices_txt(devices, output_path):
with open(output_path, "w", encoding="utf-8") as f:
f.write("# Found conditional devices\n")
for dev in sorted(set(devices)):
f.write(dev + "\n")
def warn_missing_critical_devices(found_devices):
missing = critical_devices - set(found_devices)
if missing:
return "\n⚠️ " + _("Critical devices missing:") + "\n" + "\n".join(f" - {d}" for d in sorted(missing))
return ""
def run_iasl(dsdt_aml_path, log_func):
iasl_path = shutil.which("iasl.exe") or shutil.which("iasl") or (Path(__file__).parent / "iasl.exe")
if not iasl_path or not Path(iasl_path).is_file():
log_func(_("✘ Fehler: iasl.exe nicht gefunden. Bitte im Skriptordner oder System-PATH ablegen."))
return False
iasl_path = Path(iasl_path)
try:
# *** Korrektur hier: cwd muss Ordner sein, nicht Datei ***
subprocess.run(
[str(iasl_path), "-d", str(dsdt_aml_path)],
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
cwd=dsdt_aml_path.parent # <-- Korrektur: Ordner der AML-Datei
)
log_func(_("✔ Decompilation erfolgreich."))
return True
except subprocess.CalledProcessError as e:
log_func(_("✘ Fehler: iasl.exe Ausführung fehlgeschlagen."))
log_func(e.stderr)
return False
except Exception as e:
log_func(_("✘ Unerwarteter Fehler bei Ausführung von iasl.exe: ") + str(e))
return False
def check_all_devices_in_dsdt(dsdt_dsl_path, output_path):
with open(dsdt_dsl_path, "r", encoding="utf-8") as f:
content = f.read()
found_devices = set(re.findall(r"Device\s+\((\w+)\)", content))
missing = critical_devices - found_devices
with open(output_path, "w", encoding="utf-8") as f:
f.write(_("Critical devices – Full analysis:\n\n"))
for dev in sorted(critical_devices):
status = _("✔ gefunden") if dev in found_devices else _("✘ fehlt")
f.write(f"{dev}: {status}\n")
return missing
def generate_individual_ssdts(devices, out_folder, log_func):
out_folder.mkdir(parents=True, exist_ok=True)
iasl_path = shutil.which("iasl.exe") or shutil.which("iasl") or (Path(__file__).parent / "iasl.exe")
if not iasl_path or not Path(iasl_path).is_file():
log_func(_("✘ iasl.exe nicht gefunden zum Kompilieren individueller SSDTs."))
return
iasl_path = Path(iasl_path)
for dev in devices:
ssdt = [
f'DefinitionBlock ("", "SSDT", 2, "DRVN", "XXX_{dev}", 0x00000000)',
"{",
f" External (_SB_.{dev}, DeviceObj)",
" Scope (_SB)",
" {",
f" Device ({dev})",
" {",
' Name (_HID, "FAKE0000")',
" }",
" }",
"}"
]
ssdt_dsl_path = out_folder / f"SSDT-XXX-{dev}.dsl"
ssdt_aml_path = out_folder / f"SSDT-XXX-{dev}.aml"
with open(ssdt_dsl_path, "w", encoding="utf-8") as f:
f.write("\n".join(ssdt))
try:
result = subprocess.run(
[str(iasl_path), str(ssdt_dsl_path)],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
check=True,
cwd=out_folder
)
except subprocess.CalledProcessError as e:
log_func(f"✘ Fehler bei der Kompilierung von {ssdt_dsl_path.name}:")
log_func(e.stderr)
else:
if ssdt_aml_path.exists():
log_func(f"✔ Erstellt: {ssdt_aml_path.name}")
else:
log_func(f"✘ Fehlgeschlagen: {ssdt_aml_path.name}")
# --- Tkinter GUI Klasse ---
class DSDTApp(tk.Tk):
def __init__(self):
super().__init__()
self.title(_("OC & Clover DSDT Analyzer & SSDT-Force Generator"))
self.geometry("800x700")
header_frame = tk.Frame(self)
header_frame.pack(fill=tk.X, pady=5)
self.label_toolname = tk.Label(
header_frame,
text="OC & Clover DSDT Analyzer & SSDT-Force Generator",
font=("TkDefaultFont", 18, "bold"),
fg="blue"
)
self.label_toolname.pack()
self.label_link = tk.Label(
header_frame,
text="#spakk# - https://www.insanelymac.com",
font=("TkDefaultFont", 12, "italic"),
fg="darkblue",
cursor="hand2"
)
self.label_link.pack()
self.label_link.bind("<Button-1>", lambda e: os.system("open https://github.com/packiyam/dsdt_analyzer"))
btn_frame = tk.Frame(self)
btn_frame.pack(pady=5, fill=tk.X)
self.btn_select_aml = tk.Button(btn_frame, text=_("DSDT.aml auswählen"), command=self.select_dsdt_aml)
self.btn_select_aml.pack(side=tk.LEFT, padx=5)
self.btn_decompile = tk.Button(btn_frame, text=_("Decompile DSDT.aml (iasl)"), command=self.decompile_dsdt)
self.btn_decompile.pack(side=tk.LEFT, padx=5)
self.btn_decompile["state"] = "disabled"
self.btn_analyze = tk.Button(btn_frame, text=_("Analyse (If & Device)"), command=self.analyze_dsdt)
self.btn_analyze.pack(side=tk.LEFT, padx=5)
self.btn_analyze["state"] = "disabled"
self.btn_generate_force_ssdt = tk.Button(btn_frame, text=_("SSDT-Force erstellen"), command=self.generate_ssdt_force)
self.btn_generate_force_ssdt.pack(side=tk.LEFT, padx=5)
self.btn_generate_force_ssdt["state"] = "disabled"
self.btn_generate_oc_patch = tk.Button(btn_frame, text=_("OpenCore Patch erstellen"), command=self.generate_oc_patch)
self.btn_generate_oc_patch.pack(side=tk.LEFT, padx=5)
self.btn_generate_oc_patch["state"] = "disabled"
self.btn_check_full_devices = tk.Button(btn_frame, text=_("Alle Critical Devices prüfen"), command=self.check_full_devices)
self.btn_check_full_devices.pack(side=tk.LEFT, padx=5)
self.btn_check_full_devices["state"] = "disabled"
self.btn_generate_individual_ssdt = tk.Button(btn_frame, text=_("Individuelle SSDTs erzeugen"), command=self.generate_individual_ssdts)
self.btn_generate_individual_ssdt.pack(side=tk.LEFT, padx=5)
self.btn_generate_individual_ssdt["state"] = "disabled"
self.text_output = scrolledtext.ScrolledText(self, width=100, height=30)
self.text_output.pack(padx=5, pady=5, fill=tk.BOTH, expand=True)
self.dsdt_aml_path = None
self.dsdt_dsl_path = None
self.devices_found = []
def log(self, msg):
self.text_output.insert(tk.END, msg + "\n")
self.text_output.see(tk.END)
def select_dsdt_aml(self):
file = filedialog.askopenfilename(
title=_("Wähle DSDT.aml"),
filetypes=[("AML Dateien", "*.aml"), ("Alle Dateien", "*.*")]
)
if not file:
return
self.dsdt_aml_path = Path(file)
self.log(_("DSDT.aml ausgewählt: ") + str(self.dsdt_aml_path))
self.btn_decompile["state"] = "normal"
self.btn_analyze["state"] = "disabled"
self.btn_generate_force_ssdt["state"] = "disabled"
self.btn_generate_oc_patch["state"] = "disabled"
self.btn_check_full_devices["state"] = "disabled"
self.btn_generate_individual_ssdt["state"] = "disabled"
self.text_output.delete(1.0, tk.END)
def decompile_dsdt(self):
if not self.dsdt_aml_path or not self.dsdt_aml_path.exists():
self.log(_("✘ Keine gültige DSDT.aml ausgewählt."))
return
out_dsl = self.dsdt_aml_path.with_suffix(".dsl")
self.log(_("Starte Decompilierung..."))
success = run_iasl(self.dsdt_aml_path, self.log)
if success and out_dsl.exists():
self.dsdt_dsl_path = out_dsl
self.log(_("Decompilierte Datei: ") + str(out_dsl))
self.btn_analyze["state"] = "normal"
else:
self.log(_("✘ Decompilierung fehlgeschlagen."))
self.btn_analyze["state"] = "disabled"
def analyze_dsdt(self):
if not self.dsdt_dsl_path or not self.dsdt_dsl_path.exists():
self.log(_("✘ Keine dekompilierte DSDT (DSL) verfügbar."))
return
self.log(_("Analysiere bedingte If-Device-Blöcke..."))
cond_info, devices = analyze_conditionals(self.dsdt_dsl_path)
self.devices_found = devices
self.text_output.delete(1.0, tk.END)
for (line_num, cond, eval_res, dev) in cond_info:
self.log(f"Zeile {line_num}: If ({cond}) -> {eval_res} (Device {dev})")
self.log(warn_missing_critical_devices(devices))
self.btn_generate_force_ssdt["state"] = "normal"
self.btn_generate_oc_patch["state"] = "normal"
self.btn_check_full_devices["state"] = "normal"
self.btn_generate_individual_ssdt["state"] = "normal"
# Optional: Schreiben der Devices in Datei
dev_txt = self.dsdt_dsl_path.parent / "conditional_devices.txt"
generate_conditional_devices_txt(devices, dev_txt)
self.log(_("Gefundene Geräte in Datei gespeichert: ") + str(dev_txt))
def generate_ssdt_force(self):
if not self.devices_found:
self.log(_("✘ Keine Geräte zum Erzeugen einer SSDT-Force."))
return
out_file = self.dsdt_dsl_path.parent / "SSDT-Force.dsl"
generate_ssdt_force(self.devices_found, out_file)
self.log(_("SSDT-Force erstellt: ") + str(out_file))
def generate_oc_patch(self):
if not self.devices_found:
self.log(_("✘ Keine Geräte zum Erzeugen eines OpenCore-Patches."))
return
out_file = self.dsdt_dsl_path.parent / "OpenCore-Patch.txt"
generate_oc_patches(self.devices_found, out_file)
self.log(_("OpenCore-Patch erstellt: ") + str(out_file))
def check_full_devices(self):
if not self.dsdt_dsl_path or not self.dsdt_dsl_path.exists():
self.log(_("✘ Dekomplilierte DSDT (DSL) wird benötigt."))
return
out_file = self.dsdt_dsl_path.parent / "full_device_check.txt"
missing = check_all_devices_in_dsdt(self.dsdt_dsl_path, out_file)
self.log(_("Geräte-Check abgeschlossen. Ergebnis in: ") + str(out_file))
if missing:
self.log(_("⚠️ Fehlende Critical Devices: ") + ", ".join(missing))
else:
self.log(_("Alle Critical Devices gefunden."))
def generate_individual_ssdts(self):
if not self.devices_found:
self.log(_("✘ Keine Geräte zum Erzeugen individueller SSDTs."))
return
out_folder = self.dsdt_dsl_path.parent / "Individual_SSDTs"
generate_individual_ssdts(self.devices_found, out_folder, self.log)
if __name__ == "__main__":
app = DSDTApp()
app.mainloop()
@zx0r
Copy link
Author

zx0r commented Jun 2, 2025

	• Install Tkinter:
	• Ubuntu/Debian: sudo apt install python3-tk
	• macOS: brew install python-tk

	• Install iasl (ACPI compiler):
	• Linux: sudo apt install acpica-tools
	• macOS: brew install iasl
	• Run:
  python3 dsdt_analyser.py

	• How to use:
	• Select your DSDT.aml file when prompted.
	• Use the GUI buttons to decompile, analyze conditionals, check devices, and generate SSDTs or OpenCore patches.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment