#!/usr/bin/env bash clear # Gum theme export GUM_THEME="\ [\"ui\"] = { background = \"#000000\", foreground = \"#FFA500\" }\ [\"ui.focused\"] = { background = \"#FFA500\", foreground = \"#000000\" }\ [\"ui.text\"] = { foreground = \"#FFA500\" }\ [\"box\"] = { background = \"#000000\", foreground = \"#FFA500\", border = \"#FFA500\" }\ [\"box.border\"] = { foreground = \"#FFA500\" }\ " # FZF colors (orange highlight) export FZF_DEFAULT_OPTS="--color=fg:#FFA500,bg:#000000,hl:#FFA500,fg+:#000000,bg+:#FFA500,hl+:#000000,info:#FFA500,prompt:#FFA500,pointer:#FFA500,marker:#FFA500,spinner:#FFA500" title() { gum style \ --foreground="#FFA500" \ --background="#000000" \ --border-foreground="#FFA500" \ --border="double" \ --align="center" \ --width="50" \ --margin="1" \ --padding="2 4" \ "MEGADRIVE CART FLASH" } # ------------------------- # Dependencies # ------------------------- check_dependencies() { for cmd in flashkit fzf md5sum; do if ! command -v $cmd &> /dev/null; then gum confirm "$cmd is not installed. Install it now?" && { gum spin --spinner="line" --title="Installing $cmd..." -- sudo apt-get install -y $cmd } fi done if ! python3 -c "import serial" &> /dev/null; then gum confirm "pyserial is not installed. Install it now?" && { gum spin --spinner="line" --title="Installing pyserial..." -- python3 -m pip install pyserial } fi } # ------------------------- # Detect FTDI port # ------------------------- detect_port() { gum style --foreground="#FFA500" "Detecting flash cartridge..." if [ -d /dev/serial/by-id ]; then matches=($(ls /dev/serial/by-id/*FTDI* 2>/dev/null)) fi if [ ${#matches[@]} -eq 0 ]; then for dev in /dev/ttyUSB*; do [ -e "$dev" ] || continue if udevadm info --query=property --name="$dev" | grep -q "ID_VENDOR_ID=0403"; then matches+=("$dev") fi done fi if [ ${#matches[@]} -eq 0 ]; then gum style --foreground="#FFA500" "No FTDI flash device detected." exit 1 fi selected_port=$(readlink -f "${matches[0]}") gum style --foreground="#FFA500" "Using port: $selected_port" } # ------------------------- # Read cart # ------------------------- read_cart() { clear title gum style --foreground="#FFA500" "Checking current cartridge content..." check_output=$(flashkit --port "$selected_port" check 2>&1) gum style \ --foreground="#FFA500" \ --border="rounded" \ --border-foreground="#FFA500" \ --padding="1 2" \ "$check_output" } # ------------------------- # FZF file browser # ------------------------- browse_files() { find ~/ -type f -name "*.md" -size +256k 2>/dev/null \ | fzf \ --height=40% \ --reverse \ --border \ --prompt="Select ROM > " \ --preview 'echo Size: $(du -h {} | awk "{print \$1}"); echo MD5: $(md5sum {} | awk "{print \$1}")' } # ------------------------- # Write ROM # ------------------------- write_rom() { clear title rom_file=$(browse_files) [ -z "$rom_file" ] && { gum style --foreground="#FFA500" "No file selected." return } # File info rom_size=$(du -h "$rom_file" | cut -f1) rom_md5=$(md5sum "$rom_file" | cut -d ' ' -f1) gum style \ --foreground="#FFA500" \ --border="rounded" \ --border-foreground="#FFA500" \ --padding="1 2" \ "File: $(basename "$rom_file") Size: $rom_size MD5: $rom_md5" gum confirm "Write this ROM to $selected_port?" && { gum spin --spinner="line" --title="Writing ROM..." -- flashkit --port "$selected_port" write-rom -i "$rom_file" gum style --foreground="#FFA500" "Done! ROM written successfully." # Auto refresh read_cart } || { gum style --foreground="#FFA500" "Cancelled." } } # ------------------------- # Main # ------------------------- check_dependencies detect_port read_cart while true; do choice=$(gum choose \ --header="Select an option:" \ "Read Cart" \ "Write ROM" \ "Exit") case "$choice" in "Read Cart") read_cart ;; "Write ROM") write_rom ;; "Exit") gum style --foreground="#FFA500" "Goodbye." exit 0 ;; esac done