Remove redundant hashing code, use hashing.h instead.

Remove overabstraction in hash.h; it's ok to hard code the
two types of hashes we have. Even adding another one would
not be very difficult. ;)
This commit is contained in:
Aaron Giles 2012-02-16 21:53:30 +00:00
parent a825e9730d
commit e055a551c1
10 changed files with 246 additions and 577 deletions

View File

@ -446,7 +446,7 @@ audit_record *media_auditor::audit_one_disk(const rom_entry *rom)
// if there's a SHA1 hash, add them to the output hash // if there's a SHA1 hash, add them to the output hash
if (source.sha1() != sha1_t::null) if (source.sha1() != sha1_t::null)
hashes.add_from_buffer(hash_collection::HASH_SHA1, source.sha1().m_raw, sizeof(source.sha1().m_raw)); hashes.add_sha1(source.sha1());
// update the actual values // update the actual values
record.set_actual(hashes); record.set_actual(hashes);

View File

@ -1080,6 +1080,7 @@ void cli_frontend::listsoftware(const char *gamename)
drivlist.reset(); drivlist.reset();
list_count = 0; list_count = 0;
astring tempstr;
while (drivlist.next()) while (drivlist.next())
{ {
software_list_device_iterator iter(drivlist.config().root_device()); software_list_device_iterator iter(drivlist.config().root_device());
@ -1158,19 +1159,9 @@ void cli_frontend::listsoftware(const char *gamename)
/* dump checksum information only if there is a known dump */ /* dump checksum information only if there is a known dump */
hash_collection hashes(ROM_GETHASHDATA(rom)); hash_collection hashes(ROM_GETHASHDATA(rom));
if (!hashes.flag(hash_collection::FLAG_NO_DUMP)) if ( !hashes.flag(hash_collection::FLAG_NO_DUMP) )
{ fprintf( out, " %s", hashes.attribute_string(tempstr) );
astring tempstr; else
for (hash_base *hash = hashes.first(); hash != NULL; hash = hash->next())
fprintf(out, " %s=\"%s\"", hash->name(), hash->string(tempstr));
}
if (!is_disk)
fprintf( out, " offset=\"0x%x\"", ROM_GETOFFSET(rom) );
if ( hashes.flag(hash_collection::FLAG_BAD_DUMP) )
fprintf( out, " status=\"baddump\"" );
if ( hashes.flag(hash_collection::FLAG_NO_DUMP) )
fprintf( out, " status=\"nodump\"" ); fprintf( out, " status=\"nodump\"" );
if (is_disk) if (is_disk)
@ -1517,7 +1508,7 @@ void media_identifier::identify_file(const char *name)
// otherwise, get the hash collection for this CHD // otherwise, get the hash collection for this CHD
hash_collection hashes; hash_collection hashes;
if (chd.sha1() != sha1_t::null) if (chd.sha1() != sha1_t::null)
hashes.add_from_buffer(hash_collection::HASH_SHA1, chd.sha1().m_raw, sizeof(chd.sha1().m_raw)); hashes.add_sha1(chd.sha1());
// determine whether this file exists // determine whether this file exists
int found = find_by_hash(hashes, chd.logical_bytes()); int found = find_by_hash(hashes, chd.logical_bytes());

View File

@ -497,7 +497,8 @@ void device_image_interface::image_checkhash()
device_image_partialhash_func partialhash; device_image_partialhash_func partialhash;
/* only calculate CRC if it hasn't been calculated, and the open_mode is read only */ /* only calculate CRC if it hasn't been calculated, and the open_mode is read only */
if (m_hash.first() == NULL && m_readonly && !m_created) UINT32 crcval;
if (!m_hash.crc(crcval) && m_readonly && !m_created)
{ {
/* do not cause a linear read of 600 megs please */ /* do not cause a linear read of 600 megs please */
/* TODO: use SHA1 in the CHD header as the hash */ /* TODO: use SHA1 in the CHD header as the hash */

View File

@ -250,10 +250,14 @@ emu_file::operator core_file &()
hash_collection &emu_file::hashes(const char *types) hash_collection &emu_file::hashes(const char *types)
{ {
// determine the hashes we already have
astring already_have;
m_hashes.hash_types(already_have);
// determine which hashes we need // determine which hashes we need
astring needed; astring needed;
for (const char *scan = types; *scan != 0; scan++) for (const char *scan = types; *scan != 0; scan++)
if (m_hashes.hash(*scan) == NULL) if (already_have.chr(0, *scan) == -1)
needed.cat(*scan); needed.cat(*scan);
// if we need nothing, skip it // if we need nothing, skip it

View File

@ -40,61 +40,10 @@
***************************************************************************/ ***************************************************************************/
#include "emu.h" #include "emu.h"
#include "zlib.h" #include "hashing.h"
#include "sha1.h"
#include <ctype.h> #include <ctype.h>
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> hash_crc
// CRC-32 hash implementation
class hash_crc : public hash_base
{
public:
// construction/destruction
hash_crc();
// operators
operator UINT32() const { return (m_buffer[0] << 24) | (m_buffer[1] << 16) | (m_buffer[2] << 8) | m_buffer[3]; }
// creation
virtual void begin();
virtual void buffer(const UINT8 *data, UINT32 length);
virtual void end();
private:
// internal state
UINT8 m_buffer[4];
};
// ======================> hash_sha1
// SHA1 hash implementation
class hash_sha1 : public hash_base
{
public:
// construction/destruction
hash_sha1();
// creation
virtual void begin();
virtual void buffer(const UINT8 *data, UINT32 length);
virtual void end();
private:
// internal state
UINT8 m_buffer[20];
struct sha1_ctx m_context;
};
//************************************************************************** //**************************************************************************
// GLOBAL VARIABLES // GLOBAL VARIABLES
//************************************************************************** //**************************************************************************
@ -105,220 +54,6 @@ const char *hash_collection::HASH_TYPES_ALL = "RS";
//**************************************************************************
// HASH BASE
//**************************************************************************
//-------------------------------------------------
// hash_base - constructor
//-------------------------------------------------
hash_base::hash_base(char id, const char *name, UINT8 length, UINT8 *bufptr)
: m_next(NULL),
m_name(name),
m_in_progress(false),
m_parse_error(false),
m_id(id),
m_length(length),
m_bufptr(bufptr)
{
memset(m_bufptr, 0, length);
}
//-------------------------------------------------
// fromhex - convert a character to a hex value
//-------------------------------------------------
int hash_base::fromhex(char c)
{
if (c >= '0' && c <= '9')
return c - '0';
else if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
else if (c >= 'a' && c <= 'f')
return (c - 'a' + 10);
else
return -1;
}
//-------------------------------------------------
// from_buffer - copy a raw buffer into the
// current hash
//-------------------------------------------------
bool hash_base::from_buffer(const UINT8 *buffer, int buflen)
{
// fail if we're too small
if (buflen < m_length)
return false;
memcpy(m_bufptr, buffer, m_length);
return true;
}
//-------------------------------------------------
// string - output a string for the current hash
//-------------------------------------------------
const char *hash_base::string(astring &buffer)
{
buffer.reset();
for (int index = 0; index < m_length; index++)
buffer.catprintf("%02x", m_bufptr[index]);
return buffer;
}
//-------------------------------------------------
// from_string - parse a string into the current
// hash
//-------------------------------------------------
bool hash_base::from_string(const char *&string, int length)
{
// reset the error and our buffer
m_parse_error = false;
memset(m_bufptr, 0, m_length);
// special case for idiom HASH(1) to map to a dummy (0) hash
if (string[0] == '1' && fromhex(string[1]) == -1)
{
string++;
return true;
}
// fail if we're too short
if (length < 2 * m_length)
return false;
// loop over bytes
for (int index = 0; index < m_length; index++)
{
// parse the upper digit
int upper = fromhex(string[0]);
if (upper == -1)
{
m_parse_error = true;
return false;
}
// parse the lower digit
int lower = fromhex(string[1]);
if (lower == -1)
{
m_parse_error = true;
return false;
}
// set the byte and advance
m_bufptr[index] = (upper << 4) | lower;
string += 2;
}
return true;
}
//**************************************************************************
// HASH CRC
//**************************************************************************
//-------------------------------------------------
// hash_crc - constructor
//-------------------------------------------------
hash_crc::hash_crc()
: hash_base(hash_collection::HASH_CRC, "crc", sizeof(m_buffer), m_buffer)
{
}
//-------------------------------------------------
// begin - initialize state for hash computation
//-------------------------------------------------
void hash_crc::begin()
{
m_in_progress = true;
memset(m_buffer, 0, sizeof(m_buffer));
}
//-------------------------------------------------
// buffer - hash a buffer's worth of data
//-------------------------------------------------
void hash_crc::buffer(const UINT8 *data, UINT32 length)
{
UINT32 crc = crc32(*this, data, length);
m_buffer[0] = crc >> 24;
m_buffer[1] = crc >> 16;
m_buffer[2] = crc >> 8;
m_buffer[3] = crc >> 0;
}
//-------------------------------------------------
// end - finish hash computation
//-------------------------------------------------
void hash_crc::end()
{
m_in_progress = false;
}
//**************************************************************************
// HASH SHA1
//**************************************************************************
//-------------------------------------------------
// hash_sha1 - constructor
//-------------------------------------------------
hash_sha1::hash_sha1()
: hash_base(hash_collection::HASH_SHA1, "sha1", sizeof(m_buffer), m_buffer)
{
}
//-------------------------------------------------
// begin - initialize state for hash computation
//-------------------------------------------------
void hash_sha1::begin()
{
m_in_progress = true;
sha1_init(&m_context);
}
//-------------------------------------------------
// buffer - hash a buffer's worth of data
//-------------------------------------------------
void hash_sha1::buffer(const UINT8 *data, UINT32 length)
{
sha1_update(&m_context, length, data);
}
//-------------------------------------------------
// end - finish hash computation
//-------------------------------------------------
void hash_sha1::end()
{
sha1_final(&m_context);
sha1_digest(&m_context, sizeof(m_buffer), m_buffer);
m_in_progress = false;
}
//************************************************************************** //**************************************************************************
// HASH COLLECTION // HASH COLLECTION
//************************************************************************** //**************************************************************************
@ -328,17 +63,26 @@ void hash_sha1::end()
//------------------------------------------------- //-------------------------------------------------
hash_collection::hash_collection() hash_collection::hash_collection()
: m_has_crc32(false),
m_has_sha1(false),
m_creator(NULL)
{ {
} }
hash_collection::hash_collection(const char *string) hash_collection::hash_collection(const char *string)
: m_has_crc32(false),
m_has_sha1(false),
m_creator(NULL)
{ {
from_internal_string(string); from_internal_string(string);
} }
hash_collection::hash_collection(const hash_collection &src) hash_collection::hash_collection(const hash_collection &src)
: m_has_crc32(false),
m_has_sha1(false),
m_creator(NULL)
{ {
copyfrom(src); copyfrom(src);
} }
@ -350,6 +94,7 @@ hash_collection::hash_collection(const hash_collection &src)
hash_collection::~hash_collection() hash_collection::~hash_collection()
{ {
delete m_creator;
} }
@ -372,17 +117,21 @@ hash_collection &hash_collection::operator=(const hash_collection &src)
bool hash_collection::operator==(const hash_collection &rhs) const bool hash_collection::operator==(const hash_collection &rhs) const
{ {
// look for a mismatch in any hash; do not fail if one is missing // match CRCs
int matches = 0; int matches = 0;
for (hash_base *hash = m_hashlist.first(); hash != NULL; hash = hash->next()) if (m_has_crc32 && rhs.m_has_crc32)
{ {
hash_base *rhs_hash = rhs.hash(hash->id()); if (m_crc32 != rhs.m_crc32)
if (rhs_hash != NULL)
{
if (*hash != *rhs_hash)
return false; return false;
matches++; matches++;
} }
// match SHA1s
if (m_has_sha1 && rhs.m_has_sha1)
{
if (m_sha1 != rhs.m_sha1)
return false;
matches++;
} }
// if all shared hashes match, return true // if all shared hashes match, return true
@ -390,20 +139,6 @@ bool hash_collection::operator==(const hash_collection &rhs) const
} }
//-------------------------------------------------
// hash - return a hash of the given type
//-------------------------------------------------
hash_base *hash_collection::hash(char type) const
{
// look for a mismatch in any hash; do not fail if one is missing
for (hash_base *hash = m_hashlist.first(); hash != NULL; hash = hash->next())
if (hash->id() == type)
return hash;
return NULL;
}
//------------------------------------------------- //-------------------------------------------------
// hash_types - return a list of hash types as // hash_types - return a list of hash types as
// a string // a string
@ -412,26 +147,14 @@ hash_base *hash_collection::hash(char type) const
const char *hash_collection::hash_types(astring &buffer) const const char *hash_collection::hash_types(astring &buffer) const
{ {
buffer.reset(); buffer.reset();
for (hash_base *hash = m_hashlist.first(); hash != NULL; hash = hash->next()) if (m_has_crc32)
buffer.cat(hash->id()); buffer.cat(HASH_CRC);
if (m_has_sha1)
buffer.cat(HASH_SHA1);
return buffer; return buffer;
} }
//-------------------------------------------------
// reset - reset the hash collection to an empty
// set of hashes and flags
//-------------------------------------------------
bool hash_collection::parse_errors() const
{
for (hash_base *hash = m_hashlist.first(); hash != NULL; hash = hash->next())
if (hash->parse_error())
return true;
return false;
}
//------------------------------------------------- //-------------------------------------------------
// reset - reset the hash collection to an empty // reset - reset the hash collection to an empty
// set of hashes and flags // set of hashes and flags
@ -439,37 +162,10 @@ bool hash_collection::parse_errors() const
void hash_collection::reset() void hash_collection::reset()
{ {
m_hashlist.reset();
m_flags.reset(); m_flags.reset();
} m_has_crc32 = m_has_sha1 = false;
delete m_creator;
m_creator = NULL;
//-------------------------------------------------
// add_from_buffer - add a new hash, importing
// from a buffer
//-------------------------------------------------
hash_base *hash_collection::add_from_buffer(char type, const UINT8 *buffer, int bufflen)
{
// nuke any existing hash with the same ID
hash_base *existing = hash(type);
if (existing != NULL)
m_hashlist.remove(*existing);
// first allocate by ID
hash_base *newhash = alloc_by_id(type);
if (newhash == NULL)
return NULL;
// then import
if (!newhash->from_buffer(buffer, bufflen))
{
global_free(newhash);
return NULL;
}
// and append to our list
return &m_hashlist.append(*newhash);
} }
@ -478,27 +174,17 @@ hash_base *hash_collection::add_from_buffer(char type, const UINT8 *buffer, int
// from a string // from a string
//------------------------------------------------- //-------------------------------------------------
hash_base *hash_collection::add_from_string(char type, const char *buffer, int length) bool hash_collection::add_from_string(char type, const char *buffer, int length)
{ {
// nuke any existing hash with the same ID // handle CRCs
hash_base *existing = hash(type); if (type == HASH_CRC)
if (existing != NULL) return m_has_crc32 = m_crc32.from_string(buffer, length);
m_hashlist.remove(*existing);
// first allocate by ID // handle SHA1s
hash_base *newhash = alloc_by_id(type); else if (type == HASH_SHA1)
if (newhash == NULL) return m_has_sha1 = m_sha1.from_string(buffer, length);
return NULL;
// then import return false;
if (!newhash->from_string(buffer, length))
{
global_free(newhash);
return NULL;
}
// and append to our list
return &m_hashlist.append(*newhash);
} }
@ -508,51 +194,22 @@ hash_base *hash_collection::add_from_string(char type, const char *buffer, int l
bool hash_collection::remove(char type) bool hash_collection::remove(char type)
{ {
// scan the list of hashes for a match bool result = false;
for (hash_base *hash = m_hashlist.first(); hash != NULL; hash = hash->next())
if (hash->id() == type) // handle CRCs
if (type == HASH_CRC)
{ {
m_hashlist.remove(*hash); result = m_has_crc32;
return true; m_has_crc32 = false;
} }
// didn't find it // handle SHA1s
return false; else if (type == HASH_SHA1)
} {
result = m_has_sha1;
m_has_sha1 = false;
//------------------------------------------------- }
// crc - return the CRC hash if present return result;
//-------------------------------------------------
bool hash_collection::crc(UINT32 &result) const
{
// attempt to find the CRC hash; if we fail, return false
hash_base *crchash = hash(HASH_CRC);
if (crchash == NULL)
return false;
// downcast to a hash_crc and convert to a UINT32
result = *downcast<const hash_crc *>(crchash);
return true;
}
//-------------------------------------------------
// add_crc - add a CRC hash
//-------------------------------------------------
hash_base *hash_collection::add_crc(UINT32 crc)
{
// expand to a buffer
UINT8 buffer[4];
buffer[0] = crc >> 24;
buffer[1] = crc >> 16;
buffer[2] = crc >> 8;
buffer[3] = crc >> 0;
// add it the standard way
return add_from_buffer(HASH_CRC, buffer, sizeof(buffer));
} }
@ -564,16 +221,19 @@ hash_base *hash_collection::add_crc(UINT32 crc)
const char *hash_collection::internal_string(astring &buffer) const const char *hash_collection::internal_string(astring &buffer) const
{ {
astring temp;
// output hashes first
buffer.reset(); buffer.reset();
for (hash_base *hash = m_hashlist.first(); hash != NULL; hash = hash->next())
buffer.cat(hash->id()).cat(hash->string(temp)); // handle CRCs
astring temp;
if (m_has_crc32)
buffer.cat(HASH_CRC).cat(m_crc32.as_string(temp));
// handle SHA1s
if (m_has_sha1)
buffer.cat(HASH_SHA1).cat(m_sha1.as_string(temp));
// append flags // append flags
buffer.cat(m_flags); return buffer.cat(m_flags);
return buffer;
} }
@ -584,15 +244,16 @@ const char *hash_collection::internal_string(astring &buffer) const
const char *hash_collection::macro_string(astring &buffer) const const char *hash_collection::macro_string(astring &buffer) const
{ {
astring temp;
// output hashes first
buffer.reset(); buffer.reset();
for (hash_base *hash = m_hashlist.first(); hash != NULL; hash = hash->next())
{ // handle CRCs
buffer.cat(temp.cpy(hash->name()).makeupper()); astring temp;
buffer.cat("(").cat(hash->string(temp)).cat(") "); if (m_has_crc32)
} buffer.cat("CRC(").cat(m_crc32.as_string(temp)).cat(" )");
// handle SHA1s
if (m_has_sha1)
buffer.cat("SHA1(").cat(m_sha1.as_string(temp)).cat(" )");
// append flags // append flags
if (flag(FLAG_NO_DUMP)) if (flag(FLAG_NO_DUMP))
@ -603,6 +264,33 @@ const char *hash_collection::macro_string(astring &buffer) const
} }
//-------------------------------------------------
// attribute_string - convert set of hashes and
// flags to a string in XML attribute format
//-------------------------------------------------
const char *hash_collection::attribute_string(astring &buffer) const
{
buffer.reset();
// handle CRCs
astring temp;
if (m_has_crc32)
buffer.cat("crc=\"").cat(m_crc32.as_string(temp)).cat("\" ");
// handle SHA1s
if (m_has_sha1)
buffer.cat("sha1=\"").cat(m_sha1.as_string(temp)).cat("\" ");
// append flags
if (flag(FLAG_NO_DUMP))
buffer.cat("status=\"nodump\"" );
if (flag(FLAG_BAD_DUMP))
buffer.cat("status=\"baddump\"" );
return buffer.trimspace();
}
//------------------------------------------------- //-------------------------------------------------
// from_internal_string - convert an internal // from_internal_string - convert an internal
// compact string to set of hashes and flags // compact string to set of hashes and flags
@ -619,28 +307,29 @@ bool hash_collection::from_internal_string(const char *string)
// loop until we hit it // loop until we hit it
bool errors = false; bool errors = false;
bool skip_digits = false;
while (ptr < stringend) while (ptr < stringend)
{ {
char c = *ptr++; char c = *ptr++;
char lc = tolower(c); char uc = toupper(c);
// non-hex alpha values specify a hash type // non-hex alpha values specify a hash type
if (lc >= 'g' && lc <= 'z') if (uc >= 'G' && uc <= 'Z')
{ {
hash_base *hash = alloc_by_id(c); if (uc == HASH_CRC)
if (hash != NULL) skip_digits = m_has_crc32 = m_crc32.from_string(ptr, stringend - ptr);
{ else if (uc == HASH_SHA1)
if (!hash->from_string(ptr, stringend - ptr)) skip_digits = m_has_sha1 = m_sha1.from_string(ptr, stringend - ptr);
errors = true;
m_hashlist.append(*hash);
}
else else
errors = true; errors = true;
} }
// hex values are ignored, though unexpected // hex values are ignored, though unexpected
else if ((lc >= '0' && lc <= '9') || (lc >= 'a' && lc <= 'f')) else if ((uc >= '0' && uc <= '9') || (uc >= 'A' && uc <= 'F'))
{
if (!skip_digits)
errors = true; errors = true;
}
// anything else is a flag // anything else is a flag
else else
@ -656,26 +345,19 @@ bool hash_collection::from_internal_string(const char *string)
void hash_collection::begin(const char *types) void hash_collection::begin(const char *types)
{ {
// nuke previous creator and make a new one
delete m_creator;
m_creator = new hash_creator;
// by default use all types // by default use all types
if (types == NULL) if (types == NULL)
{ m_creator->m_doing_crc32 = m_creator->m_doing_sha1 = true;
m_hashlist.append(*alloc_by_id(HASH_CRC)).begin();
m_hashlist.append(*alloc_by_id(HASH_SHA1)).begin();
}
// otherwise, just allocate the ones that are specified // otherwise, just allocate the ones that are specified
else else
{ {
for (const char *scan = types; *scan != 0; scan++) m_creator->m_doing_crc32 = (strchr(types, HASH_CRC) != NULL);
{ m_creator->m_doing_sha1 = (strchr(types, HASH_SHA1) != NULL);
// nuke any existing hash of this type
hash_base *existing = hash(*scan);
if (existing != NULL)
m_hashlist.remove(*existing);
// append a new one
m_hashlist.append(*alloc_by_id(*scan)).begin();
}
} }
} }
@ -686,10 +368,13 @@ void hash_collection::begin(const char *types)
void hash_collection::buffer(const UINT8 *data, UINT32 length) void hash_collection::buffer(const UINT8 *data, UINT32 length)
{ {
// buffer each hash appropriately assert(m_creator != NULL);
for (hash_base *hash = m_hashlist.first(); hash != NULL; hash = hash->next())
if (hash->in_progress()) // append to each active hash
hash->buffer(data, length); if (m_creator->m_doing_crc32)
m_creator->m_crc32_creator.append(data, length);
if (m_creator->m_doing_sha1)
m_creator->m_sha1_creator.append(data, length);
} }
@ -699,26 +384,28 @@ void hash_collection::buffer(const UINT8 *data, UINT32 length)
void hash_collection::end() void hash_collection::end()
{ {
// end each hash assert(m_creator != NULL);
for (hash_base *hash = m_hashlist.first(); hash != NULL; hash = hash->next())
if (hash->in_progress())
hash->end();
}
// default to getting nothing
m_has_crc32 = m_has_sha1 = false;
//------------------------------------------------- // finish up the CRC32
// alloc_by_id - based on the ID character, if (m_creator->m_doing_crc32)
// allocate a new hash
//-------------------------------------------------
hash_base *hash_collection::alloc_by_id(char id)
{
switch (id)
{ {
case HASH_CRC: return global_alloc(hash_crc); m_has_crc32 = true;
case HASH_SHA1: return global_alloc(hash_sha1); m_crc32 = m_creator->m_crc32_creator.finish();
default: return NULL;
} }
// finish up the SHA1
if (m_creator->m_doing_sha1)
{
m_has_sha1 = true;
m_sha1 = m_creator->m_sha1_creator.finish();
}
// nuke the creator
delete m_creator;
m_creator = NULL;
} }
@ -732,8 +419,12 @@ void hash_collection::copyfrom(const hash_collection &src)
// copy flags directly // copy flags directly
m_flags = src.m_flags; m_flags = src.m_flags;
// rebuild the hashlist by copying from the source // copy hashes
m_hashlist.reset(); m_has_crc32 = src.m_has_crc32;
for (hash_base *hash = src.first(); hash != NULL; hash = hash->next()) m_crc32 = src.m_crc32;
add_from_buffer(hash->id(), hash->buffer(), hash->length()); m_has_sha1 = src.m_has_sha1;
m_sha1 = src.m_sha1;
// don't copy creators
m_creator = NULL;
} }

View File

@ -44,6 +44,8 @@
#ifndef __HASH_H__ #ifndef __HASH_H__
#define __HASH_H__ #define __HASH_H__
#include "hashing.h"
//************************************************************************** //**************************************************************************
// MACROS // MACROS
@ -62,59 +64,6 @@
//************************************************************************** //**************************************************************************
// ======================> hash_base
// base class for all hash types, which does most of the heavy lifting
class hash_base
{
friend class simple_list<hash_base>;
public:
// construction/destruction
hash_base(char id, const char *name, UINT8 length, UINT8 *bufptr);
virtual ~hash_base() { }
// operators
bool operator==(const hash_base &rhs) const { return (m_length == rhs.m_length && memcmp(m_bufptr, rhs.m_bufptr, m_length) == 0); }
bool operator!=(const hash_base &rhs) const { return (m_length != rhs.m_length || memcmp(m_bufptr, rhs.m_bufptr, m_length) != 0); }
// getters
hash_base *next() const { return m_next; }
char id() const { return m_id; }
const char *name() const { return m_name; }
int length() const { return m_length; }
bool in_progress() const { return m_in_progress; }
bool parse_error() const { return m_parse_error; }
UINT8 byte(int index) const { return (index >= 0 && index < m_length) ? m_bufptr[index] : 0; }
// buffer conversion
const UINT8 *buffer() { return m_bufptr; }
bool from_buffer(const UINT8 *buffer, int buflen);
// string conversion
const char *string(astring &buffer);
bool from_string(const char *&string, int length);
// creation
virtual void begin() = 0;
virtual void buffer(const UINT8 *data, UINT32 length) = 0;
virtual void end() = 0;
protected:
// internal helpers
int fromhex(char c);
// internal state
hash_base * m_next;
const char * m_name;
bool m_in_progress;
bool m_parse_error;
char m_id;
UINT8 m_length;
UINT8 * m_bufptr;
};
// ======================> hash_collection // ======================> hash_collection
// a collection of the various supported hashes and flags // a collection of the various supported hashes and flags
@ -147,24 +96,25 @@ public:
// getters // getters
bool flag(char flag) const { return (m_flags.chr(0, flag) != -1); } bool flag(char flag) const { return (m_flags.chr(0, flag) != -1); }
hash_base *hash(char type) const;
hash_base *first() const { return m_hashlist.first(); }
const char *hash_types(astring &buffer) const; const char *hash_types(astring &buffer) const;
bool parse_errors() const;
// hash manipulators // hash manipulators
void reset(); void reset();
hash_base *add_from_buffer(char type, const UINT8 *buffer, int bufflen); bool add_from_string(char type, const char *buffer, int length = -1);
hash_base *add_from_string(char type, const char *buffer, int length);
bool remove(char type); bool remove(char type);
// CRC-specific helpers // CRC-specific helpers
bool crc(UINT32 &result) const; bool crc(UINT32 &result) const { result = m_crc32; return m_has_crc32; }
hash_base *add_crc(UINT32 crc); void add_crc(UINT32 crc) { m_crc32 = crc; m_has_crc32 = true; }
// SHA1-specific helpers
bool sha1(sha1_t &result) const { result = m_sha1; return m_has_sha1; }
void add_sha1(sha1_t sha1) { m_has_sha1 = true; m_sha1 = sha1; }
// string conversion // string conversion
const char *internal_string(astring &buffer) const; const char *internal_string(astring &buffer) const;
const char *macro_string(astring &buffer) const; const char *macro_string(astring &buffer) const;
const char *attribute_string(astring &buffer) const;
bool from_internal_string(const char *string); bool from_internal_string(const char *string);
// creation // creation
@ -175,12 +125,24 @@ public:
private: private:
// internal helpers // internal helpers
static hash_base *alloc_by_id(char id);
void copyfrom(const hash_collection &src); void copyfrom(const hash_collection &src);
// internal state // internal state
astring m_flags; astring m_flags;
simple_list<hash_base> m_hashlist; bool m_has_crc32;
crc32_t m_crc32;
bool m_has_sha1;
sha1_t m_sha1;
// creators
struct hash_creator
{
bool m_doing_crc32;
crc32_creator m_crc32_creator;
bool m_doing_sha1;
sha1_creator m_sha1_creator;
};
hash_creator * m_creator;
}; };

View File

@ -524,19 +524,14 @@ void info_xml_creator::output_rom(const rom_source *source)
{ {
// iterate over hash function types and print m_output their values // iterate over hash function types and print m_output their values
astring tempstr; astring tempstr;
for (hash_base *hash = hashes.first(); hash != NULL; hash = hash->next()) fprintf(m_output, " %s", hashes.attribute_string(tempstr));
fprintf(m_output, " %s=\"%s\"", hash->name(), hash->string(tempstr));
} }
else
fprintf(m_output, " status=\"nodump\"");
// append a region name // append a region name
fprintf(m_output, " region=\"%s\"", ROMREGION_GETTAG(region)); fprintf(m_output, " region=\"%s\"", ROMREGION_GETTAG(region));
// add nodump/baddump flags
if (hashes.flag(hash_collection::FLAG_NO_DUMP))
fprintf(m_output, " status=\"nodump\"");
if (hashes.flag(hash_collection::FLAG_BAD_DUMP))
fprintf(m_output, " status=\"baddump\"");
// for non-disk entries, print offset // for non-disk entries, print offset
if (!is_disk) if (!is_disk)
fprintf(m_output, " offset=\"%x\"", offset); fprintf(m_output, " offset=\"%x\"", offset);

View File

@ -455,7 +455,7 @@ static void dump_wrong_and_correct_checksums(rom_load_data *romdata, const hash_
astring tempstr; astring tempstr;
romdata->errorstring.catprintf(" EXPECTED: %s\n", hashes.macro_string(tempstr)); romdata->errorstring.catprintf(" EXPECTED: %s\n", hashes.macro_string(tempstr));
romdata->errorstring.catprintf(" FOUND: %s\n", acthashes.macro_string(tempstr)); romdata->errorstring.catprintf(" FOUND: %s\n", acthashes.macro_string(tempstr));
/*
// warn about any ill-formed hashes // warn about any ill-formed hashes
for (hash_base *hash = hashes.first(); hash != NULL; hash = hash->next()) for (hash_base *hash = hashes.first(); hash != NULL; hash = hash->next())
if (hash->parse_error()) if (hash->parse_error())
@ -463,6 +463,7 @@ static void dump_wrong_and_correct_checksums(rom_load_data *romdata, const hash_
romdata->errorstring.catprintf("\tInvalid %s checksum treated as 0 (check leading zeros)\n", hash->name()); romdata->errorstring.catprintf("\tInvalid %s checksum treated as 0 (check leading zeros)\n", hash->name());
romdata->warnings++; romdata->warnings++;
} }
*/
} }
@ -1228,7 +1229,7 @@ static void process_disk_entries(rom_load_data *romdata, const char *regiontag,
/* get the header and extract the SHA1 */ /* get the header and extract the SHA1 */
hash_collection acthashes; hash_collection acthashes;
acthashes.add_from_buffer(hash_collection::HASH_SHA1, chd->orig_chd().sha1().m_raw, sizeof(chd->orig_chd().sha1().m_raw)); acthashes.add_sha1(chd->orig_chd().sha1());
/* verify the hash */ /* verify the hash */
if (hashes != acthashes) if (hashes != acthashes)

View File

@ -38,6 +38,7 @@
***************************************************************************/ ***************************************************************************/
#include "hashing.h" #include "hashing.h"
#include "zlib.h"
//************************************************************************** //**************************************************************************
@ -81,10 +82,12 @@ inline int char_to_hex(char c)
// from_string - convert from a string // from_string - convert from a string
//------------------------------------------------- //-------------------------------------------------
bool sha1_t::from_string(const char *string) bool sha1_t::from_string(const char *string, int length)
{ {
// must be at least long enough to hold everything // must be at least long enough to hold everything
if (strlen(string) < 2 * sizeof(m_raw)) if (length == -1)
length = strlen(string);
if (length < 2 * sizeof(m_raw))
return false; return false;
// iterate through our raw buffer // iterate through our raw buffer
@ -104,7 +107,7 @@ bool sha1_t::from_string(const char *string)
// as_string - convert to a string // as_string - convert to a string
//------------------------------------------------- //-------------------------------------------------
const char *sha1_t::as_string(astring &buffer) const char *sha1_t::as_string(astring &buffer) const
{ {
buffer.reset(); buffer.reset();
for (int i = 0; i < ARRAY_LENGTH(m_raw); i++) for (int i = 0; i < ARRAY_LENGTH(m_raw); i++)
@ -121,10 +124,12 @@ const char *sha1_t::as_string(astring &buffer)
// from_string - convert from a string // from_string - convert from a string
//------------------------------------------------- //-------------------------------------------------
bool md5_t::from_string(const char *string) bool md5_t::from_string(const char *string, int length)
{ {
// must be at least long enough to hold everything // must be at least long enough to hold everything
if (strlen(string) < 2 * sizeof(m_raw)) if (length == -1)
length = strlen(string);
if (length < 2 * sizeof(m_raw))
return false; return false;
// iterate through our raw buffer // iterate through our raw buffer
@ -144,7 +149,7 @@ bool md5_t::from_string(const char *string)
// as_string - convert to a string // as_string - convert to a string
//------------------------------------------------- //-------------------------------------------------
const char *md5_t::as_string(astring &buffer) const char *md5_t::as_string(astring &buffer) const
{ {
buffer.reset(); buffer.reset();
for (int i = 0; i < ARRAY_LENGTH(m_raw); i++) for (int i = 0; i < ARRAY_LENGTH(m_raw); i++)
@ -162,10 +167,12 @@ const char *md5_t::as_string(astring &buffer)
// from_string - convert from a string // from_string - convert from a string
//------------------------------------------------- //-------------------------------------------------
bool crc32_t::from_string(const char *string) bool crc32_t::from_string(const char *string, int length)
{ {
// must be at least long enough to hold everything // must be at least long enough to hold everything
if (strlen(string) < 2 * sizeof(m_raw)) if (length == -1)
length = strlen(string);
if (length < 2 * sizeof(m_raw))
return false; return false;
// iterate through our raw buffer // iterate through our raw buffer
@ -185,12 +192,23 @@ bool crc32_t::from_string(const char *string)
// as_string - convert to a string // as_string - convert to a string
//------------------------------------------------- //-------------------------------------------------
const char *crc32_t::as_string(astring &buffer) const char *crc32_t::as_string(astring &buffer) const
{ {
return buffer.format("%08x", m_raw); return buffer.format("%08x", m_raw);
} }
//-------------------------------------------------
// append - hash a block of data, appending to
// the currently-accumulated value
//-------------------------------------------------
void crc32_creator::append(const void *data, UINT32 length)
{
m_accum.m_raw = crc32(m_accum, reinterpret_cast<const Bytef *>(data), length);
}
//************************************************************************** //**************************************************************************
// CRC-16 HELPERS // CRC-16 HELPERS
@ -200,10 +218,12 @@ const char *crc32_t::as_string(astring &buffer)
// from_string - convert from a string // from_string - convert from a string
//------------------------------------------------- //-------------------------------------------------
bool crc16_t::from_string(const char *string) bool crc16_t::from_string(const char *string, int length)
{ {
// must be at least long enough to hold everything // must be at least long enough to hold everything
if (strlen(string) < 2 * sizeof(m_raw)) if (length == -1)
length = strlen(string);
if (length < 2 * sizeof(m_raw))
return false; return false;
// iterate through our raw buffer // iterate through our raw buffer
@ -223,7 +243,7 @@ bool crc16_t::from_string(const char *string)
// as_string - convert to a string // as_string - convert to a string
//------------------------------------------------- //-------------------------------------------------
const char *crc16_t::as_string(astring &buffer) const char *crc16_t::as_string(astring &buffer) const
{ {
return buffer.format("%04x", m_raw); return buffer.format("%04x", m_raw);
} }

View File

@ -44,7 +44,7 @@
#include "osdcore.h" #include "osdcore.h"
#include "astring.h" #include "astring.h"
#include "zlib.h" //#include "zlib.h"
#include "md5.h" #include "md5.h"
#include "sha1.h" #include "sha1.h"
@ -62,8 +62,8 @@ struct sha1_t
bool operator==(const sha1_t &rhs) const { return memcmp(m_raw, rhs.m_raw, sizeof(m_raw)) == 0; } bool operator==(const sha1_t &rhs) const { return memcmp(m_raw, rhs.m_raw, sizeof(m_raw)) == 0; }
bool operator!=(const sha1_t &rhs) const { return memcmp(m_raw, rhs.m_raw, sizeof(m_raw)) != 0; } bool operator!=(const sha1_t &rhs) const { return memcmp(m_raw, rhs.m_raw, sizeof(m_raw)) != 0; }
operator UINT8 *() { return m_raw; } operator UINT8 *() { return m_raw; }
const char *as_string(astring &buffer); bool from_string(const char *string, int length = -1);
bool from_string(const char *string); const char *as_string(astring &buffer) const;
UINT8 m_raw[20]; UINT8 m_raw[20];
static const sha1_t null; static const sha1_t null;
}; };
@ -113,8 +113,8 @@ struct md5_t
bool operator==(const md5_t &rhs) const { return memcmp(m_raw, rhs.m_raw, sizeof(m_raw)) == 0; } bool operator==(const md5_t &rhs) const { return memcmp(m_raw, rhs.m_raw, sizeof(m_raw)) == 0; }
bool operator!=(const md5_t &rhs) const { return memcmp(m_raw, rhs.m_raw, sizeof(m_raw)) != 0; } bool operator!=(const md5_t &rhs) const { return memcmp(m_raw, rhs.m_raw, sizeof(m_raw)) != 0; }
operator UINT8 *() { return m_raw; } operator UINT8 *() { return m_raw; }
const char *as_string(astring &buffer); bool from_string(const char *string, int length = -1);
bool from_string(const char *string); const char *as_string(astring &buffer) const;
UINT8 m_raw[16]; UINT8 m_raw[16];
static const md5_t null; static const md5_t null;
}; };
@ -161,9 +161,11 @@ protected:
struct crc32_t struct crc32_t
{ {
bool operator==(const crc32_t &rhs) const { return m_raw == rhs.m_raw; } bool operator==(const crc32_t &rhs) const { return m_raw == rhs.m_raw; }
bool operator!=(const crc32_t &rhs) const { return m_raw != rhs.m_raw; }
crc32_t &operator=(const UINT32 crc) { m_raw = crc; return *this; }
operator UINT32() const { return m_raw; } operator UINT32() const { return m_raw; }
const char *as_string(astring &buffer); bool from_string(const char *string, int length = -1);
bool from_string(const char *string); const char *as_string(astring &buffer) const;
UINT32 m_raw; UINT32 m_raw;
static const crc32_t null; static const crc32_t null;
}; };
@ -179,7 +181,7 @@ public:
void reset() { m_accum.m_raw = 0; } void reset() { m_accum.m_raw = 0; }
// append data // append data
void append(const void *data, UINT32 length) { m_accum.m_raw = crc32(m_accum, reinterpret_cast<const Bytef *>(data), length); } void append(const void *data, UINT32 length);
// finalize and compute the final digest // finalize and compute the final digest
crc32_t finish() { return m_accum; } crc32_t finish() { return m_accum; }
@ -205,9 +207,11 @@ protected:
struct crc16_t struct crc16_t
{ {
bool operator==(const crc16_t &rhs) const { return m_raw == rhs.m_raw; } bool operator==(const crc16_t &rhs) const { return m_raw == rhs.m_raw; }
bool operator!=(const crc16_t &rhs) const { return m_raw != rhs.m_raw; }
crc16_t &operator=(const UINT16 crc) { m_raw = crc; return *this; }
operator UINT16() const { return m_raw; } operator UINT16() const { return m_raw; }
const char *as_string(astring &buffer); bool from_string(const char *string, int length = -1);
bool from_string(const char *string); const char *as_string(astring &buffer) const;
UINT16 m_raw; UINT16 m_raw;
static const crc16_t null; static const crc16_t null;
}; };