summaryrefslogblamecommitdiffstatshomepage
path: root/src/emu/hashfile.cpp
blob: 6ded9a0e39706007e6173a11cbebd90f3a5d417d (plain) (tree)
1
2
3
4
5
6
7
8
9
10

                                 







                                                                      
                

                     

                    
                     
                      

                                                   
                   

                                                   
                                                                                                                                  
 
                         
                                                 
                                                                
         
                             
         
 
                               
 
                                                                    
                
         

                                                      

                                                                    


                                                                                                      
                 

                                                                  
                 
 
                                           







                                                                                                      
 
         
                     

 

                                                                                                                                   
 
                                    
                                            
                               
                       

          
                                                                                                        
                                                              
                                                            

                                                  
                                      

                                                 
                 
                                                      

                                   
         
                                                                                              

                                         
 












                                                                           
// license:BSD-3-Clause
// copyright-holders:Nathan Woods
/*********************************************************************

    hashfile.c

    Code for parsing hash info (*.hsi) files

*********************************************************************/

#include "emu.h"
#include "hashfile.h"
#include "pool.h"
#include "emuopts.h"
#include "hash.h"
#include "drivenum.h"
#include <pugixml.hpp>

/*-------------------------------------------------
    hashfile_lookup
-------------------------------------------------*/

static bool read_hash_config(const char *hash_path, const util::hash_collection &hashes, const char *sysname, std::string &result)
{
	/* open a file */
	emu_file file(hash_path, OPEN_FLAG_READ);
	if (file.open(sysname, ".hsi") != osd_file::error::NONE)
	{
		return false;
	}

	pugi::xml_document doc;

	pugi::xml_parse_result res = doc.load_file(file.fullpath());
	if (res)
	{
		// Do search by CRC32 and SHA1
		std::string query = "/hashfile/hash[";
		auto crc = hashes.internal_string().substr(1,8);
		auto sha1 = hashes.internal_string().substr(10, 40);
		query += "@crc32='" + crc + "' and @sha1='" + sha1 + "']/extrainfo";
		pugi::xpath_node_set tools = doc.select_nodes(query.c_str());
		for (pugi::xpath_node_set::const_iterator it = tools.begin(); it != tools.end(); ++it)
		{
			result = it->node().first_child().value();
			return true;
		}

		// Try search by CRC32 only
		query = "/hashfile/hash[";
		query += "@crc32='" + crc + "']/extrainfo";
		tools = doc.select_nodes(query.c_str());
		for (pugi::xpath_node_set::const_iterator it = tools.begin(); it != tools.end(); ++it)
		{
			result = it->node().first_child().value();
			return true;
		}

	}
	return false;
}


bool hashfile_extrainfo(const char *hash_path, const game_driver &driver, const util::hash_collection &hashes, std::string &result)
{
	/* now read the hash file */
	int drv = driver_list::find(driver);
	int compat, open = drv;
	bool hashfound;
	do
	{
		hashfound = read_hash_config(hash_path, hashes, driver_list::driver(open).name, result);
		// first check if there are compatible systems
		compat = driver_list::compatible_with(open);
		// if so, try to open its hashfile
		if (compat != -1)
			open = compat;
		// otherwise, try with the parent
		else
		{
			drv = driver_list::clone(drv);
			open = drv;
		}
	}
	// if no extrainfo has been found but we can try a compatible or a parent set, go back
	while (!hashfound && open != -1);
	return hashfound;
}



bool hashfile_extrainfo(device_image_interface &image, std::string &result)
{
	return hashfile_extrainfo(
		image.device().mconfig().options().hash_path(),
		image.device().mconfig().gamedrv(),
		image.hash(),
		result);
}