1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258 |
- /* Changes:
- * - 64-bit fixes
- * - BigEndian fixes
- * - Enable sanity checking
- * - Various bugfixes
- */
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include <unistd.h>
- #include <limits.h>
- #include <libgen.h>
- #include <ctype.h>
- #define DEBUG 0
- #define CHECK 1
- typedef uint16_t le16_t; /* Little-endian 16-bit */
- typedef uint32_t le32_t; /* Little-endian 32-bit */
- //----------------Wave Stuff---------------------/
- typedef struct wavHdr {
- uint8_t riff[4];
- le32_t bytestoend;
- uint8_t wavetxt[4];
- uint8_t fmttxt[4];
- le32_t formatsize; // 16 byte format specifier
- le16_t format; // Windows PCM
- le16_t channels; // 2 channels
- le32_t samplerate; // 44,100 Samples/sec
- le32_t avgbyterate; // 176,400 Bytes/sec
- le16_t samplebytes; // 4 bytes/sample
- le16_t channelbits; // 16 bits/channel
- uint8_t datatxt[4];
- le32_t blocksize;
- } tWavHead;
- #define HEADBYTES 36
- #define WINDOWS_PCM 0x0001
- //-------------------------------------------------/
- /* G L O B A L D E F I N E S */
- typedef uint8_t byte;
- #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 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
- static inline le16_t cpu_to_le16(uint16_t value)
- {
- uint8_t *bytes = (uint8_t *)&value;
- le16_t ret;
- ret = bytes[0];
- ret |= (uint16_t)(bytes[1]) << 8;
- return ret;
- }
- static inline le32_t cpu_to_le32(uint32_t value)
- {
- uint8_t *bytes = (uint8_t *)&value;
- le32_t ret;
- ret = bytes[0];
- ret |= (uint32_t)(bytes[1]) << 8;
- ret |= (uint32_t)(bytes[2]) << 16;
- ret |= (uint32_t)(bytes[3]) << 24;
- return ret;
- }
- 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));
- 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
- static FILE *fdBinFile;
- static FILE *fdCueFile;
- static FILE *fdOutFile;
- static char sBinFilename[PATH_MAX];
- static char sOutFilename[PATH_MAX];
- static unsigned long int writepos = 0; // for inplace conversions...
- #define OUTBUF_SIZE 4*1024*1024
- #define INBUF_SIZE 4*1024*1024
- static unsigned char OUTBUF[OUTBUF_SIZE];
- static unsigned int OUTBUF_IDX = 0;
- static unsigned char INBUF[INBUF_SIZE];
- static unsigned int INBUF_RIDX = 0;
- static unsigned int INBUF_WIDX = 0;
- static int mode2to1 = 0;
- typedef struct track {
- unsigned short mode;
- unsigned long idx0;
- unsigned long idx1;
- char num[3];
- char name[80];
- unsigned long offset0;
- unsigned long offset1;
- unsigned long size; /* track size in bytes */
- } tTrack;
- static int 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
- }
- static void buffered_fwrite(unsigned char *array, unsigned int size)
- {
- unsigned int idx;
- unsigned long int readpos = 0;
- 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;
- }
- }
- static void flush_buffers(void)
- {
- unsigned long int readpos = 0;
- 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
- static 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 %s 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);
- }
- static 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",
- cpu_to_le32(0),
- "WAVE",
- "fmt ",
- cpu_to_le32(16), // 16 byte format specifier
- cpu_to_le16(WINDOWS_PCM), // format
- cpu_to_le16(2), // 2 Channels
- cpu_to_le32(44100), // 44,100 Samples/sec
- cpu_to_le32(176400), // 176,400 Bytes/sec
- cpu_to_le16(4), // 4 bytes/sample
- cpu_to_le16(16), // 16 bits/channel
- "data",
- cpu_to_le32(0),
- };
- uiLastIndex = startidx - 1;
- // Input -- process -- Output
- if (startidx != 0)
- printf("\nNote: PreGap = %ld 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 (%06ld,%06ld) ", sOutFilename, startidx, endidx - 1);
- } else {
- printf("Converting (%06ld,%06ld) ", 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%06ld", 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%06ld", 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%06ld", 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 = cpu_to_le32(blockswritten * SIZERAW);
- wavhead.bytestoend = cpu_to_le32((blockswritten * SIZERAW) + 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);
- }
- static 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.
- static int checkGaps(FILE * fdBinFile, tTrack tracks[], int nTracks)
- {
- int i, k;
- unsigned long int j;
- unsigned char buf[SIZERAW];
- 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;
- }
- static void string_tolower(char *str, size_t len)
- {
- while (len && *str) {
- *str = tolower(*str);
- str++;
- len--;
- }
- }
- static void string_toupper(char *str, size_t len)
- {
- while (len && *str) {
- *str = toupper(*str);
- str++;
- len--;
- }
- }
- static FILE * fopen_filecase(const char *path, const char *file, const char *openmode)
- {
- char filename[PATH_MAX] = { 0, };
- char final[PATH_MAX] = { 0, };
- FILE *fd;
- char *pos;
- /* Try original */
- strncpy(filename, file, sizeof(filename) - 1);
- snprintf(final, sizeof(final), "%s/%s", path, filename);
- fd = fopen(final, openmode);
- if (fd)
- goto ok;
- /* Try lower.lower */
- strncpy(filename, file, sizeof(filename) - 1);
- string_tolower(filename, (size_t)-1);
- snprintf(final, sizeof(final), "%s/%s", path, filename);
- fd = fopen(final, openmode);
- if (fd)
- goto ok;
- /* Try UPPER.UPPER */
- strncpy(filename, file, sizeof(filename) - 1);
- string_toupper(filename, (size_t)-1);
- snprintf(final, sizeof(final), "%s/%s", path, filename);
- fd = fopen(final, openmode);
- if (fd)
- goto ok;
- /* Try lower.UPPER */
- strncpy(filename, file, sizeof(filename) - 1);
- string_tolower(filename, (size_t)-1);
- pos = strrchr(filename, '.');
- if (pos)
- string_toupper(pos, (size_t)-1);
- snprintf(final, sizeof(final), "%s/%s", path, filename);
- fd = fopen(final, openmode);
- if (fd)
- goto ok;
- /* Try UPPER.lower */
- strncpy(filename, file, sizeof(filename) - 1);
- string_toupper(filename, (size_t)-1);
- pos = strrchr(filename, '.');
- if (pos)
- string_tolower(pos, (size_t)-1);
- snprintf(final, sizeof(final), "%s/%s", path, filename);
- fd = fopen(final, openmode);
- if (fd)
- goto ok;
- return NULL;
- ok:
- printf("%s: Opening file %s\n", file, final);
- return fd;
- }
- /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ */
- int main(int argc, char **argv)
- {
- // 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[PATH_MAX];
- const char *cueFilename;
- char cuePathBuf[PATH_MAX];
- char *cuePath;
- 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 <cuefile> [<output dir>] [-[a]wg] [-t XX] [-i] [-nob]\n");
- printf("or : bin2iso <cuefile> -c <binfile>\n");
- printf("\n");
- printf("Where:\n");
- printf(" <cuefile> - the .cue file that belongs to the .bin file to \n");
- printf(" be converted\n");
- printf(" <output dir> - 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 %d 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 <cuefile> from an existing\n");
- printf(" <binfile> \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]);
- }
- }
- cueFilename = argv[1];
- strcpy(cuePathBuf, cueFilename);
- cuePath = dirname(cuePathBuf);
- if (createCue == 1) {
- fdBinFile = fopen(sBinFilename, "rb");
- if (fdBinFile == NULL) {
- printf("Unable to open %s\n", sBinFilename);
- exit(1);
- }
- fdCueFile = fopen(cueFilename, "w");
- if (fdCueFile == NULL) {
- printf("Unable to create %s\n", cueFilename);
- 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(cueFilename, "r");
- if (fdCueFile == NULL) {
- printf("Unable to open %s\n", cueFilename);
- 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';
- } else {
- printf("Error: Filename not found on first line of cuefile.\n");
- exit(1);
- }
- // Open the bin file
- if (doInPlace == 1) {
- fdBinFile = fopen_filecase(cuePath, sBinFilename, "rb+");
- } else {
- fdBinFile = fopen_filecase(cuePath, 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 (%3ld 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;
- }
|