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