#! /usr/bin/perl

$quick = shift(@ARGV) if $ARGV[0] eq "-q";
$verbose = shift(@ARGV) if $ARGV[0] eq "-v";

unless(-f $ARGV[0] || -f $ARGV[0] . ".vfo") {
  print STDERR "Usage: $0 file.vfo [...]
Dump info from a /usr/gfx/ucode/.../vfo/*.vfo file.\n";
  exit(1);
}

while(@ARGV) {
  $fname = shift(@ARGV);
  %entry = ();
  $maxname = 1;

  unless(open(F, $fname) || open(F, $fname . ".vfo")) {
    print STDERR "$fname: Cannot open: $!\n";
    next;
  }

  seek(F, 128, 0);
  read(F, $hdr, 3*4);
  ($nstrings, $zero, $stringbase) = unpack("NNN", $hdr);

  (print STDERR "$fname doesn't appear to be a .vfo file\n"), next
    if $nstrings<=0 || $nstrings>10000 || $stringbase<=0 || $stringbase>1e6;


  $offset = $stringbase + 4;
  for($i = 0; $i < $nstrings; $i++) {
    seek(F, $offset, 0);
    read(F, $slen, 4);
    ($strlen) = unpack("N", $slen);
    if($strlen < 0 || $strlen > 100) {
      print STDERR "$fname: unreasonable string length $strlen at offset $offset\n";
      last;
    }
    read(F, $name, $strlen);
    $pad4size = (($strlen + 3) & ~3) - $strlen;
    read(F, $pad4, $pad4size) if $pad4size > 0;
    read(F, $strinfo, 3*4);
    ($dtype, $array, $doffset) = unpack("NNN", $strinfo);
    seek(F, $doffset, 0);

    $dlen = $dtype==17 ? 8 : 4;
    $val = "";
    if($array > 0) {
	$val = "[$array]{ ";
	read(F, $data, 4);
	($array2) = unpack("N", $data);
	if($array2 != $array) {
	    printf STDERR "%s: claimed array length %d at %d doesn't match %d at %d\n",
		$fname, $array, $offset+$strlen+$pad4size+4, $array2, $doffset;
	    last;
	}
    }

    $index = 0;
    do {
	if(read(F, $data, $dlen) != $dlen) {
	    print STDERR "$fname offset $doffset: couldn't read value for $name\n";
	    last;
	}
	if($dtype == 15) {
	    ($dstrlen) = unpack("N", $data);
	    read(F, $data, $dstrlen);
	    $data = '"' . $data . '"';
	} elsif($dtype == 17) {
	    ($data) = unpack("d", $data);
	    $data = sprintf("%.10g", $data);
	} else {
	    ($data) = unpack("N", $data);
	}
	$val .= $data . " ";
    } while(++$index < $array);
    if($array > 0) {
	$val .= "}";
    } else {
	chop($val);
    }
    $val .= " <$dtype>[$zero]@$doffset" if $verbose;

    $entry{$name} = $val;
    $maxname = length($name) if $maxname < length($name);

    $offset += 4 + $strlen + $pad4size + 3*4;
  }

  if($quick) {
    $qname = sprintf("%dx%d_%d%s",
	$entry{"ActivePixelsPerLine"},
	$entry{"ActiveLinesPerFrame"} / $entry{"FieldsPerFrame"},
	$entry{"FormatInfo_PixelClock"}
	  / ($entry{"TotalPixelsPerLine"} * $entry{"TotalLinesPerFrame"}),
	$entry{"FormatInfo_Stereo"} ? "s" : ""
	);
    printf "%s\t%s (%s)\n", $fname, $qname, $entry{"FormatName"};
  } else {
    $maxname = ($maxname + 8) & ~7;
    print "== $fname ==\n";
    foreach $name (sort {$a cmp $b} keys(entry)) {
	print $name, "\t" x int((7+$maxname-length($name))/8), $entry{$name}, "\n";
    }
    print "\n\n" if @ARGV;
  }
}

