diff --git a/tasks/task_database.c b/tasks/task_database.c index 4eb70322a9..87652818e2 100644 --- a/tasks/task_database.c +++ b/tasks/task_database.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include "tasks_internal.h" #include "../database_info.h" @@ -69,13 +71,60 @@ typedef struct db_handle int find_first_data_track(const char* cue_path, int32_t* offset, char* track_path, size_t max_len); -int detect_system(const char* track_path, const char** system_name); +int detect_system(intfstream_t *fd, const char** system_name); -int detect_ps1_game(const char *track_path, char *game_id); +int detect_ps1_game(intfstream_t *fd, char *game_id); -int detect_psp_game(const char *track_path, char *game_id); +int detect_psp_game(intfstream_t *fd, char *game_id); -int detect_serial_ascii_game(const char *track_path, char *game_id); +int detect_serial_ascii_game(intfstream_t *fd, char *game_id); + +static intfstream_t* +open_file(const char *path) +{ + intfstream_info_t info; + intfstream_t *fd = NULL; + + info.type = INTFSTREAM_FILE; + + fd = intfstream_init(&info); + if (!fd) + { + return NULL; + } + + if (!intfstream_open(fd, path, RFILE_MODE_READ, -1)) + { + intfstream_close(fd); + return NULL; + } + + return fd; +} + +static intfstream_t* +open_chd_track(const char *path, int32_t track) +{ + intfstream_info_t info; + intfstream_t *fd = NULL; + + info.type = INTFSTREAM_CHD; + info.chd.track = track; + + fd = intfstream_init(&info); + if (!fd) + { + return NULL; + } + + if (!intfstream_open(fd, path, RFILE_MODE_READ, -1)) + { + intfstream_close(fd); + return NULL; + } + + return fd; +} static void database_info_set_type(database_info_handle_t *handle, enum database_type type) { @@ -137,16 +186,16 @@ static int task_database_iterate_start(database_info_handle_t *db, return 0; } -static int iso_get_serial(database_state_handle_t *db_state, - database_info_handle_t *db, const char *name, char* serial) +static int stream_get_serial(database_state_handle_t *db_state, + database_info_handle_t *db, intfstream_t *fd, char* serial) { const char* system_name = NULL; /* Check if the system was not auto-detected. */ - if (detect_system(name, &system_name) < 0) + if (detect_system(fd, &system_name) < 0) { /* Attempt to read an ASCII serial, like Wii. */ - if (detect_serial_ascii_game(name, serial)) + if (detect_serial_ascii_game(fd, serial)) { /* ASCII serial (Wii) was detected. */ RARCH_LOG("%s '%s'\n", msg_hash_to_str(MSG_FOUND_DISK_LABEL), serial); @@ -159,18 +208,38 @@ static int iso_get_serial(database_state_handle_t *db_state, if (string_is_equal_fast(system_name, "psp", 3)) { - if (detect_psp_game(name, serial) == 0) + if (detect_psp_game(fd, serial) == 0) return 0; RARCH_LOG("%s '%s'\n", msg_hash_to_str(MSG_FOUND_DISK_LABEL), serial); } else if (string_is_equal_fast(system_name, "ps1", 3)) { - if (detect_ps1_game(name, serial) == 0) + if (detect_ps1_game(fd, serial) == 0) return 0; RARCH_LOG("%s '%s'\n", msg_hash_to_str(MSG_FOUND_DISK_LABEL), serial); } + else + { + return 0; + } - return 0; + return 1; +} + +static int iso_get_serial(database_state_handle_t *db_state, + database_info_handle_t *db, const char *name, char* serial) +{ + intfstream_t *fd = open_file(name); + int rv; + + if (!fd) + { + return 0; + } + + rv = stream_get_serial(db_state, db, fd, serial); + intfstream_close(fd); + return rv; } static int cue_get_serial(database_state_handle_t *db_state, @@ -193,7 +262,7 @@ static int cue_get_serial(database_state_handle_t *db_state, msg_hash_to_str(MSG_COULD_NOT_FIND_VALID_DATA_TRACK), strerror(-rv)); free(track_path); - return rv; + return 0; } RARCH_LOG("%s\n", msg_hash_to_str(MSG_READING_FIRST_DATA_TRACK)); @@ -204,6 +273,23 @@ static int cue_get_serial(database_state_handle_t *db_state, return ret; } +static int chd_get_serial(database_state_handle_t *db_state, + database_info_handle_t *db, const char *name, char* serial) +{ + intfstream_t *fd = NULL; + int result; + + fd = open_chd_track(name, CHDSTREAM_TRACK_FIRST_DATA); + if (!fd) + { + return 0; + } + + result = stream_get_serial(db_state, db, fd, serial); + intfstream_close(fd); + return result; +} + static bool file_get_crc(database_state_handle_t *db_state, const char *name, uint32_t *crc) { @@ -219,6 +305,37 @@ static bool file_get_crc(database_state_handle_t *db_state, return 1; } +static bool chd_get_crc(database_state_handle_t *db_state, + const char *name, uint32_t *crc) +{ + intfstream_t *fd = NULL; + int result; + uint32_t acc = 0; + uint8_t buffer[4096]; + ssize_t size; + + fd = open_chd_track(name, CHDSTREAM_TRACK_FIRST_DATA); + if (!fd) + { + return 0; + } + + while ((size = intfstream_read(fd, buffer, sizeof(buffer))) > 0) + { + acc = encoding_crc32(acc, buffer, size); + } + if (size < 0) + { + return 0; + } + + RARCH_LOG("CHD '%s' crc: %x\n", name, acc); + + *crc = acc; + + return 1; +} + static int task_database_iterate_playlist( database_state_handle_t *db_state, database_info_handle_t *db, const char *name) @@ -235,14 +352,33 @@ static int task_database_iterate_playlist( #endif case FILE_TYPE_CUE: db_state->serial[0] = '\0'; - cue_get_serial(db_state, db, name, db_state->serial); - database_info_set_type(db, DATABASE_TYPE_SERIAL_LOOKUP); + if (cue_get_serial(db_state, db, name, db_state->serial)) + { + database_info_set_type(db, DATABASE_TYPE_SERIAL_LOOKUP); + } + else + { + database_info_set_type(db, DATABASE_TYPE_CRC_LOOKUP); + return file_get_crc(db_state, name, &db_state->crc); + } break; case FILE_TYPE_ISO: db_state->serial[0] = '\0'; iso_get_serial(db_state, db, name, db_state->serial); database_info_set_type(db, DATABASE_TYPE_SERIAL_LOOKUP); break; + case FILE_TYPE_CHD: + db_state->serial[0] = '\0'; + if (chd_get_serial(db_state, db, name, db_state->serial)) + { + database_info_set_type(db, DATABASE_TYPE_SERIAL_LOOKUP); + } + else + { + database_info_set_type(db, DATABASE_TYPE_CRC_LOOKUP); + return chd_get_crc(db_state, name, &db_state->crc); + } + break; case FILE_TYPE_LUTRO: database_info_set_type(db, DATABASE_TYPE_ITERATE_LUTRO); break; diff --git a/tasks/task_database_cue.c b/tasks/task_database_cue.c index 13139ae889..648ad47a95 100644 --- a/tasks/task_database_cue.c +++ b/tasks/task_database_cue.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #ifdef HAVE_CONFIG_H @@ -63,7 +64,7 @@ static struct magic_entry MAGIC_NUMBERS[] = { { 0, NULL, NULL} }; -static ssize_t get_token(RFILE *fd, char *token, size_t max_len) +static ssize_t get_token(intfstream_t *fd, char *token, size_t max_len) { char *c = token; ssize_t len = 0; @@ -71,7 +72,7 @@ static ssize_t get_token(RFILE *fd, char *token, size_t max_len) while (1) { - int rv = (int)filestream_read(fd, c, 1); + int rv = (int)intfstream_read(fd, c, 1); if (rv == 0) return 0; @@ -123,7 +124,7 @@ static ssize_t get_token(RFILE *fd, char *token, size_t max_len) } } -static int find_token(RFILE *fd, const char *token) +static int find_token(intfstream_t *fd, const char *token) { int tmp_len = (int)strlen(token); char *tmp_token = (char*)calloc(tmp_len+1, 1); @@ -146,30 +147,26 @@ static int find_token(RFILE *fd, const char *token) } -static int detect_ps1_game_sub(const char *track_path, +static int detect_ps1_game_sub(intfstream_t *fp, char *game_id, int sub_channel_mixed) { uint8_t* tmp; uint8_t* boot_file; int skip, frame_size, is_mode1, cd_sector; uint8_t buffer[2048 * 2]; - RFILE *fp = - filestream_open(track_path, RFILE_MODE_READ, -1); - if (!fp) - return 0; buffer[0] = '\0'; is_mode1 = 0; - filestream_seek(fp, 0, SEEK_END); + intfstream_seek(fp, 0, SEEK_END); if (!sub_channel_mixed) { - if (!(filestream_tell(fp) & 0x7FF)) + if (!(intfstream_tell(fp) & 0x7FF)) { unsigned int mode_test = 0; - filestream_seek(fp, 0, SEEK_SET); - filestream_read(fp, &mode_test, 4); + intfstream_seek(fp, 0, SEEK_SET); + intfstream_read(fp, &mode_test, 4); if (mode_test != MODETEST_VAL) is_mode1 = 1; } @@ -178,12 +175,12 @@ static int detect_ps1_game_sub(const char *track_path, skip = is_mode1? 0: 24; frame_size = sub_channel_mixed? 2448: is_mode1? 2048: 2352; - filestream_seek(fp, 156 + skip + 16 * frame_size, SEEK_SET); - filestream_read(fp, buffer, 6); + intfstream_seek(fp, 156 + skip + 16 * frame_size, SEEK_SET); + intfstream_read(fp, buffer, 6); cd_sector = buffer[2] | (buffer[3] << 8) | (buffer[4] << 16); - filestream_seek(fp, skip + cd_sector * frame_size, SEEK_SET); - filestream_read(fp, buffer, 2048 * 2); + intfstream_seek(fp, skip + cd_sector * frame_size, SEEK_SET); + intfstream_read(fp, buffer, 2048 * 2); tmp = buffer; while (tmp < (buffer + 2048 * 2)) @@ -201,8 +198,8 @@ static int detect_ps1_game_sub(const char *track_path, goto error; cd_sector = tmp[2] | (tmp[3] << 8) | (tmp[4] << 16); - filestream_seek(fp, skip + cd_sector * frame_size, SEEK_SET); - filestream_read(fp, buffer, 256); + intfstream_seek(fp, skip + cd_sector * frame_size, SEEK_SET); + intfstream_read(fp, buffer, 256); buffer[256] = '\0'; tmp = buffer; @@ -240,41 +237,30 @@ static int detect_ps1_game_sub(const char *track_path, *game_id = 0; - filestream_close(fp); return 1; error: - filestream_close(fp); return 0; } -int detect_ps1_game(const char *track_path, char *game_id) +int detect_ps1_game(intfstream_t *fd, char *game_id) { - if (detect_ps1_game_sub(track_path, game_id, 0)) + if (detect_ps1_game_sub(fd, game_id, 0)) return 1; - return detect_ps1_game_sub(track_path, game_id, 1); + return detect_ps1_game_sub(fd, game_id, 1); } -int detect_psp_game(const char *track_path, char *game_id) +int detect_psp_game(intfstream_t *fd, char *game_id) { unsigned pos; bool rv = false; - RFILE *fd = filestream_open(track_path, RFILE_MODE_READ, -1); - - if (!fd) - { - RARCH_LOG("%s: %s\n", - msg_hash_to_str(MSG_COULD_NOT_OPEN_DATA_TRACK), - strerror(errno)); - return -errno; - } for (pos = 0; pos < 100000; pos++) { - filestream_seek(fd, pos, SEEK_SET); + intfstream_seek(fd, pos, SEEK_SET); - if (filestream_read(fd, game_id, 5) > 0) + if (intfstream_read(fd, game_id, 5) > 0) { game_id[5] = '\0'; @@ -306,8 +292,8 @@ int detect_psp_game(const char *track_path, char *game_id) || (string_is_equal(game_id, "NPJZ-")) ) { - filestream_seek(fd, pos, SEEK_SET); - if (filestream_read(fd, game_id, 10) > 0) + intfstream_seek(fd, pos, SEEK_SET); + if (intfstream_read(fd, game_id, 10) > 0) { #if 0 game_id[4] = '-'; @@ -324,34 +310,22 @@ int detect_psp_game(const char *track_path, char *game_id) break; } - filestream_close(fd); return rv; } /** * Check for an ASCII serial in the first few bits of the ISO (Wii). */ -int detect_serial_ascii_game(const char *track_path, char *game_id) +int detect_serial_ascii_game(intfstream_t *fd, char *game_id) { unsigned pos; int numberOfAscii = 0; bool rv = false; - RFILE *fd = filestream_open(track_path, RFILE_MODE_READ, -1); - - /* Attempt to load the file. */ - if (!fd) - { - RARCH_LOG("%s: %s\n", - msg_hash_to_str(MSG_COULD_NOT_OPEN_DATA_TRACK), - strerror(errno)); - return -errno; - } for (pos = 0; pos < 10000; pos++) { - filestream_seek(fd, pos, SEEK_SET); - /* Current logic only requires 15 characters (max of 4096 per sizeof game_id). */ - if (filestream_read(fd, game_id, 15) > 0) + intfstream_seek(fd, pos, SEEK_SET); + if (intfstream_read(fd, game_id, 15) > 0) { unsigned i; game_id[15] = '\0'; @@ -378,34 +352,24 @@ int detect_serial_ascii_game(const char *track_path, char *game_id) } } - filestream_close(fd); return rv; } -int detect_system(const char *track_path, const char **system_name) +int detect_system(intfstream_t *fd, const char **system_name) { int rv; char magic[MAGIC_LEN]; int i; - RFILE *fd = filestream_open(track_path, RFILE_MODE_READ, -1); - - if (!fd) - { - RARCH_LOG("Could not open data track of file '%s': %s\n", - track_path, strerror(errno)); - rv = -errno; - goto clean; - } RARCH_LOG("%s\n", msg_hash_to_str(MSG_COMPARING_WITH_KNOWN_MAGIC_NUMBERS)); for (i = 0; MAGIC_NUMBERS[i].system_name != NULL; i++) { - filestream_seek(fd, MAGIC_NUMBERS[i].offset, SEEK_SET); + intfstream_seek(fd, MAGIC_NUMBERS[i].offset, SEEK_SET); - if (filestream_read(fd, magic, MAGIC_LEN) < MAGIC_LEN) + if (intfstream_read(fd, magic, MAGIC_LEN) < MAGIC_LEN) { - RARCH_LOG("Could not read data from file '%s' at offset %d: %s\n", - track_path, MAGIC_NUMBERS[i].offset, strerror(errno)); + RARCH_LOG("Could not read data at offset %d: %s\n", + MAGIC_NUMBERS[i].offset, strerror(errno)); rv = -errno; goto clean; } @@ -418,8 +382,8 @@ int detect_system(const char *track_path, const char **system_name) } } - filestream_seek(fd, 0x8008, SEEK_SET); - if (filestream_read(fd, magic, 8) > 0) + intfstream_seek(fd, 0x8008, SEEK_SET); + if (intfstream_read(fd, magic, 8) > 0) { magic[8] = '\0'; if (!string_is_empty(magic) && @@ -435,7 +399,6 @@ int detect_system(const char *track_path, const char **system_name) rv = -EINVAL; clean: - filestream_close(fd); return rv; } @@ -443,11 +406,19 @@ int find_first_data_track(const char *cue_path, int32_t *offset, char *track_path, size_t max_len) { int rv; - char * tmp_token = (char*)(MAX_TOKEN_LEN * sizeof(char)); - RFILE *fd = - filestream_open(cue_path, RFILE_MODE_READ, -1); + char * tmp_token = malloc(MAX_TOKEN_LEN * sizeof(char)); + intfstream_info_t info; + intfstream_t *fd = NULL; + info.type = INTFSTREAM_FILE; + + fd = intfstream_init(&info); if (!fd) + { + return -errno; + } + + if (!intfstream_open(fd, cue_path, RFILE_MODE_READ, -1)) { RARCH_LOG("Could not open CUE file '%s': %s\n", cue_path, strerror(errno)); @@ -494,10 +465,6 @@ int find_first_data_track(const char *cue_path, *offset = ((m * 60) * (s * 75) * f) * 25; - RARCH_LOG("%s '%s+%d'\n", - msg_hash_to_str(MSG_FOUND_FIRST_DATA_TRACK_ON_FILE), - track_path, *offset); - rv = 0; goto clean; } @@ -507,12 +474,12 @@ int find_first_data_track(const char *cue_path, clean: free(tmp_token); - filestream_close(fd); + intfstream_close(fd); return rv; error: free(tmp_token); if (fd) - filestream_close(fd); + intfstream_close(fd); return -errno; }