From b16ec83a33f52e44a72bd464aa08128f44e915d4 Mon Sep 17 00:00:00 2001 From: ISSOtm Date: Thu, 30 Jan 2020 02:43:31 +0100 Subject: [PATCH] Add `gbdiff.bash` script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This script allows diffing two Game Boy ROMs using `xxd` and `diff` and attempts to augment the diff using information pulled from SYM files. It's not part of RGBDS proper, but can be useful to debug tests (when ROMs fail to match). --- contrib/gbdiff.bash | 71 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100755 contrib/gbdiff.bash diff --git a/contrib/gbdiff.bash b/contrib/gbdiff.bash new file mode 100755 index 00000000..39014040 --- /dev/null +++ b/contrib/gbdiff.bash @@ -0,0 +1,71 @@ +#!/bin/bash + +# SPDX-License-Identifier: MIT +# +# Copyright (c) 2020 Eldred Habert +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +STATE=0 +diff <(xxd $1) <(xxd $2) | while read -r LINE; do + if [ $STATE -eq 0 ]; then + # Discard first line (line info) + STATE=1 + elif [ "$LINE" = '---' ]; then + # Separator between files switches states + echo $LINE + STATE=3 + elif echo $LINE | grep -Eq '^[0-9]+(,[0-9]+)?c[0-9]+(,[0-9]+)?'; then + # Line info resets the whole thing + STATE=1 + elif [ $STATE -eq 1 -o $STATE -eq 3 ]; then + # Compute the GB address from the ROM offset + OFS=$(echo $LINE | cut -d ' ' -f 2 | tr -d ':') + BANK=$((0x$OFS / 0x4000)) + ADDR=$((0x$OFS % 0x4000 + ($BANK != 0) * 0x4000)) + # Try finding the preceding symbol closest to the diff + if [ $STATE -eq 1 ]; then + STATE=2 + SYMFILE=$(echo $1 | cut -d '.' -f 1).sym + else + STATE=4 + SYMFILE=$(echo $2 | cut -d '.' -f 1).sym + fi + EXTRA=$(if [ -f "$SYMFILE" ]; then + # Read the sym file for such a symbol + # Ignore comment lines, only pick matching bank + grep -Fv ';' "$SYMFILE" | + grep -Ei $(printf "^%02x:" $BANK) | + while read -r SYMADDR SYM; do + SYMADDR=$((0x$(echo $SYMADDR | cut -d ':' -f 2))) + if [ $SYMADDR -le $ADDR ]; then + printf " (%s+%#x)\n" $SYM $(($ADDR - $SYMADDR)) + fi + # TODO: assumes sorted sym files + done | tail -n 1 + fi) + printf "%02x:%04x %s\n" $BANK $ADDR $EXTRA + fi + if [ $STATE -eq 2 -o $STATE -eq 4 ]; then + OFS=$(echo $LINE | cut -d ' ' -f 2 | tr -d ':') + BANK=$((0x$OFS / 0x4000)) + ADDR=$((0x$OFS % 0x4000 + ($BANK != 0) * 0x4000)) + printf "%s %02x:%04x: %s\n" "$(echo $LINE | cut -d ' ' -f 1)" $BANK $ADDR "$(echo $LINE | cut -d ' ' -f 3-)" + fi +done