// File: ke6jjj[P]r-dat/main.cc
// Function: main
int
main(int argc, char *argv[])
{
  float buf[SAMPLES_PER_READ];
  size_t nread;
  bool do_raw = false;
  bool do_dat = false;
  bool do_dds = false;
  bool do_file = false;
  bool do_output = false;
  bool do_dds_session = false;
  enum { DECODE_RAW, DECODE_DAT, DECODE_DDS } decode_mode = DECODE_DAT;
  int c;
  const char *filename, *outfile;
  unsigned int dds_session;

  while ((c = getopt(argc, argv, "hdraf:o:s:")) != -1) {
    switch (c) {
    default:
    case 'h':
      usage(argv[0]);
      break;
    case 'd':
      do_dds = true;
      break;
    case 'r':
      do_raw = true;
      break;
    case 'a':
      do_dat = true;
      break;
    case 'f':
      do_file = true;
      filename = optarg;
      break;
    case 'o':
      do_output = true;
      outfile = optarg;
      break;
    case 's':
      do_dds_session = true;
      dds_session = strtoul(optarg, NULL, 0);
      break;
    }
  }

  //
  // Only one decode mode allowed.
  //
  if ((do_raw && (do_dds || do_dat)) || (do_dat && do_dds)) {
    usage(argv[0]);
  }

  //
  // Can only do output if DAT or DDS is selected.
  //
  if (do_output && !do_dat && !do_dds) {
    fprintf(stderr, "Can't dump result unless doing DAT audio or DDS.\n");
    usage(argv[0]);
  }
  
  //
  // Can only do DDS session if DDS is selected.
  //
  if (do_dds_session && !do_dds) {
    fprintf(stderr, "DDS session number is only valid for DDS.\n");
    usage(argv[0]);
  }

  //
  // Default to DAT if no choice specified.
  //
  if (!do_raw && !do_dds && !do_dat)
    do_raw = true;

  if (do_raw)
    decode_mode = DECODE_RAW;
  else if (do_dat)
    decode_mode = DECODE_DAT;
  else if (do_dds)
    decode_mode = DECODE_DDS;

  File in;

  if (do_file) {
    if (!in.Open(filename, sizeof(float)))  {
      fprintf(stderr, "Can't open file '%s'.\n", filename);
      exit(1);
    }
  } else {
    in.Open(STDIN_FILENO, sizeof(float));
  }

  RDATDecoder      *decoder;
  NRZISyncDeframer *deframer;
  DATWordReceiver  *blocker;
  DATTrackFramer   *tracker = NULL;
  DATFrameReceiver *streamer = NULL;

  switch (decode_mode) {
  case DECODE_DAT:
    {
    AudioFrameReceiver *audio = new AudioFrameReceiver();
    if (do_output) {
      if (!audio->SetDumpFile(outfile)) {
        fprintf(stderr, "Can't dump to output file '%s'.\n", outfile);
        exit(1);
      }
    }
    // Cast receiver to generic base class for rest of code.
    streamer = audio;
    }
    break;
  case DECODE_DDS:
    {
    DDSFrameReceiver *dds = new DDSFrameReceiver();
    if (do_output) {
      dds->DumpToDirectory(outfile);
    }
    if (do_dds_session) {
      dds->DumpSession(dds_session);
    }
    streamer = dds;
    }
    break;
  default:
    break;
  }

  if (decode_mode == DECODE_RAW) {
    blocker = new DATWordReceiver(NULL, true);
  } else {
    tracker = new DATTrackFramer(*streamer);
    blocker = new DATWordReceiver(tracker, false);
  }
    
  deframer = new NRZISyncDeframer(blocker);
  decoder = new RDATDecoder(9408000.0 * 8);
  decoder->SetSymbolDecoder(deframer);

  running = true;

  //
  // Install the sigint handler so that the user can stop the
  // processing safely.
  //
  struct sigaction int_handler = { .sa_handler = sigint_handler };
  ::sigaction(SIGINT, &int_handler, NULL);

  while (running) {
    nread = in.Read(buf, SAMPLES_PER_READ);
    if (nread == 0)
      break;
    decoder->Process(buf, nread);
  }

  decoder->Stop();

  in.Close();
  
  delete decoder;
  delete deframer;
  delete blocker;
  delete streamer;

  return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1160, %rsp           # imm = 0x1160
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movb $0x0, -0xfb9(%rbp)
movb $0x0, -0xfba(%rbp)
movb $0x0, -0xfbb(%rbp)
movb $0x0, -0xfbc(%rbp)
movb $0x0, -0xfbd(%rbp)
movb $0x0, -0xfbe(%rbp)
movl $0x1, -0xfc4(%rbp)
movl -0x8(%rbp), %edi
movq -0x10(%rbp), %rsi
leaq 0xbce9(%rip), %rdx      # 0xe054
callq 0x2050
movl %eax, -0xfc8(%rbp)
cmpl $-0x1, %eax
je 0x2433
movl -0xfc8(%rbp), %eax
addl $-0x61, %eax
movl %eax, %ecx
movq %rcx, -0x10e8(%rbp)
subl $0x12, %eax
ja 0x23ad
movq -0x10e8(%rbp), %rax
leaq 0xbc64(%rip), %rcx      # 0xe008
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
jmp 0x23af
movq -0x10(%rbp), %rax
movq (%rax), %rdi
callq 0x2b10
jmp 0x242e
movb $0x1, -0xfbb(%rbp)
jmp 0x242e
movb $0x1, -0xfb9(%rbp)
jmp 0x242e
movb $0x1, -0xfba(%rbp)
jmp 0x242e
movb $0x1, -0xfbc(%rbp)
movq 0x12bea(%rip), %rax     # 0x14fd0
movq (%rax), %rax
movq %rax, -0xfd0(%rbp)
jmp 0x242e
movb $0x1, -0xfbd(%rbp)
movq 0x12bd0(%rip), %rax     # 0x14fd0
movq (%rax), %rax
movq %rax, -0xfd8(%rbp)
jmp 0x242e
movb $0x1, -0xfbe(%rbp)
movq 0x12bb6(%rip), %rax     # 0x14fd0
movq (%rax), %rdi
xorl %eax, %eax
movl %eax, %esi
xorl %edx, %edx
callq 0x2070
movl %eax, -0xfdc(%rbp)
jmp 0x235d
testb $0x1, -0xfb9(%rbp)
je 0x244e
testb $0x1, -0xfbb(%rbp)
jne 0x2460
testb $0x1, -0xfba(%rbp)
jne 0x2460
testb $0x1, -0xfba(%rbp)
je 0x246c
testb $0x1, -0xfbb(%rbp)
je 0x246c
movq -0x10(%rbp), %rax
movq (%rax), %rdi
callq 0x2b10
testb $0x1, -0xfbd(%rbp)
je 0x24ab
testb $0x1, -0xfba(%rbp)
jne 0x24ab
testb $0x1, -0xfbb(%rbp)
jne 0x24ab
movq 0x12b52(%rip), %rax     # 0x14fe0
movq (%rax), %rdi
leaq 0xbbc7(%rip), %rsi      # 0xe05f
movb $0x0, %al
callq 0x2190
movq -0x10(%rbp), %rax
movq (%rax), %rdi
callq 0x2b10
testb $0x1, -0xfbe(%rbp)
je 0x24e1
testb $0x1, -0xfbb(%rbp)
jne 0x24e1
movq 0x12b1c(%rip), %rax     # 0x14fe0
movq (%rax), %rdi
leaq 0xbbc3(%rip), %rsi      # 0xe091
movb $0x0, %al
callq 0x2190
movq -0x10(%rbp), %rax
movq (%rax), %rdi
callq 0x2b10
testb $0x1, -0xfb9(%rbp)
jne 0x2503
testb $0x1, -0xfbb(%rbp)
jne 0x2503
testb $0x1, -0xfba(%rbp)
jne 0x2503
movb $0x1, -0xfb9(%rbp)
testb $0x1, -0xfb9(%rbp)
je 0x2518
movl $0x0, -0xfc4(%rbp)
jmp 0x2544
testb $0x1, -0xfba(%rbp)
je 0x252d
movl $0x1, -0xfc4(%rbp)
jmp 0x2542
testb $0x1, -0xfbb(%rbp)
je 0x2540
movl $0x2, -0xfc4(%rbp)
jmp 0x2542
jmp 0x2544
leaq -0x1000(%rbp), %rdi
callq 0xaa90
testb $0x1, -0xfbc(%rbp)
je 0x25c7
movq -0xfd0(%rbp), %rsi
leaq -0x1000(%rbp), %rdi
movl $0x4, %edx
callq 0xab60
movb %al, -0x10e9(%rbp)
jmp 0x2579
movb -0x10e9(%rbp), %al
testb $0x1, %al
jne 0x25c5
jmp 0x2585
movq 0x12a54(%rip), %rax     # 0x14fe0
movq (%rax), %rdi
movq -0xfd0(%rbp), %rdx
leaq 0xbb1f(%rip), %rsi      # 0xe0bc
movb $0x0, %al
callq 0x2190
movl $0x1, %edi
callq 0x2150
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1008(%rbp)
movl %eax, -0x100c(%rbp)
jmp 0x2af5
jmp 0x25de
leaq -0x1000(%rbp), %rdi
xorl %esi, %esi
movl $0x4, %edx
callq 0xac30
jmp 0x25dc
jmp 0x25de
movq $0x0, -0x1030(%rbp)
movq $0x0, -0x1038(%rbp)
movl -0xfc4(%rbp), %eax
movl %eax, -0x10f0(%rbp)
subl $0x1, %eax
je 0x261b
jmp 0x2607
movl -0x10f0(%rbp), %eax
subl $0x2, %eax
je 0x26e0
jmp 0x2786
movl $0x2de0, %edi           # imm = 0x2DE0
callq 0x20f0
movq %rax, -0x10f8(%rbp)
jmp 0x262e
movq -0x10f8(%rbp), %rdi
callq 0x52b0
jmp 0x263c
movq -0x10f8(%rbp), %rax
movq %rax, -0x1040(%rbp)
testb $0x1, -0xfbd(%rbp)
je 0x26cd
movq -0x1040(%rbp), %rdi
movq -0xfd8(%rbp), %rsi
callq 0x69d0
movb %al, -0x10f9(%rbp)
jmp 0x266e
movb -0x10f9(%rbp), %al
testb $0x1, %al
jne 0x26cb
jmp 0x267a
movq 0x1295f(%rip), %rax     # 0x14fe0
movq (%rax), %rdi
movq -0xfd8(%rbp), %rdx
leaq 0xba41(%rip), %rsi      # 0xe0d3
movb $0x0, %al
callq 0x2190
movl $0x1, %edi
callq 0x2150
movq -0x10f8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1008(%rbp)
movl %eax, -0x100c(%rbp)
movl $0x2de0, %esi           # imm = 0x2DE0
callq 0x2100
jmp 0x2af5
jmp 0x26cd
movq -0x1040(%rbp), %rax
movq %rax, -0x1038(%rbp)
jmp 0x2788
movl $0x30, %edi
callq 0x20f0
movq %rax, -0x1108(%rbp)
jmp 0x26f3
movq -0x1108(%rbp), %rdi
callq 0x6ac0
jmp 0x2701
movq -0x1108(%rbp), %rax
movq %rax, -0x1048(%rbp)
testb $0x1, -0xfbd(%rbp)
je 0x2757
movq -0x1048(%rbp), %rdi
movq -0xfd8(%rbp), %rsi
callq 0x6bc0
jmp 0x272d
jmp 0x2757
movq -0x1108(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1008(%rbp)
movl %eax, -0x100c(%rbp)
movl $0x30, %esi
callq 0x2100
jmp 0x2af5
testb $0x1, -0xfbe(%rbp)
je 0x2776
movq -0x1048(%rbp), %rdi
movl -0xfdc(%rbp), %esi
callq 0x6c00
jmp 0x2774
jmp 0x2776
movq -0x1048(%rbp), %rax
movq %rax, -0x1038(%rbp)
jmp 0x2788
jmp 0x2788
cmpl $0x0, -0xfc4(%rbp)
jne 0x27f6
movl $0xa8, %edi
callq 0x20f0
movq %rax, -0x1110(%rbp)
jmp 0x27a4
movq -0x1110(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
movl $0x1, %edx
callq 0x34f0
jmp 0x27bb
movq -0x1110(%rbp), %rax
movq %rax, -0x1028(%rbp)
jmp 0x28b6
movq -0x1110(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1008(%rbp)
movl %eax, -0x100c(%rbp)
movl $0xa8, %esi
callq 0x2100
jmp 0x2af5
movl $0x30, %edi
callq 0x20f0
movq %rax, -0x1118(%rbp)
jmp 0x2809
movq -0x1118(%rbp), %rdi
movq -0x1038(%rbp), %rsi
callq 0x39e0
jmp 0x281e
movq -0x1118(%rbp), %rax
movq %rax, -0x1030(%rbp)
movl $0xa8, %edi
callq 0x20f0
movq %rax, -0x1120(%rbp)
jmp 0x283f
movq -0x1120(%rbp), %rdi
movq -0x1030(%rbp), %rsi
xorl %edx, %edx
callq 0x34f0
jmp 0x2856
movq -0x1120(%rbp), %rax
movq %rax, -0x1028(%rbp)
jmp 0x28b6
movq -0x1118(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1008(%rbp)
movl %eax, -0x100c(%rbp)
movl $0x30, %esi
callq 0x2100
jmp 0x2af5
movq -0x1120(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1008(%rbp)
movl %eax, -0x100c(%rbp)
movl $0xa8, %esi
callq 0x2100
jmp 0x2af5
movl $0x40, %edi
callq 0x20f0
movq %rax, -0x1128(%rbp)
jmp 0x28c9
movq -0x1128(%rbp), %rdi
movq -0x1028(%rbp), %rsi
callq 0x31b0
jmp 0x28de
movq -0x1128(%rbp), %rax
movq %rax, -0x1020(%rbp)
movl $0x58, %edi
callq 0x20f0
movq %rax, -0x1130(%rbp)
jmp 0x28ff
movq -0x1130(%rbp), %rdi
movss 0xb6f6(%rip), %xmm0     # 0xe004
callq 0x2b60
jmp 0x2915
movq -0x1130(%rbp), %rax
movq %rax, -0x1018(%rbp)
movq -0x1018(%rbp), %rdi
movq -0x1020(%rbp), %rsi
callq 0x2d30
jmp 0x2938
movb $0x1, 0x127e2(%rip)     # 0x15121
leaq -0x10e0(%rbp), %rdi
leaq 0x11ea3(%rip), %rsi     # 0x147f0
movl $0x98, %edx
callq 0x20d0
movl $0x2, %edi
leaq -0x10e0(%rbp), %rsi
xorl %eax, %eax
movl %eax, %edx
callq 0x2160
movb 0x127af(%rip), %al      # 0x15121
testb $0x1, %al
je 0x2a26
leaq -0x1000(%rbp), %rdi
leaq -0xfb0(%rbp), %rsi
movl $0x3e8, %edx            # imm = 0x3E8
callq 0xac80
movq %rax, -0x1138(%rbp)
jmp 0x299b
movq -0x1138(%rbp), %rax
movq %rax, -0xfb8(%rbp)
cmpq $0x0, -0xfb8(%rbp)
jne 0x2a05
jmp 0x2a26
movq -0x1128(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1008(%rbp)
movl %eax, -0x100c(%rbp)
movl $0x40, %esi
callq 0x2100
jmp 0x2af5
movq -0x1130(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1008(%rbp)
movl %eax, -0x100c(%rbp)
movl $0x58, %esi
callq 0x2100
jmp 0x2af5
movq -0x1018(%rbp), %rdi
movq -0xfb8(%rbp), %rdx
leaq -0xfb0(%rbp), %rsi
callq 0x2d50
jmp 0x2a21
jmp 0x296c
movq -0x1018(%rbp), %rdi
callq 0x2fa0
jmp 0x2a34
leaq -0x1000(%rbp), %rdi
callq 0xab20
jmp 0x2a42
movq -0x1018(%rbp), %rax
movq %rax, -0x1140(%rbp)
cmpq $0x0, %rax
je 0x2a63
movq -0x1140(%rbp), %rdi
movq (%rdi), %rax
callq *0x8(%rax)
movq -0x1020(%rbp), %rax
movq %rax, -0x1148(%rbp)
cmpq $0x0, %rax
je 0x2a84
movq -0x1148(%rbp), %rdi
movq (%rdi), %rax
callq *0x38(%rax)
movq -0x1028(%rbp), %rax
movq %rax, -0x1150(%rbp)
cmpq $0x0, %rax
je 0x2ab5
movq -0x1150(%rbp), %rdi
callq 0x3540
movq -0x1150(%rbp), %rdi
movl $0xa8, %esi
callq 0x2100
movq -0x1038(%rbp), %rax
movq %rax, -0x1158(%rbp)
cmpq $0x0, %rax
je 0x2ad6
movq -0x1158(%rbp), %rdi
movq (%rdi), %rax
callq *0x8(%rax)
movl $0x0, -0x4(%rbp)
leaq -0x1000(%rbp), %rdi
callq 0xaac0
movl -0x4(%rbp), %eax
addq $0x1160, %rsp           # imm = 0x1160
popq %rbp
retq
leaq -0x1000(%rbp), %rdi
callq 0xaac0
movq -0x1008(%rbp), %rdi
callq 0x21d0
nopl (%rax)