#!/usr/bin/perl

@MODES = (" FM", "WFM", " AM", "???");
@STEPS = (5, 6.25, 8.33, 9, 10, 12.5, 15, 20, 25, 30, 50, 100, 125, 200, "Auto", "???");


print "ADDR         00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15\n";
print "------------------------------------------------------------\n";


while (defined($cur_line = <STDIN>)) {
  chomp($cur_line);



#0000 10 48710008007800080072000000000000
#001010F04F0108004001080072000000000000
#002010184C001A000000080072000000000000
#003010DA4D001A000000080072000000000000
#0040109C4F001A0000000800720008EC873CE9
#0050 10 E44D001A000000080072000000000000
#...
#6E501049636F6D436C6F6E65466F726D617433

  # Skip the model line...
  next if $cur_line =~ /^32500001/;

  # Skip comments
  next if $cur_line =~ /^\#/;

  # MSDOS To unix as CS-R6 is saving MSDOS...
  $cur_line =~ s/\x0D$//;

  # Skip current mode (cmd 00)
  if (length($cur_line) !=38) {
    die("FATAL: Unexpected length (not 38):\n<$cur_line>\n\n")
  }

  if ($cur_line !~ /^[0-6][0-9A-F]{3}10[0-9A-F]{32}$/) {
    die("FATAL: Unknown command in line:\n<$cur_line>\n\n")
  }


  ($addr1, $addr2) = ($cur_line =~ /^(..)(..)/);
  $cur_line =~ s/^....10//;
  $address = hex($addr1 . $addr2);
  print(sprintf("%s%s %6d  ", $addr1, $addr2, $address));
  
  @hex_code = ( $cur_line =~ m/../g );
  #  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15


  # Data split at byte boundaries
  print join(" ", @hex_code[0..15]);


  @int_val = [];
  for ($i=0; $i<=15; $i++) {
    # Str to value
    $int_val[$i] = hex($hex_code[$i]);
    # print "\n$i: " . $hex_code[$i] . " -> " . $int_val[$i]. "\n"
  }

  if ($address <= 20799) {
    # Main memories
    if (1==1) {
      print "  <Ch " . sprintf("%04d", int ($address/16)) . ">";

      # Decodes from what we know already:
      $CODED_CHARS = " ^^^^^^^()*+^-./0123456789:^^=^^^ABCDEFGHIJKLMNOPQRSTUVWXYZ^^^^^";
      $mem_name = substr($CODED_CHARS, ((($int_val[11] & 0x0f) << 2) | (($int_val[12] & 0xc0) >> 6)), 1) .
                  substr($CODED_CHARS, ($int_val[12] & 0x3f), 1) .
                  substr($CODED_CHARS, (($int_val[13] & 0xfc) >> 2), 1) .
                  substr($CODED_CHARS, ((($int_val[13] & 0x03) << 4) | (($int_val[14] & 0xf0) >> 4)), 1) .
                  substr($CODED_CHARS, ((($int_val[14] & 0x0f) << 2) | (($int_val[15] & 0xc0) >> 6)), 1) .
                  substr($CODED_CHARS, ($int_val[15] & 0x3f), 1);
      print "  <$mem_name>";

      $mode_int = ($int_val[3] & 0x30) >> 4;
      $mode = $MODES[$mode_int];
      print "  Mode:<$mode_int><$mode>";

      # Tuning Step:
      $ts = ($int_val[3] & 0x0f);
      $ts_str = $STEPS[$ts];
      print "  TS:<", sprintf("%2d", $ts), "><", sprintf("%4s", $ts_str), ">";

      # Freq:
      print "  Freq:<", sprintf("%3d", $int_val[0]), "><", sprintf("%3d", $int_val[1]), "><",sprintf("%3d", $int_val[2]), ">";
      print "  Freq:<", sprintf("%.8b", $int_val[0]), "><", sprintf("%.8b", $int_val[1]), "><",sprintf("%.8b", $int_val[2]), ">";
      print "  RFreq:<", sprintf("%.8b", $int_val[2]), "><", sprintf("%.8b", $int_val[1]), "><",sprintf("%.8b", $int_val[0]), ">";

      # Duplex mode and freq offset
      $dplx = ($int_val[4] & 0x30)/16;
      print "  Dplx:";
      if ($dplx == 0) {
          print " "
      } elsif ($dplx == 1) {
          print "-"
      }
      elsif ($dplx == 2) {
          print "+"
      }
      elsif ($dplx == 3) {
          print "!"
      }
      print "", sprintf("%3d", $int_val[5]), "><", sprintf("%3d", $int_val[6]), ">";
      print "  <", sprintf("%.8b", $int_val[5]), "><", sprintf("%.8b", $int_val[6]), ">";
      print "  <", sprintf("%4d", 256*$int_val[6] + $int_val[5]), ">\n";
    }
  } elsif ($address <= 23984) {
    print "  <Unknown>\n";
  } elsif ($address <= 24399) {
    print "  Scan Edge:";
    print " <Name:" . chr($int_val[10]) . chr($int_val[11]) . chr($int_val[12]) . chr($int_val[13]) .
          chr($int_val[14]) . chr($int_val[15]) . ">";
    $scan_edge_dis = ($int_val[8] & 0x80)/128;
    print " <Dis:$scan_edge_dis>";
    $scan_edge_mode = ($int_val[8] & 0x70)/16;
    print " <Mod:$scan_edge_mode>";
    $scan_edge_att = ($int_val[9] & 0x30)/16;
    print " <Att=$scan_edge_att>\n";

  } elsif ($address <= 24447) {
    print "  <Unknown>\n";
  } elsif ($address <= 27047) {
    $channel = int(($address - 24448)/2);
    print "  <Ch Flags> ";
    for($i=0; $i<=7; $i++) {
      if ($channel+$i < 1300) {
        #if ($hex_code[$i*2] != "FF" || $hex_code[$i*2 +1] != "00") {
          print " <" . sprintf("%04d", $channel+$i) . ": " . $hex_code[$i*2] . " " . $hex_code[$i*2 +1] . ">"
        #} else {
        #  print " <" . sprintf("%04d", $channel+$i) . "       >";
        #}
      } else {
        print "\n                                          <Unknown> <" . $hex_code[$i*2] . " " . $hex_code[$i*2 +1] . ">"
      }
    }
      print "\n"
  } elsif ($address <= 27919) {
    print "  <Unknown>\n";
  } elsif ($address <= 28095) {
    # Bank names in ASCII
    print "  <Bank names> <" . chr($int_val[0]) . chr($int_val[1]) . chr($int_val[2]) . chr($int_val[3]) .
          chr($int_val[4]) . chr($int_val[5]) . ">  <" .
          chr($int_val[8]) . chr($int_val[9]) . chr($int_val[10]) . chr($int_val[11]) .
          chr($int_val[12]) . chr($int_val[13]) . ">\n";
  } else {
    print "  <Unknown>\n";
  }
}
