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