diff options
author | R. Belmont <rb6502@users.noreply.github.com> | 2010-09-15 02:36:37 +0000 |
---|---|---|
committer | R. Belmont <rb6502@users.noreply.github.com> | 2010-09-15 02:36:37 +0000 |
commit | 32e006222b6d8b05d5666c6adb46455f6cf12ddf (patch) | |
tree | 218fbaf91e9019561b39a7ad4481d88c44b3b7a2 | |
parent | 99c5d52312cda6dfc1bf4182f21e4443f1a6808e (diff) |
CHDMAN: support for .WAV tracks in bin/cue images [R. Belmont]
-rw-r--r-- | src/tools/chdcd.c | 287 |
1 files changed, 219 insertions, 68 deletions
diff --git a/src/tools/chdcd.c b/src/tools/chdcd.c index 73199026013..b0bdc3d0143 100644 --- a/src/tools/chdcd.c +++ b/src/tools/chdcd.c @@ -13,6 +13,7 @@ #include "osdcore.h" #include "chd.h" #include "chdcd.h" +#include "corefile.h" @@ -49,6 +50,7 @@ static UINT64 get_file_size(const char *filename) filerr = osd_open(filename, OPEN_FLAG_READ, &file, &filesize); if (filerr == FILERR_NONE) osd_close(file); + return filesize; } @@ -121,6 +123,136 @@ static int msf_to_frames( char *token ) return f; } +/*------------------------------------------------- + parse_wav_sample - takes a .WAV file, verifies + that the file is 16 bits, and returns the + length in bytes of the data and the offset in + bytes to where the data starts in the file. +-------------------------------------------------*/ +static UINT32 parse_wav_sample(char *filename, UINT32 *dataoffs) +{ + unsigned long offset = 0; + UINT32 length, rate, filesize; + UINT16 bits, temp16; + char buf[32]; + osd_file *file; + file_error filerr; + UINT64 fsize = 0; + UINT32 actual; + + filerr = osd_open(filename, OPEN_FLAG_READ, &file, &fsize); + if (filerr != FILERR_NONE) + { + osd_close(file); + return 0; + } + + /* read the core header and make sure it's a WAVE file */ + osd_read(file, buf, 0, 4, &actual); + offset += actual; + if (offset < 4) + return 0; + if (memcmp(&buf[0], "RIFF", 4) != 0) + return 0; + + /* get the total size */ + osd_read(file, &filesize, offset, 4, &actual); + offset += actual; + if (offset < 8) + return 0; + filesize = LITTLE_ENDIANIZE_INT32(filesize); + + /* read the RIFF file type and make sure it's a WAVE file */ + osd_read(file, buf, offset, 4, &actual); + offset += actual; + if (offset < 12) + return 0; + if (memcmp(&buf[0], "WAVE", 4) != 0) + return 0; + + /* seek until we find a format tag */ + while (1) + { + osd_read(file, buf, offset, 4, &actual); + offset += actual; + osd_read(file, &length, offset, 4, &actual); + offset += actual; + length = LITTLE_ENDIANIZE_INT32(length); + if (memcmp(&buf[0], "fmt ", 4) == 0) + break; + + /* seek to the next block */ + offset += length; + if (offset >= filesize) + return 0; + } + + /* read the format -- make sure it is PCM */ + osd_read(file, &temp16, offset, 2, &actual); + offset += actual; + temp16 = LITTLE_ENDIANIZE_INT16(temp16); + if (temp16 != 1) + return 0; + + /* number of channels -- only mono is supported */ + osd_read(file, &temp16, offset, 2, &actual); + offset += actual; + temp16 = LITTLE_ENDIANIZE_INT16(temp16); + if (temp16 != 2) + return 0; + + /* sample rate */ + osd_read(file, &rate, offset, 4, &actual); + offset += actual; + rate = LITTLE_ENDIANIZE_INT32(rate); + if (rate != 44100) + return 0; + + /* bytes/second and block alignment are ignored */ + osd_read(file, buf, offset, 6, &actual); + offset += actual; + + /* bits/sample */ + osd_read(file, &bits, offset, 2, &actual); + offset += actual; + if (bits != 16) + return 0; + + /* seek past any extra data */ + offset += length - 16; + + /* seek until we find a data tag */ + while (1) + { + osd_read(file, buf, offset, 4, &actual); + offset += actual; + osd_read(file, &length, offset, 4, &actual); + offset += actual; + length = LITTLE_ENDIANIZE_INT32(length); + if (memcmp(&buf[0], "data", 4) == 0) + break; + + /* seek to the next block */ + offset += length; + if (offset >= filesize) + return 0; + } + + /* if there was a 0 length data block, we're done */ + if (length == 0) + return 0; + + osd_close(file); + + *dataoffs = offset; + + return length; +} + +/*------------------------------------------------- + chdcd_parse_gdi - parse a Sega GD-ROM rip +-------------------------------------------------*/ + static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc *outtoc, chdcd_track_input_info *outinfo) { FILE *infile; @@ -241,6 +373,7 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc *outtoc, chdcd_track_i int i, trknum; static char token[128]; static char lastfname[128]; + UINT32 wavlen, wavoffs; infile = fopen(tocfname, "rt"); @@ -254,6 +387,7 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc *outtoc, chdcd_track_i memset(outinfo, 0, sizeof(chdcd_track_input_info)); trknum = -1; + wavoffs = wavlen = 0; while (!feof(infile)) { @@ -273,7 +407,6 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc *outtoc, chdcd_track_i TOKENIZE /* keep the filename */ - strncpy(&outinfo->fname[trknum][0], token, strlen(token)); strncpy(lastfname, token, 128); /* get the file type */ @@ -287,6 +420,22 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc *outtoc, chdcd_track_i { outinfo->swap[trknum] = 1; } + else if (!strcmp(token, "WAVE")) + { + wavlen = parse_wav_sample(lastfname, &wavoffs); + if (!wavlen) + { + file_error err; + core_file *fhand; + + err = core_fopen(lastfname, OPEN_FLAG_READ, &fhand); + if (err != FILERR_NONE) printf("holy shit!\n"); + else core_fclose(fhand); + + printf("ERROR: couldn't read [%s] or not a valid .WAV\n", lastfname); + return CHDERR_FILE_NOT_FOUND; + } + } else { printf("ERROR: Unhandled track type %s\n", token); @@ -302,15 +451,26 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc *outtoc, chdcd_track_i /* next token on the line is the track type */ TOKENIZE - outtoc->tracks[trknum].trktype = CD_TRACK_MODE1; - outtoc->tracks[trknum].datasize = 0; + if (wavlen != 0) + { + outtoc->tracks[trknum].trktype = CD_TRACK_AUDIO; + outtoc->tracks[trknum].frames = wavlen/2352; + outinfo->offset[trknum] = wavoffs; + wavoffs = wavlen = 0; + } + else + { + outtoc->tracks[trknum].trktype = CD_TRACK_MODE1; + outtoc->tracks[trknum].datasize = 0; + outinfo->offset[trknum] = 0; + } outtoc->tracks[trknum].subtype = CD_SUB_NONE; outtoc->tracks[trknum].subsize = 0; outtoc->tracks[trknum].pregap = 0; outinfo->idx0offs[trknum] = -1; outinfo->idx1offs[trknum] = 0; strcpy(&outinfo->fname[trknum][0], lastfname); // default filename to the last one -// printf("trk %d: fname %s\n", trknum+1, &outinfo->fname[trknum][0]); +// printf("trk %d: fname %s offset %d\n", trknum, &outinfo->fname[trknum][0], outinfo->offset[trknum]); cdrom_convert_type_string_to_track_info(token, &outtoc->tracks[trknum]); if (outtoc->tracks[trknum].datasize == 0) @@ -318,13 +478,6 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc *outtoc, chdcd_track_i printf("ERROR: Unknown track type [%s]. Contact MAMEDEV.\n", token); return CHDERR_FILE_NOT_FOUND; } - else if (outtoc->tracks[trknum].trktype != CD_TRACK_MODE1_RAW && - outtoc->tracks[trknum].trktype != CD_TRACK_MODE2_RAW && - outtoc->tracks[trknum].trktype != CD_TRACK_AUDIO) - { - printf("Note: MAME prefers and can accept RAW format images.\n"); - printf("At least one track of this rip is not either RAW or AUDIO.\n"); - } /* next (optional) token on the line is the subcode type */ TOKENIZE @@ -379,7 +532,7 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc *outtoc, chdcd_track_i } } - /* close the input CUE */ + /* close the input CUE */ fclose(infile); /* store the number of tracks found */ @@ -390,75 +543,80 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc *outtoc, chdcd_track_i { UINT64 tlen = 0; + // this is true for cue/bin and cue/iso, and we need it for cue/wav since .WAV is little-endian if (outtoc->tracks[trknum].trktype == CD_TRACK_AUDIO) { outinfo->swap[trknum] = 1; } - // is this the last track? - if (trknum == (outtoc->numtrks-1)) + // don't do this for .WAV tracks, we already have their length and offset filled out + if (outinfo->offset[trknum] == 0) { - /* if we have the same filename as the last track, do it that way */ - if (!strcmp(&outinfo->fname[trknum][0], &outinfo->fname[trknum-1][0])) + // is this the last track? + if (trknum == (outtoc->numtrks-1)) { - tlen = get_file_size(outinfo->fname[trknum]); - if (tlen == 0) + /* if we have the same filename as the last track, do it that way */ + if (!strcmp(&outinfo->fname[trknum][0], &outinfo->fname[trknum-1][0])) { - printf("ERROR: couldn't find bin file [%s]\n", outinfo->fname[trknum-1]); - return CHDERR_FILE_NOT_FOUND; + tlen = get_file_size(outinfo->fname[trknum]); + if (tlen == 0) + { + printf("ERROR: couldn't find bin file [%s]\n", outinfo->fname[trknum-1]); + return CHDERR_FILE_NOT_FOUND; + } + outinfo->offset[trknum] = outinfo->offset[trknum-1] + outtoc->tracks[trknum-1].frames * (outtoc->tracks[trknum-1].datasize + outtoc->tracks[trknum-1].subsize); + outtoc->tracks[trknum].frames = (tlen - outinfo->offset[trknum]) / (outtoc->tracks[trknum].datasize + outtoc->tracks[trknum].subsize); } - outinfo->offset[trknum] = outinfo->offset[trknum-1] + outtoc->tracks[trknum-1].frames * (outtoc->tracks[trknum-1].datasize + outtoc->tracks[trknum-1].subsize); - outtoc->tracks[trknum].frames = (tlen - outinfo->offset[trknum]) / (outtoc->tracks[trknum].datasize + outtoc->tracks[trknum].subsize); - } - else /* data files are different */ - { - tlen = get_file_size(outinfo->fname[trknum]); - if (tlen == 0) + else /* data files are different */ { - printf("ERROR: couldn't find bin file [%s]\n", outinfo->fname[trknum-1]); - return CHDERR_FILE_NOT_FOUND; + tlen = get_file_size(outinfo->fname[trknum]); + if (tlen == 0) + { + printf("ERROR: couldn't find bin file [%s]\n", outinfo->fname[trknum-1]); + return CHDERR_FILE_NOT_FOUND; + } + tlen /= (outtoc->tracks[trknum].datasize + outtoc->tracks[trknum].subsize); + outtoc->tracks[trknum].frames = tlen; + outinfo->offset[trknum] = 0; } - tlen /= (outtoc->tracks[trknum].datasize + outtoc->tracks[trknum].subsize); - outtoc->tracks[trknum].frames = tlen; - outinfo->offset[trknum] = 0; } - } - else - { - /* if we have the same filename as the next track, do it that way */ - if (!strcmp(&outinfo->fname[trknum][0], &outinfo->fname[trknum+1][0])) + else { - outtoc->tracks[trknum].frames = outinfo->idx1offs[trknum+1] - outinfo->idx1offs[trknum]; - - if (trknum == 0) // track 0 offset is 0 - { - outinfo->offset[trknum] = 0; - } - else + /* if we have the same filename as the next track, do it that way */ + if (!strcmp(&outinfo->fname[trknum][0], &outinfo->fname[trknum+1][0])) { - outinfo->offset[trknum] = outinfo->offset[trknum-1] + outtoc->tracks[trknum-1].frames * (outtoc->tracks[trknum-1].datasize + outtoc->tracks[trknum-1].subsize); - } + outtoc->tracks[trknum].frames = outinfo->idx1offs[trknum+1] - outinfo->idx1offs[trknum]; - if (!outtoc->tracks[trknum].frames) - { - printf("ERROR: unable to determine size of track %d, missing INDEX 01 markers?\n", trknum+1); - return CHDERR_FILE_NOT_FOUND; + if (trknum == 0) // track 0 offset is 0 + { + outinfo->offset[trknum] = 0; + } + else + { + outinfo->offset[trknum] = outinfo->offset[trknum-1] + outtoc->tracks[trknum-1].frames * (outtoc->tracks[trknum-1].datasize + outtoc->tracks[trknum-1].subsize); + } + + if (!outtoc->tracks[trknum].frames) + { + printf("ERROR: unable to determine size of track %d, missing INDEX 01 markers?\n", trknum+1); + return CHDERR_FILE_NOT_FOUND; + } } - } - else /* data files are different */ - { - tlen = get_file_size(outinfo->fname[trknum-1]); - if (tlen == 0) + else /* data files are different */ { - printf("ERROR: couldn't find bin file [%s]\n", outinfo->fname[trknum-1]); - return CHDERR_FILE_NOT_FOUND; + tlen = get_file_size(outinfo->fname[trknum]); + if (tlen == 0) + { + printf("ERROR: couldn't find bin file [%s]\n", outinfo->fname[trknum]); + return CHDERR_FILE_NOT_FOUND; + } + tlen /= (outtoc->tracks[trknum].datasize + outtoc->tracks[trknum].subsize); + outtoc->tracks[trknum].frames = tlen; + outinfo->offset[trknum] = 0; } - tlen /= (outtoc->tracks[trknum].datasize + outtoc->tracks[trknum].subsize); - outtoc->tracks[trknum].frames = tlen; - outinfo->offset[trknum] = 0; } } -// printf("trk %d: %d frames @ offset %d\n", trknum+1, outtoc->tracks[trknum].frames, outinfo->offset[trknum]); + printf("trk %d: %d frames @ offset %d\n", trknum+1, outtoc->tracks[trknum].frames, outinfo->offset[trknum]); } return CHDERR_NONE; @@ -604,13 +762,6 @@ chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc *outtoc, chdcd_track_i printf("ERROR: Unknown track type [%s]. Contact MAMEDEV.\n", token); return CHDERR_FILE_NOT_FOUND; } - else if (outtoc->tracks[trknum].trktype != CD_TRACK_MODE1_RAW && - outtoc->tracks[trknum].trktype != CD_TRACK_MODE2_RAW && - outtoc->tracks[trknum].trktype != CD_TRACK_AUDIO) - { - printf("Note: MAME prefers and can accept RAW format images.\n"); - printf("At least one track of this rip is not either RAW or AUDIO.\n"); - } /* next (optional) token on the line is the subcode type */ TOKENIZE |