summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/diimage.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/diimage.c')
-rw-r--r--src/emu/diimage.c196
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