2828
2929#define VERSION "1.2.3"
3030#define USAGE "Usage: bchunk [-t] [-v] [-r] [-p (PSX)] [-w (wav)] [-s (swabaudio)]\n" \
31- " <image.bin | track # | '*'> <image.cue> [ <basename> ]\n" \
31+ " <image.bin | image.wav | track # | '*'> <image.cue> [ <basename> ]\n" \
3232 "Example: bchunk foo.bin foo.cue foo\n" \
3333 " bchunk foo.bin foo.cue\n" \
3434 " bchunk 2 foo.cue foo\n" \
3535 " -t Insert track # in between the basename and the format extension\n" \
3636 " -v Verbose mode\n" \
37+ " -d Debug mode\n" \
3738 " -r Raw mode for MODE2/2352: write all 2352 bytes from offset 0 (VCD/MPEG)\n" \
3839 " -p PSX mode for MODE2/2352: write 2336 bytes from offset 24\n" \
3940 " (default MODE2/2352 mode writes 2048 bytes from offset 24)\n"\
5758#define WAV_RIFF_HLEN 12
5859#define WAV_FORMAT_HLEN 24
5960#define WAV_DATA_HLEN 8
61+ #define WAV_DATA_FOURCC "data"
62+ #define WAV_DATA_FLEN sizeof(WAV_DATA_FOURCC) - 1
6063#define WAV_HEADER_LEN WAV_RIFF_HLEN + WAV_FORMAT_HLEN + WAV_DATA_HLEN
64+ #define WAV_HEADER_MAX WAV_HEADER_LEN + 100
65+
66+ #define TRACK_TOKEN "##"
6167
6268/*
6369 * Ugly way to convert integers to little-endian format.
@@ -93,6 +99,7 @@ struct track_t {
9399 char * extension ;
94100 int bstart ;
95101 int bsize ;
102+ long dataoffs ;
96103 long startsect ;
97104 long stopsect ;
98105 long start ;
@@ -106,6 +113,7 @@ char *cuefile = NULL;
106113char * bname = NULL ;
107114char * file = NULL ;
108115int verbose = 0 ;
116+ int debug = 0 ;
109117int psxtruncate = 0 ;
110118int raw = 0 ;
111119int swabaudio = 0 ;
@@ -170,14 +178,17 @@ void parse_args(int argc, char *argv[])
170178{
171179 int s ;
172180
173- while ((s = getopt (argc , argv , "swvp?hrt " )) != -1 ) {
181+ while ((s = getopt (argc , argv , "swvp?hrtd " )) != -1 ) {
174182 switch (s ) {
175183 case 'r' :
176184 raw = 1 ;
177185 break ;
178186 case 'v' :
179187 verbose = 1 ;
180188 break ;
189+ case 'd' :
190+ debug = 1 ;
191+ break ;
181192 case 'w' :
182193 towav = 1 ;
183194 break ;
@@ -242,6 +253,44 @@ long time2frames(char *s)
242253 return 75 * (mins * 60 + secs ) + frames ;
243254}
244255
256+ /*
257+ * Check WAV file name extension
258+ */
259+
260+ int is_wav_file (struct track_t * track ) {
261+ static char ext_wav [] = ".wav" ;
262+ return !strcasecmp (track -> file + strlen (track -> file ) - strlen (ext_wav ), ext_wav );
263+ }
264+
265+ /*
266+ * Set WAV data header offset
267+ */
268+
269+ int set_wav_data_offset (FILE * bf , struct track_t * track ) {
270+ char s [WAV_DATA_FLEN + 1 ];
271+ s [WAV_DATA_FLEN ] = '\0' ;
272+ for (int offset = WAV_HEADER_LEN ; offset < WAV_HEADER_MAX ; offset ++ ) {
273+ if (fseek (binf , offset , SEEK_SET ) == -1 )
274+ die_format (4 , " Could not fseek to offset %d: %s\n" , offset , strerror (errno ));
275+ fread (s , WAV_DATA_FLEN , 1 , binf );
276+ if (strcmp (WAV_DATA_FOURCC , s ) == 0 ) {
277+ track -> dataoffs = offset + WAV_DATA_HLEN ;
278+ if (debug ) {
279+ fseek (binf , offset + WAV_DATA_FLEN , SEEK_SET );
280+ uint32_t w ;
281+ fread (& w , WAV_DATA_FLEN , 1 , binf );
282+ fprintf (stderr , " data header at %d\n"
283+ " WAV data at %ld\n"
284+ " WAV data bytes %u\n" ,
285+ offset , track -> dataoffs , w );
286+ }
287+ return 1 ;
288+ }
289+ }
290+ printf ("No WAV data header found in %s for track %d\n" , track -> file , track -> num );
291+ return 0 ;
292+ }
293+
245294/*
246295 * Parse the mode string
247296 */
@@ -284,7 +333,7 @@ void gettrackmode(struct track_t *track, char *modes)
284333 track -> bsize = 2336 ;
285334 track -> extension = ext_iso ;
286335
287- } else if (!strcasecmp (modes , "AUDIO" )) {
336+ } else if (!strcasecmp (modes , "AUDIO" ) || is_wav_file ( track ) ) {
288337 track -> bstart = 0 ;
289338 track -> bsize = 2352 ;
290339 track -> audio = 1 ;
@@ -345,7 +394,7 @@ int writetrack(FILE *bf, struct track_t *track)
345394
346395 printf ("%2d: %s " , track -> num , track -> output );
347396
348- if (fseek (bf , track -> start , SEEK_SET ))
397+ if (fseek (bf , track -> start + track -> dataoffs , SEEK_SET ))
349398 die_format (4 , " Could not fseek to track location: %s\n" , strerror (errno ));
350399
351400 reallen = (track -> stopsect - track -> startsect + 1 ) * track -> bsize ;
@@ -385,7 +434,7 @@ int writetrack(FILE *bf, struct track_t *track)
385434 i = htoles (2 * 8 ); // bits per channel
386435 fwrite (& i , 2 , 1 , f );
387436 // DATA header
388- fputs ("data" , f );
437+ fputs (WAV_DATA_FOURCC , f );
389438 l = htolel (reallen );
390439 fwrite (& l , 4 , 1 , f );
391440 }
@@ -394,6 +443,7 @@ int writetrack(FILE *bf, struct track_t *track)
394443 sz = track -> start ;
395444 sect = track -> startsect ;
396445 fl = 0 ;
446+
397447 while ((sect <= track -> stopsect ) && (fread (buf , SECTLEN , 1 , bf ) > 0 )) {
398448 if (track -> audio ) {
399449 if (swabaudio ) {
@@ -439,7 +489,7 @@ int writetrack(FILE *bf, struct track_t *track)
439489 */
440490
441491int set_output (struct track_t * track , char * binfile , char * basefile , int trackadd ) {
442- char * t ;
492+ char * e , * s , * t ;
443493 if (strchr (binfile , '*' )) {
444494 if (!basefile )
445495 bname = prune_ext (track -> file );
@@ -460,6 +510,19 @@ int set_output(struct track_t *track, char *binfile, char *basefile, int trackad
460510 if (asprintf (& bname , "%s" , basefile ) == -1 )
461511 die (4 , "set_output(): asprintf() failed, out of memory\n" );
462512 }
513+ if (basefile )
514+ if ((e = strstr (basefile , TRACK_TOKEN ))) {
515+ int l = e - basefile ;
516+ if (!(s = calloc (l + 1 , 1 )))
517+ die (4 , "set_output(): calloc() failed, out of memory\n" );
518+ strncpy (s , basefile , l );
519+ if (bname )
520+ t = bname ;
521+ if (asprintf (& bname , "%s%.2d%s" , s , track -> num , e + strlen (TRACK_TOKEN )) == -1 )
522+ die (4 , "set_output(): asprintf() failed, out of memory\n" );
523+ free (s );
524+ free (t );
525+ }
463526 if (trackadd ) {
464527 if (bname )
465528 t = bname ;
@@ -484,7 +547,7 @@ int set_output(struct track_t *track, char *binfile, char *basefile, int trackad
484547int main (int argc , char * * argv )
485548{
486549 char s [CUELLEN + 1 ];
487- char * b , * e , * p , * t ;
550+ char * b , * e , * i , * p , * t , * u ;
488551 struct track_t * prevtrack = NULL ;
489552 struct track_t * * prevp = & tracks ;
490553
@@ -551,6 +614,7 @@ int main(int argc, char **argv)
551614 track -> output = NULL ;
552615 track -> mode = 0 ;
553616 track -> audio = 0 ;
617+ track -> dataoffs = 0 ;
554618 track -> bsize = track -> bstart = -1 ;
555619 track -> bsize = -1 ;
556620 track -> startsect = track -> stopsect = -1 ;
@@ -566,13 +630,33 @@ int main(int argc, char **argv)
566630 * t = '\0' ;
567631 t ++ ;
568632 printf (" %s %s" , p , t );
569- track -> startsect = time2frames (t );
570- track -> start = track -> startsect * SECTLEN ;
633+ long index = strtol (p , & i , 10 );
634+ if (strlen (i ))
635+ die_format (3 , "... ouch, non-digit found in INDEX %s: %s\n" , p , i );
636+ u = strdupa (t );
637+ int ss ;
638+ // handle unordered pregap, ignore subtracks
639+ for (ss = time2frames (t ); ss > track -> startsect && index < 2 ;) {
640+ track -> startsect = ss ;
641+ track -> start = track -> startsect * SECTLEN ;
642+ }
643+ if (debug )
644+ fprintf (stderr , "INDEX %s%s: %s startsect %d\n" ,
645+ p , track -> startsect + 1 ? "" : " updating" ,
646+ u , ss );
571647 if (verbose )
572- printf (" (startsect %ld ofs %ld)" , track -> startsect , track -> start );
573- if ((prevtrack ) && (prevtrack -> stopsect < 0 ) && !(strcmp (prevtrack -> file ,track -> file ))) { // only when files match
574- prevtrack -> stopsect = track -> startsect - 1 ;
575- prevtrack -> stop = track -> start - 1 ;
648+ printf (" (%sstartsect %ld ofs %ld)" ,
649+ index == 0 ? "pregap " : "" ,
650+ track -> startsect , track -> start );
651+ if (prevtrack ) {
652+ // only when files match, ignore subtracks
653+ if (!(strcmp (prevtrack -> file ,track -> file )) && index < 2 ) {
654+ prevtrack -> stopsect = track -> startsect - 1 ;
655+ prevtrack -> stop = track -> start - 1 ;
656+ }
657+ if (debug )
658+ fprintf (stderr , "TRACK %.2d: stopsect %ld\n" ,
659+ prevtrack -> num , prevtrack -> stopsect );
576660 }
577661 }
578662 }
@@ -586,10 +670,13 @@ int main(int argc, char **argv)
586670 fprintf (stderr , "Could not open BIN %s: %s\n" , track -> file , strerror (errno ));
587671 continue ;
588672 }
673+ if (is_wav_file (track ))
674+ if (!set_wav_data_offset (binf , track ))
675+ continue ;
589676 if (track -> stopsect < 0 ) { // if not set yet
590677 if (fseek (binf , 0 , SEEK_END ) == -1 )
591678 die_format (4 , "main(): fseek failure in %s\n" , track -> file );
592- track -> stop = ftell (binf ) - 1 ;
679+ track -> stop = ftell (binf ) - track -> dataoffs - 1 ;
593680 track -> stopsect = track -> stop / SECTLEN ;
594681 }
595682 writetrack (binf , track );
0 commit comments