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