#include #include #include #define DEBUG 0 #define CHECK 0 /* don't bother checking bin for validity... */ //----------------Wave Stuff---------------------/ typedef unsigned char BYTE1 ; typedef unsigned short int BYTE2 ; typedef unsigned long int BYTE4 ; typedef struct wavHdr { BYTE1 riff[4]; BYTE4 bytestoend; BYTE1 wavetxt[4]; BYTE1 fmttxt[4]; BYTE4 formatsize; // 16 byte format specifier BYTE2 format; // Windows PCM BYTE2 channels; // 2 channels BYTE4 samplerate; // 44,100 Samples/sec BYTE4 avgbyterate; // 176,400 Bytes/sec BYTE2 samplebytes; // 4 bytes/sample BYTE2 channelbits; // 16 bits/channel BYTE1 datatxt[4]; BYTE4 blocksize; } tWavHead; #define HEADBYTES 36 #define WINDOWS_PCM 0x0001 //-------------------------------------------------/ /* G L O B A L D E F I N E S */ #define byte unsigned char #define SIZERAW 2352 #define SIZEISO_MODE1 2048 #define SIZEISO_MODE2_RAW 2352 #define SIZEISO_MODE2_FORM1 2048 #define SIZEISO_MODE2_FORM2 2336 #define AUDIO 0 #define MODE1 1 #define MODE2 2 #define MODE1_2352 10 #define MODE2_2352 20 #define MODE1_2048 30 #define MODE2_2336 40 #define RAWDATA FF // using this for leftover data when truncating for non-overburn #define PROG_INTERVAL 1024 #define UNKNOWN -1 #define OFFSET 150 // got this from easycd pro by looking at a blank disk so it may be off... #define CD74_MAX_SECTORS 334873 // 653.75 Mb unsigned long int Index(char m, char s, char f) { unsigned long int temp; temp = (((m>>4)*10) + (m&0xf)) * 60; temp = ( temp + (((s>>4)*10) + (s&0xf))) * 75; temp = temp + (((f>>4)*10) + (f&0xf)); // printf("\n%d%d %d%d %d%d = %06d", m>>4, m&f, s>>4, s&f, f>>4, f&f, temp); return temp; } void unIndex(unsigned long int index, char *ptr) { char m, s, f; f = (char) (index % 75); s = (char) ((index/75) % 60); m = (char) (index/(75*60)); sprintf(ptr, "%d%d:%d%d:%d%d", m/10, m%10, s/10, s%10, f/10, f%10); } // global variables FILE* fdBinFile; FILE* fdCueFile; FILE* fdOutFile; char sBinFilename[256]; char sOutFilename[256]; unsigned long int writepos = 0; // for inplace conversions... #define OUTBUF_SIZE 4*1024*1024 #define INBUF_SIZE 4*1024*1024 unsigned char OUTBUF[OUTBUF_SIZE]; unsigned int OUTBUF_IDX = 0; unsigned char INBUF[INBUF_SIZE]; unsigned int INBUF_RIDX = 0; unsigned int INBUF_WIDX = 0; int mode2to1 = 0; typedef struct track { unsigned short mode; unsigned long idx0; unsigned long idx1; unsigned char num[3]; unsigned char name[80]; unsigned long offset0; unsigned long offset1; unsigned long size; /* track size in bytes */ } tTrack; buffered_fread(unsigned char *array, unsigned int size) { unsigned int i; if(INBUF_WIDX == 0) { INBUF_WIDX += fread( INBUF, 1, (INBUF_SIZE/size)*size, fdBinFile ); } if(INBUF_WIDX == 0) return 0; // read failed. for(i = 0; i< size; i++) { array[i] = INBUF[INBUF_RIDX++]; if((INBUF_RIDX == INBUF_WIDX) && (i < (size -1))) { printf(" Warning: Premature EOF\n"); while(i++ < size) { array[i] == 0; }/* zero fill the rest */ break; } } if(INBUF_RIDX == INBUF_WIDX) { INBUF_RIDX = 0; INBUF_WIDX = 0; } return 1; // read passed } void buffered_fwrite(unsigned char *array, unsigned int size) { unsigned int idx; unsigned long int readpos; if(OUTBUF_IDX+size >= OUTBUF_SIZE) { if(fdOutFile == fdBinFile) { readpos = ftell(fdOutFile); if(0 != fseek(fdOutFile, writepos, SEEK_SET)) { perror("\nbin2iso(fseek)"); exit(1); } } // printf("\nWriting \n"); if( 1 != fwrite( OUTBUF, OUTBUF_IDX, 1, fdOutFile )) { perror("\nbin2iso(fwrite)"); fclose(fdOutFile); // remove(sOutFilename); exit(1); } if( 1 != fwrite( array, size, 1, fdOutFile )) { perror("\nbin2iso(fwrite)"); fclose(fdOutFile); // remove(sOutFilename); exit(1); } // printf("\nWrote %d bytes \n", OUTBUF_IDX+size); OUTBUF_IDX = 0; if(fdOutFile == fdBinFile) { writepos = ftell(fdOutFile); if(0 != fseek(fdOutFile, readpos, SEEK_SET)) { perror("\nbin2iso(fseek)"); exit(1); } } } else { for(idx = 0; idx < size; idx++) { OUTBUF[OUTBUF_IDX + idx] = array[idx]; } OUTBUF_IDX+=size; } } void flush_buffers(void) { unsigned long int readpos; if(fdOutFile == fdBinFile) { readpos = ftell(fdOutFile); if(0 != fseek(fdOutFile, writepos, SEEK_SET)) { perror("\nbin2iso(fseek)"); exit(1); } } if( 1 != fwrite( OUTBUF, OUTBUF_IDX, 1, fdOutFile )) { perror("\nbin2iso(fwrite)"); fclose(fdOutFile); // remove(sOutFilename); exit(1); } // printf("\nWrote %d bytes \n", OUTBUF_IDX); OUTBUF_IDX = 0; INBUF_RIDX = 0; INBUF_WIDX = 0; if(fdOutFile == fdBinFile) { writepos = ftell(fdOutFile); if(0 != fseek(fdOutFile, readpos, SEEK_SET)) { perror("\nbin2iso(fseek)"); exit(1); } } } // presumes Line is preloaded with the "current" line of the file int getTrackinfo(char *Line, tTrack *track) { // char tnum[3]; char inum[3]; char min; char sec; char block; track->idx0 = -1; track->idx1 = -1; // Get the 'mode' if (strncmp(&Line[2], "TRACK ", 6)==0) { strncpy(track->num, &Line[8], 2); track->num[2] = '\0'; track->mode = UNKNOWN; if(strncmp(&Line[11], "AUDIO", 5)==0) track->mode = AUDIO; if(strncmp(&Line[11], "MODE1/2352", 10)==0) track->mode = MODE1_2352; if(strncmp(&Line[11], "MODE1/2048", 10)==0) track->mode = MODE1_2048; if(strncmp(&Line[11], "MODE2/2352", 10)==0) track->mode = MODE2_2352; if(strncmp(&Line[11], "MODE2/2336", 10)==0) track->mode = MODE2_2336; } else return(1); // Set the name strcpy(track->name, sBinFilename); track->name[strlen(sBinFilename)-4] = '\0'; strcat(track->name, "-"); strcat(track->name, track->num); if( (track->mode == MODE1_2352) || (track->mode == MODE1_2048) || (track->mode == MODE2_2352) || (track->mode == MODE2_2336) ) { strcat(track->name, ".iso"); } else if(track->mode == AUDIO) { strcat(track->name, ".wav"); } else { printf("Track %d Unsupported mode\n", track->num); return(1); } // Get the track indexes while(1) { if(! fgets( Line, 256, fdCueFile ) ) { break; } if (strncmp(&Line[2], "TRACK ", 6)==0) { break; // next track starting } if (strncmp(&Line[4], "INDEX ", 6)==0) { strncpy(inum, &Line[10], 2); inum[2] = '\0'; min = ((Line[13]-'0')<<4) | Line[14]-'0'; sec = ((Line[16]-'0')<<4) | Line[17]-'0'; block = ((Line[19]-'0')<<4) | Line[20]-'0'; if(strcmp(inum, "00")==0) track->idx0 = Index(min, sec, block); else if(strcmp(inum, "01")==0) track->idx1 = Index(min, sec, block); else { printf("Unexpected Index number: %s\n", inum); exit(1); } } else if (strncmp(&Line[4], "PREGAP ", 7)==0) { ; /* ignore, handled below */ } else if (strncmp(&Line[4], "FLAGS ", 6)==0) { ; /* ignore */ } else { printf("Unexpected cuefile line: %s\n", Line); } } if(track->idx0 == -1) track->idx0 = track->idx1; if(track->idx1 == -1) track->idx1 = track->idx0; return(0); } void dotrack(short mode, long preidx, long startidx, long endidx, unsigned long offset) { unsigned char buf[SIZERAW+100]; unsigned long blockswritten = 0; unsigned int uiLastIndex; #if CHECK unsigned int uiCurrentIndex; #endif unsigned int write = 1; tWavHead wavhead = { "RIFF", 0, "WAVE", "fmt ", 16, // 16 byte format specifier WINDOWS_PCM, // format 2, // 2 Channels 44100, // 44,100 Samples/sec 176400, // 176,400 Bytes/sec 4, // 4 bytes/sample 16, // 16 bits/channel "data", 0 }; uiLastIndex = startidx-1; // Input -- process -- Output if(startidx != 0) printf("\nNote: PreGap = %d frames\n", startidx-preidx); else printf("\nNote: PreGap = %d frames\n", OFFSET); // cd standard: starting offset // - of course this isn't true for bootable cd's... if(sOutFilename[0] != '\0') { printf("Creating %s (%06d,%06d) ", sOutFilename, startidx, endidx-1); } else { printf("Converting (%06d,%06d) ", startidx, endidx-1); } switch(mode) { case AUDIO: printf("Audio"); break; case MODE1_2352: printf("Mode1/2048"); break; case MODE2_2336: printf("Mode2/2352"); break; case MODE2_2352: if(mode2to1 != 1) printf("Mode2/2352"); else printf("Mode1/2048"); break; case MODE1_2048: printf("Mode1/2048"); break; default: printf("Huh? What's going on?"); exit(1); } printf(" : "); if(sOutFilename[0] != '\0') { if(NULL == (fdOutFile = fopen (sOutFilename, "wb"))) { perror("bin2iso(fopen)"); } // printf("\nOpened File %s: %d\n", sOutFilename, fdOutFile); } else { fdOutFile = fdBinFile; } if (fdOutFile == NULL) { printf (" Unable to create %s\n", sOutFilename); exit (1); } if(0 != fseek(fdBinFile, offset, SEEK_SET)) { perror("\nbin2iso(fseek)"); exit(1); } #if (DEBUG == 0) if(mode == AUDIO) { if( 1 != fwrite( &wavhead, sizeof(wavhead), 1, fdOutFile ) ) { // write placeholder perror("\nbin2iso(fwrite)"); fclose(fdOutFile); // remove(sOutFilename); exit(1); } } #endif memset( &buf[0], '\0', sizeof( buf ) ); if(mode == MODE2_2336) { unsigned int M = 0, S = 2, F = 0; while( buffered_fread( &buf[16], SIZEISO_MODE2_FORM2) ) { //setup headed area (probably not necessary though... //buf[0] = 0; memset( &buf[1], 0xFF, sizeof(buf[0])*10 ); //buf[11] = 0; buf[12] = M; buf[13] = S; buf[14] = F; buf[15] = MODE2; if((++F&0xF) == 0xA) F += 6; if(F == 0x75) { S++; F = 0; } if((S&0xF) == 0xA) S += 6; if(S == 0x60) { M++; S = 0; } if((M&0xF) == 0xA) M += 6; // printf("\n%x:%x:%x", M, S, F); buffered_fwrite( buf, SIZERAW ); uiLastIndex++; memset( &buf[0], '\0', sizeof( buf ) ); if (startidx%PROG_INTERVAL == 0) { printf("\b\b\b\b\b\b%06d", startidx); } if (++startidx == endidx) { printf("\b\b\b\b\b\bComplete\n"); break; } } } else if (mode == MODE1_2048) { while( buffered_fread( buf, SIZEISO_MODE1) ) { buffered_fwrite( buf, SIZEISO_MODE1 ); uiLastIndex++; if (startidx%PROG_INTERVAL == 0) { printf("\b\b\b\b\b\b%06d", startidx); } if (++startidx == endidx) { printf("\b\b\b\b\b\bComplete\n"); break; } } } else { while( buffered_fread( buf, SIZERAW) ) { switch(mode) { case AUDIO: #if (DEBUG == 0) buffered_fwrite( buf, SIZERAW ); #endif uiLastIndex++; blockswritten++; break; case MODE1_2352: // should put a crc check in here... #if CHECK if( buf[15] != MODE1) { printf("\nWarning: Mode Error in bin file!\n"); printf(" %02x:%02x:%02x : mode %02x\n", buf[12], buf[13], buf[14], buf[15] ); //exit(1); } uiCurrentIndex = Index(buf[12], buf[13], buf[14]) - OFFSET; if(uiCurrentIndex != uiLastIndex+1) { printf("\nWarning: Frame Error in bin file!\n"); printf("Last %02d:%02d:%02d (%d)\n", ((uiLastIndex+OFFSET)/75)/60, ((uiLastIndex+OFFSET)/75)%60, (uiLastIndex+OFFSET)%75, uiLastIndex ); printf("Current %02x:%02x:%02x (%d)\n", buf[12], buf[13], buf[14], uiCurrentIndex ); printf("Expecting %02d:%02d:%02d (%d)\n", ((uiLastIndex+OFFSET+1)/75)/60, ((uiLastIndex+OFFSET+1)/75)%60, (uiLastIndex+OFFSET+1)%75, uiLastIndex+1 ); } #endif #if (DEBUG == 0) buffered_fwrite( &buf[16], SIZEISO_MODE1 ); #endif #if CHECK uiLastIndex = uiCurrentIndex; #endif break; case MODE2_2352: #if CHECK if( (buf[15]&0xf) != MODE2) { printf("\nWarning: Mode Error in bin file!\n"); printf(" %02x:%02x:%02x : mode %02x\n", buf[12], buf[13], buf[14], buf[15] ); //exit(1); } uiCurrentIndex = Index(buf[12], buf[13], buf[14]) - OFFSET; if(uiCurrentIndex != uiLastIndex+1) { printf("\nWarning: Frame Error in bin file!\n"); printf("Last %02d:%02d:%02d (%d)\n", ((uiLastIndex+OFFSET)/75)/60, ((uiLastIndex+OFFSET)/75)%60, (uiLastIndex+OFFSET)%75, uiLastIndex ); printf("Current %02x:%02x:%02x (%d)\n", buf[12], buf[13], buf[14], uiCurrentIndex ); printf("Expecting %02d:%02d:%02d (%d)\n", ((uiLastIndex+OFFSET+1)/75)/60, ((uiLastIndex+OFFSET+1)/75)%60, (uiLastIndex+OFFSET+1)%75, uiLastIndex+1 ); } #endif #if (DEBUG == 0) if(mode2to1) buffered_fwrite( &buf[16+8], SIZEISO_MODE1 ); else if(write) buffered_fwrite( &buf[0], SIZEISO_MODE2_RAW ); #endif #if CHECK uiLastIndex = uiCurrentIndex; #endif break; default: printf("Unkown Mode\n"); exit(1); break; } memset( &buf[0], '\0', sizeof( buf ) ); if (startidx%PROG_INTERVAL == 0) { printf("\b\b\b\b\b\b%06d", startidx); } if (++startidx == endidx) { printf("\b\b\b\b\b\bComplete\n"); break; } } } flush_buffers(); // flushes write buffer // and clears read buffer. if(mode == AUDIO) { wavhead.blocksize = blockswritten*SIZERAW; wavhead.bytestoend = wavhead.blocksize + HEADBYTES; // rewind to the beginning if(0 != fseek(fdOutFile, 0, SEEK_SET)) { perror("\nbin2iso(fseek)"); exit(1); } #if (DEBUG == 0) fwrite( &wavhead, sizeof(wavhead), 1, fdOutFile ); #endif } fclose(fdOutFile); } void doCueFile(void) { int track = 1; unsigned long int binIndex = 0; unsigned long int trackIndex = 0; const int gapThreshold = 20; // look for 0.266 sec gap const int valueThreshold = 800; // look for samples < 700 int count = 0; int i, blank; int gapon = 0; short value; char mode[12] = "AUDIO"; char index0[9] = "00:00:00"; char index1[9] = "00:00:00"; unsigned char buf[SIZERAW+100]; printf( "FILE %s BINARY\n", sBinFilename); fprintf(fdCueFile, "FILE %s BINARY\n", sBinFilename); memset( buf, '\0', sizeof( buf ) ); while( fread( buf, 1, SIZERAW, fdBinFile ) ) { if(trackIndex == 0) { if ( (buf[0] == 0x00) && (buf[1] == 0xFF) && (buf[2] == 0xFF) && (buf[3] == 0xFF) && (buf[4] == 0xFF) && (buf[5] == 0xFF) && (buf[6] == 0xFF) && (buf[7] == 0xFF) && (buf[8] == 0xFF) && (buf[9] == 0xFF) && (buf[10] == 0xFF) && (buf[11] == 0x00) ) { sprintf(mode, "MODE%d/2352", buf[15]); } else { sprintf(mode, "AUDIO"); } } if(binIndex == 0) { printf( " TRACK %02d %s\n", track, mode); fprintf(fdCueFile, " TRACK %02d %s\n", track, mode); printf( " INDEX 01 %s\n", index0); fprintf(fdCueFile, " INDEX 01 %s\n", index0); } blank = 1; for(i = 0; i < SIZERAW; i+=2) { value = buf[i+1]; value = ((value << 8) | buf[i]); // printf("%f %i\n",(1.0/75)*binIndex, value); if(abs(value) > valueThreshold) { blank = 0; break; } } // if(i == SIZERAW) printf("%f ~blank~\n", (1.0/75)*binIndex); if(blank == 1) count++; else if (gapon == 1) { gapon = 0; unIndex(binIndex-count, index0); count = 0; unIndex(binIndex, index1); printf( " TRACK %02d %s\n", track, mode); fprintf(fdCueFile, " TRACK %02d %s\n", track, mode); printf( " INDEX 00 %s\n", index0); fprintf(fdCueFile, " INDEX 00 %s\n", index0); printf( " INDEX 01 %s\n", index1); fprintf(fdCueFile, " INDEX 01 %s\n", index1); } if((count > gapThreshold) && (gapon == 0)) { gapon = 1; track++; trackIndex = -1; } memset( buf, '\0', sizeof( buf ) ); binIndex++; trackIndex++; } } // return 0 to when no data found, 1 when there is. int checkGaps(FILE *fdBinFile, tTrack tracks[], int nTracks) { int i, k; unsigned long int j; unsigned char buf[SIZERAW]; int c = 0; int writegap = 0; short value; int count; if(nTracks == 2) { return 0; }; // don't need to bother with single track images printf("Checking gap data:\n"); for (i = 0; i < nTracks; i++) { if((tracks[i].offset0 != tracks[i].offset1) && (tracks[i-1].mode == AUDIO)) { if(0 != fseek(fdBinFile, tracks[i].offset0, SEEK_SET)) { perror("\nbin2iso(fseek)"); exit(1); } count = 0; for(j = tracks[i].idx0; j < tracks[i].idx1; j++) { if(0 == fread( buf, SIZERAW, 1, fdBinFile ) ) { perror("bin2iso(fread)"); exit(1); } for(k = 0; k < SIZERAW; k+=2) { value = buf[k+1]; value = ((value << 8) | buf[k]); if(value != 0) { count++; // printf("%10d: %2x\n", count ,value ); } } } if(count != 0) { printf(" Track%02d - %d values of Non-Zero gap data encountered\n", i-1, count); if((count > SIZERAW/2/2) && (writegap == 0)) { printf(" -->Threashold reached\n"); writegap = 1; } } } } return writegap; } /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ */ int main(int argc, char **argv) { unsigned long int count = 0; // int printon = 0; char sLine[256]; int i,j,q; // int writegap = -1; // auto detect pregap data action by default. int writegap = 1; // keep pregap data by default. int no_overburn = 0; int createCue = 0; char sTrack[3] = "00"; int doOneTrack = 0; int doInPlace = 0; tTrack trackA; tTrack trackB; tTrack tracks[100]; int nTracks = 0; char sOutdir[192]; sOutFilename[0] = '\0'; /* Tell them what I am. */ printf ("\n%s, %s", __DATE__, __TIME__); printf ("\nbin2iso V1.9b - Converts RAW format (.bin) files to ISO/WAV format"); printf ("\n Bob Doiron, ICQ#280251 \n"); printf ("\nCheck for updates at http://users.andara.com/~doiron\n\n"); if(argc < 2) { printf("Usage: bin2iso [] [-[a]wg] [-t XX] [-i] [-nob]\n"); printf("or : bin2iso -c \n"); printf("\n"); printf("Where:\n"); printf(" - the .cue file that belongs to the .bin file to \n"); printf(" be converted\n"); printf(" - the output directory (defaults to current dir) \n"); printf(" -nwg - indicates that audio data found in the track \n"); printf(" 'gaps' shouldn't be appended to the audio tracks\n"); printf(" -awg - looks for non-zero data in the 'gaps', if found\n"); printf(" then gaps are appended to audio tracks. Looks \n"); printf(" for more than 1/2 of a sector of non-zero values\n"); printf(" (%d values), \n", SIZERAW/2/2); printf(" -t XX - Extracts the XX'th track. \n"); printf(" -i - Performs the conversion 'in place'. Meaning it \n"); printf(" truncates the binfile after each track is \n"); printf(" created to minimize diskspace requirements. \n"); printf(" [not valid with -t] \n"); printf(" -nob - Doesn't use overburn data past %ld sectors. \n", CD74_MAX_SECTORS); printf(" This of course presumes that the data is not \n"); printf(" useful. \n"); printf(" -c - Attempts to create a from an existing\n"); printf(" \n"); exit (1); } strcpy(sOutdir, "./"); // default path printf("\n"); for (i=2; i < argc; i++) { if (argv[i][0] == '-') { /* if (strncmp(&(argv[i][1]), "wg", 2)==0) { writegap = 1; } else */ if (strncmp(&(argv[i][1]), "awg", 3)==0) { writegap = -1; printf("Note: Auto-detecting pregap data\n"); } else if (strncmp(&(argv[i][1]), "nwg", 3)==0) { writegap = 0; } else if (strncmp(&(argv[i][1]), "m2to1", 5)==0) { mode2to1 = 1; printf("Note: Converting Mode2 ISO to Mode1\n"); } else if (strncmp(&(argv[i][1]), "t", 1)==0) { strcpy(sTrack, argv[i+1]); doOneTrack = 1; i++; } else if (strncmp(&(argv[i][1]), "i", 1)==0) { if(doOneTrack == 1) { printf("Invalid combination of options...\n"); exit(1); } printf("Bin file will be truncated after each track created\n"); doInPlace = 1; } else if (strncmp(&(argv[i][1]), "c", 1)==0) { createCue = 1; strcpy(sBinFilename, argv[i+1]); i++; } else if (strncmp(&(argv[i][1]), "nob", 3)==0) { no_overburn = 1; } } else { strcpy(sOutdir, argv[2]); } } if(createCue == 1) { fdBinFile = fopen (sBinFilename, "rb"); if (fdBinFile == NULL) { printf ("Unable to open %s\n", sBinFilename); exit (1); } fdCueFile = fopen (argv[1], "w"); if (fdCueFile == NULL) { printf ("Unable to create %s\n", argv[1]); exit (1); } if((strcmp(&sBinFilename[strlen(sBinFilename)-4], ".wav")==0) || (strcmp(&sBinFilename[strlen(sBinFilename)-4], ".WAV")==0) ) { printf(".wav binfile - Skipping wav header\n"); fread( sLine, 1, sizeof(tWavHead), fdBinFile ); } doCueFile(); } else { fdCueFile = fopen (argv[1], "r"); if (fdCueFile == NULL) { printf ("Unable to open %s\n", argv[1]); exit (1); } // get bin filename from cuefile... why? why not. if(! fgets( sLine, 256, fdCueFile ) ) { printf ("Error Reading Cuefile\n"); exit (1); } if (strncmp(sLine, "FILE ", 5)==0) { i = 0; j = 0; q = 0; // track open and closed quotes do { sBinFilename[j] = sLine[5+i]; i++; j++; if ((sBinFilename[j-1] == '\\') || (sBinFilename[j-1] == '/')) { j = 0; } //strip out path info if (sBinFilename[j-1] == '"') { j--; q++;} // strip out quotes } while ((sLine[5+i-1] != ' ') || (q == 1)); sBinFilename[j] = '\0'; //bug?? Why did a trailing space show up?? while(sBinFilename[--j] == ' ') sBinFilename[j] = '\0'; // do not need to convert to lower case on unix system // strlwr(sBinFilename); } else { printf ("Error: Filename not found on first line of cuefile.\n", argv[1]); exit (1); } // Open the bin file if(doInPlace == 1) { fdBinFile = fopen (sBinFilename, "rb+"); } else { fdBinFile = fopen (sBinFilename, "rb"); } if (fdBinFile == NULL) { printf ("Unable to open %s\n", sBinFilename); perror("\nbin2iso(fopen)"); exit(1); } // Get next line if(! fgets( sLine, 256, fdCueFile ) ) { printf ("Error Reading Cuefile\n"); exit (1); } if(strlen(sOutdir) > 0) { if((sOutdir[strlen(sOutdir)-1] != '/' ) && (sOutdir[strlen(sOutdir)-1] != ':' ) ) { strcat(sOutdir, "/"); } } while(!feof(fdCueFile)) { getTrackinfo(sLine, &tracks[nTracks++]); } tracks[nTracks].idx0 = tracks[nTracks].idx1 = -1; switch (tracks[0].mode) { case MODE1_2048: tracks[0].offset0 = tracks[0].idx0*SIZEISO_MODE1; break; case MODE2_2336: tracks[0].offset0 = tracks[0].idx0*SIZEISO_MODE2_FORM2; break; default: // AUDIO, MODE1_2352, MODE2_2352: tracks[0].offset0 = tracks[0].idx0*SIZERAW; break; } /* set offsets */ if(0 != fseek(fdBinFile, 0, SEEK_END)) { perror("\nbin2iso(fseek)"); exit(1); } tracks[nTracks].offset0 = tracks[nTracks].offset1 = ftell(fdBinFile); for(i = 0; i < nTracks; i++) { switch (tracks[i].mode) { case MODE1_2048: tracks[i].offset1 = tracks[i].offset0 + (tracks[i].idx1-tracks[i].idx0)*SIZEISO_MODE1; if(tracks[i+1].idx0 != -1) tracks[i+1].offset0 = tracks[i].offset1 + (tracks[i+1].idx0 - tracks[i].idx1)*SIZEISO_MODE1; else { tracks[i+1].idx0 = tracks[i+1].idx1 = (tracks[i+1].offset0 - tracks[i].offset1)/SIZEISO_MODE1 + tracks[i].idx1; if(((tracks[i+1].offset0 - tracks[i].offset1)%SIZEISO_MODE1) != 0) printf("Warning: Bin file has invalid byte count for cuefile.\n"); } break; case MODE2_2336: tracks[i].offset1 = tracks[i].offset0 + (tracks[i].idx1-tracks[i].idx0)*SIZEISO_MODE2_FORM2; if(tracks[i+1].idx0 != -1) tracks[i+1].offset0 = tracks[i].offset1 + (tracks[i+1].idx0 - tracks[i].idx1)*SIZEISO_MODE2_FORM2; else { tracks[i+1].idx0 = tracks[i+1].idx1 = (tracks[i+1].offset0 - tracks[i].offset1)/SIZEISO_MODE2_FORM2 + tracks[i].idx1; if(((tracks[i+1].offset0 - tracks[i].offset1)%SIZEISO_MODE2_FORM2) != 0) printf("Warning: Bin file has invalid byte count for cuefile.\n"); } break; default: // AUDIO, MODE1_2352, MODE2_2352: tracks[i].offset1 = tracks[i].offset0 + (tracks[i].idx1-tracks[i].idx0)*SIZERAW; if(tracks[i+1].idx0 != -1) tracks[i+1].offset0 = tracks[i].offset1 + (tracks[i+1].idx0 - tracks[i].idx1)*SIZERAW; else { tracks[i+1].idx0 = tracks[i+1].idx1 = (tracks[i+1].offset0 - tracks[i].offset1)/SIZERAW + tracks[i].idx1; if(((tracks[i+1].offset0 - tracks[i].offset1)%SIZERAW) != 0) printf("Warning: Bin file has invalid byte count for cuefile.\n"); } break; } } // if not allowing overburn, then create a new track to hold extra data... if(no_overburn == 1) { i = nTracks; if(tracks[i].idx0 > CD74_MAX_SECTORS) { tracks[i+1] = tracks[nTracks]; strcpy(tracks[i].name, "obdatatemp.bin"); tracks[i].idx0 = CD74_MAX_SECTORS; tracks[i].idx1 = CD74_MAX_SECTORS; switch (tracks[i-1].mode) { case MODE1_2048: tracks[i].offset0 = tracks[i-1].offset1 + (tracks[i].idx0 - tracks[i-1].idx1)*SIZEISO_MODE1; break; case MODE2_2336: tracks[i].offset0 = tracks[i-1].offset1 + (tracks[i].idx0 - tracks[i-1].idx1)*SIZEISO_MODE2_FORM2; break; default: // AUDIO, MODE1_2352, MODE2_2352: tracks[i].offset0 = tracks[i-1].offset1 + (tracks[i].idx0 - tracks[i-1].idx1)*SIZERAW; break; } tracks[i].offset1 = tracks[i].offset0; tracks[i].mode = tracks[i-1].mode; nTracks++; } } /* set sizes */ for(i = 0; i < nTracks; i++) { switch (tracks[i].mode) { case MODE1_2352: tracks[i].size = ((tracks[i+1].offset1 - tracks[i].offset1) / SIZERAW ) * SIZEISO_MODE1; break; case MODE2_2336: tracks[i].size = ((tracks[i+1].offset1 - tracks[i].offset1) / SIZEISO_MODE2_FORM2 ) * SIZERAW; break; default: // MODE1_2048, MODE2_2352, AUDIO tracks[i].size = tracks[i+1].offset1 - tracks[i].offset1; break; } } if(writegap == -1) { writegap = checkGaps(fdBinFile, tracks, nTracks); } if(writegap == 1) printf("Note: Appending pregap data to end of audio tracks\n"); else printf("Note: Discarding pregap data\n"); printf("\n"); for(i = 0; i <= nTracks-1; i++) { printf("%s (%3d Mb) - sectors %06ld:%06ld (offset %09ld:%09ld)\n", tracks[i].name, tracks[i].size/(1024*1024), tracks[i].idx1, ( ((writegap == 0) || (tracks[i].mode != AUDIO)) ? tracks[i+1].idx0 : tracks[i+1].idx1)-1, tracks[i].offset1, ( ((writegap == 0) || (tracks[i].mode != AUDIO)) ? tracks[i+1].offset0 : tracks[i+1].offset1)-1 ); } printf("\n"); if( (((mode2to1 != 1) && (tracks[0].mode == MODE2_2352)) || (tracks[0].mode == MODE1_2048)) && (nTracks == 1) ) { if(tracks[0].mode == MODE2_2352) { printf("Mode2/2352"); } if(tracks[0].mode == MODE1_2048) { printf("Mode1/2048"); } printf(" single track bin file indicated by cue file\n"); fclose(fdBinFile); if( 0 != rename(sBinFilename, tracks[0].name) ) { perror("\nbin2iso(rename)"); exit(1); } printf("%s renamed to %s\n", sBinFilename, tracks[0].name); fclose(fdCueFile); return(0); } for(i=nTracks-1; i>=0; i--) { trackA = tracks[i]; trackB = tracks[i+1]; // audio can't be done in the bin file due to header. // 2336 can't either because it's expanded to 2352 if((doInPlace == 1) && (i == 0) && (trackA.mode != AUDIO) && (trackA.mode != MODE2_2336) ) { sOutFilename[0] = '\0'; } else { strcpy(sOutFilename, sOutdir); strcat(sOutFilename, trackA.name); } if ( ((doOneTrack == 1) && strcmp(trackA.num, sTrack)==0) || (doOneTrack == 0) ) { if(!((i == 0) && ((trackA.mode == MODE2_2352)||(trackA.mode == MODE1_2048)) && (doInPlace == 1) )){ if (!writegap || (trackA.mode != AUDIO)) { // when not Audio, don't append. dotrack(trackA.mode, trackA.idx0, trackA.idx1, trackB.idx0, trackA.offset1); } else { /* if(trackA.idx0 == 0) // handles first track with pregap. dotrack(trackA.mode, 0, trackA.idx1, trackB.idx1, trackA.offset1); else */ dotrack(trackA.mode, trackA.idx1, trackA.idx1, trackB.idx1, trackA.offset1); } } } /*else { fclose(fdBinFile); // just close bin file. Already MODE1_2048 or MODE2_2352 }*/ if( (doOneTrack == 0) && (doInPlace == 1) ) { if( (i != 0) || ( (i == 0) && ((trackA.mode == AUDIO)||(trackA.mode == MODE2_2336)) ) ) { printf("Truncating bin file to %ld bytes\n", trackA.offset1); if( -1 == ftruncate(fileno(fdBinFile), trackA.offset1) ) { perror("\nbin2iso(_chsize)"); exit(1); } } else { printf("Renaming %s to %s\n", sBinFilename, trackA.name); fclose(fdBinFile); if( 0 != rename(sBinFilename, trackA.name) ) { perror("\nbin2iso(rename)"); exit(1); } // fix writepos for case when simply truncating... if((trackA.mode == MODE2_2352) || (trackA.mode == MODE1_2048)){ writepos = trackB.offset0; } printf("Truncating to %ld bytes\n", writepos); fdBinFile = fopen(trackA.name, "rb+"); // gets closed in doTrack... if(fdBinFile == NULL) { perror("bin2iso(fopen)"); exit(1); } if( -1 == ftruncate(fileno(fdBinFile), writepos) ) { perror("\nbin2iso(_chsize)"); exit(1); } } } } } fclose(fdCueFile); fclose(fdBinFile); return(0); }