diff --git a/tasks/task_database.c b/tasks/task_database.c index 9b49c11cec..6c831dbbff 100644 --- a/tasks/task_database.c +++ b/tasks/task_database.c @@ -68,9 +68,11 @@ typedef struct db_handle bool scan_started; } db_handle_t; -int find_track(const char *cue_path, bool first, size_t *offset, size_t *size, +int cue_find_track(const char *cue_path, bool first, size_t *offset, size_t *size, char *track_path, size_t max_len); +int gdi_find_track(const char *gdi_path, bool first, char *track_path, size_t max_len); + int detect_system(intfstream_t *fd, const char** system_name); int detect_ps1_game(intfstream_t *fd, char *game_id); @@ -304,7 +306,7 @@ static int cue_get_serial(const char *name, char* serial) track_path[0] = '\0'; - rv = find_track(name, true, &offset, &size, track_path, PATH_MAX_LENGTH); + rv = cue_find_track(name, true, &offset, &size, track_path, PATH_MAX_LENGTH); if (rv < 0) { @@ -323,6 +325,34 @@ static int cue_get_serial(const char *name, char* serial) return ret; } +static int gdi_get_serial(const char *name, char* serial) +{ + char *track_path = (char*)malloc(PATH_MAX_LENGTH + * sizeof(char)); + int ret = 0; + int rv = 0; + + track_path[0] = '\0'; + + rv = gdi_find_track(name, true, track_path, PATH_MAX_LENGTH); + + if (rv < 0) + { + RARCH_LOG("%s: %s\n", + msg_hash_to_str(MSG_COULD_NOT_FIND_VALID_DATA_TRACK), + strerror(-rv)); + free(track_path); + return 0; + } + + RARCH_LOG("%s\n", msg_hash_to_str(MSG_READING_FIRST_DATA_TRACK)); + + ret = file_get_serial(track_path, 0, SIZE_MAX, serial); + free(track_path); + + return ret; +} + static int chd_get_serial(const char *name, char* serial) { intfstream_t *fd = NULL; @@ -412,7 +442,7 @@ static int cue_get_crc(const char *name, uint32_t *crc) track_path[0] = '\0'; - rv = find_track(name, false, &offset, &size, track_path, PATH_MAX_LENGTH); + rv = cue_find_track(name, false, &offset, &size, track_path, PATH_MAX_LENGTH); if (rv < 0) { RARCH_LOG("%s: %s\n", msg_hash_to_str(MSG_COULD_NOT_FIND_VALID_DATA_TRACK), @@ -433,6 +463,35 @@ static int cue_get_crc(const char *name, uint32_t *crc) return rv; } +static int gdi_get_crc(const char *name, uint32_t *crc) +{ + char *track_path = (char *)malloc(PATH_MAX_LENGTH); + int ret = 0; + int rv = 0; + + track_path[0] = '\0'; + + rv = gdi_find_track(name, false, track_path, PATH_MAX_LENGTH); + + if (rv < 0) { + RARCH_LOG("%s: %s\n", msg_hash_to_str(MSG_COULD_NOT_FIND_VALID_DATA_TRACK), + strerror(-rv)); + free(track_path); + return 0; + } + + RARCH_LOG("GDI '%s' primary track: %s\n", name, track_path); + + RARCH_LOG("%s\n", msg_hash_to_str(MSG_READING_FIRST_DATA_TRACK)); + + rv = file_get_crc(track_path, 0, SIZE_MAX, crc); + if (rv == 1) { + RARCH_LOG("GDI '%s' crc: %x\n", name, *crc); + } + free(track_path); + return rv; +} + static bool chd_get_crc(const char *name, uint32_t *crc) { intfstream_t *fd = NULL; @@ -481,6 +540,18 @@ static int task_database_iterate_playlist( return cue_get_crc(name, &db_state->crc); } break; + case FILE_TYPE_GDI: + db_state->serial[0] = '\0'; + if (gdi_get_serial(name, db_state->serial)) + { + database_info_set_type(db, DATABASE_TYPE_SERIAL_LOOKUP); + } + else + { + database_info_set_type(db, DATABASE_TYPE_CRC_LOOKUP); + return gdi_get_crc(name, &db_state->crc); + } + break; case FILE_TYPE_ISO: db_state->serial[0] = '\0'; file_get_serial(name, 0, SIZE_MAX, db_state->serial); @@ -488,7 +559,9 @@ static int task_database_iterate_playlist( break; case FILE_TYPE_CHD: db_state->serial[0] = '\0'; - if (chd_get_serial(name, db_state->serial)) + /* There are no serial databases, so don't bother with + serials at the moment */ + if (0 && chd_get_serial(name, db_state->serial)) { database_info_set_type(db, DATABASE_TYPE_SERIAL_LOOKUP); } diff --git a/tasks/task_database_cue.c b/tasks/task_database_cue.c index fed2ff865e..3481a3c12d 100644 --- a/tasks/task_database_cue.c +++ b/tasks/task_database_cue.c @@ -409,7 +409,7 @@ static bool update_cand(ssize_t *cand_index, ssize_t *last_index, return false; } -int find_track(const char *cue_path, bool first, +int cue_find_track(const char *cue_path, bool first, size_t *offset, size_t *size, char *track_path, size_t max_len) { int rv; @@ -536,3 +536,122 @@ error: intfstream_close(fd); return -errno; } + +int gdi_find_track(const char *gdi_path, bool first, char *track_path, size_t max_len) +{ + int rv; + char *tmp_token = malloc(MAX_TOKEN_LEN); + char *last_file = malloc(PATH_MAX_LENGTH + 1); + intfstream_info_t info; + intfstream_t *fd = NULL; + int32_t track = 0; + size_t largest = 0; + int size = -1; + int mode = -1; + ssize_t file_size = -1; + char *gdi_dir = (char*)malloc(PATH_MAX_LENGTH); + gdi_dir[0] = '\0'; + + fill_pathname_basedir(gdi_dir, gdi_path, PATH_MAX_LENGTH); + + info.type = INTFSTREAM_FILE; + + fd = intfstream_init(&info); + if (!fd) + { + goto error; + } + + if (!intfstream_open(fd, gdi_path, RFILE_MODE_READ, -1)) + { + RARCH_LOG("Could not open GDI file '%s': %s\n", gdi_path, + strerror(errno)); + goto error; + } + + RARCH_LOG("Parsing GDI file '%s'...\n", gdi_path); + + tmp_token[0] = '\0'; + + rv = -EINVAL; + + /* Skip track count */ + get_token(fd, tmp_token, MAX_TOKEN_LEN); + + /* Track number */ + while (get_token(fd, tmp_token, MAX_TOKEN_LEN) > 0) + { + /* Offset */ + if (get_token(fd, tmp_token, MAX_TOKEN_LEN) <= 0) + { + errno = EINVAL; + goto error; + } + + /* Mode */ + if (get_token(fd, tmp_token, MAX_TOKEN_LEN) <= 0) + { + errno = EINVAL; + goto error; + } + mode = atoi(tmp_token); + + /* Sector size */ + if (get_token(fd, tmp_token, MAX_TOKEN_LEN) <= 0) + { + errno = EINVAL; + goto error; + } + size = atoi(tmp_token); + + /* File name */ + if (get_token(fd, tmp_token, MAX_TOKEN_LEN) <= 0) + { + errno = EINVAL; + goto error; + } + + /* Check for data track */ + if (!(mode == 0 && size == 2352)) + { + fill_pathname_join(last_file, gdi_dir, tmp_token, PATH_MAX_LENGTH); + file_size = get_file_size(last_file); + if (file_size < 0) + { + goto error; + } + if (file_size > largest) + { + strlcpy(track_path, last_file, max_len); + rv = 0; + largest = file_size; + if (first) + { + goto clean; + } + } + } + + /* Disc offset (not used?) */ + if (get_token(fd, tmp_token, MAX_TOKEN_LEN) <= 0) + { + errno = EINVAL; + goto error; + } + } + +clean: + free(gdi_dir); + free(tmp_token); + free(last_file); + intfstream_close(fd); + return rv; + +error: + free(gdi_dir); + free(tmp_token); + free(last_file); + if (fd) + intfstream_close(fd); + return -errno; +}