Skip to content

Instantly share code, notes, and snippets.

@drzo1dberg
Created November 16, 2025 20:09
Show Gist options
  • Select an option

  • Save drzo1dberg/4efbea837c08dde3785762c032f3789c to your computer and use it in GitHub Desktop.

Select an option

Save drzo1dberg/4efbea837c08dde3785762c032f3789c to your computer and use it in GitHub Desktop.
Get License and Key for Citron Emulator Script
#!/bin/bash
# Simplified script for downloading and setting up keys and firmware for Citron emulator only
set -e # Exit on any error
# ============================================================================
# CONFIGURATION
# ============================================================================
# Citron configuration
CITRON_LINUX_BASE="$HOME/.local/share/citron"
CITRON_WINDOWS_BASE="$APPDATA/citron"
# ============================================================================
# END CONFIGURATION
# ============================================================================
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# Global variables
SKIP_KEYS=false
CUSTOM_DIR=""
KEYS_VERSION=""
INSTALL_DIR=""
OS=""
ARCH=""
print_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
print_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# ============================================================================
# FIRMWARE AND KEYS FUNCTIONS
# ============================================================================
fetch_firmware_tags() {
local tags_json
if ! tags_json=$(curl -sL "https://api.github.com/repos/THZoria/NX_Firmware/tags"); then
return 1
fi
echo "$tags_json" | grep -oE '"name"[[:space:]]*:[[:space:]]*"[^\"]*"' | cut -d'"' -f4
}
get_firmware_versions() {
print_info "Fetching available firmware/key versions from GitHub..."
local versions
if ! versions=$(fetch_firmware_tags); then
print_warning "Failed to fetch version tags from GitHub API"
return 1
fi
if [[ -z "$versions" ]]; then
print_warning "No versions found in GitHub tags response"
return 1
fi
print_info "Available versions:"
echo "$versions"
print_info "re-run the script with --keys-version <version>"
return 0
}
get_latest_firmware_version() {
local versions latest_version
if ! versions=$(fetch_firmware_tags); then
print_warning "Failed to fetch version tags from GitHub API"
return 1
fi
latest_version=$(echo "$versions" | head -1)
if [[ -z "$latest_version" ]]; then
print_warning "No versions found in GitHub tags response"
return 1
fi
echo "$latest_version"
return 0
}
ensure_keys_version() {
if [[ -z "$KEYS_VERSION" ]]; then
if ! KEYS_VERSION=$(get_latest_firmware_version); then
print_error "Failed to determine firmware version"
exit 1
fi
print_info "Using latest firmware version: $KEYS_VERSION"
else
print_info "Using firmware version: $KEYS_VERSION"
fi
}
usage() {
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " -s, --skip-keys Skip downloading prod.keys and firmware"
echo " -d, --dir DIR Specify custom Citron installation directory"
echo " -v, --keys-version VER Specify prod.keys / firmware version (e.g. 20.3.0)."
echo " If omitted the script will use the latest version."
echo " -h, --help Show this help message"
echo ""
echo "Examples:"
echo " $0"
echo " $0 --skip-keys"
echo " $0 -d /opt/citron"
echo " $0 -v 20.3.0"
exit 1
}
while [[ $# -gt 0 ]]; do
case $1 in
-s|--skip-keys)
SKIP_KEYS=true
shift
;;
-d|--dir)
CUSTOM_DIR="$2"
shift 2
;;
-v|--keys-version)
if [[ -z "$2" || "$2" == -* ]]; then
print_warning "No version provided for --keys-version"
get_firmware_versions || true
exit 1
fi
KEYS_VERSION="$2"
shift 2
;;
-h|--help)
usage
;;
*)
echo "Unknown option: $1"
usage
;;
esac
done
detect_os() {
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
OS="linux"
ARCH=$(uname -m)
case $ARCH in
x86_64) ARCH="x64" ;;
aarch64) ARCH="arm64" ;;
*) print_error "Unsupported architecture: $ARCH"; exit 1 ;;
esac
elif [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" ]]; then
OS="windows"
ARCH="x64"
else
print_error "Unsupported operating system: $OSTYPE"
exit 1
fi
print_info "Detected OS: $OS, Architecture: $ARCH"
}
set_emu_directory() {
if [[ -n "$CUSTOM_DIR" ]]; then
INSTALL_DIR="$CUSTOM_DIR"
elif [[ "$OS" == "linux" ]]; then
INSTALL_DIR="$CITRON_LINUX_BASE"
elif [[ "$OS" == "windows" ]]; then
INSTALL_DIR="$CITRON_WINDOWS_BASE"
fi
mkdir -p "$INSTALL_DIR"
INSTALL_DIR="$(cd "$INSTALL_DIR"; pwd)" # to absolute
print_info "Citron base directory: $INSTALL_DIR"
}
download_keys() {
if [[ "$SKIP_KEYS" == true ]]; then
print_info "Skipping prod.keys download"
return
fi
print_info "Preparing to download prod.keys..."
ensure_keys_version
# Determine keys directory for Citron
if [[ "$OS" == "linux" ]]; then
KEYS_DIR="$INSTALL_DIR/keys"
else
KEYS_DIR="$INSTALL_DIR/user/keys"
fi
mkdir -p "$KEYS_DIR"
PROD_KEYS_URL="https://github.com/DeaconBlood/PROD.KEYS/releases/download/${KEYS_VERSION}/prod.keys"
print_info "Downloading prod.keys from: $PROD_KEYS_URL"
if curl -L -o "$KEYS_DIR/prod.keys" "$PROD_KEYS_URL"; then
print_success "prod.keys downloaded successfully"
else
print_warning "Failed to download prod.keys from $PROD_KEYS_URL."
get_firmware_versions || true
exit 1
fi
}
download_firmware() {
if [[ "$SKIP_KEYS" == true ]]; then
print_info "Skipping firmware download"
return
fi
print_info "Preparing to download firmware..."
ensure_keys_version
# Determine firmware directory for Citron
if [[ "$OS" == "linux" ]]; then
NAND_DIR="$INSTALL_DIR/nand/system/Contents/registered"
else
NAND_DIR="$INSTALL_DIR/user/nand/system/Contents/registered"
fi
mkdir -p "$NAND_DIR"
TEMP_DIR=$(mktemp -d)
FIRMWARE_URL="https://github.com/THZoria/NX_Firmware/releases/download/${KEYS_VERSION}/Firmware.${KEYS_VERSION}.zip"
print_info "Downloading firmware from: $FIRMWARE_URL"
if curl -L -o "$TEMP_DIR/firmware.zip" "$FIRMWARE_URL"; then
print_info "Extracting firmware..."
if unzip -o -q "$TEMP_DIR/firmware.zip" -d "$NAND_DIR/"; then
print_success "Firmware downloaded and extracted successfully"
else
print_warning "Downloaded firmware but failed to extract it. File may be different than expected."
get_firmware_versions || true
exit 1
fi
else
print_warning "Failed to download firmware from $FIRMWARE_URL."
get_firmware_versions || true
exit 1
fi
}
cleanup() {
if [[ -n "$TEMP_DIR" && -d "$TEMP_DIR" ]]; then
rm -rf "$TEMP_DIR"
print_info "Cleaned up temporary files"
fi
}
main() {
print_info "Starting keys and firmware setup for Citron..."
detect_os
set_emu_directory
download_keys
download_firmware
cleanup
print_success "Keys and firmware setup completed!"
print_info "Base directory: $INSTALL_DIR"
if [[ "$SKIP_KEYS" == false ]]; then
print_info "Keys directory: $KEYS_DIR"
print_info "Firmware directory: $NAND_DIR"
fi
}
trap cleanup EXIT
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment