Game / editor prototyping with Godot
at main 121 lines 3.1 kB view raw
1# QEMURunner.gd 2# Alpine Linux ARM64 QEMU Runner as a Node 3# Add to your scene and call run_vm() 4 5extends Node 6 7# Configuration 8const ALP_ARCH = "aarch64" 9const PORT = "2221" 10var DISK_NAME = "alpine.%s.qcow2" % ALP_ARCH 11 12# Working directory - qemu/ folder in project root 13var working_dir: String = "" 14 15@export var run_button: Button 16@export var code_edit: CodeEdit 17 18signal vm_started() 19signal vm_stopped(exit_code: int) 20signal vm_error(error_message: String) 21 22var qemu_pid: int = -1 23 24func handle_run(): 25 print(code_edit.text) 26 27func _ready(): 28 # Set working directory to PROJECT_ROOT/qemu/ 29 working_dir = ProjectSettings.globalize_path("res://qemu/") 30 print("QEMU working directory: %s" % working_dir) 31 32 # Create qemu directory if it doesn't exist 33 if not DirAccess.dir_exists_absolute(working_dir): 34 DirAccess.make_dir_recursive_absolute(working_dir) 35 print("Created qemu directory: %s" % working_dir) 36 37 run_vm() 38 39 run_button.button_up.connect(handle_run) 40 41func _exit_tree() -> void: 42 stop_vm() 43 44func check_file_exists(filename: String) -> bool: 45 """Check if required file exists in working directory""" 46 var full_path = working_dir.path_join(filename) 47 print(full_path) 48 if not FileAccess.file_exists(full_path): 49 print("Error: %s not found!" % full_path) 50 return false 51 return true 52 53func run_vm(): 54 print("Alpine Linux ARM64 QEMU Runner") 55 print() 56 57 # Check required files 58 var required_files = [ 59 "AAVMF_CODE.fd", 60 DISK_NAME 61 ] 62 63 var missing_files = [] 64 for file in required_files: 65 if not check_file_exists(file): 66 missing_files.append(file) 67 68 if not missing_files.is_empty(): 69 print("\nMissing required files:") 70 for file in missing_files: 71 print(" - %s" % file) 72 print("\nPlease run the setup script first to create these files.") 73 vm_error.emit("Missing required files: " + str(missing_files)) 74 return 75 76 # Display connection info 77 print("Starting Alpine Linux VM...") 78 print("SSH Port: %s" % PORT) 79 print("Connect with: ssh -p %s <username>@localhost" % PORT) 80 print() 81 print("To exit QEMU: Press Ctrl+A then X") 82 print() 83 84 # Build QEMU command 85 var qemu_cmd = PackedStringArray([ 86 "qemu-system-aarch64", 87 "-accel", "tcg,thread=multi", 88 "-machine", "virt", 89 "-cpu", "cortex-a53", 90 "-smp", "cores=1", 91 "-m", "512", 92 "-bios", working_dir.path_join("AAVMF_CODE.fd"), 93 "-nographic", 94 "-drive", "if=virtio,id=hd,format=qcow2,file=%s" % working_dir.path_join(DISK_NAME), 95 "-nic", "user,hostfwd=tcp::%s-:22,model=virtio" % PORT, 96 "-device", "virtio-rng-pci", 97 "-rtc", "base=utc,clock=host", 98 "-s" 99 ]) 100 101 # Run QEMU 102 vm_started.emit() 103 104 qemu_pid = OS.create_process(qemu_cmd[0], qemu_cmd.slice(1)) 105 106 if qemu_pid == -1: 107 print("\nError: qemu-system-aarch64 not found in PATH") 108 print("Please install QEMU for Windows: https://qemu.weilnetz.de/w64/") 109 print("Make sure qemu-system-aarch64 is in your system PATH") 110 vm_error.emit("Failed to start QEMU process") 111 return 112 113 print("QEMU started with PID: %d" % qemu_pid) 114 115func stop_vm(): 116 print("Attempting to kill QEMU") 117 if qemu_pid != -1: 118 OS.kill(qemu_pid) 119 print("QEMU stopped") 120 vm_stopped.emit(0) 121 qemu_pid = -1