diff options
Diffstat (limited to 'src/emu/diimage.c')
-rw-r--r-- | src/emu/diimage.c | 196 |
1 files changed, 195 insertions, 1 deletions
diff --git a/src/emu/diimage.c b/src/emu/diimage.c index 370df5e38cf..a437449647f 100644 --- a/src/emu/diimage.c +++ b/src/emu/diimage.c @@ -41,6 +41,7 @@ #include "ui.h" #include "pool.h" #include "zippath.h" +#include "hashfile.h" //************************************************************************** @@ -121,6 +122,24 @@ const char *device_config_image_interface::device_brieftypename(iodevice_t type) return (info != NULL) ? info->m_shortname : NULL; } +/*------------------------------------------------- + device_compute_hash - compute a hash, + using this device's partial hash if appropriate +-------------------------------------------------*/ + +void device_config_image_interface::device_compute_hash(char *dest, const void *data, size_t length, unsigned int functions) const +{ + /* retrieve the partial hash func */ + device_image_partialhash_func partialhash = get_partial_hash(); + + /* compute the hash */ + if (partialhash) + partialhash(dest, (const unsigned char*)data, length, functions); + else + hash_compute(dest, (const unsigned char*)data, length, functions); +} + + //************************************************************************** // DEVICE image INTERFACE //************************************************************************** @@ -145,7 +164,8 @@ device_image_interface::device_image_interface(running_machine &machine, const d m_file(NULL), m_full_software_name(NULL), m_software_info_ptr(NULL), - m_software_part_ptr(NULL) + m_software_part_ptr(NULL), + m_hash(NULL) { m_mempool = pool_alloc_lib(memory_error); } @@ -463,3 +483,177 @@ void device_image_interface::image_freeptr(void *ptr) { pool_object_remove(m_mempool, ptr, 0); } + + +/**************************************************************************** + Hash info loading + + If the hash is not checked and the relevant info not loaded, force that info + to be loaded +****************************************************************************/ + +/*------------------------------------------------- + hash_data_extract_crc32 - extract crc32 value + from hash string +-------------------------------------------------*/ + +static UINT32 hash_data_extract_crc32(const char *d) +{ + UINT32 crc = 0; + UINT8 crc_bytes[4]; + + if (hash_data_extract_binary_checksum(d, HASH_CRC, crc_bytes) == 1) + { + crc = (((UINT32) crc_bytes[0]) << 24) + | (((UINT32) crc_bytes[1]) << 16) + | (((UINT32) crc_bytes[2]) << 8) + | (((UINT32) crc_bytes[3]) << 0); + } + return crc; +} + +int device_image_interface::read_hash_config(const char *sysname) +{ + hash_file *hashfile = NULL; + const hash_info *info = NULL; + + /* open the hash file */ + hashfile = hashfile_open(sysname, FALSE, NULL); + if (!hashfile) + goto done; + + /* look up this entry in the hash file */ + info = hashfile_lookup(hashfile, m_hash); + + if (!info) + goto done; + + /* copy the relevant entries */ + m_longname = info->longname ? astring(info->longname) : ""; + m_manufacturer = info->manufacturer ? astring(info->manufacturer) : ""; + m_year = info->year ? astring(info->year) : ""; + m_playable = info->playable ? astring(info->playable) : ""; + m_pcb = info->pcb ? astring(info->pcb) : ""; + m_extrainfo = info->extrainfo ? astring(info->extrainfo) : ""; + +done: + if (hashfile != NULL) + hashfile_close(hashfile); + return !hashfile || !info; +} + + + +void device_image_interface::run_hash(void (*partialhash)(char *, const unsigned char *, unsigned long, unsigned int), + char *dest, unsigned int hash_functions) +{ + UINT32 size; + UINT8 *buf = NULL; + + *dest = '\0'; + size = (UINT32) length(); + + buf = (UINT8*)malloc(size); + memset(buf,0,size); + + /* read the file */ + fseek(0, SEEK_SET); + fread(buf, size); + + if (partialhash) + partialhash(dest, buf, size, hash_functions); + else + hash_compute(dest, buf, size, hash_functions); + + /* cleanup */ + free(buf); + fseek(0, SEEK_SET); +} + + + +void device_image_interface::image_checkhash() +{ + const game_driver *drv; + char hash_string[HASH_BUF_SIZE]; + device_image_partialhash_func partialhash; + int rc; + + /* only calculate CRC if it hasn't been calculated, and the open_mode is read only */ + if (!m_hash && !m_writeable && !m_created) + { + /* do not cause a linear read of 600 megs please */ + /* TODO: use SHA/MD5 in the CHD header as the hash */ + if (m_image_config.image_type() == IO_CDROM) + return; + + /* Skip calculating the hash when we have an image mounted through a software list */ + if ( m_software_info_ptr ) + return; + + /* retrieve the partial hash func */ + partialhash = get_partial_hash(); + + run_hash(partialhash, hash_string, HASH_CRC | HASH_MD5 | HASH_SHA1); + + m_hash = hash_string; + + /* now read the hash file */ + drv = device().machine->gamedrv; + do + { + rc = read_hash_config(drv->name); + drv = driver_get_compatible(drv); + } + while(rc && (drv != NULL)); + } + return; +} + +UINT32 device_image_interface::crc() +{ + UINT32 crc = 0; + + image_checkhash(); + if (m_hash != NULL) + crc = hash_data_extract_crc32(m_hash); + + return crc; +} + +/**************************************************************************** + Battery functions + + These functions provide transparent access to battery-backed RAM on an + image; typically for cartridges. +****************************************************************************/ + + +/*------------------------------------------------- + battery_load - retrieves the battery + backed RAM for an image. The file name is + created from the machine driver name and the + image name. +-------------------------------------------------*/ +void device_image_interface::battery_load(void *buffer, int length, int fill) +{ + astring *fname = astring_assemble_4(astring_alloc(), device().machine->gamedrv->name, PATH_SEPARATOR, m_basename_noext, ".nv"); + + image_battery_load_by_name(astring_c(fname), buffer, length, fill); + astring_free(fname); +} + +/*------------------------------------------------- + battery_save - stores the battery + backed RAM for an image. The file name is + created from the machine driver name and the + image name. +-------------------------------------------------*/ +void device_image_interface::battery_save(const void *buffer, int length) +{ + astring *fname = astring_assemble_4(astring_alloc(), device().machine->gamedrv->name, PATH_SEPARATOR, m_basename_noext, ".nv"); + + image_battery_save_by_name(astring_c(fname), buffer, length); + astring_free(fname); +} +
\ No newline at end of file |