From a71c49be97900c139b8a4a92fb58021331344647 Mon Sep 17 00:00:00 2001 From: zakk4223 Date: Wed, 8 Jan 2020 02:16:47 -0500 Subject: [PATCH] MRA: lookup rom parts by CRC first if "crc" attribute exists MRA: supported ordered list "zip" attribute, (use '|' as delimiter) --- file_io.cpp | 98 +++++++++++++++++++++++++++++++++++++ file_io.h | 1 + support/arcade/romutils.cpp | 55 ++++++++++++++++----- 3 files changed, 142 insertions(+), 12 deletions(-) diff --git a/file_io.cpp b/file_io.cpp index 5e68049..872c04b 100644 --- a/file_io.cpp +++ b/file_io.cpp @@ -235,6 +235,104 @@ void FileClose(fileTYPE *file) file->filp = nullptr; } + +int zip_search_by_crc(mz_zip_archive *zipArchive, uint32_t crc32) +{ + + for (unsigned int file_index = 0; file_index < zipArchive->m_total_files; file_index++) + { + mz_zip_archive_file_stat s; + if (mz_zip_reader_file_stat(zipArchive, file_index, &s)) + { + if (s.m_crc32 == crc32) + { + return file_index; + } + } + } + + return -1; +} + + +int FileOpenZip(fileTYPE *file, const char *name, uint32_t crc32, int mode, char mute) +{ + make_fullpath((char*)name, mode); + FileClose(file); + file->mode = 0; + file->type = 0; + + char *p = strrchr(full_path, '/'); + strcpy(file->name, (mode == -1) ? full_path : p + 1); + + char *zip_path, *file_path; + if ((mode != -1) && FileIsZipped(full_path, &zip_path, &file_path)) + { + if (mode & O_RDWR || mode & O_WRONLY) + { + if(!mute) printf("FileOpenZip(mode) Zip:%s, writing to zipped files is not supported.\n", + full_path); + return 0; + } + + file->zip = new fileZipArchive{}; + if (!mz_zip_reader_init_file(&file->zip->archive, zip_path, 0)) + { + if(!mute) printf("FileOpenZip(mz_zip_reader_init_file) Zip:%s, error:%s\n", zip_path, + mz_zip_get_error_string(mz_zip_get_last_error(&file->zip->archive))); + return 0; + } + + if (crc32) + { + file->zip->index = zip_search_by_crc(&file->zip->archive, crc32); + } + + + + if (file->zip->index < 0 || !crc32) + { + file->zip->index = mz_zip_reader_locate_file(&file->zip->archive, file_path, NULL, 0); + } + + if (file->zip->index < 0) + { + if(!mute) printf("FileOpenZip(mz_zip_reader_locate_file) Zip:%s, file:%s, error: %s\n", + zip_path, file_path, + mz_zip_get_error_string(mz_zip_get_last_error(&file->zip->archive))); + FileClose(file); + return 0; + } + + mz_zip_archive_file_stat s; + if (!mz_zip_reader_file_stat(&file->zip->archive, file->zip->index, &s)) + { + if(!mute) printf("FileOpenZip(mz_zip_reader_file_stat) Zip:%s, file:%s, error:%s\n", + zip_path, file_path, + mz_zip_get_error_string(mz_zip_get_last_error(&file->zip->archive))); + FileClose(file); + return 0; + } + file->size = s.m_uncomp_size; + + file->zip->iter = mz_zip_reader_extract_iter_new(&file->zip->archive, file->zip->index, 0); + if (!file->zip->iter) + { + if(!mute) printf("FileOpenZip(mz_zip_reader_extract_iter_new) Zip:%s, file:%s, error:%s\n", + zip_path, file_path, + mz_zip_get_error_string(mz_zip_get_last_error(&file->zip->archive))); + FileClose(file); + return 0; + } + file->zip->offset = 0; + file->offset = 0; + file->mode = mode; + } else { + return 0; + } + return 1; +} + int FileOpenEx(fileTYPE *file, const char *name, int mode, char mute) { make_fullpath((char*)name, mode); diff --git a/file_io.h b/file_io.h index b03fb21..443a49e 100644 --- a/file_io.h +++ b/file_io.h @@ -59,6 +59,7 @@ int getStorage(int from_setting); void setStorage(int dev); int isUSBMounted(); +int FileOpenZip(fileTYPE *file, const char *name, uint32_t crc32, int mode, char mute = 0); int FileOpenEx(fileTYPE *file, const char *name, int mode, char mute = 0); int FileOpen(fileTYPE *file, const char *name, char mute = 0); void FileClose(fileTYPE *file); diff --git a/support/arcade/romutils.cpp b/support/arcade/romutils.cpp index d55cf15..dbd52a5 100644 --- a/support/arcade/romutils.cpp +++ b/support/arcade/romutils.cpp @@ -31,6 +31,7 @@ struct arc_struct { int patchaddr; int validrom0; int insidesw; + uint32_t crc; buffer_data *data; struct MD5Context context; }; @@ -156,12 +157,12 @@ static int file_data(const uint8_t *buf, uint16_t chunk, struct MD5Context *md5c return 1; } -static int file_file(const char *name, int start, int len, struct MD5Context *md5context) +static int file_file(const char *name, uint32_t crc32, int start, int len, struct MD5Context *md5context) { char mute = 0; fileTYPE f = {}; static uint8_t buf[4096]; - if (!FileOpen(&f, name, mute)) return 0; + if (!FileOpenZip(&f, name, crc32, mute)) return 0; if (start) FileSeek(&f, start, SEEK_SET); unsigned long bytes2send = f.size; if (len > 0 && len < (int)bytes2send) bytes2send = len; @@ -310,6 +311,7 @@ static int xml_send_rom(XMLEvent evt, const XMLNode* node, SXML_CHAR* text, cons arc_info->offset = 0; arc_info->length = -1; arc_info->repeat = 1; + arc_info->crc = 0; /* on the beginning of a rom tag, we need to reset the state*/ if (!strcasecmp(node->tag, "rom")) @@ -381,6 +383,10 @@ static int xml_send_rom(XMLEvent evt, const XMLNode* node, SXML_CHAR* text, cons { arc_info->repeat = atoi(node->attributes[i].value); } + if (!strcasecmp(node->attributes[i].name, "crc") && !strcasecmp(node->tag, "part")) + { + arc_info->crc = (uint32_t)strtoul(node->attributes[i].value, NULL, 16); + } if (!strcasecmp(node->attributes[i].name, "offset") && !strcasecmp(node->tag, "patch")) { arc_info->patchaddr = strtoul(node->attributes[i].value, NULL, 0); @@ -553,8 +559,10 @@ static int xml_send_rom(XMLEvent evt, const XMLNode* node, SXML_CHAR* text, cons if (arc_info->romindex == 0 && arc_info->validrom0 == 1) break; char fname[kBigTextSize * 2 + 16]; int start, length, repeat; + uint32_t crc32; repeat = arc_info->repeat; start = arc_info->offset; + crc32 = arc_info->crc; length = 0; if (arc_info->length > 0) length = arc_info->length; //printf("partname[%s]\n",arc_info->partname); @@ -567,21 +575,44 @@ static int xml_send_rom(XMLEvent evt, const XMLNode* node, SXML_CHAR* text, cons //user_io_file_tx_body_filepart(getFullPath(fname),0,0); if (strlen(arc_info->partname)) { - char *zipname = (strlen(arc_info->partzipname)) ? arc_info->partzipname : arc_info->zipname; - const char *root = get_arcade_root(0); - sprintf(fname, (zipname[0] == '/') ? "%s%s/%s" : "%s/mame/%s/%s", root, zipname, arc_info->partname); + char zipnames_list[kBigTextSize]; - printf("file: %s, start=%d, len=%d\n", fname, start, length); - for (int i = 0; i < repeat; i++) + if (strlen(arc_info->partzipname)) { - int result = file_file(fname, start, length, &arc_info->context); + strcpy(zipnames_list, arc_info->partzipname); + } else { + strcpy(zipnames_list, arc_info->zipname); + } + + char *zipname = NULL; + char *zipptr = zipnames_list; + const char *root = get_arcade_root(0); + int result = 0; + while ((zipname = strsep(&zipptr, "|")) != NULL) + { + sprintf(fname, (zipname[0] == '/') ? "%s%s/%s" : "%s/mame/%s/%s", root, zipname, arc_info->partname); - // we should check file not found error for the zip - if (result == 0) + printf("file: %s, start=%d, len=%d\n", fname, start, length); + for (int i = 0; i < repeat; i++) { - printf("%s does not exist\n", fname); - snprintf(arc_info->error_msg, kBigTextSize, "%s\nFile Not Found", fname + strlen(root)); + result = file_file(fname, crc32, start, length, &arc_info->context); + + // we should check file not found error for the zip + if (result == 0) + { + break; + } } + + if (result) + { + break; + } + } + if (result == 0) + { + printf("%s does not exist\n", arc_info->partname); + snprintf(arc_info->error_msg, kBigTextSize, "%s\nFile Not Found", arc_info->partname); } } else // we have binary data?