diff options
Diffstat (limited to 'src/lib/util/chdcd.cpp')
-rw-r--r-- | src/lib/util/chdcd.cpp | 1333 |
1 files changed, 0 insertions, 1333 deletions
diff --git a/src/lib/util/chdcd.cpp b/src/lib/util/chdcd.cpp deleted file mode 100644 index 85bd7cdad27..00000000000 --- a/src/lib/util/chdcd.cpp +++ /dev/null @@ -1,1333 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:R. Belmont -/*************************************************************************** - - TOC parser for CHD compression frontend - Handles CDRDAO .toc, CDRWIN .cue, Nero .nrg, and Sega GDROM .gdi - -***************************************************************************/ - -#include <ctype.h> -#include <stdlib.h> -#include <assert.h> -#include "osdcore.h" -#include "chd.h" -#include "chdcd.h" -#include "corefile.h" - - - -/*************************************************************************** - CONSTANTS & DEFINES -***************************************************************************/ - -/** - * @def TOKENIZE(); - * - * @brief A macro that defines tokenize. - * - * @param linebuffer The linebuffer. - * @param i Zero-based index of the. - * @param sizeof(linebuffer) The sizeof(linebuffer) - * @param token The token. - * @param sizeof(token) The sizeof(token) - */ - -#define TOKENIZE i = tokenize( linebuffer, i, sizeof(linebuffer), token, sizeof(token) ); - - - -/*************************************************************************** - GLOBAL VARIABLES -***************************************************************************/ - -/** @brief The linebuffer[ 512]. */ -static char linebuffer[512]; - - - -/*************************************************************************** - IMPLEMENTATION -***************************************************************************/ - -/** - * @fn static std::string get_file_path(std::string &path) - * - * @brief Gets file path. - * - * @param [in,out] path Full pathname of the file. - * - * @return The file path. - */ - -static std::string get_file_path(std::string &path) -{ - int pos = path.find_last_of('\\'); - if (pos!=-1) { - path = path.substr(0,pos+1); - } else { - pos = path.find_last_of('/'); - path = path.substr(0,pos+1); - } - return path; -} -/*------------------------------------------------- - get_file_size - get the size of a file --------------------------------------------------*/ - -/** - * @fn static uint64_t get_file_size(const char *filename) - * - * @brief Gets file size. - * - * @param filename Filename of the file. - * - * @return The file size. - */ - -static uint64_t get_file_size(const char *filename) -{ - osd_file::ptr file; - std::uint64_t filesize = 0; - - osd_file::open(filename, OPEN_FLAG_READ, file, filesize); - - return filesize; -} - - -/*------------------------------------------------- - tokenize - get a token from the line buffer --------------------------------------------------*/ - -/** - * @fn static int tokenize( const char *linebuffer, int i, int linebuffersize, char *token, int tokensize ) - * - * @brief Tokenizes. - * - * @param linebuffer The linebuffer. - * @param i Zero-based index of the. - * @param linebuffersize The linebuffersize. - * @param [in,out] token If non-null, the token. - * @param tokensize The tokensize. - * - * @return An int. - */ - -static int tokenize( const char *linebuffer, int i, int linebuffersize, char *token, int tokensize ) -{ - int j = 0; - int singlequote = 0; - int doublequote = 0; - - while ((i < linebuffersize) && isspace((uint8_t)linebuffer[i])) - { - i++; - } - - while ((i < linebuffersize) && (j < tokensize)) - { - if (!singlequote && linebuffer[i] == '"' ) - { - doublequote = !doublequote; - } - else if (!doublequote && linebuffer[i] == '\'') - { - singlequote = !singlequote; - } - else if (!singlequote && !doublequote && isspace((uint8_t)linebuffer[i])) - { - break; - } - else - { - token[j] = linebuffer[i]; - j++; - } - - i++; - } - - token[j] = '\0'; - - return i; -} - - -/*------------------------------------------------- - msf_to_frames - convert m:s:f into a number of frames --------------------------------------------------*/ - -/** - * @fn static int msf_to_frames( char *token ) - * - * @brief Msf to frames. - * - * @param [in,out] token If non-null, the token. - * - * @return An int. - */ - -static int msf_to_frames( char *token ) -{ - int m = 0; - int s = 0; - int f = 0; - - if( sscanf( token, "%d:%d:%d", &m, &s, &f ) == 1 ) - { - f = m; - } - else - { - /* convert to just frames */ - s += (m * 60); - f += (s * 75); - } - - 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. --------------------------------------------------*/ - -/** - * @fn static uint32_t parse_wav_sample(const char *filename, uint32_t *dataoffs) - * - * @brief Parse WAV sample. - * - * @param filename Filename of the file. - * @param [in,out] dataoffs If non-null, the dataoffs. - * - * @return An uint32_t. - */ - -static uint32_t parse_wav_sample(const char *filename, uint32_t *dataoffs) -{ - unsigned long offset = 0; - uint32_t length, rate, filesize; - uint16_t bits, temp16; - char buf[32]; - osd_file::ptr file; - uint64_t fsize = 0; - std::uint32_t actual; - - osd_file::error filerr = osd_file::open(filename, OPEN_FLAG_READ, file, fsize); - if (filerr != osd_file::error::NONE) - { - printf("ERROR: could not open (%s)\n", filename); - return 0; - } - - /* read the core header and make sure it's a WAVE file */ - file->read(buf, 0, 4, actual); - offset += actual; - if (offset < 4) - { - printf("ERROR: unexpected RIFF offset %lu (%s)\n", offset, filename); - return 0; - } - if (memcmp(&buf[0], "RIFF", 4) != 0) - { - printf("ERROR: could not find RIFF header (%s)\n", filename); - return 0; - } - - /* get the total size */ - file->read(&filesize, offset, 4, actual); - offset += actual; - if (offset < 8) - { - printf("ERROR: unexpected size offset %lu (%s)\n", offset, filename); - return 0; - } - filesize = little_endianize_int32(filesize); - - /* read the RIFF file type and make sure it's a WAVE file */ - file->read(buf, offset, 4, actual); - offset += actual; - if (offset < 12) - { - printf("ERROR: unexpected WAVE offset %lu (%s)\n", offset, filename); - return 0; - } - if (memcmp(&buf[0], "WAVE", 4) != 0) - { - printf("ERROR: could not find WAVE header (%s)\n", filename); - return 0; - } - - /* seek until we find a format tag */ - while (1) - { - file->read(buf, offset, 4, actual); - offset += actual; - file->read(&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) - { - printf("ERROR: could not find fmt tag (%s)\n", filename); - return 0; - } - } - - /* read the format -- make sure it is PCM */ - file->read(&temp16, offset, 2, actual); - offset += actual; - temp16 = little_endianize_int16(temp16); - if (temp16 != 1) - { - printf("ERROR: unsupported format %u - only PCM is supported (%s)\n", temp16, filename); - return 0; - } - - /* number of channels -- only stereo is supported */ - file->read(&temp16, offset, 2, actual); - offset += actual; - temp16 = little_endianize_int16(temp16); - if (temp16 != 2) - { - printf("ERROR: unsupported number of channels %u - only stereo is supported (%s)\n", temp16, filename); - return 0; - } - - /* sample rate */ - file->read(&rate, offset, 4, actual); - offset += actual; - rate = little_endianize_int32(rate); - if (rate != 44100) - { - printf("ERROR: unsupported samplerate %u - only 44100 is supported (%s)\n", rate, filename); - return 0; - } - - /* bytes/second and block alignment are ignored */ - file->read(buf, offset, 6, actual); - offset += actual; - - /* bits/sample */ - file->read(&bits, offset, 2, actual); - offset += actual; - bits = little_endianize_int16(bits); - if (bits != 16) - { - printf("ERROR: unsupported bits/sample %u - only 16 is supported (%s)\n", bits, filename); - return 0; - } - - /* seek past any extra data */ - offset += length - 16; - - /* seek until we find a data tag */ - while (1) - { - file->read(buf, offset, 4, actual); - offset += actual; - file->read(&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) - { - printf("ERROR: could not find data tag (%s)\n", filename); - return 0; - } - } - - /* if there was a 0 length data block, we're done */ - if (length == 0) - { - printf("ERROR: empty data block (%s)\n", filename); - return 0; - } - - *dataoffs = offset; - - return length; -} - -/** - * @fn uint16_t read_uint16(FILE *infile) - * - * @brief Reads uint 16. - * - * @param [in,out] infile If non-null, the infile. - * - * @return The uint 16. - */ - -uint16_t read_uint16(FILE *infile) -{ - uint16_t res = 0; - unsigned char buffer[2]; - - fread(buffer, 2, 1, infile); - - res = buffer[1] | buffer[0]<<8; - - return res; -} - -/** - * @fn uint32_t read_uint32(FILE *infile) - * - * @brief Reads uint 32. - * - * @param [in,out] infile If non-null, the infile. - * - * @return The uint 32. - */ - -uint32_t read_uint32(FILE *infile) -{ - uint32_t res = 0; - unsigned char buffer[4]; - - fread(buffer, 4, 1, infile); - - res = buffer[3] | buffer[2]<<8 | buffer[1]<<16 | buffer[0]<<24; - - return res; -} - -/** - * @fn uint64_t read_uint64(FILE *infile) - * - * @brief Reads uint 64. - * - * @param [in,out] infile If non-null, the infile. - * - * @return The uint 64. - */ - -uint64_t read_uint64(FILE *infile) -{ - uint64_t res0(0), res1(0); - uint64_t res; - unsigned char buffer[8]; - - fread(buffer, 8, 1, infile); - - res0 = buffer[3] | buffer[2]<<8 | buffer[1]<<16 | buffer[0]<<24; - res1 = buffer[7] | buffer[6]<<8 | buffer[5]<<16 | buffer[4]<<24; - - res = res0<<32 | res1; - - return res; -} - -/*------------------------------------------------- - chdcd_parse_nero - parse a Nero .NRG file --------------------------------------------------*/ - -/** - * @fn chd_error chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) - * - * @brief Chdcd parse nero. - * - * @param tocfname The tocfname. - * @param [in,out] outtoc The outtoc. - * @param [in,out] outinfo The outinfo. - * - * @return A chd_error. - */ - -chd_error chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) -{ - FILE *infile; - unsigned char buffer[12]; - uint32_t chain_offs, chunk_size; - int done = 0; - - std::string path = std::string(tocfname); - - infile = fopen(tocfname, "rb"); - path = get_file_path(path); - - if (infile == (FILE *)nullptr) - { - return CHDERR_FILE_NOT_FOUND; - } - - /* clear structures */ - memset(&outtoc, 0, sizeof(outtoc)); - outinfo.reset(); - - // seek to 12 bytes before the end - fseek(infile, -12, SEEK_END); - fread(buffer, 12, 1, infile); - - if (memcmp(buffer, "NER5", 4)) - { - printf("ERROR: Not a Nero 5.5 or later image!\n"); - fclose(infile); - return CHDERR_UNSUPPORTED_VERSION; - } - - chain_offs = buffer[11] | (buffer[10]<<8) | (buffer[9]<<16) | (buffer[8]<<24); - - if ((buffer[7] != 0) || (buffer[6] != 0) || (buffer[5] != 0) || (buffer[4] != 0)) - { - printf("ERROR: File size is > 4GB, this version of CHDMAN cannot handle it."); - fclose(infile); - return CHDERR_UNSUPPORTED_FORMAT; - } - -// printf("NER5 detected, chain offset: %x\n", chain_offs); - - while (!done) - { - uint32_t offset; - uint8_t start, end; - int track; - - fseek(infile, chain_offs, SEEK_SET); - fread(buffer, 8, 1, infile); - - chunk_size = (buffer[7] | buffer[6]<<8 | buffer[5]<<16 | buffer[4]<<24); - -// printf("Chunk type: %c%c%c%c, size %x\n", buffer[0], buffer[1], buffer[2], buffer[3], chunk_size); - - // we want the DAOX chunk, which has the TOC information - if (!memcmp(buffer, "DAOX", 4)) - { - // skip second chunk size and UPC code - fseek(infile, 20, SEEK_CUR); - - fread(&start, 1, 1, infile); - fread(&end, 1, 1, infile); - -// printf("Start track %d End track: %d\n", start, end); - - outtoc.numtrks = (end-start) + 1; - - offset = 0; - for (track = start; track <= end; track++) - { - uint32_t size, mode; - uint64_t index0, index1, track_end; - - fseek(infile, 12, SEEK_CUR); // skip ISRC code - size = read_uint16(infile); - mode = read_uint16(infile); - fseek(infile, 2, SEEK_CUR); - index0 = read_uint64(infile); - index1 = read_uint64(infile); - track_end = read_uint64(infile); - -// printf("Track %d: sector size %d mode %x index0 %llx index1 %llx track_end %llx (pregap %d sectors, length %d sectors)\n", track, size, mode, index0, index1, track_end, (uint32_t)(index1-index0)/size, (uint32_t)(track_end-index1)/size); - outinfo.track[track-1].fname.assign(tocfname); - outinfo.track[track-1].offset = offset + (uint32_t)(index1-index0); - outinfo.track[track-1].idx0offs = 0; - outinfo.track[track-1].idx1offs = 0; - - switch (mode) - { - case 0x0000: // 2048 byte data - outtoc.tracks[track-1].trktype = CD_TRACK_MODE1; - outinfo.track[track-1].swap = false; - break; - - case 0x0300: // Mode 2 Form 1 - printf("ERROR: Mode 2 Form 1 tracks not supported\n"); - fclose(infile); - return CHDERR_UNSUPPORTED_FORMAT; - - case 0x0500: // raw data - printf("ERROR: Raw data tracks not supported\n"); - fclose(infile); - return CHDERR_UNSUPPORTED_FORMAT; - - case 0x0600: // 2352 byte mode 2 raw - outtoc.tracks[track-1].trktype = CD_TRACK_MODE2_RAW; - outinfo.track[track-1].swap = false; - break; - - case 0x0700: // 2352 byte audio - outtoc.tracks[track-1].trktype = CD_TRACK_AUDIO; - outinfo.track[track-1].swap = true; - break; - - case 0x0f00: // raw data with sub-channel - printf("ERROR: Raw data tracks with sub-channel not supported\n"); - fclose(infile); - return CHDERR_UNSUPPORTED_FORMAT; - - case 0x1000: // audio with sub-channel - printf("ERROR: Audio tracks with sub-channel not supported\n"); - fclose(infile); - return CHDERR_UNSUPPORTED_FORMAT; - - case 0x1100: // raw Mode 2 Form 1 with sub-channel - printf("ERROR: Raw Mode 2 Form 1 tracks with sub-channel not supported\n"); - fclose(infile); - return CHDERR_UNSUPPORTED_FORMAT; - - default: - printf("ERROR: Unknown track type %x, contact MAMEDEV!\n", mode); - fclose(infile); - return CHDERR_UNSUPPORTED_FORMAT; - } - - outtoc.tracks[track-1].datasize = size; - - outtoc.tracks[track-1].subtype = CD_SUB_NONE; - outtoc.tracks[track-1].subsize = 0; - - outtoc.tracks[track-1].pregap = (uint32_t)(index1-index0)/size; - outtoc.tracks[track-1].frames = (uint32_t)(track_end-index1)/size; - outtoc.tracks[track-1].postgap = 0; - outtoc.tracks[track-1].pgtype = 0; - outtoc.tracks[track-1].pgsub = CD_SUB_NONE; - outtoc.tracks[track-1].pgdatasize = 0; - outtoc.tracks[track-1].pgsubsize = 0; - outtoc.tracks[track-1].padframes = 0; - - offset += (uint32_t)track_end-index1; - } - } - - if (!memcmp(buffer, "END!", 4)) - { - done = 1; - } - else - { - chain_offs += chunk_size + 8; - } - } - - fclose(infile); - - return CHDERR_NONE; -} - -/*------------------------------------------------- - chdcd_parse_iso - parse a .ISO file --------------------------------------------------*/ - -/** - * @fn chd_error chdcd_parse_iso(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) - * - * @brief Chdcd parse ISO. - * - * @param tocfname The tocfname. - * @param [in,out] outtoc The outtoc. - * @param [in,out] outinfo The outinfo. - * - * @return A chd_error. - */ - -chd_error chdcd_parse_iso(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) -{ - FILE *infile; - std::string path = std::string(tocfname); - - infile = fopen(tocfname, "rb"); - path = get_file_path(path); - - if (infile == (FILE *)nullptr) - { - return CHDERR_FILE_NOT_FOUND; - } - - /* clear structures */ - memset(&outtoc, 0, sizeof(outtoc)); - outinfo.reset(); - - uint64_t size = get_file_size(tocfname); - fclose(infile); - - - outtoc.numtrks = 1; - - outinfo.track[0].fname = tocfname; - outinfo.track[0].offset = 0; - outinfo.track[0].idx0offs = 0; - outinfo.track[0].idx1offs = 0; - - if ((size % 2048)==0 ) { - outtoc.tracks[0].trktype = CD_TRACK_MODE1; - outtoc.tracks[0].frames = size / 2048; - outtoc.tracks[0].datasize = 2048; - outinfo.track[0].swap = false; - } else if ((size % 2336)==0 ) { - // 2352 byte mode 2 - outtoc.tracks[0].trktype = CD_TRACK_MODE2; - outtoc.tracks[0].frames = size / 2336; - outtoc.tracks[0].datasize = 2336; - outinfo.track[0].swap = false; - } else if ((size % 2352)==0 ) { - // 2352 byte mode 2 raw - outtoc.tracks[0].trktype = CD_TRACK_MODE2_RAW; - outtoc.tracks[0].frames = size / 2352; - outtoc.tracks[0].datasize = 2352; - outinfo.track[0].swap = false; - } else { - printf("ERROR: Unrecognized track type\n"); - return CHDERR_UNSUPPORTED_FORMAT; - } - - outtoc.tracks[0].subtype = CD_SUB_NONE; - outtoc.tracks[0].subsize = 0; - - outtoc.tracks[0].pregap = 0; - - outtoc.tracks[0].postgap = 0; - outtoc.tracks[0].pgtype = 0; - outtoc.tracks[0].pgsub = CD_SUB_NONE; - outtoc.tracks[0].pgdatasize = 0; - outtoc.tracks[0].pgsubsize = 0; - outtoc.tracks[0].padframes = 0; - - - return CHDERR_NONE; -} - -/*------------------------------------------------- - chdcd_parse_gdi - parse a Sega GD-ROM rip --------------------------------------------------*/ - -/** - * @fn static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) - * - * @brief Chdcd parse GDI. - * - * @param tocfname The tocfname. - * @param [in,out] outtoc The outtoc. - * @param [in,out] outinfo The outinfo. - * - * @return A chd_error. - */ - -static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) -{ - FILE *infile; - int i, numtracks; - - std::string path = std::string(tocfname); - - infile = fopen(tocfname, "rt"); - path = get_file_path(path); - - if (infile == (FILE *)nullptr) - { - return CHDERR_FILE_NOT_FOUND; - } - - /* clear structures */ - memset(&outtoc, 0, sizeof(outtoc)); - outinfo.reset(); - - outtoc.flags = CD_FLAG_GDROM; - - fgets(linebuffer,511,infile); - numtracks=atoi(linebuffer); - - for(i=0;i<numtracks;++i) - { - char *tok; - int trknum; - int trksize,trktype; - int sz; - - fgets(linebuffer,511,infile); - - tok=strtok(linebuffer," "); - - trknum=atoi(tok)-1; - - outinfo.track[trknum].swap=false; - outinfo.track[trknum].offset=0; - - outtoc.tracks[trknum].datasize = 0; - outtoc.tracks[trknum].subtype = CD_SUB_NONE; - outtoc.tracks[trknum].subsize = 0; - outtoc.tracks[trknum].pgsub = CD_SUB_NONE; - - tok=strtok(nullptr," "); - outtoc.tracks[trknum].physframeofs=atoi(tok); - - tok=strtok(nullptr," "); - trktype=atoi(tok); - - tok=strtok(nullptr," "); - trksize=atoi(tok); - - if(trktype==4 && trksize==2352) - { - outtoc.tracks[trknum].trktype=CD_TRACK_MODE1_RAW; - outtoc.tracks[trknum].datasize=2352; - } - if(trktype==4 && trksize==2048) - { - outtoc.tracks[trknum].trktype=CD_TRACK_MODE1; - outtoc.tracks[trknum].datasize=2048; - } - if(trktype==0) - { - outtoc.tracks[trknum].trktype=CD_TRACK_AUDIO; - outtoc.tracks[trknum].datasize=2352; - outinfo.track[trknum].swap = true; - } - - std::string name; - - tok=strtok(nullptr," "); - name = tok; - if (tok[0]=='"') { - do { - tok=strtok(nullptr," "); - if (tok!=nullptr) { - name += " "; - name += tok; - } - } while(tok!=nullptr && (strrchr(tok,'"')-tok !=(strlen(tok)-1))); - strdelchr(name,'"'); - } - outinfo.track[trknum].fname.assign(path).append(name); - - sz = get_file_size(outinfo.track[trknum].fname.c_str()); - - outtoc.tracks[trknum].frames = sz/trksize; - outtoc.tracks[trknum].padframes = 0; - - if (trknum != 0) - { - int dif=outtoc.tracks[trknum].physframeofs-(outtoc.tracks[trknum-1].frames+outtoc.tracks[trknum-1].physframeofs); - outtoc.tracks[trknum-1].frames += dif; - outtoc.tracks[trknum-1].padframes = dif; - } - } - - #if 0 - for(i=0; i < numtracks; i++) - { - printf("%s %d %d %d (true %d)\n", outinfo.track[i].fname.c_str(), outtoc.tracks[i].frames, outtoc.tracks[i].padframes, outtoc.tracks[i].physframeofs, outtoc.tracks[i].frames - outtoc.tracks[i].padframes); - } - #endif - - /* close the input TOC */ - fclose(infile); - - /* store the number of tracks found */ - outtoc.numtrks = numtracks; - - return CHDERR_NONE; -} - -/*------------------------------------------------- - chdcd_parse_cue - parse a CDRWin format CUE file --------------------------------------------------*/ - -/** - * @fn chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) - * - * @brief Chdcd parse cue. - * - * @param tocfname The tocfname. - * @param [in,out] outtoc The outtoc. - * @param [in,out] outinfo The outinfo. - * - * @return A chd_error. - */ - -chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) -{ - FILE *infile; - int i, trknum; - static char token[512]; - std::string lastfname; - uint32_t wavlen, wavoffs; - std::string path = std::string(tocfname); - - infile = fopen(tocfname, "rt"); - path = get_file_path(path); - if (infile == (FILE *)nullptr) - { - return CHDERR_FILE_NOT_FOUND; - } - - /* clear structures */ - memset(&outtoc, 0, sizeof(outtoc)); - outinfo.reset(); - - trknum = -1; - wavoffs = wavlen = 0; - - while (!feof(infile)) - { - /* get the next line */ - fgets(linebuffer, 511, infile); - - /* if EOF didn't hit, keep going */ - if (!feof(infile)) - { - i = 0; - - TOKENIZE - - if (!strcmp(token, "FILE")) - { - /* found the data file for a track */ - TOKENIZE - - /* keep the filename */ - lastfname.assign(path).append(token); - - /* get the file type */ - TOKENIZE - - if (!strcmp(token, "BINARY")) - { - outinfo.track[trknum+1].swap = false; - } - else if (!strcmp(token, "MOTOROLA")) - { - outinfo.track[trknum+1].swap = true; - } - else if (!strcmp(token, "WAVE")) - { - wavlen = parse_wav_sample(lastfname.c_str(), &wavoffs); - if (!wavlen) - { - fclose(infile); - printf("ERROR: couldn't read [%s] or not a valid .WAV\n", lastfname.c_str()); - return CHDERR_INVALID_DATA; - } - } - else - { - fclose(infile); - printf("ERROR: Unhandled track type %s\n", token); - return CHDERR_UNSUPPORTED_FORMAT; - } - } - else if (!strcmp(token, "TRACK")) - { - /* get the track number */ - TOKENIZE - trknum = strtoul(token, nullptr, 10) - 1; - - /* next token on the line is the track type */ - TOKENIZE - - if (wavlen != 0) - { - outtoc.tracks[trknum].trktype = CD_TRACK_AUDIO; - outtoc.tracks[trknum].frames = wavlen/2352; - outinfo.track[trknum].offset = wavoffs; - wavoffs = wavlen = 0; - } - else - { - outtoc.tracks[trknum].trktype = CD_TRACK_MODE1; - outtoc.tracks[trknum].datasize = 0; - outinfo.track[trknum].offset = 0; - } - outtoc.tracks[trknum].subtype = CD_SUB_NONE; - outtoc.tracks[trknum].subsize = 0; - outtoc.tracks[trknum].pgsub = CD_SUB_NONE; - outtoc.tracks[trknum].pregap = 0; - outtoc.tracks[trknum].padframes = 0; - outinfo.track[trknum].idx0offs = -1; - outinfo.track[trknum].idx1offs = 0; - - outinfo.track[trknum].fname.assign(lastfname); // default filename to the last one - -// printf("trk %d: fname %s offset %d\n", trknum, outinfo.track[trknum].fname.c_str(), outinfo.track[trknum].offset); - - cdrom_convert_type_string_to_track_info(token, &outtoc.tracks[trknum]); - if (outtoc.tracks[trknum].datasize == 0) - { - fclose(infile); - printf("ERROR: Unknown track type [%s]. Contact MAMEDEV.\n", token); - return CHDERR_UNSUPPORTED_FORMAT; - } - - /* next (optional) token on the line is the subcode type */ - TOKENIZE - - cdrom_convert_subtype_string_to_track_info(token, &outtoc.tracks[trknum]); - } - else if (!strcmp(token, "INDEX")) /* only in bin/cue files */ - { - int idx, frames; - - /* get index number */ - TOKENIZE - idx = strtoul(token, nullptr, 10); - - /* get index */ - TOKENIZE - frames = msf_to_frames( token ); - - if (idx == 0) - { - outinfo.track[trknum].idx0offs = frames; - } - else if (idx == 1) - { - outinfo.track[trknum].idx1offs = frames; - if ((outtoc.tracks[trknum].pregap == 0) && (outinfo.track[trknum].idx0offs != -1)) - { - outtoc.tracks[trknum].pregap = frames - outinfo.track[trknum].idx0offs; - outtoc.tracks[trknum].pgtype = outtoc.tracks[trknum].trktype; - switch (outtoc.tracks[trknum].pgtype) - { - case CD_TRACK_MODE1: - case CD_TRACK_MODE2_FORM1: - outtoc.tracks[trknum].pgdatasize = 2048; - break; - - case CD_TRACK_MODE1_RAW: - case CD_TRACK_MODE2_RAW: - case CD_TRACK_AUDIO: - outtoc.tracks[trknum].pgdatasize = 2352; - break; - - case CD_TRACK_MODE2: - case CD_TRACK_MODE2_FORM_MIX: - outtoc.tracks[trknum].pgdatasize = 2336; - break; - - case CD_TRACK_MODE2_FORM2: - outtoc.tracks[trknum].pgdatasize = 2324; - break; - } - } - else // pregap sectors not in file, but we're always using idx0ofs for track length calc now - { - outinfo.track[trknum].idx0offs = frames; - } - } - } - else if (!strcmp(token, "PREGAP")) - { - int frames; - - /* get index */ - TOKENIZE - frames = msf_to_frames( token ); - - outtoc.tracks[trknum].pregap = frames; - } - else if (!strcmp(token, "POSTGAP")) - { - int frames; - - /* get index */ - TOKENIZE - frames = msf_to_frames( token ); - - outtoc.tracks[trknum].postgap = frames; - } - } - } - - /* close the input CUE */ - fclose(infile); - - /* store the number of tracks found */ - outtoc.numtrks = trknum + 1; - - /* now go over the files again and set the lengths */ - for (trknum = 0; trknum < outtoc.numtrks; trknum++) - { - uint64_t 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.track[trknum].swap = true; - } - - // don't do this for .WAV tracks, we already have their length and offset filled out - if (outinfo.track[trknum].offset == 0) - { - // is this the last track? - if (trknum == (outtoc.numtrks-1)) - { - /* if we have the same filename as the last track, do it that way */ - if (trknum != 0 && (outinfo.track[trknum].fname.compare(outinfo.track[trknum-1].fname)==0)) - { - tlen = get_file_size(outinfo.track[trknum].fname.c_str()); - if (tlen == 0) - { - printf("ERROR: couldn't find bin file [%s]\n", outinfo.track[trknum-1].fname.c_str()); - return CHDERR_FILE_NOT_FOUND; - } - outinfo.track[trknum].offset = outinfo.track[trknum-1].offset + outtoc.tracks[trknum-1].frames * (outtoc.tracks[trknum-1].datasize + outtoc.tracks[trknum-1].subsize); - outtoc.tracks[trknum].frames = (tlen - outinfo.track[trknum].offset) / (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize); - } - else /* data files are different */ - { - tlen = get_file_size(outinfo.track[trknum].fname.c_str()); - if (tlen == 0) - { - printf("ERROR: couldn't find bin file [%s]\n", outinfo.track[trknum-1].fname.c_str()); - return CHDERR_FILE_NOT_FOUND; - } - tlen /= (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize); - outtoc.tracks[trknum].frames = tlen; - outinfo.track[trknum].offset = 0; - } - } - else - { - /* if we have the same filename as the next track, do it that way */ - if (outinfo.track[trknum].fname.compare(outinfo.track[trknum+1].fname)==0) - { - outtoc.tracks[trknum].frames = outinfo.track[trknum+1].idx0offs - outinfo.track[trknum].idx0offs; - - if (trknum == 0) // track 0 offset is 0 - { - outinfo.track[trknum].offset = 0; - } - else - { - outinfo.track[trknum].offset = outinfo.track[trknum-1].offset + 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_INVALID_DATA; - } - } - else /* data files are different */ - { - tlen = get_file_size(outinfo.track[trknum].fname.c_str()); - if (tlen == 0) - { - printf("ERROR: couldn't find bin file [%s]\n", outinfo.track[trknum].fname.c_str()); - return CHDERR_FILE_NOT_FOUND; - } - tlen /= (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize); - outtoc.tracks[trknum].frames = tlen; - outinfo.track[trknum].offset = 0; - } - } - } - //printf("trk %d: %d frames @ offset %d\n", trknum+1, outtoc.tracks[trknum].frames, outinfo.track[trknum].offset); - } - - return CHDERR_NONE; -} - -/*------------------------------------------------- - chdcd_parse_toc - parse a CDRDAO format TOC file --------------------------------------------------*/ - -/** - * @fn chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) - * - * @brief Chdcd parse TOC. - * - * @param tocfname The tocfname. - * @param [in,out] outtoc The outtoc. - * @param [in,out] outinfo The outinfo. - * - * @return A chd_error. - */ - -chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) -{ - FILE *infile; - int i, trknum; - static char token[512]; - char tocftemp[512]; - - strcpy(tocftemp, tocfname); - for (i = 0; i < strlen(tocfname); i++) - { - tocftemp[i] = tolower(tocftemp[i]); - } - - if (strstr(tocftemp,".gdi")) - { - return chdcd_parse_gdi(tocfname, outtoc, outinfo); - } - - if (strstr(tocftemp,".cue")) - { - return chdcd_parse_cue(tocfname, outtoc, outinfo); - } - - if (strstr(tocftemp,".nrg")) - { - return chdcd_parse_nero(tocfname, outtoc, outinfo); - } - - if (strstr(tocftemp,".iso") || strstr(tocftemp,".cdr") || strstr(tocftemp,".toast")) - { - return chdcd_parse_iso(tocfname, outtoc, outinfo); - } - - std::string path = std::string(tocfname); - - infile = fopen(tocfname, "rt"); - path = get_file_path(path); - - if (infile == (FILE *)nullptr) - { - return CHDERR_FILE_NOT_FOUND; - } - - /* clear structures */ - memset(&outtoc, 0, sizeof(outtoc)); - outinfo.reset(); - - trknum = -1; - - while (!feof(infile)) - { - /* get the next line */ - fgets(linebuffer, 511, infile); - - /* if EOF didn't hit, keep going */ - if (!feof(infile)) - { - i = 0; - - TOKENIZE - - if ((!strcmp(token, "DATAFILE")) || (!strcmp(token, "AUDIOFILE")) || (!strcmp(token, "FILE"))) - { - int f; - - /* found the data file for a track */ - TOKENIZE - - /* keep the filename */ - outinfo.track[trknum].fname.assign(path).append(token); - - /* get either the offset or the length */ - TOKENIZE - - if (!strcmp(token, "SWAP")) - { - TOKENIZE - - outinfo.track[trknum].swap = true; - } - else - { - outinfo.track[trknum].swap = false; - } - - if (token[0] == '#') - { - /* it's a decimal offset, use it */ - f = strtoul(&token[1], nullptr, 10); - } - else if (isdigit((uint8_t)token[0])) - { - /* convert the time to an offset */ - f = msf_to_frames( token ); - - f *= (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize); - } - else - { - f = 0; - } - - outinfo.track[trknum].offset = f; - - TOKENIZE - - if (isdigit((uint8_t)token[0])) - { - // this could be the length or an offset from the previous field. - f = msf_to_frames( token ); - - TOKENIZE - - if (isdigit((uint8_t)token[0])) - { - // it was an offset. - f *= (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize); - - outinfo.track[trknum].offset += f; - - // this is the length. - f = msf_to_frames( token ); - } - } - else if( trknum == 0 && outinfo.track[trknum].offset != 0 ) - { - /* the 1st track might have a length with no offset */ - f = outinfo.track[trknum].offset / (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize); - outinfo.track[trknum].offset = 0; - } - else - { - /* guesstimate the track length? */ - f = 0; - } - - outtoc.tracks[trknum].frames = f; - } - else if (!strcmp(token, "TRACK")) - { - trknum++; - - /* next token on the line is the track type */ - TOKENIZE - - outtoc.tracks[trknum].trktype = CD_TRACK_MODE1; - outtoc.tracks[trknum].datasize = 0; - outtoc.tracks[trknum].subtype = CD_SUB_NONE; - outtoc.tracks[trknum].subsize = 0; - outtoc.tracks[trknum].pgsub = CD_SUB_NONE; - outtoc.tracks[trknum].padframes = 0; - - cdrom_convert_type_string_to_track_info(token, &outtoc.tracks[trknum]); - if (outtoc.tracks[trknum].datasize == 0) - { - fclose(infile); - printf("ERROR: Unknown track type [%s]. Contact MAMEDEV.\n", token); - return CHDERR_UNSUPPORTED_FORMAT; - } - - /* next (optional) token on the line is the subcode type */ - TOKENIZE - - cdrom_convert_subtype_string_to_track_info(token, &outtoc.tracks[trknum]); - } - else if (!strcmp(token, "START")) - { - int frames; - - /* get index */ - TOKENIZE - frames = msf_to_frames( token ); - - outtoc.tracks[trknum].pregap = frames; - } - } - } - - /* close the input TOC */ - fclose(infile); - - /* store the number of tracks found */ - outtoc.numtrks = trknum + 1; - - return CHDERR_NONE; -} |