#!/usr/bin/env bash # diagnose_melonds.sh - Automated diagnostics for melonDS via GDB set -euo pipefail ELF_FILE="${1:-snakePlus.elf}" if [ ! -f "$ELF_FILE" ]; then if [ -f "build-debug/snakePlus.elf" ]; then ELF_FILE="build-debug/snakePlus.elf" elif [ -f "build/snakePlus.elf" ]; then ELF_FILE="build/snakePlus.elf" else echo "[-] Error: ELF file not found: $ELF_FILE" exit 1 fi fi # Locate arm-none-eabi-gdb GDB_BIN="arm-none-eabi-gdb" if [ -n "${DEVKITPRO:-}" ] && [ -x "${DEVKITPRO}/devkitARM/bin/arm-none-eabi-gdb" ]; then GDB_BIN="${DEVKITPRO}/devkitARM/bin/arm-none-eabi-gdb" elif ! command -v "$GDB_BIN" &>/dev/null; then echo "[-] Error: arm-none-eabi-gdb not found on PATH or DEVKITPRO." exit 1 fi echo "[*] Connecting to melonDS on localhost:3333 using $ELF_FILE..." # Run GDB in batch mode to gather CPU state GDB_OUTPUT=$("$GDB_BIN" "$ELF_FILE" --batch \ -ex "set confirm off" \ -ex "set pagination off" \ -ex "target remote localhost:3333" \ -ex "info registers" \ -ex "x/x 0x02fffd98" \ -ex "x/x 0x02fffd90" \ -ex "detach" \ -ex "quit" 2>&1 || true) if echo "$GDB_OUTPUT" | grep -q "Connection refused"; then echo "[-] Could not connect to localhost:3333. Ensure melonDS is running with GDB enabled." exit 1 fi echo "=== Registers ===" echo "$GDB_OUTPUT" | grep -E "^(r0|r4|r8|r12|sp|lr|pc|cpsr)" || true PC=$(echo "$GDB_OUTPUT" | awk '/^pc/ {print $2}') SP=$(echo "$GDB_OUTPUT" | awk '/^sp/ {print $2}') echo "" echo "=== CPU Analysis ===" echo "Current PC: $PC" echo "Current SP: $SP" if [ "$PC" = "0x1ff8594" ] || [ "$PC" = "0x01ff8594" ]; then echo "[!] CPU is trapped in __excpt_entry (Fatal Exception / Data Abort / Prefetch Abort)!" FAULT_ADDR=$(echo "$GDB_OUTPUT" | awk '/0x2fffd98:/ {print $2}') FAULT_SPSR=$(echo "$GDB_OUTPUT" | awk '/0x2fffd90:/ {print $2}') echo " Faulted Instruction Address (lr_abt - 8): $FAULT_ADDR" echo " Faulted SPSR: $FAULT_SPSR" if [ -n "$FAULT_ADDR" ] && [ "$FAULT_ADDR" != "0x0" ]; then echo "=== Source Location ===" "$GDB_BIN" "$ELF_FILE" --batch \ -ex "info line *$FAULT_ADDR" \ -ex "quit" 2>&1 | grep -v "^(gdb)" || true fi elif [ "$PC" = "0x1ff84ec" ] || [ "$PC" = "0x01ff84ec" ]; then echo "[+] CPU is sleeping in armWaitForIrq (Normal running state waiting for VBlank/Timer IRQ)." else echo "[*] CPU is running user code at $PC." "$GDB_BIN" "$ELF_FILE" --batch \ -ex "info line *$PC" \ -ex "quit" 2>&1 | grep -v "^(gdb)" || true fi