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:
parent
a825e9730d
commit
e055a551c1
@ -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);
|
||||
|
@ -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());
|
||||
@ -1159,18 +1160,8 @@ 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) )
|
||||
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());
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
597
src/emu/hash.c
597
src/emu/hash.c
@ -40,61 +40,10 @@
|
||||
***************************************************************************/
|
||||
|
||||
#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
|
||||
//**************************************************************************
|
||||
@ -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
|
||||
//**************************************************************************
|
||||
@ -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)
|
||||
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
|
||||
@ -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
|
||||
// a string
|
||||
@ -412,26 +147,14 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// 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
|
||||
// set of hashes and flags
|
||||
@ -439,37 +162,10 @@ bool hash_collection::parse_errors() const
|
||||
|
||||
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);
|
||||
// handle CRCs
|
||||
if (type == HASH_CRC)
|
||||
return m_has_crc32 = m_crc32.from_string(buffer, length);
|
||||
|
||||
// first allocate by ID
|
||||
hash_base *newhash = alloc_by_id(type);
|
||||
if (newhash == NULL)
|
||||
return NULL;
|
||||
// handle SHA1s
|
||||
else if (type == HASH_SHA1)
|
||||
return m_has_sha1 = m_sha1.from_string(buffer, length);
|
||||
|
||||
// then import
|
||||
if (!newhash->from_string(buffer, length))
|
||||
{
|
||||
global_free(newhash);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// 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)
|
||||
bool result = false;
|
||||
|
||||
// handle CRCs
|
||||
if (type == HASH_CRC)
|
||||
{
|
||||
m_hashlist.remove(*hash);
|
||||
return true;
|
||||
result = m_has_crc32;
|
||||
m_has_crc32 = false;
|
||||
}
|
||||
|
||||
// didn't find it
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// crc - return the CRC hash if present
|
||||
//-------------------------------------------------
|
||||
|
||||
bool hash_collection::crc(UINT32 &result) const
|
||||
// handle SHA1s
|
||||
else if (type == HASH_SHA1)
|
||||
{
|
||||
// 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;
|
||||
result = m_has_sha1;
|
||||
m_has_sha1 = false;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// 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));
|
||||
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))
|
||||
@ -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
|
||||
// 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'))
|
||||
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();
|
||||
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)
|
||||
{
|
||||
m_has_crc32 = true;
|
||||
m_crc32 = m_creator->m_crc32_creator.finish();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// alloc_by_id - based on the ID character,
|
||||
// allocate a new hash
|
||||
//-------------------------------------------------
|
||||
|
||||
hash_base *hash_collection::alloc_by_id(char id)
|
||||
// finish up the SHA1
|
||||
if (m_creator->m_doing_sha1)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case HASH_CRC: return global_alloc(hash_crc);
|
||||
case HASH_SHA1: return global_alloc(hash_sha1);
|
||||
default: return NULL;
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user