home *** CD-ROM | disk | FTP | other *** search
/ Chip 2003 April (Special) / Chip-Special_2003-04_Vypalujeme-cd-i-dvd.bin / soft / bin2iso / bin2iso19b.exe / bin2iso19b.c < prev    next >
C/C++ Source or Header  |  1999-07-25  |  36KB  |  1,017 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <io.h>
  5.  
  6. #define DEBUG 0
  7. #define CHECK 0 /* don't bother checking bin for validity... */
  8.  
  9. //----------------Wave Stuff---------------------/
  10. typedef unsigned char BYTE1 ;
  11. typedef unsigned short int BYTE2 ;
  12. typedef unsigned long int  BYTE4 ;
  13.  
  14. typedef struct wavHdr {
  15.    BYTE1 riff[4];
  16.    BYTE4 bytestoend;
  17.    BYTE1 wavetxt[4];
  18.    BYTE1 fmttxt[4];
  19.    BYTE4 formatsize;  // 16 byte format specifier
  20.    BYTE2 format;          // Windows PCM
  21.    BYTE2 channels;             // 2 channels 
  22.    BYTE4 samplerate;       // 44,100 Samples/sec
  23.    BYTE4 avgbyterate;     // 176,400 Bytes/sec
  24.    BYTE2 samplebytes;          // 4 bytes/sample
  25.    BYTE2 channelbits;         // 16 bits/channel
  26.    BYTE1 datatxt[4];
  27.    BYTE4 blocksize;
  28. } tWavHead;
  29.  
  30. #define HEADBYTES 36
  31. #define WINDOWS_PCM 0x0001
  32. //-------------------------------------------------/
  33.  
  34. /*  G L O B A L   D E F I N E S  */
  35. #define byte    unsigned char
  36. #define SIZERAW 2352
  37. #define SIZEISO_MODE1 2048
  38. #define SIZEISO_MODE2_RAW 2352
  39. #define SIZEISO_MODE2_FORM1 2048
  40. #define SIZEISO_MODE2_FORM2 2336
  41. #define AUDIO 0
  42. #define MODE1 1
  43. #define MODE2 2
  44. #define MODE1_2352 10
  45. #define MODE2_2352 20
  46. #define MODE1_2048 30
  47. #define MODE2_2336 40
  48.  
  49. #define RAWDATA FF       // using this for leftover data when truncating for non-overburn
  50.  
  51. #define PROG_INTERVAL 1024
  52. #define UNKNOWN -1
  53. #define OFFSET 150                    
  54. // got this from easycd pro by looking at a blank disk so it may be off...
  55. #define CD74_MAX_SECTORS 334873 // 653.75 Mb 
  56.          
  57.  
  58. unsigned long int Index(char m, char s, char f)
  59. {
  60.   unsigned long int temp;
  61.  
  62.  
  63.   temp =  (((m>>4)*10) + (m&0xf)) * 60;
  64.   temp = ( temp + (((s>>4)*10) + (s&0xf))) * 75;
  65.   temp =  temp + (((f>>4)*10) + (f&0xf));
  66.   
  67. //  printf("\n%d%d %d%d %d%d = %06d", m>>4, m&f, s>>4, s&f, f>>4, f&f, temp);
  68.   
  69.   return temp;
  70. }
  71.  
  72. void unIndex(unsigned long int index, char *ptr)
  73. {
  74.   char m, s, f;
  75.  
  76.   f = (char) (index % 75);
  77.   s = (char) ((index/75) % 60);
  78.   m = (char) (index/(75*60));
  79.   sprintf(ptr, "%d%d:%d%d:%d%d", m/10, m%10, s/10, s%10, f/10, f%10);
  80.  
  81. }
  82.  
  83. // global variables
  84. FILE* fdBinFile;
  85. FILE* fdCueFile;
  86. FILE* fdOutFile;
  87. char sBinFilename[256];
  88. char sOutFilename[256];
  89.  
  90. unsigned long int writepos = 0; // for inplace conversions...
  91.  
  92.    
  93. #define OUTBUF_SIZE 4*1024*1024
  94. #define INBUF_SIZE 4*1024*1024
  95. unsigned char OUTBUF[OUTBUF_SIZE]; 
  96. unsigned int OUTBUF_IDX = 0;
  97. unsigned char INBUF[INBUF_SIZE]; 
  98. unsigned int INBUF_RIDX = 0;
  99. unsigned int INBUF_WIDX = 0;
  100.  
  101. int mode2to1 = 0;
  102.  
  103. typedef struct track
  104. {
  105.    unsigned short mode;
  106.    unsigned long idx0;
  107.    unsigned long idx1;
  108.    unsigned char num[3];
  109.    unsigned char name[80];
  110.    unsigned long offset0;
  111.    unsigned long offset1;
  112.    unsigned long size; /* track size in bytes */
  113. } tTrack;
  114.  
  115. buffered_fread(unsigned char *array, unsigned int size) {
  116.    unsigned int i;
  117.    
  118.    if(INBUF_WIDX == 0) {    
  119.       INBUF_WIDX += fread( INBUF, 1, (INBUF_SIZE/size)*size, fdBinFile );
  120.    }
  121.    if(INBUF_WIDX == 0) return 0; // read failed.
  122.    
  123.    for(i = 0; i< size; i++) 
  124.    {
  125.  
  126.       array[i] = INBUF[INBUF_RIDX++];
  127.       if((INBUF_RIDX == INBUF_WIDX) && (i < (size -1))) {
  128.          printf("   Warning: Premature EOF\n");
  129.          while(i++ < size) { array[i] == 0; }/* zero fill the rest */
  130.          break;
  131.       }
  132.    }
  133.  
  134.    if(INBUF_RIDX == INBUF_WIDX) {
  135.       INBUF_RIDX = 0;   
  136.       INBUF_WIDX = 0;   
  137.    }
  138.  
  139.  
  140.    return 1; // read passed
  141.      
  142. }
  143.  
  144. void buffered_fwrite(unsigned char *array, unsigned int size) {
  145.    unsigned int idx;
  146.    unsigned long int readpos;
  147.      
  148.    if(OUTBUF_IDX+size >= OUTBUF_SIZE) {     
  149.  
  150.       if(fdOutFile == fdBinFile) {
  151.          readpos = ftell(fdOutFile);
  152.          if(0 != fseek(fdOutFile, writepos, SEEK_SET)) { 
  153.             perror("\nbin2iso(fseek)"); exit(1);
  154.          }         
  155.       }
  156.  
  157.       //      printf("\nWriting            \n");
  158.       if( 1 != fwrite( OUTBUF, OUTBUF_IDX, 1, fdOutFile )) {
  159.          perror("\nbin2iso(fwrite)");
  160.          fclose(fdOutFile);
  161.          // remove(sOutFilename);
  162.          exit(1);
  163.       }
  164.       if( 1 != fwrite( array, size, 1, fdOutFile )) {
  165.          perror("\nbin2iso(fwrite)");
  166.          fclose(fdOutFile);
  167.          // remove(sOutFilename);
  168.          exit(1);
  169.       }
  170. //      printf("\nWrote %d bytes            \n", OUTBUF_IDX+size);
  171.       OUTBUF_IDX = 0;
  172.  
  173.       if(fdOutFile == fdBinFile) {
  174.          writepos = ftell(fdOutFile);
  175.          if(0 != fseek(fdOutFile, readpos, SEEK_SET)) { 
  176.             perror("\nbin2iso(fseek)"); exit(1);
  177.          }         
  178.      }
  179.  
  180.  
  181.    } else {
  182.       for(idx = 0; idx < size; idx++) {
  183.          OUTBUF[OUTBUF_IDX + idx] = array[idx];
  184.       }
  185.       OUTBUF_IDX+=size;
  186.    }
  187.      
  188. }
  189.  
  190.  
  191. void flush_buffers(void)
  192. {
  193.    unsigned long int readpos;
  194.  
  195.    if(fdOutFile == fdBinFile) {
  196.       readpos = ftell(fdOutFile);
  197.       if(0 != fseek(fdOutFile, writepos, SEEK_SET)) { 
  198.          perror("\nbin2iso(fseek)"); exit(1);
  199.       }         
  200.    }
  201.  
  202.    if( 1 != fwrite( OUTBUF, OUTBUF_IDX, 1, fdOutFile )) {
  203.       perror("\nbin2iso(fwrite)");
  204.       fclose(fdOutFile);
  205.       // remove(sOutFilename);
  206.       exit(1);
  207.    }
  208.  
  209. //   printf("\nWrote %d bytes          \n", OUTBUF_IDX);
  210.    OUTBUF_IDX = 0;
  211.    INBUF_RIDX = 0;
  212.    INBUF_WIDX = 0;
  213.  
  214.    if(fdOutFile == fdBinFile) {
  215.       writepos = ftell(fdOutFile);
  216.       if(0 != fseek(fdOutFile, readpos, SEEK_SET)) { 
  217.          perror("\nbin2iso(fseek)"); exit(1);
  218.       }         
  219.    }
  220.  
  221.  
  222. }
  223.  
  224.  
  225.  
  226. // presumes Line is preloaded with the "current" line of the file
  227. int getTrackinfo(char *Line, tTrack *track)
  228. {
  229. //   char tnum[3];
  230.    char inum[3];
  231.    char min;
  232.    char sec;
  233.    char block;
  234.    
  235.    track->idx0 = -1;
  236.    track->idx1 = -1;
  237.    
  238.    // Get the 'mode'
  239.    if (strncmp(&Line[2], "TRACK ", 6)==0) 
  240.    {
  241.       strncpy(track->num, &Line[8], 2); track->num[2] = '\0';
  242.  
  243.       track->mode = UNKNOWN;
  244.       if(strncmp(&Line[11], "AUDIO", 5)==0) track->mode = AUDIO;
  245.       if(strncmp(&Line[11], "MODE1/2352", 10)==0) track->mode = MODE1_2352;
  246.       if(strncmp(&Line[11], "MODE1/2048", 10)==0) track->mode = MODE1_2048;
  247.       if(strncmp(&Line[11], "MODE2/2352", 10)==0) track->mode = MODE2_2352;
  248.       if(strncmp(&Line[11], "MODE2/2336", 10)==0) track->mode = MODE2_2336;
  249.    }
  250.    else return(1);
  251.    
  252.    // Set the name
  253.    strcpy(track->name, sBinFilename);
  254.    track->name[strlen(sBinFilename)-4] = '\0';
  255.    strcat(track->name, "-");
  256.    strcat(track->name, track->num);
  257.  
  258.    if( (track->mode == MODE1_2352) || 
  259.        (track->mode == MODE1_2048) || 
  260.        (track->mode == MODE2_2352) || 
  261.        (track->mode == MODE2_2336)    )
  262.    {
  263.       strcat(track->name, ".iso");
  264.    } else if(track->mode == AUDIO) {
  265.       strcat(track->name, ".wav");
  266.    } else {
  267.       printf("Track %d Unsupported mode\n", track->num);
  268.       return(1);
  269.    }
  270.  
  271.    // Get the track indexes
  272.    while(1) {
  273.       if(! fgets( Line, 256, fdCueFile ) ) { break; }
  274.  
  275.       if (strncmp(&Line[2], "TRACK ", 6)==0) 
  276.       {  
  277.          break; // next track starting
  278.       }
  279.  
  280.       if (strncmp(&Line[4], "INDEX ", 6)==0) 
  281.       {
  282.          strncpy(inum, &Line[10], 2); inum[2] = '\0';
  283.          min = ((Line[13]-'0')<<4) | Line[14]-'0';
  284.          sec = ((Line[16]-'0')<<4) | Line[17]-'0';
  285.          block = ((Line[19]-'0')<<4) | Line[20]-'0';
  286.          
  287.          
  288.          if(strcmp(inum, "00")==0) track->idx0 = Index(min, sec, block);
  289.          else if(strcmp(inum, "01")==0) track->idx1 = Index(min, sec, block);
  290.          else { printf("Unexpected Index number: %s\n", inum); exit(1); } 
  291.            
  292.       }
  293.       else if (strncmp(&Line[4], "PREGAP ", 7)==0) { ; /* ignore, handled below */ }
  294.       else if (strncmp(&Line[4], "FLAGS ", 6)==0)  { ; /* ignore */ }
  295.       else { printf("Unexpected cuefile line: %s\n", Line); }
  296.    }
  297.    if(track->idx0 == -1) track->idx0 = track->idx1;
  298.    if(track->idx1 == -1) track->idx1 = track->idx0;
  299.    return(0);
  300.  
  301.  
  302. void dotrack(short mode, long preidx, long startidx, long endidx, unsigned long offset) 
  303. {
  304.    unsigned char buf[SIZERAW+100];
  305.    unsigned long blockswritten = 0;
  306.    unsigned int uiLastIndex;
  307. #if CHECK
  308.    unsigned int uiCurrentIndex;
  309. #endif
  310.    unsigned int write = 1;
  311.    
  312.    tWavHead wavhead = { "RIFF", 
  313.                              0,      
  314.                         "WAVE", 
  315.                         "fmt ", 
  316.                             16,       // 16 byte format specifier
  317.                    WINDOWS_PCM,       // format
  318.                              2,       // 2 Channels 
  319.                          44100,       // 44,100 Samples/sec    
  320.                         176400,       // 176,400 Bytes/sec
  321.                              4,       // 4 bytes/sample
  322.                             16,       // 16 bits/channel
  323.                         "data",  
  324.                              0 };
  325.                              
  326.    
  327.    uiLastIndex = startidx-1;
  328.    // Input -- process -- Output 
  329.    if(startidx != 0) printf("\nNote: PreGap = %d frames\n", startidx-preidx);
  330.    else printf("\nNote: PreGap = %d frames\n", OFFSET); // cd standard: starting offset
  331.                                                        // - of course this isn't true for bootable cd's...
  332.  
  333.    if(sOutFilename[0] != '\0') {
  334.       printf("Creating %s (%06d,%06d) ", sOutFilename, startidx, endidx-1);
  335.    } else {
  336.       printf("Converting (%06d,%06d) ", startidx, endidx-1);
  337.    }
  338.    switch(mode)
  339.    {
  340.       case AUDIO:
  341.          printf("Audio");
  342.          break;            
  343.       case MODE1_2352:
  344.          printf("Mode1/2048");
  345.          break;
  346.       case MODE2_2336:
  347.          printf("Mode2/2352");
  348.          break;
  349.       case MODE2_2352:
  350.          if(mode2to1 != 1) 
  351.             printf("Mode2/2352");
  352.          else 
  353.             printf("Mode1/2048");
  354.          break;
  355.       case MODE1_2048:
  356.          printf("Mode1/2048");
  357.          break;
  358.       default:
  359.            printf("Huh? What's going on?");
  360.            exit(1);
  361.    }
  362.    printf(" :       ");
  363.    
  364.    if(sOutFilename[0] != '\0') {
  365.       if(NULL == (fdOutFile = fopen (sOutFilename, "wb"))) {
  366.          perror("bin2iso(fopen)");
  367.       }
  368. // printf("\nOpened File %s: %d\n", sOutFilename, fdOutFile);
  369.  
  370.    } else {
  371.       fdOutFile = fdBinFile;
  372.    }
  373.    if (fdOutFile == NULL)   { printf ("    Unable to create %s\n", sOutFilename); exit (1); }
  374.    
  375.    if(0 != fseek(fdBinFile, offset, SEEK_SET)) { 
  376.       perror("\nbin2iso(fseek)"); exit(1);
  377.    }         
  378.  
  379. #if (DEBUG == 0)
  380.    if(mode == AUDIO) {
  381.       if( 1 != fwrite( &wavhead, sizeof(wavhead), 1, fdOutFile ) ) { // write placeholder
  382.          perror("\nbin2iso(fwrite)");
  383.          fclose(fdOutFile);
  384.          // remove(sOutFilename);
  385.          exit(1);
  386.       }
  387.    }
  388. #endif 
  389.          
  390.    memset( &buf[0], '\0', sizeof( buf ) );
  391.    if(mode == MODE2_2336) {
  392.       unsigned int M = 0, S = 2, F = 0;
  393.       while( buffered_fread( &buf[16], SIZEISO_MODE2_FORM2) ) {
  394.          //setup headed area (probably not necessary though...
  395.          //buf[0] = 0;
  396.          memset( &buf[1], 0xFF, sizeof(buf[0])*10 );
  397.          //buf[11] = 0;
  398.          buf[12] = M;
  399.          buf[13] = S;
  400.          buf[14] = F;
  401.          buf[15] = MODE2;
  402.          
  403.          if((++F&0xF) == 0xA) F += 6;
  404.  
  405.          if(F == 0x75) { S++; F = 0; } 
  406.          if((S&0xF) == 0xA) S += 6;
  407.   
  408.          if(S == 0x60) { M++; S = 0; }
  409.          if((M&0xF) == 0xA) M += 6;
  410. //         printf("\n%x:%x:%x", M, S, F);
  411.          
  412.          buffered_fwrite( buf, SIZERAW );   
  413.          uiLastIndex++;
  414.          memset( &buf[0], '\0', sizeof( buf ) );
  415.          if (startidx%PROG_INTERVAL == 0) { printf("\b\b\b\b\b\b%06d", startidx); }
  416.          if (++startidx == endidx) { printf("\b\b\b\b\b\bComplete\n"); break; }
  417.       }
  418.    } else if (mode == MODE1_2048) {
  419.       while( buffered_fread( buf, SIZEISO_MODE1) ) {         
  420.          buffered_fwrite( buf, SIZEISO_MODE1 );   
  421.          uiLastIndex++;
  422.          if (startidx%PROG_INTERVAL == 0) { printf("\b\b\b\b\b\b%06d", startidx); }
  423.          if (++startidx == endidx) { printf("\b\b\b\b\b\bComplete\n"); break; }
  424.       }
  425.    } else {
  426.       while( buffered_fread( buf, SIZERAW) ) {
  427.          switch(mode) {
  428.             case AUDIO:
  429. #if (DEBUG == 0)
  430.                buffered_fwrite( buf, SIZERAW );
  431. #endif        
  432.                uiLastIndex++;
  433.                blockswritten++;
  434.                break;
  435.             case MODE1_2352:
  436.                // should put a crc check in here...
  437. #if CHECK
  438.                if( buf[15] != MODE1) 
  439.                { 
  440.                   printf("\nWarning: Mode Error in bin file!\n"); 
  441.                   printf("   %02x:%02x:%02x : mode %02x\n", buf[12], buf[13], buf[14], buf[15] ); 
  442.                   //exit(1);
  443.                }
  444.              
  445.                uiCurrentIndex = Index(buf[12], buf[13], buf[14]) - OFFSET;
  446.               
  447.                if(uiCurrentIndex != uiLastIndex+1)
  448.                { 
  449.                   printf("\nWarning: Frame Error in bin file!\n"); 
  450.                   printf("Last      %02d:%02d:%02d (%d)\n", ((uiLastIndex+OFFSET)/75)/60, ((uiLastIndex+OFFSET)/75)%60, (uiLastIndex+OFFSET)%75, uiLastIndex ); 
  451.                   printf("Current   %02x:%02x:%02x (%d)\n", buf[12], buf[13], buf[14], uiCurrentIndex ); 
  452.                   printf("Expecting %02d:%02d:%02d (%d)\n", ((uiLastIndex+OFFSET+1)/75)/60, ((uiLastIndex+OFFSET+1)/75)%60, (uiLastIndex+OFFSET+1)%75, uiLastIndex+1 ); 
  453.                 
  454.                }
  455. #endif
  456. #if (DEBUG == 0)
  457.                buffered_fwrite( &buf[16], SIZEISO_MODE1 );
  458. #endif
  459. #if CHECK
  460.                uiLastIndex = uiCurrentIndex;
  461. #endif
  462.                break;
  463.             case MODE2_2352:
  464. #if CHECK
  465.                if( (buf[15]&0xf) != MODE2) 
  466.                { 
  467.                   printf("\nWarning: Mode Error in bin file!\n"); 
  468.                   printf("   %02x:%02x:%02x : mode %02x\n", buf[12], buf[13], buf[14], buf[15] ); 
  469.                   //exit(1);
  470.                }
  471.  
  472.                uiCurrentIndex = Index(buf[12], buf[13], buf[14]) - OFFSET;
  473.  
  474.                if(uiCurrentIndex != uiLastIndex+1)
  475.                { 
  476.                   printf("\nWarning: Frame Error in bin file!\n"); 
  477.                   printf("Last      %02d:%02d:%02d (%d)\n", ((uiLastIndex+OFFSET)/75)/60, ((uiLastIndex+OFFSET)/75)%60, (uiLastIndex+OFFSET)%75, uiLastIndex ); 
  478.                   printf("Current   %02x:%02x:%02x (%d)\n", buf[12], buf[13], buf[14], uiCurrentIndex ); 
  479.                   printf("Expecting %02d:%02d:%02d (%d)\n", ((uiLastIndex+OFFSET+1)/75)/60, ((uiLastIndex+OFFSET+1)/75)%60, (uiLastIndex+OFFSET+1)%75, uiLastIndex+1 ); 
  480.                }
  481. #endif
  482. #if (DEBUG == 0)
  483.                if(mode2to1) buffered_fwrite( &buf[16+8], SIZEISO_MODE1 );
  484.                else if(write) buffered_fwrite( &buf[0], SIZEISO_MODE2_RAW );
  485. #endif
  486. #if CHECK
  487.                uiLastIndex = uiCurrentIndex;
  488. #endif
  489.                break;
  490.             default:
  491.                printf("Unkown Mode\n"); exit(1);
  492.                break;
  493.          }         
  494.             
  495.          memset( &buf[0], '\0', sizeof( buf ) );
  496.          if (startidx%PROG_INTERVAL == 0) { printf("\b\b\b\b\b\b%06d", startidx); }
  497.          if (++startidx == endidx) { printf("\b\b\b\b\b\bComplete\n"); break; }
  498.       }
  499.    }
  500.    flush_buffers(); // flushes write buffer
  501.                     // and clears read buffer.
  502.    if(mode == AUDIO) {
  503.       wavhead.blocksize = blockswritten*SIZERAW;
  504.       wavhead.bytestoend = wavhead.blocksize + HEADBYTES;
  505.       // rewind to the beginning
  506.       if(0 != fseek(fdOutFile, 0, SEEK_SET)) { 
  507.          perror("\nbin2iso(fseek)"); exit(1);
  508.       }         
  509.  
  510. #if (DEBUG == 0)
  511.       fwrite( &wavhead, sizeof(wavhead), 1, fdOutFile );
  512. #endif
  513.    }      
  514.    fclose(fdOutFile);
  515. }
  516.  
  517.  
  518. void doCueFile(void) {
  519.    int track = 1;
  520.    unsigned long int binIndex = 0;
  521.    unsigned long int trackIndex = 0;
  522.    const int gapThreshold = 20; // look for 0.266 sec gap
  523.    const int valueThreshold = 800; // look for samples < 700
  524.    int count = 0;
  525.    int i, blank;
  526.    int gapon = 0;
  527.    short value;
  528.       
  529.    char mode[12] = "AUDIO";
  530.    char index0[9] = "00:00:00";
  531.    char index1[9] = "00:00:00";
  532.    unsigned char buf[SIZERAW+100];
  533.     
  534.    printf(            "FILE %s BINARY\n", sBinFilename);
  535.    fprintf(fdCueFile, "FILE %s BINARY\n", sBinFilename);
  536.    memset( buf, '\0', sizeof( buf ) );
  537.    while( fread( buf, 1, SIZERAW, fdBinFile ) ) {
  538.       if(trackIndex == 0) {
  539.          if ( (buf[0] == 0x00) &&
  540.               (buf[1] == 0xFF) &&
  541.               (buf[2] == 0xFF) &&
  542.               (buf[3] == 0xFF) &&
  543.               (buf[4] == 0xFF) &&
  544.               (buf[5] == 0xFF) &&
  545.               (buf[6] == 0xFF) &&
  546.               (buf[7] == 0xFF) &&
  547.               (buf[8] == 0xFF) &&
  548.               (buf[9] == 0xFF) &&
  549.               (buf[10] == 0xFF) &&
  550.               (buf[11] == 0x00) 
  551.             ) {
  552.             sprintf(mode, "MODE%d/2352", buf[15]);
  553.          } else { 
  554.             sprintf(mode, "AUDIO"); 
  555.          }
  556.       } 
  557.       if(binIndex == 0) {
  558.          printf(            "  TRACK %02d %s\n", track, mode);
  559.          fprintf(fdCueFile, "  TRACK %02d %s\n", track, mode);
  560.          printf(            "    INDEX 01 %s\n", index0);
  561.          fprintf(fdCueFile, "    INDEX 01 %s\n", index0);
  562.       }
  563.       blank = 1;
  564.       for(i = 0; i < SIZERAW; i+=2) {
  565.          value = buf[i+1];
  566.          value = ((value << 8) | buf[i]);
  567. //         printf("%f %i\n",(1.0/75)*binIndex, value);
  568.          if(abs(value) > valueThreshold) {
  569.             blank = 0;
  570.             break;
  571.          }
  572.       }
  573. //      if(i == SIZERAW) printf("%f ~blank~\n", (1.0/75)*binIndex);
  574.       if(blank == 1) count++;
  575.       else if (gapon == 1) {
  576.          gapon = 0; 
  577.          unIndex(binIndex-count, index0);
  578.          count = 0;
  579.          unIndex(binIndex, index1);
  580.          printf(            "  TRACK %02d %s\n", track, mode);
  581.          fprintf(fdCueFile, "  TRACK %02d %s\n", track, mode);
  582.          printf(            "    INDEX 00 %s\n", index0);
  583.          fprintf(fdCueFile, "    INDEX 00 %s\n", index0);
  584.          printf(            "    INDEX 01 %s\n", index1);
  585.          fprintf(fdCueFile, "    INDEX 01 %s\n", index1);
  586.       }
  587.       
  588.       if((count > gapThreshold) && (gapon == 0)) {
  589.          gapon = 1; track++;
  590.          trackIndex = -1;
  591.       } 
  592.       
  593.       memset( buf, '\0', sizeof( buf ) );
  594.       binIndex++;      
  595.       trackIndex++;
  596.    }
  597. }
  598.  
  599. // return 0 to when no data found, 1 when there is.
  600. int checkGaps(FILE *fdBinFile, tTrack tracks[], int nTracks) {
  601.    int i, k;
  602.    unsigned long int j;
  603.    unsigned char buf[SIZERAW];
  604.    int c = 0;
  605.    int writegap = 0;
  606.    short value;
  607.    int count;
  608.  
  609.    if(nTracks == 2) { return 0; }; // don't need to bother with single track images
  610.  
  611.    printf("Checking gap data:\n");
  612.  
  613.    for (i = 0; i < nTracks; i++) {
  614.       if((tracks[i].offset0 != tracks[i].offset1) && (tracks[i-1].mode == AUDIO)) {
  615.          if(0 != fseek(fdBinFile, tracks[i].offset0, SEEK_SET)) { 
  616.             perror("\nbin2iso(fseek)"); exit(1);
  617.          }
  618.          count = 0;
  619.          for(j = tracks[i].idx0; j < tracks[i].idx1; j++) {
  620.             if(0 == fread( buf, SIZERAW, 1, fdBinFile ) ) {
  621.                perror("bin2iso(fread)");
  622.                exit(1);
  623.             }
  624.             for(k = 0; k < SIZERAW; k+=2) {
  625.                value = buf[k+1];
  626.                value = ((value << 8) | buf[k]);
  627.                if(value != 0) { 
  628.                   count++;
  629.  
  630.                 // printf("%10d: %2x\n", count ,value );
  631.                }
  632.             }
  633.          }
  634.          if(count != 0) {
  635.             printf("   Track%02d - %d values of Non-Zero gap data encountered\n", i-1, count);
  636.             if((count > SIZERAW/2/2) && (writegap == 0)) {
  637.                printf("   -->Threashold reached\n"); writegap = 1;
  638.             }
  639.          }
  640.       }
  641.    }
  642.    return writegap; 
  643. }   
  644.  
  645. /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ */
  646.  
  647. int   main(int argc, char **argv) {
  648.    unsigned long int count = 0;
  649. //   int printon = 0;
  650.  
  651.    char sLine[256];
  652.    int i,j,q;
  653.    
  654. //   int writegap = -1;   // auto detect pregap data action by default. 
  655.    int writegap = 1;   // keep pregap data by default. 
  656.    int no_overburn = 0; 
  657.    int createCue = 0; 
  658.    char sTrack[3] = "00"; 
  659.    int doOneTrack = 0;
  660.    int doInPlace = 0;
  661.          
  662.    tTrack trackA;
  663.    tTrack trackB;
  664.    
  665.    tTrack tracks[100];
  666.    int nTracks = 0;
  667.    
  668.    char sOutdir[192];
  669.  
  670.    sOutFilename[0] = '\0';
  671.  
  672.    /* Tell them what I am. */
  673.    printf ("\n%s, %s", __DATE__, __TIME__);
  674.    printf ("\nbin2iso V1.9b - Converts RAW format (.bin) files to ISO/WAV format"); 
  675.    printf ("\n               Bob Doiron, ICQ#280251                     \n");
  676.    printf ("\nCheck for updates at http://users.andara.com/~doiron\n\n");
  677.    if(argc < 2) {
  678.       printf("Usage: bin2iso <cuefile> [<output dir>] [-[a]wg] [-t XX] [-i] [-nob]\n");
  679.       printf("or   : bin2iso <cuefile> -c <binfile>\n");
  680.       printf("\n");
  681.       printf("Where:\n");
  682.       printf("   <cuefile>    - the .cue file that belongs to the .bin file to \n");
  683.       printf("                  be converted\n");
  684.       printf("   <output dir> - the output directory (defaults to current dir) \n");
  685.       printf("   -nwg         - indicates that audio data found in the track   \n");
  686.       printf("                  'gaps' shouldn't be appended to the audio tracks\n");
  687.       printf("   -awg         - looks for non-zero data in the 'gaps', if found\n");
  688.       printf("                  then gaps are appended to audio tracks. Looks  \n");
  689.       printf("                  for more than 1/2 of a sector of non-zero values\n");
  690.       printf("                  (%d values),                                   \n", SIZERAW/2/2);
  691.       printf("   -t XX        - Extracts the XX'th track.                      \n");
  692.       printf("   -i           - Performs the conversion 'in place'. Meaning it \n");
  693.       printf("                  truncates the binfile after each track is      \n");
  694.       printf("                  created to minimize diskspace requirements.    \n");
  695.       printf("                  [not valid with -t]                            \n");
  696.       printf("   -nob         - Doesn't use overburn data past %ld sectors.    \n", CD74_MAX_SECTORS);
  697.       printf("                  This of course presumes that the data is not   \n");
  698.       printf("                  useful.                                        \n");
  699.       printf("   -c           - Attempts to create a <cuefile> from an existing\n");
  700.       printf("                  <binfile>                                      \n");
  701.       exit (1);
  702.    }
  703.  
  704.    strcpy(sOutdir, ".\\"); // default path
  705.  
  706.    printf("\n");
  707.    for (i=2; i < argc; i++) {
  708.       if (argv[i][0] == '-') {
  709.          /* if (strncmp(&(argv[i][1]), "wg", 2)==0) {
  710.             writegap = 1; 
  711.          } else */ 
  712.          
  713.          if (strncmp(&(argv[i][1]), "awg", 3)==0) {
  714.             writegap = -1; 
  715.             printf("Note: Auto-detecting pregap data\n");         
  716.          } else if (strncmp(&(argv[i][1]), "nwg", 3)==0) {
  717.             writegap = 0;          
  718.          } else if (strncmp(&(argv[i][1]), "m2to1", 5)==0) {
  719.             mode2to1 = 1;
  720.             printf("Note: Converting Mode2 ISO to Mode1\n");
  721.          } else if (strncmp(&(argv[i][1]), "t", 1)==0) {
  722.             strcpy(sTrack, argv[i+1]);
  723.             doOneTrack = 1;
  724.             i++;
  725.          } else if (strncmp(&(argv[i][1]), "i", 1)==0) {
  726.             if(doOneTrack == 1) { printf("Invalid combination of options...\n"); exit(1); }
  727.             printf("Bin file will be truncated after each track created\n");
  728.             doInPlace = 1;
  729.          } else if (strncmp(&(argv[i][1]), "c", 1)==0) {
  730.             createCue = 1;
  731.             strcpy(sBinFilename, argv[i+1]);
  732.             i++;
  733.          } else if (strncmp(&(argv[i][1]), "nob", 3)==0) {
  734.             no_overburn = 1;
  735.          }
  736.       } else {
  737.          strcpy(sOutdir, argv[2]);
  738.       }
  739.    }
  740.    
  741.    if(createCue == 1) {
  742.       fdBinFile = fopen (sBinFilename, "rb");
  743.       if (fdBinFile == NULL) {
  744.          printf ("Unable to open %s\n", sBinFilename);
  745.          exit (1);
  746.       } 
  747.       fdCueFile = fopen (argv[1], "w");
  748.       if (fdCueFile == NULL) {
  749.          printf ("Unable to create %s\n", argv[1]);
  750.          exit (1);
  751.       } 
  752.  
  753.       if((strcmp(&sBinFilename[strlen(sBinFilename)-4], ".wav")==0) ||
  754.          (strcmp(&sBinFilename[strlen(sBinFilename)-4], ".WAV")==0) ) {
  755.          printf(".wav binfile - Skipping wav header\n");
  756.          fread( sLine, 1, sizeof(tWavHead), fdBinFile );
  757.       }
  758.  
  759.       doCueFile();
  760.  
  761.    } else {   
  762.       fdCueFile = fopen (argv[1], "r");      
  763.       if (fdCueFile == NULL) {
  764.          printf ("Unable to open %s\n", argv[1]);
  765.          exit (1);
  766.       } 
  767.  
  768.       // get bin filename from cuefile... why? why not.
  769.       if(! fgets( sLine, 256, fdCueFile ) ) {
  770.          printf ("Error Reading Cuefile\n");
  771.          exit (1);
  772.       }
  773.       if (strncmp(sLine, "FILE ", 5)==0) {
  774.          i = 0;
  775.          j = 0;
  776.          q = 0; // track open and closed quotes
  777.          do { 
  778.             sBinFilename[j] = sLine[5+i]; 
  779.             i++;
  780.             j++;
  781.             if ((sBinFilename[j-1] == '\\') || (sBinFilename[j-1] == '/')) { j = 0; } //strip out path info
  782.             if (sBinFilename[j-1] == '"') { j--; q++;} // strip out quotes
  783.          } while ((sLine[5+i-1] != ' ') || (q == 1));
  784.          sBinFilename[j] = '\0';
  785.          //bug?? Why did a trailing space show up??
  786.          while(sBinFilename[--j] == ' ') sBinFilename[j] = '\0';
  787.  
  788.          strlwr(sBinFilename);
  789.  
  790.       } else {
  791.          printf ("Error: Filename not found on first line of cuefile.\n", argv[1]);
  792.          exit (1);
  793.       }
  794.    
  795.       // Open the bin file
  796.       if(doInPlace == 1) {
  797.          fdBinFile = fopen (sBinFilename, "rb+");
  798.       } else {
  799.          fdBinFile = fopen (sBinFilename, "rb");
  800.       }
  801.       if (fdBinFile == NULL) {
  802.          printf ("Unable to open %s\n", sBinFilename);
  803.          perror("\nbin2iso(fopen)");
  804.          exit(1);
  805.       }
  806.  
  807.       // Get next line
  808.       if(! fgets( sLine, 256, fdCueFile ) ) {
  809.          printf ("Error Reading Cuefile\n");
  810.          exit (1);
  811.       } 
  812.    
  813.       if(strlen(sOutdir) > 0) {
  814.          if((sOutdir[strlen(sOutdir)-1] != '\\' ) && (sOutdir[strlen(sOutdir)-1] != ':' ) ) {
  815.             strcat(sOutdir, "\\");
  816.          }
  817.       }
  818.    
  819.       while(!feof(fdCueFile)) {
  820.          getTrackinfo(sLine, &tracks[nTracks++]);
  821.       }
  822.       tracks[nTracks].idx0 = tracks[nTracks].idx1 = -1;
  823.  
  824.       switch (tracks[0].mode) {
  825.          case MODE1_2048:
  826.             tracks[0].offset0 = tracks[0].idx0*SIZEISO_MODE1;
  827.             break;
  828.          case MODE2_2336:
  829.             tracks[0].offset0 = tracks[0].idx0*SIZEISO_MODE2_FORM2;
  830.             break;
  831.          default:  // AUDIO, MODE1_2352, MODE2_2352:
  832.             tracks[0].offset0 = tracks[0].idx0*SIZERAW;
  833.             break;
  834.       }               
  835.       /* set offsets */
  836.  
  837.       
  838.       if(0 != fseek(fdBinFile, 0, SEEK_END)) { 
  839.          perror("\nbin2iso(fseek)"); exit(1);
  840.       }
  841.  
  842.       tracks[nTracks].offset0 = tracks[nTracks].offset1 = ftell(fdBinFile);
  843.  
  844.       for(i = 0; i < nTracks; i++) {
  845.          switch (tracks[i].mode) {
  846.             case MODE1_2048:
  847.                tracks[i].offset1 = tracks[i].offset0   + (tracks[i].idx1-tracks[i].idx0)*SIZEISO_MODE1;
  848.                if(tracks[i+1].idx0 != -1)
  849.                   tracks[i+1].offset0 = tracks[i].offset1 + (tracks[i+1].idx0 - tracks[i].idx1)*SIZEISO_MODE1;
  850.                else {
  851.                   tracks[i+1].idx0 = tracks[i+1].idx1 = (tracks[i+1].offset0 - tracks[i].offset1)/SIZEISO_MODE1 + tracks[i].idx1;
  852.                   if(((tracks[i+1].offset0 - tracks[i].offset1)%SIZEISO_MODE1) != 0) printf("Warning: Bin file has invalid byte count for cuefile.\n");
  853.                }
  854.                break;
  855.             case MODE2_2336:
  856.                tracks[i].offset1 = tracks[i].offset0   + (tracks[i].idx1-tracks[i].idx0)*SIZEISO_MODE2_FORM2;
  857.                if(tracks[i+1].idx0 != -1)
  858.                   tracks[i+1].offset0 = tracks[i].offset1 + (tracks[i+1].idx0 - tracks[i].idx1)*SIZEISO_MODE2_FORM2;
  859.                else {
  860.                   tracks[i+1].idx0 = tracks[i+1].idx1 = (tracks[i+1].offset0 - tracks[i].offset1)/SIZEISO_MODE2_FORM2 + tracks[i].idx1;
  861.                   if(((tracks[i+1].offset0 - tracks[i].offset1)%SIZEISO_MODE2_FORM2) != 0) printf("Warning: Bin file has invalid byte count for cuefile.\n");
  862.                }
  863.                break;
  864.             default:  // AUDIO, MODE1_2352, MODE2_2352:
  865.                tracks[i].offset1 = tracks[i].offset0   + (tracks[i].idx1-tracks[i].idx0)*SIZERAW;
  866.                if(tracks[i+1].idx0 != -1)
  867.                   tracks[i+1].offset0 = tracks[i].offset1 + (tracks[i+1].idx0 - tracks[i].idx1)*SIZERAW;
  868.                else {
  869.                   tracks[i+1].idx0 = tracks[i+1].idx1 = (tracks[i+1].offset0 - tracks[i].offset1)/SIZERAW + tracks[i].idx1;
  870.                   if(((tracks[i+1].offset0 - tracks[i].offset1)%SIZERAW) != 0) printf("Warning: Bin file has invalid byte count for cuefile.\n");
  871.                }
  872.                break;
  873.          }
  874.       }
  875.  
  876.       // if not allowing overburn, then create a new track to hold extra data...
  877.       if(no_overburn == 1) {
  878.          i = nTracks;
  879.          if(tracks[i].idx0 > CD74_MAX_SECTORS) {
  880.             tracks[i+1] = tracks[nTracks];
  881.             strcpy(tracks[i].name, "obdatatemp.bin");
  882.             tracks[i].idx0 = CD74_MAX_SECTORS;
  883.             tracks[i].idx1 = CD74_MAX_SECTORS;
  884.             switch (tracks[i-1].mode) {
  885.                case MODE1_2048:
  886.                   tracks[i].offset0 = tracks[i-1].offset1 + (tracks[i].idx0 - tracks[i-1].idx1)*SIZEISO_MODE1;
  887.                   break;
  888.                case MODE2_2336:
  889.                   tracks[i].offset0 = tracks[i-1].offset1 + (tracks[i].idx0 - tracks[i-1].idx1)*SIZEISO_MODE2_FORM2;
  890.                   break;
  891.                default:  // AUDIO, MODE1_2352, MODE2_2352:
  892.                   tracks[i].offset0 = tracks[i-1].offset1 + (tracks[i].idx0 - tracks[i-1].idx1)*SIZERAW;
  893.                   break;
  894.             }
  895.             tracks[i].offset1 = tracks[i].offset0;
  896.             tracks[i].mode = tracks[i-1].mode;
  897.             nTracks++;
  898.          }
  899.       }
  900.  
  901.       
  902.       /* set sizes */
  903.       for(i = 0; i < nTracks; i++) {
  904.          switch (tracks[i].mode) {
  905.             case MODE1_2352:
  906.                tracks[i].size = ((tracks[i+1].offset1 - tracks[i].offset1) / SIZERAW ) * SIZEISO_MODE1;
  907.                break;
  908.             case MODE2_2336:
  909.                tracks[i].size = ((tracks[i+1].offset1 - tracks[i].offset1) / SIZEISO_MODE2_FORM2 ) * SIZERAW;
  910.                break;
  911.             default: // MODE1_2048, MODE2_2352, AUDIO
  912.               tracks[i].size = tracks[i+1].offset1 - tracks[i].offset1;
  913.               break;
  914.          }
  915.       }
  916.  
  917.       if(writegap == -1)  { writegap = checkGaps(fdBinFile, tracks, nTracks); }
  918.  
  919.       if(writegap == 1) 
  920.          printf("Note: Appending pregap data to end of audio tracks\n");
  921.       else 
  922.          printf("Note: Discarding pregap data\n");
  923.  
  924.       printf("\n");
  925.       for(i = 0; i <= nTracks-1; i++) {
  926.          printf("%s (%3d Mb) - sectors %06ld:%06ld (offset %09ld:%09ld)\n", 
  927.             tracks[i].name, 
  928.             tracks[i].size/(1024*1024), 
  929.             tracks[i].idx1, 
  930.             ( ((writegap == 0) || (tracks[i].mode != AUDIO)) ? tracks[i+1].idx0 : tracks[i+1].idx1)-1, 
  931.             tracks[i].offset1, 
  932.             ( ((writegap == 0) || (tracks[i].mode != AUDIO)) ? tracks[i+1].offset0 : tracks[i+1].offset1)-1 
  933.          );
  934.       }
  935.       printf("\n");
  936.  
  937.       if( (((mode2to1 != 1) && (tracks[0].mode == MODE2_2352)) || (tracks[0].mode == MODE1_2048)) && (nTracks == 1) ) {
  938.          if(tracks[0].mode == MODE2_2352) { printf("Mode2/2352"); }
  939.          if(tracks[0].mode == MODE1_2048) { printf("Mode1/2048"); }
  940.          printf(" single track bin file indicated by cue file\n");   
  941.          fclose(fdBinFile);
  942.          if( 0 != rename(sBinFilename, tracks[0].name) ) {
  943.             perror("\nbin2iso(rename)");
  944.             exit(1);
  945.          }
  946.          printf("%s renamed to %s\n", sBinFilename, tracks[0].name);
  947.          fclose(fdCueFile);
  948.          return(0);
  949.       }
  950.  
  951.       for(i=nTracks-1; i>=0; i--) {
  952.          trackA = tracks[i];         
  953.          trackB = tracks[i+1];
  954.          // audio can't be done in the bin file due to header.
  955.          // 2336 can't either because it's expanded to 2352
  956.          if((doInPlace == 1) && (i == 0) && (trackA.mode != AUDIO) && (trackA.mode != MODE2_2336) ) {
  957.             sOutFilename[0] = '\0';
  958.          } else {
  959.             strcpy(sOutFilename, sOutdir); 
  960.             strcat(sOutFilename, trackA.name);
  961.          }
  962.          if ( ((doOneTrack == 1) && strcmp(trackA.num, sTrack)==0) || (doOneTrack == 0) ) {
  963.  
  964.             if(!((i == 0) && ((trackA.mode == MODE2_2352)||(trackA.mode == MODE1_2048)) && (doInPlace == 1) )){
  965.                if (!writegap || (trackA.mode != AUDIO)) { // when not Audio, don't append.
  966.                   dotrack(trackA.mode, trackA.idx0, trackA.idx1, trackB.idx0, trackA.offset1);
  967.                } else {
  968.                   /* if(trackA.idx0 == 0) // handles first track with pregap.
  969.                      dotrack(trackA.mode,           0, trackA.idx1, trackB.idx1, trackA.offset1);
  970.                   else
  971.                   */
  972.                   dotrack(trackA.mode, trackA.idx1, trackA.idx1, trackB.idx1, trackA.offset1);
  973.                }
  974.             }
  975.          } /*else {
  976.             fclose(fdBinFile); // just close bin file. Already MODE1_2048 or MODE2_2352
  977.          }*/
  978.          if( (doOneTrack == 0) && (doInPlace == 1) ) {
  979.             if( (i != 0) || ( (i == 0) && ((trackA.mode == AUDIO)||(trackA.mode == MODE2_2336)) ) ) {
  980.                printf("Truncating bin file to %ld bytes\n", trackA.offset1);
  981.                if( -1 == _chsize(_fileno(fdBinFile), trackA.offset1) ) {
  982.                   perror("\nbin2iso(_chsize)");
  983.                   exit(1);
  984.                }
  985.             } else {
  986.                printf("Renaming %s to %s\n", sBinFilename, trackA.name);
  987.                fclose(fdBinFile);
  988.                if( 0 != rename(sBinFilename, trackA.name) ) {
  989.                   perror("\nbin2iso(rename)");
  990.                   exit(1);
  991.                }
  992.             
  993.                // fix writepos for case when simply truncating...
  994.                if((trackA.mode == MODE2_2352) || (trackA.mode == MODE1_2048)){ writepos = trackB.offset0; }
  995.  
  996.                printf("Truncating to %ld bytes\n", writepos);
  997.             
  998.                fdBinFile = fopen(trackA.name, "rb+"); // gets closed in doTrack...
  999.                if(fdBinFile == NULL) { perror("bin2iso(fopen)"); exit(1); }
  1000.  
  1001.                if( -1 == _chsize(_fileno(fdBinFile), writepos) ) {
  1002.                   perror("\nbin2iso(_chsize)");
  1003.                   exit(1);
  1004.                }
  1005.             }
  1006.          }
  1007.       }   
  1008.    }
  1009.    fclose(fdCueFile);
  1010.    fclose(fdBinFile);
  1011.    return(0);  
  1012. }
  1013.  
  1014.  
  1015.  
  1016.