diff options
-rw-r--r-- | src/emu/audit.c | 2 | ||||
-rw-r--r-- | src/emu/clifront.c | 19 | ||||
-rw-r--r-- | src/emu/diimage.c | 3 | ||||
-rw-r--r-- | src/emu/fileio.c | 6 | ||||
-rw-r--r-- | src/emu/hash.c | 625 | ||||
-rw-r--r-- | src/emu/hash.h | 86 | ||||
-rw-r--r-- | src/emu/info.c | 11 | ||||
-rw-r--r-- | src/emu/romload.c | 5 | ||||
-rw-r--r-- | src/lib/util/hashing.c | 44 | ||||
-rw-r--r-- | src/lib/util/hashing.h | 24 |
10 files changed, 247 insertions, 578 deletions
diff --git a/src/emu/audit.c b/src/emu/audit.c index 42e2ed77060..d1a07aea607 100644 --- a/src/emu/audit.c +++ b/src/emu/audit.c @@ -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 (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 record.set_actual(hashes); diff --git a/src/emu/clifront.c b/src/emu/clifront.c index f9f17ee09a3..582af2d84fc 100644 --- a/src/emu/clifront.c +++ b/src/emu/clifront.c @@ -1080,6 +1080,7 @@ void cli_frontend::listsoftware(const char *gamename) drivlist.reset(); list_count = 0; + astring tempstr; while (drivlist.next()) { 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 */ hash_collection hashes(ROM_GETHASHDATA(rom)); - if (!hashes.flag(hash_collection::FLAG_NO_DUMP)) - { - astring tempstr; - 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) ) + if ( !hashes.flag(hash_collection::FLAG_NO_DUMP) ) + fprintf( out, " %s", hashes.attribute_string(tempstr) ); + else fprintf( out, " status=\"nodump\"" ); if (is_disk) @@ -1517,7 +1508,7 @@ void media_identifier::identify_file(const char *name) // otherwise, get the hash collection for this CHD hash_collection hashes; 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 int found = find_by_hash(hashes, chd.logical_bytes()); diff --git a/src/emu/diimage.c b/src/emu/diimage.c index 8f4f949a7f1..bf5f4a3cb5a 100644 --- a/src/emu/diimage.c +++ b/src/emu/diimage.c @@ -497,7 +497,8 @@ void device_image_interface::image_checkhash() device_image_partialhash_func partialhash; /* 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 */ /* TODO: use SHA1 in the CHD header as the hash */ diff --git a/src/emu/fileio.c b/src/emu/fileio.c index d5fbf122043..ab0b361f560 100644 --- a/src/emu/fileio.c +++ b/src/emu/fileio.c @@ -250,10 +250,14 @@ emu_file::operator core_file &() 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 astring needed; for (const char *scan = types; *scan != 0; scan++) - if (m_hashes.hash(*scan) == NULL) + if (already_have.chr(0, *scan) == -1) needed.cat(*scan); // if we need nothing, skip it diff --git a/src/emu/hash.c b/src/emu/hash.c index d50395b2f74..ef03418ef50 100644 --- a/src/emu/hash.c +++ b/src/emu/hash.c @@ -40,62 +40,11 @@ ***************************************************************************/ #include "emu.h" -#include "zlib.h" -#include "sha1.h" +#include "hashing.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 //************************************************************************** @@ -106,220 +55,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 //************************************************************************** @@ -328,17 +63,26 @@ void hash_sha1::end() //------------------------------------------------- hash_collection::hash_collection() + : m_has_crc32(false), + m_has_sha1(false), + m_creator(NULL) { } hash_collection::hash_collection(const char *string) + : m_has_crc32(false), + m_has_sha1(false), + m_creator(NULL) { from_internal_string(string); } hash_collection::hash_collection(const hash_collection &src) + : m_has_crc32(false), + m_has_sha1(false), + m_creator(NULL) { copyfrom(src); } @@ -350,6 +94,7 @@ hash_collection::hash_collection(const hash_collection &src) 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 { - // look for a mismatch in any hash; do not fail if one is missing + // match CRCs 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 (rhs_hash != NULL) - { - if (*hash != *rhs_hash) - return false; - matches++; - } + if (m_crc32 != rhs.m_crc32) + return false; + 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 @@ -391,20 +140,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 // a string //------------------------------------------------- @@ -412,8 +147,10 @@ hash_base *hash_collection::hash(char type) const const char *hash_collection::hash_types(astring &buffer) const { buffer.reset(); - for (hash_base *hash = m_hashlist.first(); hash != NULL; hash = hash->next()) - buffer.cat(hash->id()); + if (m_has_crc32) + buffer.cat(HASH_CRC); + if (m_has_sha1) + buffer.cat(HASH_SHA1); return buffer; } @@ -423,53 +160,12 @@ const char *hash_collection::hash_types(astring &buffer) const // 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 -// set of hashes and flags -//------------------------------------------------- - void hash_collection::reset() { - m_hashlist.reset(); m_flags.reset(); -} - - -//------------------------------------------------- -// 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); + m_has_crc32 = m_has_sha1 = false; + delete m_creator; + m_creator = NULL; } @@ -478,27 +174,17 @@ hash_base *hash_collection::add_from_buffer(char type, const UINT8 *buffer, int // 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 - 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_string(buffer, length)) - { - global_free(newhash); - return NULL; - } + // handle CRCs + if (type == HASH_CRC) + return m_has_crc32 = m_crc32.from_string(buffer, length); + + // handle SHA1s + else if (type == HASH_SHA1) + return m_has_sha1 = m_sha1.from_string(buffer, length); - // and append to our list - return &m_hashlist.append(*newhash); + return false; } @@ -508,51 +194,22 @@ hash_base *hash_collection::add_from_string(char type, const char *buffer, int l bool hash_collection::remove(char type) { - // scan the list of hashes for a match - for (hash_base *hash = m_hashlist.first(); hash != NULL; hash = hash->next()) - if (hash->id() == type) - { - m_hashlist.remove(*hash); - return true; - } - - // didn't find it - return false; -} - - -//------------------------------------------------- -// crc - return the CRC hash if present -//------------------------------------------------- - -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)); + bool result = false; + + // handle CRCs + if (type == HASH_CRC) + { + result = m_has_crc32; + m_has_crc32 = false; + } + + // handle SHA1s + else if (type == HASH_SHA1) + { + result = m_has_sha1; + m_has_sha1 = false; + } + return result; } @@ -564,16 +221,19 @@ hash_base *hash_collection::add_crc(UINT32 crc) const char *hash_collection::internal_string(astring &buffer) const { - astring temp; - - // output hashes first 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 - buffer.cat(m_flags); - return buffer; + return buffer.cat(m_flags); } @@ -584,15 +244,16 @@ const char *hash_collection::internal_string(astring &buffer) const const char *hash_collection::macro_string(astring &buffer) const { - astring temp; - - // output hashes first buffer.reset(); - for (hash_base *hash = m_hashlist.first(); hash != NULL; hash = hash->next()) - { - buffer.cat(temp.cpy(hash->name()).makeupper()); - buffer.cat("(").cat(hash->string(temp)).cat(") "); - } + + // 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)) @@ -604,6 +265,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 // 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 bool errors = false; + bool skip_digits = false; while (ptr < stringend) { char c = *ptr++; - char lc = tolower(c); + char uc = toupper(c); // 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 (hash != NULL) - { - if (!hash->from_string(ptr, stringend - ptr)) - errors = true; - m_hashlist.append(*hash); - } + if (uc == HASH_CRC) + skip_digits = m_has_crc32 = m_crc32.from_string(ptr, stringend - ptr); + else if (uc == HASH_SHA1) + skip_digits = m_has_sha1 = m_sha1.from_string(ptr, stringend - ptr); else errors = true; } // hex values are ignored, though unexpected - else if ((lc >= '0' && lc <= '9') || (lc >= 'a' && lc <= 'f')) - errors = true; + else if ((uc >= '0' && uc <= '9') || (uc >= 'A' && uc <= 'F')) + { + if (!skip_digits) + errors = true; + } // anything else is a flag else @@ -656,26 +345,19 @@ bool hash_collection::from_internal_string(const char *string) 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 if (types == NULL) - { - m_hashlist.append(*alloc_by_id(HASH_CRC)).begin(); - m_hashlist.append(*alloc_by_id(HASH_SHA1)).begin(); - } - + m_creator->m_doing_crc32 = m_creator->m_doing_sha1 = true; + // otherwise, just allocate the ones that are specified else { - for (const char *scan = types; *scan != 0; scan++) - { - // 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(); - } + m_creator->m_doing_crc32 = (strchr(types, HASH_CRC) != NULL); + m_creator->m_doing_sha1 = (strchr(types, HASH_SHA1) != NULL); } } @@ -686,10 +368,13 @@ void hash_collection::begin(const char *types) void hash_collection::buffer(const UINT8 *data, UINT32 length) { - // buffer each hash appropriately - for (hash_base *hash = m_hashlist.first(); hash != NULL; hash = hash->next()) - if (hash->in_progress()) - hash->buffer(data, length); + assert(m_creator != NULL); + + // append to each active hash + 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() { - // end each hash - for (hash_base *hash = m_hashlist.first(); hash != NULL; hash = hash->next()) - if (hash->in_progress()) - hash->end(); -} - - -//------------------------------------------------- -// alloc_by_id - based on the ID character, -// allocate a new hash -//------------------------------------------------- - -hash_base *hash_collection::alloc_by_id(char id) -{ - switch (id) + assert(m_creator != NULL); + + // default to getting nothing + m_has_crc32 = m_has_sha1 = false; + + // finish up the CRC32 + if (m_creator->m_doing_crc32) { - case HASH_CRC: return global_alloc(hash_crc); - case HASH_SHA1: return global_alloc(hash_sha1); - default: return NULL; + m_has_crc32 = true; + m_crc32 = m_creator->m_crc32_creator.finish(); } + + // 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; } @@ -731,9 +418,13 @@ void hash_collection::copyfrom(const hash_collection &src) { // copy flags directly m_flags = src.m_flags; - - // rebuild the hashlist by copying from the source - m_hashlist.reset(); - for (hash_base *hash = src.first(); hash != NULL; hash = hash->next()) - add_from_buffer(hash->id(), hash->buffer(), hash->length()); + + // copy hashes + m_has_crc32 = src.m_has_crc32; + m_crc32 = src.m_crc32; + m_has_sha1 = src.m_has_sha1; + m_sha1 = src.m_sha1; + + // don't copy creators + m_creator = NULL; } diff --git a/src/emu/hash.h b/src/emu/hash.h index 04c25853856..e12aa4ce974 100644 --- a/src/emu/hash.h +++ b/src/emu/hash.h @@ -44,6 +44,8 @@ #ifndef __HASH_H__ #define __HASH_H__ +#include "hashing.h" + //************************************************************************** // 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 // a collection of the various supported hashes and flags @@ -147,24 +96,25 @@ public: // getters 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; - bool parse_errors() const; // hash manipulators void reset(); - hash_base *add_from_buffer(char type, const UINT8 *buffer, int bufflen); - hash_base *add_from_string(char type, const char *buffer, int length); + bool add_from_string(char type, const char *buffer, int length = -1); bool remove(char type); // CRC-specific helpers - bool crc(UINT32 &result) const; - hash_base *add_crc(UINT32 crc); + bool crc(UINT32 &result) const { result = m_crc32; return m_has_crc32; } + 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 const char *internal_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); // creation @@ -175,12 +125,24 @@ public: private: // internal helpers - static hash_base *alloc_by_id(char id); void copyfrom(const hash_collection &src); // internal state 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; }; diff --git a/src/emu/info.c b/src/emu/info.c index 8ef8c3c7f33..462dc594c0c 100644 --- a/src/emu/info.c +++ b/src/emu/info.c @@ -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 astring tempstr; - for (hash_base *hash = hashes.first(); hash != NULL; hash = hash->next()) - fprintf(m_output, " %s=\"%s\"", hash->name(), hash->string(tempstr)); + fprintf(m_output, " %s", hashes.attribute_string(tempstr)); } + else + fprintf(m_output, " status=\"nodump\""); // append a region name 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 if (!is_disk) fprintf(m_output, " offset=\"%x\"", offset); diff --git a/src/emu/romload.c b/src/emu/romload.c index 85351c74b8d..b8173ef9485 100644 --- a/src/emu/romload.c +++ b/src/emu/romload.c @@ -455,7 +455,7 @@ static void dump_wrong_and_correct_checksums(rom_load_data *romdata, const hash_ astring tempstr; romdata->errorstring.catprintf(" EXPECTED: %s\n", hashes.macro_string(tempstr)); romdata->errorstring.catprintf(" FOUND: %s\n", acthashes.macro_string(tempstr)); - +/* // warn about any ill-formed hashes for (hash_base *hash = hashes.first(); hash != NULL; hash = hash->next()) 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->warnings++; } +*/ } @@ -1228,7 +1229,7 @@ static void process_disk_entries(rom_load_data *romdata, const char *regiontag, /* get the header and extract the SHA1 */ 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 */ if (hashes != acthashes) diff --git a/src/lib/util/hashing.c b/src/lib/util/hashing.c index 97afb184156..866cec8fc0d 100644 --- a/src/lib/util/hashing.c +++ b/src/lib/util/hashing.c @@ -38,6 +38,7 @@ ***************************************************************************/ #include "hashing.h" +#include "zlib.h" //************************************************************************** @@ -81,10 +82,12 @@ inline int char_to_hex(char c) // 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 - if (strlen(string) < 2 * sizeof(m_raw)) + if (length == -1) + length = strlen(string); + if (length < 2 * sizeof(m_raw)) return false; // iterate through our raw buffer @@ -104,7 +107,7 @@ bool sha1_t::from_string(const char *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(); 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 //------------------------------------------------- -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 - if (strlen(string) < 2 * sizeof(m_raw)) + if (length == -1) + length = strlen(string); + if (length < 2 * sizeof(m_raw)) return false; // iterate through our raw buffer @@ -144,7 +149,7 @@ bool md5_t::from_string(const char *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(); 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 //------------------------------------------------- -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 - if (strlen(string) < 2 * sizeof(m_raw)) + if (length == -1) + length = strlen(string); + if (length < 2 * sizeof(m_raw)) return false; // iterate through our raw buffer @@ -185,12 +192,23 @@ bool crc32_t::from_string(const char *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); } +//------------------------------------------------- +// 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 @@ -200,10 +218,12 @@ const char *crc32_t::as_string(astring &buffer) // 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 - if (strlen(string) < 2 * sizeof(m_raw)) + if (length == -1) + length = strlen(string); + if (length < 2 * sizeof(m_raw)) return false; // iterate through our raw buffer @@ -223,7 +243,7 @@ bool crc16_t::from_string(const char *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); } diff --git a/src/lib/util/hashing.h b/src/lib/util/hashing.h index 8bb59b9c5cc..08aeec5ac60 100644 --- a/src/lib/util/hashing.h +++ b/src/lib/util/hashing.h @@ -44,7 +44,7 @@ #include "osdcore.h" #include "astring.h" -#include "zlib.h" +//#include "zlib.h" #include "md5.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; } operator UINT8 *() { return m_raw; } - const char *as_string(astring &buffer); - bool from_string(const char *string); + bool from_string(const char *string, int length = -1); + const char *as_string(astring &buffer) const; UINT8 m_raw[20]; 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; } operator UINT8 *() { return m_raw; } - const char *as_string(astring &buffer); - bool from_string(const char *string); + bool from_string(const char *string, int length = -1); + const char *as_string(astring &buffer) const; UINT8 m_raw[16]; static const md5_t null; }; @@ -161,9 +161,11 @@ protected: 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; } + crc32_t &operator=(const UINT32 crc) { m_raw = crc; return *this; } operator UINT32() const { return m_raw; } - const char *as_string(astring &buffer); - bool from_string(const char *string); + bool from_string(const char *string, int length = -1); + const char *as_string(astring &buffer) const; UINT32 m_raw; static const crc32_t null; }; @@ -179,7 +181,7 @@ public: void reset() { m_accum.m_raw = 0; } // 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 crc32_t finish() { return m_accum; } @@ -205,9 +207,11 @@ protected: 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; } + crc16_t &operator=(const UINT16 crc) { m_raw = crc; return *this; } operator UINT16() const { return m_raw; } - const char *as_string(astring &buffer); - bool from_string(const char *string); + bool from_string(const char *string, int length = -1); + const char *as_string(astring &buffer) const; UINT16 m_raw; static const crc16_t null; }; |