From 16cbbd91031df43437ee393cfd18ebc6373409eb Mon Sep 17 00:00:00 2001 From: AJR Date: Thu, 11 May 2017 18:30:04 -0400 Subject: [PATCH] Improvements to romcmp - Identify plain ASCII text files as such - If a ROM has the same data in each half, print the hashes for that - Avoid buffer overruns - For calculating address masks, don't assume file size to be a power of 2 --- src/tools/romcmp.cpp | 95 ++++++++++++++++++++++++++++---------------- 1 file changed, 60 insertions(+), 35 deletions(-) diff --git a/src/tools/romcmp.cpp b/src/tools/romcmp.cpp index f45ff7f6eeb..8341353c029 100644 --- a/src/tools/romcmp.cpp +++ b/src/tools/romcmp.cpp @@ -11,6 +11,7 @@ #include "unzip.h" #include "osdcore.h" #include "osdcomm.h" +#include "hash.h" #include #include @@ -114,31 +115,45 @@ static fileinfo files[2][MAX_FILES]; static float matchscore[MAX_FILES][MAX_FILES][TOTAL_MODES][TOTAL_MODES]; -static void checkintegrity(const fileinfo *file,int side) +static bool is_ascii_char(int ch) { - int i; - int mask0,mask1; - int addrbit; + return (ch >= 0x20 && ch < 0x7f) || (ch == '\n') || (ch == '\r') || (ch == '\t'); +} +static void checkintegrity(const fileinfo *file, int side) +{ if (file->buf == nullptr) return; /* check for bad data lines */ - mask0 = 0x0000; - mask1 = 0xffff; + unsigned mask0 = 0x0000; + unsigned mask1 = 0xffff; - for (i = 0;i < file->size;i+=2) + bool is_ascii = true; + for (unsigned i = 0; i < file->size; i += 2) { - mask0 |= ((file->buf[i] << 8) | file->buf[i+1]); - mask1 &= ((file->buf[i] << 8) | file->buf[i+1]); + is_ascii = is_ascii && is_ascii_char(file->buf[i]); + mask0 |= file->buf[i] << 8; + mask1 &= file->buf[i] << 8; + if (i < file->size - 1) + { + is_ascii = is_ascii && is_ascii_char(file->buf[i+1]); + mask0 |= file->buf[i+1]; + mask1 &= file->buf[i+1]; + } if (mask0 == 0xffff && mask1 == 0x0000) break; } + if (is_ascii && mask0 == 0x7f7f && mask1 == 0) + { + printf("%-23s %-23s ASCII TEXT FILE\n", side ? "" : file->name, side ? file->name : ""); + return; + } + if (mask0 != 0xffff || mask1 != 0x0000) { int fixedmask; int bits; - fixedmask = (~mask0 | mask1) & 0xffff; if (((mask0 >> 8) & 0xff) == (mask0 & 0xff) && ((mask1 >> 8) & 0xff) == (mask1 & 0xff)) @@ -146,7 +161,7 @@ static void checkintegrity(const fileinfo *file,int side) else bits = 16; printf("%-23s %-23s FIXED BITS (",side ? "" : file->name,side ? file->name : ""); - for (i = 0;i < bits;i++) + for (int i = 0; i < bits; i++) { if (~mask0 & 0x8000) printf("0"); else if (mask1 & 0x8000) printf("1"); @@ -163,57 +178,68 @@ static void checkintegrity(const fileinfo *file,int side) return; } - - addrbit = 1; - mask0 = 0; + unsigned addrbit = 1; + unsigned addrmirror = 0; while (addrbit <= file->size/2) { - for (i = 0;i < file->size;i++) + unsigned i = 0; + for (i = 0; i < file->size; i++) { - if (file->buf[i] != file->buf[i ^ addrbit]) break; + if ((i ^ addrbit) < file->size && file->buf[i] != file->buf[i ^ addrbit]) break; } if (i == file->size) - mask0 |= addrbit; + addrmirror |= addrbit; addrbit <<= 1; } - if (mask0) + if (addrmirror != 0) { - if (mask0 == file->size/2) - printf("%-23s %-23s 1ST AND 2ND HALF IDENTICAL\n",side ? "" : file->name,side ? file->name : ""); + if (addrmirror == file->size/2) + { + printf("%-23s %-23s 1ST AND 2ND HALF IDENTICAL\n", side ? "" : file->name, side ? file->name : ""); + util::hash_collection hash; + hash.begin(); + hash.buffer(file->buf, file->size / 2); + hash.end(); + printf("%-23s %-23s %s\n", side ? "" : file->name, side ? file->name : "", hash.attribute_string().c_str()); + } else { printf("%-23s %-23s BADADDR",side ? "" : file->name,side ? file->name : ""); - for (i = 0;i < 24;i++) + for (int i = 0; i < 24; i++) { if (file->size <= (1<<(23-i))) printf(" "); - else if (mask0 & 0x800000) printf("-"); + else if (addrmirror & 0x800000) printf("-"); else printf("x"); - mask0 <<= 1; + addrmirror <<= 1; } printf("\n"); } return; } + unsigned sizemask = 1; + while (sizemask < file->size - 1) + sizemask = (sizemask << 1) | 1; + mask0 = 0x000000; - mask1 = file->size-1; - for (i = 0;i < file->size;i++) + mask1 = sizemask; + for (unsigned i = 0; i < file->size; i++) { if (file->buf[i] != 0xff) { mask0 |= i; mask1 &= i; - if (mask0 == file->size-1 && mask1 == 0x00) break; + if (mask0 == sizemask && mask1 == 0x00) break; } } - if (mask0 != file->size-1 || mask1 != 0x00) + if (mask0 != sizemask || mask1 != 0x00) { printf("%-23s %-23s ",side ? "" : file->name,side ? file->name : ""); - for (i = 0;i < 24;i++) + for (int i = 0; i < 24; i++) { if (file->size <= (1<<(23-i))) printf(" "); else if (~mask0 & 0x800000) printf("1"); @@ -229,21 +255,21 @@ static void checkintegrity(const fileinfo *file,int side) mask0 = 0x000000; - mask1 = file->size-1; - for (i = 0;i < file->size;i++) + mask1 = sizemask; + for (unsigned i = 0; i < file->size; i++) { if (file->buf[i] != 0x00) { mask0 |= i; mask1 &= i; - if (mask0 == file->size-1 && mask1 == 0x00) break; + if (mask0 == sizemask && mask1 == 0x00) break; } } - if (mask0 != file->size-1 || mask1 != 0x00) + if (mask0 != sizemask || mask1 != 0x00) { printf("%-23s %-23s ",side ? "" : file->name,side ? file->name : ""); - for (i = 0;i < 24;i++) + for (int i = 0; i < 24; i++) { if (file->size <= (1<<(23-i))) printf(" "); else if ((mask0 & 0x800000) == 0) printf("1"); @@ -257,9 +283,8 @@ static void checkintegrity(const fileinfo *file,int side) return; } - mask0 = 0xff; - for (i = 0;i < file->size/4 && mask0;i++) + for (unsigned i = 0; i < file->size/4 && mask0 != 0x00; i++) { if (file->buf[ 2*i ] != 0x00) mask0 &= ~0x01; if (file->buf[ 2*i ] != 0xff) mask0 &= ~0x02;