/* index scanner first version
   caution: some drive deliver verbatim bcd values like plextor.
   Do mmc-3 drives really assemble/convert-to-hex/serialize ???
   Cannot believe this. */

#include <stdio.h>

#define CD_FRAMESIZE_RAW 2352
#define SUBSIZE 96

union u {
 unsigned char b[SUBSIZE/8];
 struct q {
   unsigned char ctrl_adr;
   unsigned char track;
   unsigned char index;
   unsigned char min;
   unsigned char sec;
   unsigned char frame;
   unsigned char zero;
   unsigned char amin;
   unsigned char asec;
   unsigned char aframe;
   unsigned char crc1;    /* all bits inverted. Polynom is */
   unsigned char crc2;    /* X^16 + X^12 + X^5 + 1 */
/*
   unsigned char pad[3];
   unsigned char Psub;
*/
 } q;
};

union u u;

void bcd2hex(unsigned char *p)
{
  *p = (*p>>4)*10+(*p&0x0F);
}

void getQ(unsigned char subs[])
{
  int i;

  for (i = 0; i < SUBSIZE; i++) {
    u.b[i / 8] <<= 1;
    u.b[i / 8] |= (subs[i] >> 6) & 1;
  }

  /* optionally convert BCD to Hex */
  bcd2hex(&u.q.track);
  bcd2hex(&u.q.index);
  bcd2hex(&u.q.min);
  bcd2hex(&u.q.sec);
  bcd2hex(&u.q.frame);
  bcd2hex(&u.q.amin);
  bcd2hex(&u.q.asec);
  bcd2hex(&u.q.aframe);
}

int main(int argc, char **argv)
{
  FILE *fp;
  unsigned char subs[SUBSIZE];
  unsigned int count_sectors = 0;
  unsigned int sectors_trackrel = 0;
  unsigned char tr=0, in=255;

  if (argc != 2) return 1;

  fp = fopen(argv[1], "rb");
  if (fp == NULL) return 2;

  for (;! feof(fp); count_sectors++, sectors_trackrel++ ) {

    fseek (fp, CD_FRAMESIZE_RAW, SEEK_CUR); /* skip cdda data */
    fread (subs, SUBSIZE, 1, fp);

    getQ(subs); 

    if ((u.q.ctrl_adr & 0x0f) != 1) continue;

    if (tr == u.q.track - 1 || in != u.q.index) {
      if (tr != u.q.track) {
        sectors_trackrel = 0;
      }
      fprintf(stderr,
      "sec: %5u   MSF %2d %2d %2d  rel_sec: %5u   MSF %2d %2d %2d    track %2d, index %2d\n",
      /*count_sectors,*/
      u.q.aframe + (75*u.q.asec) + (75*60*u.q.amin) - 150,
      u.q.amin, u.q.asec, u.q.aframe,
      u.q.frame + (75*u.q.sec) + (75*60*u.q.min),
      /*sectors_trackrel,*/
      u.q.min, u.q.sec, u.q.frame,
      u.q.track, u.q.index);

      tr = u.q.track;
      in = u.q.index;
    }
  }
  return 0;
}
