bin2iso.c 32 KB

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