From dcf06f4ba9d51249bae843672f7b2bcf71ee3c6d Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 13 Jan 2020 21:06:32 +0100 Subject: [PATCH] Fixed the mess in cdrom/cdrom_image_backend.c. --- src/cdrom/cdrom_image_backend.c | 980 -------------------------------- 1 file changed, 980 deletions(-) diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index a888c882e..61260b44d 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -1,51 +1,3 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * CD-ROM image file handling module, translated to C from - * cdrom_dosbox.cpp. - * - * Version: @(#)cdrom_image_backend.c 1.0.2 2020/01/11 - * - * Authors: Miran Grca, - * Fred N. van Kempen, - * The DOSBox Team, - * - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2002-2020 The DOSBox Team. - */ -#define _LARGEFILE_SOURCE -#define _LARGEFILE64_SOURCE -#define __STDC_FORMAT_MACROS -#include -#include -#include -#include -#include -#include -#ifdef _WIN32 -# include -#else -# include -#endif -#include -#define HAVE_STDARG_H -#include "../86box.h" -#include "../plat.h" -#include "cdrom_image_backend.h" - - -#define CDROM_BCD(x) (((x) % 10) | (((x) / 10) << 4)) - -#define MAX_LINE_LENGTH 512 -#define MAX_FILENAME_LENGTH 256 -#define CROSS_LEN 512 - /* * 86Box A hypervisor and IBM PC system emulator that specializes in * running old operating systems and software designed for IBM @@ -1023,938 +975,6 @@ cdi_has_data_track(cd_img_t *cdi) } -int -cdi_has_audio_track(cd_img_t *cdi) -{ - int i; - - if ((cdi == NULL) || (cdi->tracks == NULL)) - return 0; - - /* Audio track has attribute 0x14. */ - for (i = 0; i < cdi->tracks_num; i++) { - if (cdi->tracks[i].attr == AUDIO_TRACK) - return 1; - } - - return 0; -} - -#ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG -int cdrom_image_backend_do_log = ENABLE_CDROM_IMAGE_BACKEND_LOG; - - -void -cdrom_image_backend_log(const char *fmt, ...) -{ - va_list ap; - - if (cdrom_image_backend_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -#define cdrom_image_backend_log(fmt, ...) -#endif - - -/* Binary file functions. */ -static int -bin_read(void *p, uint8_t *buffer, uint64_t seek, size_t count) -{ - track_file_t *tf = (track_file_t *) p; - - cdrom_image_backend_log("CDROM: binary_read(%08lx, pos=%" PRIu64 " count=%lu\n", - tf->file, seek, count); - - if (tf->file == NULL) - return 0; - - fseeko64(tf->file, seek, SEEK_SET); - - if (fread(buffer, count, 1, tf->file) != 1) { -#ifdef ENABLE_cdrom_image_backend_log - cdrom_image_backend_log("CDROM: binary_read failed!\n"); -#endif - return 0; - } - - return 1; -} - - -static uint64_t -bin_get_length(void *p) -{ - off64_t len; - track_file_t *tf = (track_file_t *) p; - - cdrom_image_backend_log("CDROM: binary_length(%08lx)\n", bf->file); - - if (tf->file == NULL) - return 0; - - fseeko64(tf->file, 0, SEEK_END); - len = ftello64(tf->file); - cdrom_image_backend_log("CDROM: binary_length(%08lx) = %" PRIu64 "\n", tf->file, len); - - return len; -} - - -static void -bin_close(void *p) -{ - track_file_t *tf = (track_file_t *) p; - - if (tf == NULL) - return; - - if (tf->file != NULL) { - fclose(tf->file); - tf->file = NULL; - } - - memset(tf->fn, 0x00, sizeof(tf->fn)); - - free(p); -} - - -static track_file_t * -bin_init(const wchar_t *filename, int *error) -{ - track_file_t *tf = (track_file_t *) malloc(sizeof(track_file_t)); - - memset(tf->fn, 0x00, sizeof(tf->fn)); - wcscpy(tf->fn, filename); - tf->file = plat_fopen64(tf->fn, L"rb"); - cdrom_image_backend_log("CDROM: binary_open(%ls) = %08lx\n", tf->fn, tf->file); - - *error = (tf->file == NULL); - - /* Set the function pointers. */ - if (!*error) { - tf->read = bin_read; - tf->get_length = bin_get_length; - tf->close = bin_close; - } - - return tf; -} - - -static track_file_t * -track_file_init(const wchar_t *filename, int *error) -{ - /* Current we only support .BIN files, either combined or one per - track. In the future, more is planned. */ - return bin_init(filename, error); -} - - -static void -track_file_close(track_t *trk) -{ - if (trk == NULL) - return; - - if (trk->file == NULL) - return; - - trk->file->close(trk->file); - trk->file = NULL; -} - - -/* Root functions. */ -static void -cdi_clear_tracks(cd_img_t *cdi) -{ - int i; - track_file_t *last = NULL; - track_t *cur = NULL; - - if ((cdi->tracks == NULL) || (cdi->tracks_num == 0)) - return; - - for (i = 0; i < cdi->tracks_num; i++) { - cur = &cdi->tracks[i]; - - if (cur->file != last) { - track_file_close(cur); - last = cur->file; - } - } - - /* Now free the array. */ - free(cdi->tracks); - cdi->tracks = NULL; - - /* Mark that there's no tracks. */ - cdi->tracks_num = 0; -} - - -void -cdi_close(cd_img_t *cdi) -{ - cdi_clear_tracks(cdi); - free(cdi); -} - - -int -cdi_set_device(cd_img_t *cdi, const wchar_t *path) -{ - if (cdi_load_cue(cdi, path)) - return 1; - - if (cdi_load_iso(cdi, path)) - return 1; - - return 0; -} - - -/* TODO: This never returns anything other than 1, should it even be an int? */ -int -cdi_get_audio_tracks(cd_img_t *cdi, int *st_track, int *end, TMSF *lead_out) -{ - *st_track = 1; - *end = cdi->tracks_num - 1; - FRAMES_TO_MSF(cdi->tracks[*end].start + 150, &lead_out->min, &lead_out->sec, &lead_out->fr); - - return 1; -} - - -/* This replaces both Info and EndInfo, they are specified by a variable. */ -int -cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF *start, uint8_t *attr) -{ - track_t *trk = &cdi->tracks[track - 1]; - int pos = trk->start + 150; - - if ((track < 1) || (track > cdi->tracks_num)) - return 0; - - pos = trk->start + 150; - - FRAMES_TO_MSF(pos, &start->min, &start->sec, &start->fr); - *track_num = trk->track_number; - *attr = trk->attr; - - return 1; -} - - -int -cdi_get_track(cd_img_t *cdi, uint32_t sector) -{ - int i; - track_t *cur, *next; - - /* There must be at least two tracks - data and lead out. */ - if (cdi->tracks_num < 2) - return -1; - - /* This has a problem - the code skips the last track, which is - lead out - is that correct? */ - for (i = 0; i < (cdi->tracks_num - 1); i++) { - cur = &cdi->tracks[i]; - next = &cdi->tracks[i + 1]; - if ((cur->start <= sector) && (sector < next->start)) - return cur->number; - } - - return -1; -} - - -/* TODO: See if track start is adjusted by 150 or not. */ -int -cdi_get_audio_sub(cd_img_t *cdi, uint32_t sector, uint8_t *attr, uint8_t *track, uint8_t *index, TMSF *rel_pos, TMSF *abs_pos) -{ - int cur_track = cdi_get_track(cdi, sector); - track_t *trk; - - if (cur_track < 1) - return 0; - - *track = (uint8_t) cur_track; - trk = &cdi->tracks[*track - 1]; - *attr = trk->attr; - *index = 1; - - FRAMES_TO_MSF(sector + 150, &abs_pos->min, &abs_pos->sec, &abs_pos->fr); - - /* Absolute position should be adjusted by 150, not the relative ones. */ - FRAMES_TO_MSF(sector - trk->start, &rel_pos->min, &rel_pos->sec, &rel_pos->fr); - - return 1; -} - - -int -cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector) -{ - size_t length; - int track = cdi_get_track(cdi, sector) - 1; - uint64_t sect = (uint64_t) sector, seek; - track_t *trk; - int track_is_raw, ret; - int raw_size, cooked_size; - uint64_t offset = 0ULL; - int m = 0, s = 0, f = 0; - - if (track < 0) - return 0; - - trk = &cdi->tracks[track]; - track_is_raw = ((trk->sector_size == RAW_SECTOR_SIZE) || (trk->sector_size == 2448)); - if (raw && !track_is_raw) - return 0; - seek = trk->skip + ((sect - trk->start) * trk->sector_size); - - if (track_is_raw) - raw_size = trk->sector_size; - else - raw_size = 2448; - - if (trk->mode2 && (trk->form != 1)) { - if (trk->form == 2) - cooked_size = (track_is_raw ? 2328 : trk->sector_size); /* Both 2324 + ECC and 2328 variants are valid. */ - else - cooked_size = 2336; - } else - cooked_size = COOKED_SECTOR_SIZE; - - length = (raw ? raw_size : cooked_size); - - if (trk->mode2 && (trk->form >= 1)) - offset = 24ULL; - else - offset = 16ULL; - - if (raw && !track_is_raw) { - memset(buffer, 0x00, 2448); - ret = trk->file->read(trk->file, buffer + offset, seek, length); - if (!ret) - return 0; - /* Construct the rest of the raw sector. */ - memset(buffer + 1, 0xff, 10); - buffer += 12; - FRAMES_TO_MSF(sector + 150, &m, &s, &f); - /* These have to be BCD. */ - buffer[12] = CDROM_BCD(m & 0xff); - buffer[13] = CDROM_BCD(s & 0xff); - buffer[14] = CDROM_BCD(f & 0xff); - buffer[15] = trk->mode2 ? 2 : 1; /* Data, should reflect the actual sector type. */ - return 1; - } else if (!raw && track_is_raw) - return trk->file->read(trk->file, buffer, seek + offset, length); - else - return trk->file->read(trk->file, buffer, seek, length); -} - - -int -cdi_read_sectors(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector, uint32_t num) -{ - int sector_size, success = 1; - uint8_t buf_len, *buf; - uint32_t i; - - /* TODO: This fails to account for Mode 2. Shouldn't we have a function - to get sector size? */ - sector_size = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE; - buf_len = num * sector_size; - buf = (uint8_t *) malloc(buf_len * sizeof(uint8_t)); - - for (i = 0; i < num; i++) { - success = cdi_read_sector(cdi, &buf[i * sector_size], raw, sector + i); - if (!success) - break; - } - - memcpy((void *) buffer, buf, buf_len); - free(buf); - buf = NULL; - - return success; -} - - -/* TODO: Do CUE+BIN images with a sector size of 2448 even exist? */ -int -cdi_read_sector_sub(cd_img_t *cdi, uint8_t *buffer, uint32_t sector) -{ - int track = cdi_get_track(cdi, sector) - 1; - track_t *trk; - uint64_t s = (uint64_t) sector, seek; - - if (track < 0) - return 0; - - trk = &cdi->tracks[track]; - seek = trk->skip + ((s - trk->start) * trk->sector_size); - if (trk->sector_size != 2448) - return 0; - - return trk->file->read(trk->file, buffer, seek, 2448); -} - - -int -cdi_get_sector_size(cd_img_t *cdi, uint32_t sector) -{ - int track = cdi_get_track(cdi, sector) - 1; - track_t *trk; - - if (track < 0) - return 0; - - trk = &cdi->tracks[track]; - return trk->sector_size; -} - - -int -cdi_is_mode2(cd_img_t *cdi, uint32_t sector) -{ - int track = cdi_get_track(cdi, sector) - 1; - track_t *trk; - - if (track < 0) - return 0; - - trk = &cdi->tracks[track]; - - return !!(trk->mode2); -} - - -int -cdi_get_mode2_form(cd_img_t *cdi, uint32_t sector) -{ - int track = cdi_get_track(cdi, sector) - 1; - track_t *trk; - - if (track < 0) - return 0; - - trk = &cdi->tracks[track]; - - return trk->form; -} - - -static int -cdi_can_read_pvd(track_file_t *file, uint64_t sector_size, int mode2, int form) -{ - uint8_t pvd[COOKED_SECTOR_SIZE]; - uint64_t seek = 16ULL * sector_size; /* First VD is located at sector 16. */ - - if ((!mode2 || (form == 0)) && (sector_size == RAW_SECTOR_SIZE)) - seek += 16; - if (mode2 && (form >= 1)) - seek += 24; - - file->read(file, pvd, seek, COOKED_SECTOR_SIZE); - - return ((pvd[0] == 1 && !strncmp((char*)(&pvd[1]), "CD001", 5) && pvd[6] == 1) || - (pvd[8] == 1 && !strncmp((char*)(&pvd[9]), "CDROM", 5) && pvd[14] == 1)); -} - - -/* This reallocates the array and returns the pointer to the last track. */ -static void -cdi_track_push_back(cd_img_t *cdi, track_t *trk) -{ - /* This has to be done so situations in which realloc would misbehave - can be detected and reported to the user. */ - if ((cdi->tracks != NULL) && (cdi->tracks_num == 0)) - fatal("CD-ROM Image: Non-null tracks array at 0 loaded tracks\n"); - if ((cdi->tracks == NULL) && (cdi->tracks_num != 0)) - fatal("CD-ROM Image: Null tracks array at non-zero loaded tracks\n"); - - cdi->tracks = realloc(cdi->tracks, (cdi->tracks_num + 1) * sizeof(track_t)); - memcpy(&(cdi->tracks[cdi->tracks_num]), trk, sizeof(track_t)); - cdi->tracks_num++; -} - - -int -cdi_load_iso(cd_img_t *cdi, const wchar_t *filename) -{ - int error; - track_t trk; - - cdi->tracks = NULL; - cdi->tracks_num = 0; - - memset(&trk, 0, sizeof(track_t)); - - /* Data track (shouldn't there be a lead in track?). */ - trk.file = bin_init(filename, &error); - if (error) { - if (trk.file != NULL) - trk.file->close(trk.file); - return 0; - } - trk.number = 1; - trk.track_number = 1; - trk.attr = DATA_TRACK; - - /* Try to detect ISO type. */ - trk.form = 0; - trk.mode2 = 0; - /* TODO: Merge the first and last cases since they result in the same thing. */ - if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 0, 0)) - trk.sector_size = RAW_SECTOR_SIZE; - else if (cdi_can_read_pvd(trk.file, 2336, 1, 0)) { - trk.sector_size = 2336; - trk.mode2 = 1; - } else if (cdi_can_read_pvd(trk.file, 2324, 1, 2)) { - trk.sector_size = 2324; - trk.mode2 = 1; - trk.form = 2; - } else if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 1, 0)) { - trk.sector_size = RAW_SECTOR_SIZE; - trk.mode2 = 1; - } else { - /* We use 2048 mode 1 as the default. */ - trk.sector_size = COOKED_SECTOR_SIZE; - } - - trk.length = trk.file->get_length(trk.file) / trk.sector_size; - cdi_track_push_back(cdi, &trk); - - /* Lead out track. */ - trk.number = 2; - trk.track_number = 0xAA; - trk.attr = 0x16; /* Was originally 0x00, but I believe 0x16 is appropriate. */ - trk.start = trk.length; - trk.length = 0; - trk.file = NULL; - cdi_track_push_back(cdi, &trk); - - return 1; -} - - -static int -cdi_cue_get_buffer(char *str, char **line, int up) -{ - char *s = *line; - char *p = str; - int quote = 0; - int done = 0; - int space = 1; - - /* Copy to local buffer until we have end of string or whitespace. */ - while (! done) { - switch(*s) { - case '\0': - if (quote) { - /* Ouch, unterminated string.. */ - return 0; - } - done = 1; - break; - - case '\"': - quote ^= 1; - break; - - case ' ': - case '\t': - if (space) - break; - - if (! quote) { - done = 1; - break; - } - /*FALLTHROUGH*/ - - default: - if (up && islower((int) *s)) - *p++ = toupper((int) *s); - else - *p++ = *s; - space = 0; - break; - } - - if (! done) - s++; - } - *p = '\0'; - - *line = s; - - return 1; -} - - -static int -cdi_cue_get_keyword(char **dest, char **line) -{ - char temp[1024]; - int success; - - success = cdi_cue_get_buffer(temp, line, 1); - if (success) - *dest = temp; - - return success; -} - - -/* Get a string from the input line, handling quotes properly. */ -static uint64_t -cdi_cue_get_number(char **line) -{ - char temp[128]; - uint64_t num; - - if (!cdi_cue_get_buffer(temp, line, 0)) - return 0; - - if (sscanf(temp, "%" PRIu64, &num) != 1) - return 0; - - return num; -} - - -static int -cdi_cue_get_frame(uint64_t *frames, char **line) -{ - char temp[128]; - int min, sec, fr; - int success; - - success = cdi_cue_get_buffer(temp, line, 0); - if (! success) return 0; - - success = sscanf(temp, "%d:%d:%d", &min, &sec, &fr) == 3; - if (! success) return 0; - - *frames = MSF_TO_FRAMES(min, sec, fr); - - return 1; -} - - -static int -cdi_add_track(cd_img_t *cdi, track_t *cur, uint64_t *shift, uint64_t prestart, uint64_t *total_pregap, uint64_t cur_pregap) -{ - /* Frames between index 0 (prestart) and 1 (current track start) must be skipped. */ - uint64_t skip, temp; - track_t *prev = NULL; - - if (prestart > 0) { - if (prestart > cur->start) - return 0; - skip = cur->start - prestart; - } else - skip = 0ULL; - - if ((cdi->tracks != NULL) && (cdi->tracks_num != 0)) - prev = &cdi->tracks[cdi->tracks_num - 1]; - - /* First track (track number must be 1). */ - if (cdi->tracks_num == 0) { - /* I guess this makes sure the structure is not filled with invalid data. */ - if (cur->number != 1) - return 0; - cur->skip = skip * cur->sector_size; - cur->start += cur_pregap; - *total_pregap = cur_pregap; - cdi_track_push_back(cdi, cur); - return 1; - } - - /* Current track consumes data from the same file as the previous. */ - if (prev->file == cur->file) { - cur->start += *shift; - prev->length = cur->start + *total_pregap - prev->start - skip; - cur->skip += prev->skip + (prev->length * prev->sector_size) + (skip * cur->sector_size); - *total_pregap += cur_pregap; - cur->start += *total_pregap; - } else { - temp = prev->file->get_length(prev->file) - ((uint64_t) prev->skip); - prev->length = temp / ((uint64_t) prev->sector_size); - if ((temp % prev->sector_size) != 0) - prev->length++; /* Padding. */ - - cur->start += prev->start + prev->length + cur_pregap; - cur->skip = skip * cur->sector_size; - *shift += prev->start + prev->length; - *total_pregap = cur_pregap; - } - - /* Error checks. */ - if (cur->number <= 1) - return 0; - if ((prev->number + 1) != cur->number) - return 0; - if (cur->start < (prev->start + prev->length)) - return 0; - - cdi_track_push_back(cdi, cur); - - return 1; -} - - -int -cdi_load_cue(cd_img_t *cdi, const wchar_t *cuefile) -{ - track_t trk; - wchar_t pathname[MAX_FILENAME_LENGTH], filename[MAX_FILENAME_LENGTH]; - wchar_t temp[MAX_FILENAME_LENGTH]; - uint64_t shift = 0ULL, prestart = 0ULL; - uint64_t cur_pregap = 0ULL, total_pregap = 0ULL; - uint64_t frame = 0ULL, index; - int i, success; - int error, can_add_track = 0; - FILE *fp; - char buf[MAX_LINE_LENGTH], ansi[MAX_FILENAME_LENGTH]; - char *line, *command; - char *type; - - cdi->tracks = NULL; - cdi->tracks_num = 0; - - memset(&trk, 0, sizeof(track_t)); - - /* Get a copy of the filename into pathname, we need it later. */ - memset(pathname, 0, MAX_FILENAME_LENGTH * sizeof(wchar_t)); - plat_get_dirname(pathname, cuefile); - - /* Open the file. */ - fp = plat_fopen((wchar_t *) cuefile, L"r"); - if (fp == NULL) - return 0; - - success = 0; - - for (;;) { - line = buf; - - /* Read a line from the cuesheet file. */ - if (feof(fp) || fgets(buf, sizeof(buf), fp) == NULL || ferror(fp)) - break; - - /* Do two iterations to make sure to nuke even if it's \r\n or \n\r, - but do checks to make sure we're not nuking other bytes. */ - for (i = 0; i < 2; i++) { - if (strlen(buf) > 0) { - if (buf[strlen(buf) - 1] == '\n') - buf[strlen(buf) - 1] = '\0'; /* nuke trailing newline */ - else if (buf[strlen(buf) - 1] == '\r') - buf[strlen(buf) - 1] = '\0'; /* nuke trailing newline */ - } - } - - success = cdi_cue_get_keyword(&command, &line); - - if (!strcmp(command, "TRACK")) { - if (can_add_track) - success = cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap); - else - success = 1; - - trk.start = 0; - trk.skip = 0; - cur_pregap = 0; - prestart = 0; - - trk.number = cdi_cue_get_number(&line); - trk.track_number = trk.number; - success = cdi_cue_get_keyword(&type, &line); - if (!success) - break; - - trk.form = 0; - trk.mode2 = 0; - - if (!strcmp(type, "AUDIO")) { - trk.sector_size = RAW_SECTOR_SIZE; - trk.attr = AUDIO_TRACK; - } else if (!strcmp(type, "MODE1/2048")) { - trk.sector_size = COOKED_SECTOR_SIZE; - trk.attr = DATA_TRACK; - } else if (!strcmp(type, "MODE1/2352")) { - trk.sector_size = RAW_SECTOR_SIZE; - trk.attr = DATA_TRACK; - } else if (!strcmp(type, "MODE1/2448")) { - trk.sector_size = 2448; - trk.attr = DATA_TRACK; - } else if (!strcmp(type, "MODE2/2048")) { - trk.form = 1; - trk.sector_size = COOKED_SECTOR_SIZE; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "MODE2/2324")) { - trk.form = 2; - trk.sector_size = 2324; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "MODE2/2328")) { - trk.form = 2; - trk.sector_size = 2328; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "MODE2/2336")) { - trk.sector_size = 2336; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "MODE2/2352")) { - trk.form = 1; /* Assume this is XA Mode 2 Form 1. */ - trk.sector_size = RAW_SECTOR_SIZE; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "MODE2/2448")) { - trk.form = 1; /* Assume this is XA Mode 2 Form 1. */ - trk.sector_size = 2448; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "CDG/2448")) { - trk.sector_size = 2448; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "CDI/2336")) { - trk.sector_size = 2336; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "CDI/2352")) { - trk.sector_size = RAW_SECTOR_SIZE; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else - success = 0; - - can_add_track = 1; - } else if (!strcmp(command, "INDEX")) { - index = cdi_cue_get_number(&line); - success = cdi_cue_get_frame(&frame, &line); - - switch(index) { - case 0: - prestart = frame; - break; - - case 1: - trk.start = frame; - break; - - default: - /* ignore other indices */ - break; - } - } else if (!strcmp(command, "FILE")) { - if (can_add_track) - success = cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap); - else - success = 1; - can_add_track = 0; - - memset(ansi, 0, MAX_FILENAME_LENGTH * sizeof(char)); - memset(filename, 0, MAX_FILENAME_LENGTH * sizeof(wchar_t)); - - success = cdi_cue_get_buffer(ansi, &line, 0); - if (!success) - break; - success = cdi_cue_get_keyword(&type, &line); - if (!success) - break; - - trk.file = NULL; - error = 1; - - if (!strcmp(type, "BINARY")) { - memset(temp, 0, MAX_FILENAME_LENGTH * sizeof(wchar_t)); - mbstowcs(temp, ansi, sizeof_w(temp)); - plat_append_filename(filename, pathname, temp); - trk.file = track_file_init(filename, &error); - } - if (error) { -#ifdef ENABLE_cdrom_image_backend_log - cdrom_image_backend_log("CUE: cannot open fille '%ls' in cue sheet!\n", - filename); -#endif - if (trk.file != NULL) { - trk.file->close(trk.file); - trk.file = NULL; - } - success = 0; - } - } else if (!strcmp(command, "PREGAP")) - success = cdi_cue_get_frame(&cur_pregap, &line); - else if (!strcmp(command, "CATALOG") || !strcmp(command, "CDTEXTFILE") || !strcmp(command, "FLAGS") || !strcmp(command, "ISRC") || - !strcmp(command, "PERFORMER") || !strcmp(command, "POSTGAP") || !strcmp(command, "REM") || - !strcmp(command, "SONGWRITER") || !strcmp(command, "TITLE") || !strcmp(command, "")) { - /* Ignored commands. */ - success = 1; - } else { -#ifdef ENABLE_cdrom_image_backend_log - cdrom_image_backend_log("CUE: unsupported command '%s' in cue sheet!\n", - command.c_str()); -#endif - success = 0; - } - - if (!success) - break; - } - - fclose(fp); - if (!success) - return 0; - - /* Add last track. */ - if (!cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap)) - return 0; - - /* Add lead out track. */ - trk.number++; - trk.track_number = 0xAA; - trk.attr = 0x16; /* Was 0x00 but I believe 0x16 is appropriate. */ - trk.start = 0; - trk.length = 0; - trk.file = NULL; - if (!cdi_add_track(cdi, &trk, &shift, 0, &total_pregap, 0)) - return 0; - - return 1; -} - - -int -cdi_has_data_track(cd_img_t *cdi) -{ - int i; - - if ((cdi == NULL) || (cdi->tracks == NULL)) - return 0; - - /* Data track has attribute 0x14. */ - for (i = 0; i < cdi->tracks_num; i++) { - if (cdi->tracks[i].attr == DATA_TRACK) - return 1; - } - - return 0; -} - - int cdi_has_audio_track(cd_img_t *cdi) {