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
This commit is contained in:
AJR 2017-05-11 18:30:04 -04:00
parent 78ecf89a06
commit 16cbbd9103

View File

@ -11,6 +11,7 @@
#include "unzip.h" #include "unzip.h"
#include "osdcore.h" #include "osdcore.h"
#include "osdcomm.h" #include "osdcomm.h"
#include "hash.h"
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
@ -114,31 +115,45 @@ static fileinfo files[2][MAX_FILES];
static float matchscore[MAX_FILES][MAX_FILES][TOTAL_MODES][TOTAL_MODES]; static float matchscore[MAX_FILES][MAX_FILES][TOTAL_MODES][TOTAL_MODES];
static bool is_ascii_char(int ch)
{
return (ch >= 0x20 && ch < 0x7f) || (ch == '\n') || (ch == '\r') || (ch == '\t');
}
static void checkintegrity(const fileinfo *file, int side) static void checkintegrity(const fileinfo *file, int side)
{ {
int i;
int mask0,mask1;
int addrbit;
if (file->buf == nullptr) return; if (file->buf == nullptr) return;
/* check for bad data lines */ /* check for bad data lines */
mask0 = 0x0000; unsigned mask0 = 0x0000;
mask1 = 0xffff; 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]); is_ascii = is_ascii && is_ascii_char(file->buf[i]);
mask1 &= ((file->buf[i] << 8) | file->buf[i+1]); 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 (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) if (mask0 != 0xffff || mask1 != 0x0000)
{ {
int fixedmask; int fixedmask;
int bits; int bits;
fixedmask = (~mask0 | mask1) & 0xffff; fixedmask = (~mask0 | mask1) & 0xffff;
if (((mask0 >> 8) & 0xff) == (mask0 & 0xff) && ((mask1 >> 8) & 0xff) == (mask1 & 0xff)) 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; else bits = 16;
printf("%-23s %-23s FIXED BITS (",side ? "" : file->name,side ? file->name : ""); 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"); if (~mask0 & 0x8000) printf("0");
else if (mask1 & 0x8000) printf("1"); else if (mask1 & 0x8000) printf("1");
@ -163,57 +178,68 @@ static void checkintegrity(const fileinfo *file,int side)
return; return;
} }
unsigned addrbit = 1;
addrbit = 1; unsigned addrmirror = 0;
mask0 = 0;
while (addrbit <= file->size/2) while (addrbit <= file->size/2)
{ {
unsigned i = 0;
for (i = 0; i < file->size; i++) 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) if (i == file->size)
mask0 |= addrbit; addrmirror |= addrbit;
addrbit <<= 1; addrbit <<= 1;
} }
if (mask0) if (addrmirror != 0)
{
if (addrmirror == file->size/2)
{ {
if (mask0 == file->size/2)
printf("%-23s %-23s 1ST AND 2ND HALF IDENTICAL\n", side ? "" : file->name, side ? file->name : ""); 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 else
{ {
printf("%-23s %-23s BADADDR",side ? "" : file->name,side ? file->name : ""); 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(" "); if (file->size <= (1<<(23-i))) printf(" ");
else if (mask0 & 0x800000) printf("-"); else if (addrmirror & 0x800000) printf("-");
else printf("x"); else printf("x");
mask0 <<= 1; addrmirror <<= 1;
} }
printf("\n"); printf("\n");
} }
return; return;
} }
unsigned sizemask = 1;
while (sizemask < file->size - 1)
sizemask = (sizemask << 1) | 1;
mask0 = 0x000000; mask0 = 0x000000;
mask1 = file->size-1; mask1 = sizemask;
for (i = 0;i < file->size;i++) for (unsigned i = 0; i < file->size; i++)
{ {
if (file->buf[i] != 0xff) if (file->buf[i] != 0xff)
{ {
mask0 |= i; mask0 |= i;
mask1 &= 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 : ""); 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(" "); if (file->size <= (1<<(23-i))) printf(" ");
else if (~mask0 & 0x800000) printf("1"); else if (~mask0 & 0x800000) printf("1");
@ -229,21 +255,21 @@ static void checkintegrity(const fileinfo *file,int side)
mask0 = 0x000000; mask0 = 0x000000;
mask1 = file->size-1; mask1 = sizemask;
for (i = 0;i < file->size;i++) for (unsigned i = 0; i < file->size; i++)
{ {
if (file->buf[i] != 0x00) if (file->buf[i] != 0x00)
{ {
mask0 |= i; mask0 |= i;
mask1 &= 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 : ""); 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(" "); if (file->size <= (1<<(23-i))) printf(" ");
else if ((mask0 & 0x800000) == 0) printf("1"); else if ((mask0 & 0x800000) == 0) printf("1");
@ -257,9 +283,8 @@ static void checkintegrity(const fileinfo *file,int side)
return; return;
} }
mask0 = 0xff; 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 ] != 0x00) mask0 &= ~0x01;
if (file->buf[ 2*i ] != 0xff) mask0 &= ~0x02; if (file->buf[ 2*i ] != 0xff) mask0 &= ~0x02;