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