bin_to_cso_mp3.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
  1. /*
  2. * bin_to_cso_mp3
  3. * originally written by Exophase as "bin_to_iso_ogg"
  4. * updated for cso/mp3 by notaz
  5. * v2
  6. */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <unistd.h>
  10. #include <sys/stat.h>
  11. #include <string.h>
  12. #include <ctype.h>
  13. #include <stdint.h>
  14. #ifndef MAX_PATH
  15. #define MAX_PATH 1024
  16. #endif
  17. #ifdef _WIN32
  18. #include <windows.h>
  19. #define DIR_SEPARATOR_CHAR '\\'
  20. #define PATH_SEPARATOR_CHAR ';'
  21. #define LAME_BINARY "lame.exe"
  22. #define CISO_BINARY "ciso.exe"
  23. #define NULL_REDIR "> NUL 2>&1"
  24. #else
  25. #define DIR_SEPARATOR_CHAR '/'
  26. #define PATH_SEPARATOR_CHAR ':'
  27. #define LAME_BINARY "lame"
  28. #define CISO_BINARY "ciso"
  29. #define NULL_REDIR "> /dev/null 2>&1"
  30. #define mkdir(x) mkdir(x, S_IRWXU)
  31. #endif
  32. #define LAME_OPTIONS "-h --cbr"
  33. typedef uint8_t u8;
  34. typedef uint16_t u16;
  35. typedef uint32_t u32;
  36. typedef uint64_t u64;
  37. typedef int8_t s8;
  38. typedef int16_t s16;
  39. typedef int32_t s32;
  40. typedef int64_t s64;
  41. typedef enum
  42. {
  43. TRACK_FILE_TYPE_BINARY,
  44. TRACK_FILE_TYPE_WAVE,
  45. } track_file_type_enum;
  46. typedef struct
  47. {
  48. u32 file_number;
  49. u32 physical_offset;
  50. u32 sector_offset;
  51. u32 sector_count;
  52. u32 pregap_offset;
  53. u32 sector_size;
  54. u32 format_type;
  55. } cd_track_struct;
  56. typedef struct
  57. {
  58. track_file_type_enum type;
  59. FILE *file_handle;
  60. u32 current_offset;
  61. } cd_track_file_struct;
  62. typedef struct
  63. {
  64. FILE *bin_file;
  65. cd_track_file_struct track_files[100];
  66. u32 num_files;
  67. s32 first_track;
  68. s32 last_track;
  69. u32 num_physical_tracks;
  70. u32 num_sectors;
  71. s32 last_seek_track;
  72. cd_track_struct physical_tracks[100];
  73. cd_track_struct *logical_tracks[100];
  74. } cd_bin_struct;
  75. cd_bin_struct cd_bin;
  76. int opt_use_mp3 = 1;
  77. int opt_mp3_bitrate = 128;
  78. int opt_use_cso = 1;
  79. static void myexit(int code)
  80. {
  81. #ifdef _WIN32
  82. system("pause");
  83. #endif
  84. exit(code);
  85. }
  86. char *skip_whitespace(char *str)
  87. {
  88. while (isspace(*str))
  89. str++;
  90. return str;
  91. }
  92. char *skip_whitespace_rev(char *str)
  93. {
  94. while (isspace(*str))
  95. str--;
  96. return str;
  97. }
  98. char *skip_nonspace_rev(char *str)
  99. {
  100. while (!isspace(*str))
  101. str--;
  102. return str;
  103. }
  104. s32 load_bin_cue(char *cue_file_name)
  105. {
  106. FILE *cue_file = fopen(cue_file_name, "rb");
  107. printf("loading cue file %s\n", cue_file_name);
  108. if(cue_file)
  109. {
  110. char line_buffer[256];
  111. char *line_buffer_ptr;
  112. char *tmp;
  113. char bin_file_name[MAX_PATH];
  114. char *separator_pos;
  115. s32 current_physical_track_number = -1;
  116. u32 current_physical_offset;
  117. u32 current_pregap = 0;
  118. u32 bin_file_size;
  119. cd_track_struct *current_physical_track = NULL;
  120. u32 i;
  121. // First, get filename. Only support binary right now.
  122. tmp = fgets(line_buffer, 255, cue_file);
  123. if (tmp == NULL) goto invalid;
  124. separator_pos = line_buffer + strlen(line_buffer) - 1;
  125. separator_pos = skip_whitespace_rev(separator_pos);
  126. if (separator_pos <= line_buffer) goto invalid;
  127. separator_pos = skip_nonspace_rev(separator_pos);
  128. if (separator_pos <= line_buffer) goto invalid;
  129. separator_pos = skip_whitespace_rev(separator_pos);
  130. if (separator_pos <= line_buffer) goto invalid;
  131. // see if what's there is a quote.
  132. if(*separator_pos == '"')
  133. {
  134. separator_pos[0] = 0;
  135. separator_pos = strrchr(line_buffer, '"');
  136. if (separator_pos == NULL) goto invalid;
  137. strcpy(bin_file_name, separator_pos + 1);
  138. }
  139. else
  140. {
  141. // Otherwise go to the next space.
  142. separator_pos[1] = 0;
  143. separator_pos = strrchr(line_buffer, ' ');
  144. if (separator_pos == NULL) goto invalid;
  145. strcpy(bin_file_name, separator_pos + 1);
  146. }
  147. // Might have to change directory first.
  148. separator_pos = strrchr(cue_file_name, DIR_SEPARATOR_CHAR);
  149. if(separator_pos)
  150. {
  151. char current_dir[MAX_PATH];
  152. getcwd(current_dir, MAX_PATH);
  153. *separator_pos = 0;
  154. chdir(cue_file_name);
  155. #ifdef GP2X_BUILD
  156. cd_bin.bin_file = open(bin_file_name, O_RDONLY);
  157. #else
  158. cd_bin.bin_file = fopen(bin_file_name, "rb");
  159. #endif
  160. *separator_pos = DIR_SEPARATOR_CHAR;
  161. chdir(current_dir);
  162. }
  163. else
  164. {
  165. #ifdef GP2X_BUILD
  166. cd_bin.bin_file = open(bin_file_name, O_RDONLY);
  167. #else
  168. cd_bin.bin_file = fopen(bin_file_name, "rb");
  169. #endif
  170. }
  171. if (cd_bin.bin_file == NULL)
  172. {
  173. printf("can't open bin file: \"%s\"\n", bin_file_name);
  174. return -1;
  175. }
  176. else
  177. {
  178. printf("found bin file: %s\n", bin_file_name);
  179. }
  180. for(i = 0; i < 100; i++)
  181. {
  182. cd_bin.logical_tracks[i] = NULL;
  183. }
  184. cd_bin.first_track = -1;
  185. cd_bin.last_track = -1;
  186. cd_bin.num_physical_tracks = 0;
  187. cd_bin.num_sectors = 0;
  188. // Get line
  189. while(fgets(line_buffer, 256, cue_file))
  190. {
  191. // Skip trailing whitespace
  192. line_buffer_ptr = skip_whitespace(line_buffer);
  193. // Dirty, but should work - switch on first character.
  194. switch(line_buffer_ptr[0])
  195. {
  196. // New track number
  197. case 'T':
  198. {
  199. u32 new_track_number;
  200. char track_type[64];
  201. sscanf(line_buffer_ptr, "TRACK %d %s", &new_track_number,
  202. track_type);
  203. current_physical_track_number++;
  204. current_physical_track =
  205. cd_bin.physical_tracks + current_physical_track_number;
  206. current_physical_track->sector_size = 2352;
  207. if(!strcmp(track_type, "AUDIO"))
  208. {
  209. current_physical_track->format_type = 0;
  210. current_physical_track->sector_size = 2352;
  211. }
  212. if(!strcmp(track_type, "MODE1/2352"))
  213. {
  214. current_physical_track->format_type = 4;
  215. current_physical_track->sector_size = 2352;
  216. }
  217. if(!strcmp(track_type, "MODE1/2048"))
  218. {
  219. current_physical_track->format_type = 4;
  220. current_physical_track->sector_size = 2048;
  221. }
  222. cd_bin.logical_tracks[new_track_number] = current_physical_track;
  223. cd_bin.num_physical_tracks++;
  224. if((cd_bin.first_track == -1) ||
  225. (new_track_number < cd_bin.first_track))
  226. {
  227. cd_bin.first_track = new_track_number;
  228. }
  229. if((cd_bin.last_track == -1) ||
  230. (new_track_number > cd_bin.last_track))
  231. {
  232. cd_bin.last_track = new_track_number;
  233. }
  234. break;
  235. }
  236. // Pregap
  237. case 'P':
  238. {
  239. u32 minutes, seconds, frames;
  240. sscanf(line_buffer_ptr, "PREGAP %d:%d:%d", &minutes,
  241. &seconds, &frames);
  242. current_pregap += frames + (seconds * 75) + (minutes * 75 * 60);
  243. break;
  244. }
  245. // Index
  246. case 'I':
  247. {
  248. u32 index_number;
  249. u32 minutes, seconds, frames;
  250. u32 sector_offset;
  251. sscanf(line_buffer_ptr, "INDEX %d %d:%d:%d", &index_number,
  252. &minutes, &seconds, &frames);
  253. sector_offset = frames + (seconds * 75) + (minutes * 75 * 60);
  254. if(index_number == 1)
  255. {
  256. current_physical_track->pregap_offset = current_pregap;
  257. current_physical_track->sector_offset = sector_offset;
  258. }
  259. break;
  260. }
  261. }
  262. }
  263. current_physical_offset = 0;
  264. for(i = 0; i < cd_bin.num_physical_tracks - 1; i++)
  265. {
  266. cd_bin.physical_tracks[i].sector_count =
  267. cd_bin.physical_tracks[i + 1].sector_offset -
  268. cd_bin.physical_tracks[i].sector_offset;
  269. cd_bin.physical_tracks[i].physical_offset = current_physical_offset;
  270. current_physical_offset += (cd_bin.physical_tracks[i].sector_count *
  271. cd_bin.physical_tracks[i].sector_size);
  272. cd_bin.physical_tracks[i].sector_offset +=
  273. cd_bin.physical_tracks[i].pregap_offset;
  274. cd_bin.num_sectors += cd_bin.physical_tracks[i].sector_count;
  275. }
  276. #ifdef GP2X_BUILD
  277. bin_file_size = lseek(cd_bin.bin_file, 0, SEEK_END);
  278. lseek(cd_bin.bin_file, 0, SEEK_SET);
  279. #else
  280. fseek(cd_bin.bin_file, 0, SEEK_END);
  281. bin_file_size = ftell(cd_bin.bin_file);
  282. fseek(cd_bin.bin_file, 0, SEEK_SET);
  283. #endif
  284. // Set the last track data
  285. cd_bin.physical_tracks[i].physical_offset = current_physical_offset;
  286. cd_bin.physical_tracks[i].sector_offset +=
  287. cd_bin.physical_tracks[i].pregap_offset;
  288. cd_bin.physical_tracks[i].sector_count =
  289. (bin_file_size - current_physical_offset) /
  290. cd_bin.physical_tracks[i].sector_size;
  291. cd_bin.num_sectors += cd_bin.physical_tracks[i].sector_count;
  292. printf("finished loading cue %s\n", cue_file_name);
  293. printf("bin file: %s (%p)\n", bin_file_name, cd_bin.bin_file);
  294. printf("first track: %d, last track: %d\n", cd_bin.first_track,
  295. cd_bin.last_track);
  296. for(i = cd_bin.first_track; i <= cd_bin.last_track; i++)
  297. {
  298. printf("track %d (%p):\n", i, cd_bin.logical_tracks[i]);
  299. if(cd_bin.logical_tracks[i] == NULL)
  300. {
  301. printf(" (invalid)\n");
  302. }
  303. else
  304. {
  305. printf(" physical offset 0x%x\n",
  306. cd_bin.logical_tracks[i]->physical_offset);
  307. printf(" sector offset 0x%x\n",
  308. cd_bin.logical_tracks[i]->sector_offset);
  309. printf(" sector size %d\n",
  310. cd_bin.logical_tracks[i]->sector_size);
  311. }
  312. }
  313. cd_bin.last_seek_track = 0;
  314. fclose(cue_file);
  315. return 0;
  316. }
  317. return -1;
  318. invalid:
  319. printf("error: invalid/unsupported .cue file\n");
  320. return -1;
  321. }
  322. #define address8(base, offset) \
  323. *((u8 *)((u8 *)base + (offset))) \
  324. #define address16(base, offset) \
  325. *((u16 *)((u8 *)base + (offset))) \
  326. #define address32(base, offset) \
  327. *((u32 *)((u8 *)base + (offset))) \
  328. // This will only work on little endian platforms for now.
  329. s32 convert_bin_to_wav(FILE *bin_file, char *output_dir, char *wav_file_name,
  330. u32 sector_count)
  331. {
  332. FILE *wav_file;
  333. u8 wav_header[36];
  334. u8 *riff_header = wav_header + 0;
  335. u8 *fmt_header = wav_header + 0x0C;
  336. u8 sector_buffer[2352];
  337. u32 byte_length = sector_count * 2352;
  338. u32 i;
  339. chdir(output_dir);
  340. wav_file = fopen(wav_file_name, "wb");
  341. printf("writing wav %s, %x sectors\n", wav_file_name, sector_count);
  342. // RIFF type chunk
  343. memcpy(riff_header + 0x00, "RIFF", 4);
  344. address32(riff_header, 0x04) = byte_length + 44 - 8;
  345. memcpy(riff_header + 0x08, "WAVE", 4);
  346. // WAVE file chunk: format
  347. memcpy(fmt_header + 0x00, "fmt ", 4);
  348. // Chunk data size
  349. address32(fmt_header, 0x04) = 16;
  350. // Compression code: PCM
  351. address16(fmt_header, 0x08) = 1;
  352. // Number of channels: Stereo
  353. address16(fmt_header, 0x0a) = 2;
  354. // Sample rate: 44100Hz
  355. address32(fmt_header, 0x0c) = 44100;
  356. // Average bytes per second: sample rate * 4
  357. address32(fmt_header, 0x10) = 44100 * 4;
  358. // Block align (bytes per sample)
  359. address16(fmt_header, 0x14) = 4;
  360. // Bit depth
  361. address16(fmt_header, 0x16) = 16;
  362. // Write out header
  363. fwrite(wav_header, 36, 1, wav_file);
  364. // DATA chunk
  365. fprintf(wav_file, "data");
  366. // length
  367. fwrite(&byte_length, 4, 1, wav_file);
  368. // Write out sectors
  369. for(i = 0; i < sector_count; i++)
  370. {
  371. printf("\b\b\b%3i", i*100 / sector_count);
  372. fflush(stdout);
  373. fread(sector_buffer, 2352, 1, bin_file);
  374. fwrite(sector_buffer, 2352, 1, wav_file);
  375. }
  376. printf("\b\b\b100\n");
  377. fclose(wav_file);
  378. chdir("..");
  379. return 0;
  380. }
  381. void convert_wav_to_ogg(char *wav_file_name, char *output_dir,
  382. char *ogg_file_name)
  383. {
  384. char cmd_string[(MAX_PATH * 2) + 16];
  385. chdir(output_dir);
  386. sprintf(cmd_string, "oggenc %s", wav_file_name);
  387. system(cmd_string);
  388. unlink(wav_file_name);
  389. chdir("..");
  390. }
  391. void convert_wav_to_mp3(char *wav_file_name, char *output_dir,
  392. char *mp3_file_name)
  393. {
  394. char cmd_string[(MAX_PATH * 2) + 16];
  395. chdir(output_dir);
  396. sprintf(cmd_string, LAME_BINARY " " LAME_OPTIONS " -b %i \"%s\" \"%s\"",
  397. opt_mp3_bitrate, wav_file_name, mp3_file_name);
  398. if (system(cmd_string) != 0)
  399. {
  400. printf("failed to encode mp3\n");
  401. myexit(1);
  402. }
  403. unlink(wav_file_name);
  404. chdir("..");
  405. }
  406. s32 convert_bin_to_iso(FILE *bin_file, char *output_dir, char *iso_file_name,
  407. u32 sector_count)
  408. {
  409. FILE *iso_file;
  410. u8 sector_buffer[2352];
  411. u32 i;
  412. chdir(output_dir);
  413. iso_file = fopen(iso_file_name, "wb");
  414. if (iso_file == NULL)
  415. {
  416. printf("failed to open: %s\n", iso_file_name);
  417. myexit(1);
  418. }
  419. printf("writing iso %s, %x sectors\n", iso_file_name, sector_count);
  420. for(i = 0; i < sector_count; i++)
  421. {
  422. printf("\b\b\b%3i", i*100 / sector_count);
  423. fflush(stdout);
  424. fread(sector_buffer, 2352, 1, bin_file);
  425. fwrite(sector_buffer + 16, 2048, 1, iso_file);
  426. }
  427. printf("\b\b\b100\n");
  428. fclose(iso_file);
  429. chdir("..");
  430. return 0;
  431. }
  432. void convert_iso_to_cso(char *output_dir, char *iso_file_name, char *cso_file_name)
  433. {
  434. char cmd_string[(MAX_PATH * 2) + 16];
  435. chdir(output_dir);
  436. sprintf(cmd_string, CISO_BINARY " 9 \"%s\" \"%s\"", iso_file_name, cso_file_name);
  437. if (system(cmd_string) != 0)
  438. {
  439. printf("failed to convert iso to cso\n");
  440. myexit(1);
  441. }
  442. unlink(iso_file_name);
  443. chdir("..");
  444. }
  445. #define sector_offset_to_msf(offset, minutes, seconds, frames) \
  446. { \
  447. u32 _offset = offset; \
  448. minutes = (_offset / 75) / 60; \
  449. seconds = (_offset / 75) % 60; \
  450. frames = _offset % 75; \
  451. } \
  452. s32 convert_bin_cue(char *output_name_base)
  453. {
  454. char output_file_name[MAX_PATH];
  455. FILE *output_cue_file;
  456. FILE *bin_file = cd_bin.bin_file;
  457. cd_track_struct *current_track;
  458. u32 m, s, f;
  459. u32 current_pregap = 0;
  460. u32 last_pregap = 0;
  461. u32 i;
  462. struct stat sb;
  463. if(stat(output_name_base, &sb))
  464. mkdir(output_name_base);
  465. sprintf(output_file_name, "%s.cue", output_name_base);
  466. chdir(output_name_base);
  467. output_cue_file = fopen(output_file_name, "wb");
  468. chdir("..");
  469. // Every track gets its own file. It's either going to be of type ISO
  470. // or of type WAV.
  471. for(i = 0; i < 100; i++)
  472. {
  473. current_track = cd_bin.logical_tracks[i];
  474. if(current_track != NULL)
  475. {
  476. switch(current_track->format_type)
  477. {
  478. char output_name_tmp[MAX_PATH];
  479. // Audio
  480. case 0:
  481. {
  482. sprintf(output_file_name, "%s_%02d.mp3", output_name_base, i);
  483. sprintf(output_name_tmp, "%s_%02d.wav", output_name_base, i);
  484. fprintf(output_cue_file, "FILE \"%s\" %s\n",
  485. opt_use_mp3 ? output_file_name : output_name_tmp,
  486. opt_use_mp3 ? "MP3" : "WAVE");
  487. fprintf(output_cue_file, " TRACK %02d AUDIO\n", i);
  488. current_pregap = current_track->pregap_offset - last_pregap;
  489. last_pregap = current_track->pregap_offset;
  490. if(current_pregap > 0)
  491. {
  492. sector_offset_to_msf(current_pregap, m, s, f);
  493. fprintf(output_cue_file, " PREGAP %02d:%02d:%02d\n", m, s, f);
  494. }
  495. fprintf(output_cue_file, " INDEX 01 00:00:00\n");
  496. sector_offset_to_msf(current_track->sector_count, m, s, f);
  497. fprintf(output_cue_file, " REM LENGTH %02d:%02d:%02d\n", m, s, f);
  498. fseek(bin_file, current_track->physical_offset, SEEK_SET);
  499. convert_bin_to_wav(bin_file, output_name_base, output_name_tmp,
  500. current_track->sector_count);
  501. if(opt_use_mp3)
  502. {
  503. convert_wav_to_mp3(output_name_tmp, output_name_base,
  504. output_file_name);
  505. }
  506. break;
  507. }
  508. // Data
  509. default:
  510. sprintf(output_file_name, "%s_%02d.cso", output_name_base, i);
  511. sprintf(output_name_tmp, "%s_%02d.iso", output_name_base, i);
  512. fprintf(output_cue_file, "FILE \"%s\" BINARY\n",
  513. opt_use_cso ? output_file_name : output_name_tmp);
  514. fprintf(output_cue_file, " TRACK %02d MODE1/2048\n", i);
  515. current_pregap = current_track->pregap_offset - last_pregap;
  516. last_pregap = current_track->pregap_offset;
  517. if(current_pregap > 0)
  518. {
  519. sector_offset_to_msf(current_pregap, m, s, f);
  520. fprintf(output_cue_file, " PREGAP %02d:%02d:%02d\n", m, s, f);
  521. }
  522. fprintf(output_cue_file, " INDEX 01 00:00:00\n");
  523. fseek(bin_file, current_track->physical_offset, SEEK_SET);
  524. convert_bin_to_iso(bin_file, output_name_base, output_name_tmp,
  525. current_track->sector_count);
  526. if(opt_use_cso)
  527. {
  528. convert_iso_to_cso(output_name_base, output_name_tmp, output_file_name);
  529. }
  530. break;
  531. }
  532. }
  533. }
  534. fclose(output_cue_file);
  535. return 0;
  536. }
  537. #ifdef _WIN32
  538. static void update_path(void)
  539. {
  540. char buff1[MAX_PATH*4], *buff2;
  541. char *path;
  542. int size, i;
  543. path = getenv("PATH");
  544. GetModuleFileNameA(NULL, buff1, sizeof(buff1));
  545. for (i = strlen(buff1)-1; i > 0; i--)
  546. if (buff1[i] == '\\') break;
  547. buff1[i] = 0;
  548. size = strlen(path) + strlen(buff1) + 3;
  549. buff2 = malloc(size);
  550. if (buff2 == NULL) return;
  551. snprintf(buff2, size, "%s;%s", path, buff1);
  552. SetEnvironmentVariableA("PATH", buff2);
  553. free(buff2);
  554. }
  555. #endif
  556. int main(int argc, char *argv[])
  557. {
  558. char out_buff[MAX_PATH], *cue_file, *out_base;
  559. int a;
  560. if(argc < 2)
  561. {
  562. printf("bin/cue to cso/mp3 converter\n");
  563. printf("usage: %s [options] <input cue> [output base]\n", argv[0]);
  564. printf("options:\n"
  565. " -m output mp3 files for audio (default) (lame required)\n"
  566. " -b <rate> mp3 bitrate to use (default is 128)\n"
  567. " -w output wav files for audio\n"
  568. " -c output cso as data track (default) (ciso required)\n"
  569. " -i output iso as data track\n");
  570. return 0;
  571. }
  572. for (a = 1; a < argc - 1; a++)
  573. {
  574. if (strcmp(argv[a], "-m") == 0)
  575. opt_use_mp3 = 1;
  576. else if (strcmp(argv[a], "-w") == 0)
  577. opt_use_mp3 = 0;
  578. else if (strcmp(argv[a], "-c") == 0)
  579. opt_use_cso = 1;
  580. else if (strcmp(argv[a], "-i") == 0)
  581. opt_use_cso = 0;
  582. else if (strcmp(argv[a], "-b") == 0)
  583. {
  584. opt_mp3_bitrate = atoi(argv[++a]);
  585. }
  586. else
  587. break;
  588. }
  589. cue_file = argv[a];
  590. out_base = argv[a+1];
  591. /* some sanity checks */
  592. if(strlen(cue_file) < 4 || strcasecmp(cue_file + strlen(cue_file) - 4, ".cue") != 0)
  593. {
  594. printf("error: not a cue file specified?\n");
  595. myexit(1);
  596. }
  597. #ifdef _WIN32
  598. update_path();
  599. #endif
  600. if(opt_use_mp3 && system(LAME_BINARY " --help " NULL_REDIR) != 0)
  601. {
  602. printf("LAME seems to be missing.\n"
  603. #ifdef _WIN32
  604. "Download from http://lame.sourceforge.net/links.php#Binaries and extract\n"
  605. "lame.exe to the same directory as %s\n", argv[0]
  606. #else
  607. "Install lame using your packet manager, obtain binaries or build from\n"
  608. "sources at http://lame.sourceforge.net/\n"
  609. #endif
  610. );
  611. myexit(1);
  612. }
  613. if(opt_use_cso && system(CISO_BINARY " " NULL_REDIR) != 0)
  614. {
  615. printf("CISO seems to be missing.\n"
  616. #ifdef _WIN32
  617. "Download ciso.exe and extract to the same directory as %s\n"
  618. "You can take ciso.exe from yacc at http://yacc.pspgen.com/\n", argv[0]
  619. #else
  620. "Install ciso using your packet manager, obtain binaries or build from\n"
  621. "sources at http://ciso.tenshu.fr/\n"
  622. #endif
  623. );
  624. myexit(1);
  625. }
  626. if(load_bin_cue(cue_file) == 0)
  627. {
  628. if(out_base == NULL)
  629. {
  630. char *p;
  631. strncpy(out_buff, cue_file, sizeof(out_buff));
  632. out_buff[sizeof(out_buff)-1] = 0;
  633. p = strrchr(out_buff, DIR_SEPARATOR_CHAR);
  634. if (p != NULL)
  635. {
  636. *p++ = 0;
  637. chdir(out_buff);
  638. memmove(out_buff, p, strlen(p)+1);
  639. }
  640. out_buff[strlen(out_buff)-4] = 0;
  641. out_base = out_buff;
  642. }
  643. if(convert_bin_cue(out_base) != 0)
  644. myexit(1);
  645. }
  646. else
  647. {
  648. printf("error: could not load cue file %s\n", cue_file);
  649. myexit(1);
  650. }
  651. return 0;
  652. }