#!/usr/bin/env bash # generate_graphics_rules.sh # # Reads JSON gfx-config files and emits explicit Make rules for files that # need special flags or segment handling. Files that need no special # treatment are left for the generic %.4bpp: %.png pattern rule in the # Makefile. # # Usage: bash generate_graphics_rules.sh graphics/**/gfx.json ... # Output: Make rules on stdout set -euo pipefail if ! command -v jq >/dev/null 2>&1; then echo "error: 'jq' is required to build graphics rules but was not found. Install it with: sudo apt install jq" >&2 exit 1 fi emit_rules() { local json="$1" local dir dir=$(dirname "$json") # Single jq call per JSON: emit one TSV line per file entry with all # resolved values. Fields: # gfx_filename mwidth mheight oam align segments_json # segments_json is "null" when there are no segments, otherwise the # raw JSON array. jq -r ' .defaults as $d | .files[]? | [ .gfx_filename, ((.mwidth // $d.mwidth // 0) | tostring), ((.mheight // $d.mheight // 0) | tostring), ((.oam // $d.oam // false) | tostring), ((.align // 0) | tostring), ((.oamshape // $d.oamshape // "null") | tostring), (if .segments then (.segments | tojson) else "null" end) ] | @tsv ' "$json" | while IFS=$'\t' read -r gfx_filename mwidth mheight oam align oamshape segments; do local stem="graphics/${dir#graphics/}/${gfx_filename}" local target="${stem}.4bpp" if [ "$segments" != "null" ]; then # --- Segmented file --- # Collect segment PNGs as prerequisites local seg_pngs seg_pngs=$(printf '%s' "$segments" | jq -r '.[].segfile' | while read -r sf; do printf '%s/%s.png ' "$dir" "$sf" done) printf '%s: %s%s\n' "$target" "$seg_pngs" "$json" # Emit a $(GFX) call for each segment local first=1 printf '%s' "$segments" | jq -r '.[] | [.segfile, (.mwidth // 0 | tostring), (.mheight // 0 | tostring), (.oam // false | tostring), (.oamshape // "null" | tostring)] | @tsv' | while IFS=$'\t' read -r segfile seg_mw seg_mh seg_oam seg_oamshape; do local seg_png="${dir}/${segfile}.png" local seg_4bpp="${stem}_${segfile}.4bpp" local flags="" if [ "$seg_mw" != "0" ] && [ -n "$seg_mw" ]; then flags="$flags -mwidth $seg_mw" fi if [ "$seg_mh" != "0" ] && [ -n "$seg_mh" ]; then flags="$flags -mheight $seg_mh" fi if [ "$seg_oam" = "true" ]; then flags="$flags -oam" fi if [ -n "$seg_oamshape" ] && [ "$seg_oamshape" != "null" ]; then flags="$flags -oamshape $dir/$seg_oamshape" fi printf '\t$(GFX) %s %s%s; \\\n' "$seg_png" "$seg_4bpp" "$flags" done # cat all segment .4bpp files together local seg_4bpps seg_4bpps=$(printf '%s' "$segments" | jq -r '.[].segfile' | while read -r sf; do printf '%s_%s.4bpp ' "$stem" "$sf" done) printf '\tcat %s> $@' "$seg_4bpps" # Alignment padding if [ "$align" != "0" ] && [ -n "$align" ]; then printf '; \\\n' printf '\tdd if=/dev/zero bs=32 count=%s >> $@ 2>/dev/null' "$align" fi printf '\n\n' else # --- Non-segmented file --- local flags="" if [ "$mwidth" != "0" ] && [ -n "$mwidth" ]; then flags="$flags -mwidth $mwidth" fi if [ "$mheight" != "0" ] && [ -n "$mheight" ]; then flags="$flags -mheight $mheight" fi if [ "$oam" = "true" ]; then flags="$flags -oam" fi if [ -n "$oamshape" ] && [ "$oamshape" != "null" ]; then flags="$flags -oamshape $dir/$oamshape" fi # Skip if no special flags and no alignment — the generic # pattern rule in the Makefile handles this case. if [ -z "$flags" ] && { [ "$align" = "0" ] || [ -z "$align" ]; }; then continue fi printf '%s: %s.png %s\n' "$target" "$stem" "$json" printf '\t$(GFX) $< $@%s\n' "$flags" if [ "$align" != "0" ] && [ -n "$align" ]; then printf '\tdd if=/dev/zero bs=32 count=%s >> $@ 2>/dev/null\n' "$align" fi printf '\n' fi done } # --- Main --- printf '# Auto-generated by %s — do not edit\n\n' "$(basename "$0")" for json in "$@"; do # Only process gfx-config files if jq -e '.kind == "gfx-config"' "$json" > /dev/null 2>&1; then emit_rules "$json" fi done