hashfile moved from MESS to emu section (needed for now in image support until softlist implementation is finished), this doesn't affect mame side (no whatsnew)

This commit is contained in:
Miodrag Milanovic 2010-06-17 06:57:05 +00:00
parent 861db1eb49
commit d2a7b5f332
4 changed files with 656 additions and 0 deletions

2
.gitattributes vendored
View File

@ -604,6 +604,8 @@ src/emu/fileio.c svneol=native#text/plain
src/emu/fileio.h svneol=native#text/plain
src/emu/hash.c svneol=native#text/plain
src/emu/hash.h svneol=native#text/plain
src/emu/hashfile.c svneol=native#text/plain
src/emu/hashfile.h svneol=native#text/plain
src/emu/info.c svneol=native#text/plain
src/emu/info.h svneol=native#text/plain
src/emu/inptport.c svneol=native#text/plain

View File

@ -63,6 +63,7 @@ EMUOBJS = \
$(EMUOBJ)/emupal.o \
$(EMUOBJ)/fileio.o \
$(EMUOBJ)/hash.o \
$(EMUOBJ)/hashfile.o \
$(EMUOBJ)/info.o \
$(EMUOBJ)/input.o \
$(EMUOBJ)/inputseq.o \

591
src/emu/hashfile.c Normal file
View File

@ -0,0 +1,591 @@
/*********************************************************************
hashfile.c
Code for parsing hash info (*.hsi) files
*********************************************************************/
#include "hashfile.h"
#include "pool.h"
#include "expat.h"
#include "emuopts.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
struct _hash_file
{
mame_file *file;
object_pool *pool;
unsigned int functions[IO_COUNT];
hash_info **preloaded_hashes;
int preloaded_hash_count;
void (*error_proc)(const char *message);
};
enum hash_parse_position
{
POS_ROOT,
POS_MAIN,
POS_HASH
};
struct hash_parse_state
{
XML_Parser parser;
hash_file *hashfile;
int done;
int (*selector_proc)(hash_file *hashfile, void *param, const char *name, const char *hash);
void (*use_proc)(hash_file *hashfile, void *param, hash_info *hi);
void (*error_proc)(const char *message);
void *param;
enum hash_parse_position pos;
char **text_dest;
hash_info *hi;
};
/***************************************************************************
PROTOTYPES
***************************************************************************/
static void *expat_malloc(size_t size);
static void *expat_realloc(void *ptr, size_t size);
static void expat_free(void *ptr);
/***************************************************************************
CORE IMPLEMENTATION
***************************************************************************/
/*-------------------------------------------------
parse_error
-------------------------------------------------*/
static void ATTR_PRINTF(2,3) parse_error(struct hash_parse_state *state, const char *fmt, ...)
{
char buf[256];
va_list va;
if (state->error_proc)
{
va_start(va, fmt);
vsnprintf(buf, ARRAY_LENGTH(buf), fmt, va);
va_end(va);
(*state->error_proc)(buf);
}
}
/*-------------------------------------------------
unknown_tag
-------------------------------------------------*/
static void unknown_tag(struct hash_parse_state *state, const char *tagname)
{
parse_error(state, "[%lu:%lu]: Unknown tag: %s\n",
XML_GetCurrentLineNumber(state->parser),
XML_GetCurrentColumnNumber(state->parser),
tagname);
}
/*-------------------------------------------------
unknown_attribute
-------------------------------------------------*/
static void unknown_attribute(struct hash_parse_state *state, const char *attrname)
{
parse_error(state, "[%lu:%lu]: Unknown attribute: %s\n",
XML_GetCurrentLineNumber(state->parser),
XML_GetCurrentColumnNumber(state->parser),
attrname);
}
/*-------------------------------------------------
unknown_attribute_value
-------------------------------------------------*/
static void unknown_attribute_value(struct hash_parse_state *state,
const char *attrname, const char *attrvalue)
{
parse_error(state, "[%lu:%lu]: Unknown attribute value: %s\n",
XML_GetCurrentLineNumber(state->parser),
XML_GetCurrentColumnNumber(state->parser),
attrvalue);
}
/*-------------------------------------------------
start_handler
-------------------------------------------------*/
static void start_handler(void *data, const char *tagname, const char **attributes)
{
struct hash_parse_state *state = (struct hash_parse_state *) data;
const char *name;
hash_info *hi;
char **text_dest;
char hash_string[HASH_BUF_SIZE];
unsigned int functions, all_functions;
iodevice_t device;
int i;
switch(state->pos)
{
case POS_ROOT:
if (!strcmp(tagname, "hashfile"))
{
}
else
{
unknown_tag(state, tagname);
}
break;
case POS_MAIN:
if (!strcmp(tagname, "hash"))
{
// we are now examining a hash tag
name = NULL;
memset(hash_string, 0, sizeof(hash_string));
all_functions = 0;
device = IO_COUNT;
while(attributes[0])
{
functions = 0;
if (!strcmp(attributes[0], "name"))
{
/* name attribute */
name = attributes[1];
}
else if (!strcmp(attributes[0], "crc32"))
{
/* crc32 attribute */
functions = HASH_CRC;
}
else if (!strcmp(attributes[0], "md5"))
{
/* md5 attribute */
functions = HASH_MD5;
}
else if (!strcmp(attributes[0], "sha1"))
{
/* sha1 attribute */
functions = HASH_SHA1;
}
else if (!strcmp(attributes[0], "type"))
{
/* type attribute */
i = 0;//device_typeid(attributes[1]);
if (i < 0)
unknown_attribute_value(state, attributes[0], attributes[1]);
else
device = (iodevice_t) i;
}
else
{
/* unknown attribute */
unknown_attribute(state, attributes[0]);
}
if (functions)
{
hash_data_insert_printable_checksum(hash_string, functions, attributes[1]);
all_functions |= functions;
}
attributes += 2;
}
if (device == IO_COUNT)
{
for (i = 0; i < IO_COUNT; i++)
state->hashfile->functions[i] |= all_functions;
}
else
state->hashfile->functions[device] |= all_functions;
/* do we use this hash? */
if (!state->selector_proc || state->selector_proc(state->hashfile, state->param, name, hash_string))
{
hi = (hash_info*)pool_malloc_lib(state->hashfile->pool, sizeof(hash_info));
if (!hi)
return;
memset(hi, 0, sizeof(*hi));
hi->longname = pool_strdup_lib(state->hashfile->pool, name);
if (!hi->longname)
return;
strcpy(hi->hash, hash_string);
state->hi = hi;
}
}
else
{
unknown_tag(state, tagname);
}
break;
case POS_HASH:
text_dest = NULL;
if (!strcmp(tagname, "year"))
text_dest = (char **) &state->hi->year;
else if (!strcmp(tagname, "manufacturer"))
text_dest = (char **) &state->hi->manufacturer;
else if (!strcmp(tagname, "status"))
text_dest = (char **) &state->hi->playable;
else if (!strcmp(tagname, "pcb"))
text_dest = (char **) &state->hi->pcb;
else if (!strcmp(tagname, "extrainfo"))
text_dest = (char **) &state->hi->extrainfo;
else
unknown_tag(state, tagname);
if (text_dest && state->hi)
state->text_dest = text_dest;
break;
}
state->pos = (hash_parse_position) (state->pos + 1);
}
/*-------------------------------------------------
end_handler
-------------------------------------------------*/
static void end_handler(void *data, const char *name)
{
struct hash_parse_state *state = (struct hash_parse_state *) data;
state->text_dest = NULL;
state->pos = (hash_parse_position) (state->pos - 1);
switch(state->pos)
{
case POS_ROOT:
case POS_HASH:
break;
case POS_MAIN:
if (state->hi)
{
if (state->use_proc)
(*state->use_proc)(state->hashfile, state->param, state->hi);
state->hi = NULL;
}
break;
}
}
/*-------------------------------------------------
data_handler
-------------------------------------------------*/
static void data_handler(void *data, const XML_Char *s, int len)
{
struct hash_parse_state *state = (struct hash_parse_state *) data;
int text_len;
char *text;
if (state->text_dest)
{
text = *state->text_dest;
text_len = text ? strlen(text) : 0;
text = (char*)pool_realloc_lib(state->hashfile->pool, text, text_len + len + 1);
if (!text)
return;
memcpy(&text[text_len], s, len);
text[text_len + len] = '\0';
*state->text_dest = text;
}
}
/*-------------------------------------------------
hashfile_parse
-------------------------------------------------*/
static void hashfile_parse(hash_file *hashfile,
int (*selector_proc)(hash_file *hashfile, void *param, const char *name, const char *hash),
void (*use_proc)(hash_file *hashfile, void *param, hash_info *hi),
void (*error_proc)(const char *message),
void *param)
{
struct hash_parse_state state;
char buf[1024];
UINT32 len;
XML_Memory_Handling_Suite memcallbacks;
mame_fseek(hashfile->file, 0, SEEK_SET);
memset(&state, 0, sizeof(state));
state.hashfile = hashfile;
state.selector_proc = selector_proc;
state.use_proc = use_proc;
state.error_proc = error_proc;
state.param = param;
/* create the XML parser */
memcallbacks.malloc_fcn = expat_malloc;
memcallbacks.realloc_fcn = expat_realloc;
memcallbacks.free_fcn = expat_free;
state.parser = XML_ParserCreate_MM(NULL, &memcallbacks, NULL);
if (!state.parser)
goto done;
XML_SetUserData(state.parser, &state);
XML_SetElementHandler(state.parser, start_handler, end_handler);
XML_SetCharacterDataHandler(state.parser, data_handler);
while(!state.done)
{
len = mame_fread(hashfile->file, buf, sizeof(buf));
state.done = mame_feof(hashfile->file);
if (XML_Parse(state.parser, buf, len, state.done) == XML_STATUS_ERROR)
{
parse_error(&state, "[%lu:%lu]: %s\n",
XML_GetCurrentLineNumber(state.parser),
XML_GetCurrentColumnNumber(state.parser),
XML_ErrorString(XML_GetErrorCode(state.parser)));
goto done;
}
}
done:
if (state.parser)
XML_ParserFree(state.parser);
}
/*-------------------------------------------------
preload_use_proc
-------------------------------------------------*/
static void preload_use_proc(hash_file *hashfile, void *param, hash_info *hi)
{
hash_info **new_preloaded_hashes;
new_preloaded_hashes = (hash_info **)pool_realloc_lib(hashfile->pool, hashfile->preloaded_hashes,
(hashfile->preloaded_hash_count + 1) * sizeof(*new_preloaded_hashes));
if (!new_preloaded_hashes)
return;
hashfile->preloaded_hashes = new_preloaded_hashes;
hashfile->preloaded_hashes[hashfile->preloaded_hash_count++] = hi;
}
/*-------------------------------------------------
hashfile_open_options
-------------------------------------------------*/
hash_file *hashfile_open_options(core_options *opts, const char *sysname, int is_preload,
void (*error_proc)(const char *message))
{
file_error filerr;
astring *fname;
hash_file *hashfile = NULL;
object_pool *pool = NULL;
/* create a pool for this hash file */
pool = pool_alloc_lib(error_proc);
if (!pool)
goto error;
/* allocate space for this hash file */
hashfile = (hash_file *) pool_malloc_lib(pool, sizeof(*hashfile));
if (!hashfile)
goto error;
/* set up the hashfile structure */
memset(hashfile, 0, sizeof(*hashfile));
hashfile->pool = pool;
hashfile->error_proc = error_proc;
/* open a file */
fname = astring_assemble_2(astring_alloc(), sysname, ".hsi");
filerr = mame_fopen_options(opts, SEARCHPATH_HASH, astring_c(fname), OPEN_FLAG_READ, &hashfile->file);
astring_free(fname);
if (filerr != FILERR_NONE)
goto error;
if (is_preload)
hashfile_parse(hashfile, NULL, preload_use_proc, hashfile->error_proc, NULL);
return hashfile;
error:
if (hashfile != NULL)
hashfile_close(hashfile);
return NULL;
}
/*-------------------------------------------------
hashfile_open
-------------------------------------------------*/
hash_file *hashfile_open(const char *sysname, int is_preload,
void (*error_proc)(const char *message))
{
return hashfile_open_options(mame_options(), sysname, is_preload, error_proc);
}
/*-------------------------------------------------
hashfile_close
-------------------------------------------------*/
void hashfile_close(hash_file *hashfile)
{
if (hashfile->file)
mame_fclose(hashfile->file);
pool_free_lib(hashfile->pool);
}
/*-------------------------------------------------
singular_selector_proc
-------------------------------------------------*/
struct hashlookup_params
{
const char *hash;
hash_info *hi;
};
static int singular_selector_proc(hash_file *hashfile, void *param, const char *name, const char *hash)
{
struct hashlookup_params *hlparams = (struct hashlookup_params *) param;
return hash_data_is_equal(hash, hlparams->hash,
hash_data_used_functions(hash)) == 1;
}
/*-------------------------------------------------
singular_use_proc
-------------------------------------------------*/
static void singular_use_proc(hash_file *hashfile, void *param, hash_info *hi)
{
struct hashlookup_params *hlparams = (struct hashlookup_params *) param;
hlparams->hi = hi;
}
/*-------------------------------------------------
hashfile_lookup
-------------------------------------------------*/
const hash_info *hashfile_lookup(hash_file *hashfile, const char *hash)
{
struct hashlookup_params param;
int i;
param.hash = hash;
param.hi = NULL;
for (i = 0; i < hashfile->preloaded_hash_count; i++)
{
if (singular_selector_proc(hashfile, &param, NULL, hashfile->preloaded_hashes[i]->hash))
return hashfile->preloaded_hashes[i];
}
hashfile_parse(hashfile, singular_selector_proc, singular_use_proc,
hashfile->error_proc, (void *) &param);
return param.hi;
}
/*-------------------------------------------------
hashfile_functions_used
-------------------------------------------------*/
unsigned int hashfile_functions_used(hash_file *hashfile, iodevice_t devtype)
{
assert(devtype >= 0);
assert(devtype < IO_COUNT);
return hashfile->functions[devtype];
}
/*-------------------------------------------------
hashfile_verify
-------------------------------------------------*/
int hashfile_verify(const char *sysname, void (*my_error_proc)(const char *message))
{
hash_file *hashfile;
hashfile = hashfile_open(sysname, FALSE, my_error_proc);
if (!hashfile)
return -1;
hashfile_parse(hashfile, NULL, NULL, my_error_proc, NULL);
hashfile_close(hashfile);
return 0;
}
/***************************************************************************
EXPAT INTERFACES
***************************************************************************/
/*-------------------------------------------------
expat_malloc/expat_realloc/expat_free -
wrappers for memory allocation functions so
that they pass through out memory tracking
systems
-------------------------------------------------*/
static void *expat_malloc(size_t size)
{
return global_alloc_array_clear(UINT8,size);
}
static void *expat_realloc(void *ptr, size_t size)
{
if (ptr) global_free(ptr);
return global_alloc_array_clear(UINT8,size);
}
static void expat_free(void *ptr)
{
global_free(ptr);
}

62
src/emu/hashfile.h Normal file
View File

@ -0,0 +1,62 @@
/*********************************************************************
hashfile.h
Code for parsing hash info (*.hsi) files
*********************************************************************/
#ifndef __HASHFILE_H__
#define __HASHFILE_H__
#include "emu.h"
#include "hash.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
typedef struct _hash_info hash_info;
struct _hash_info
{
char hash[HASH_BUF_SIZE];
const char *longname;
const char *manufacturer;
const char *year;
const char *playable;
const char *pcb;
const char *extrainfo;
};
typedef struct _hash_file hash_file;
typedef void (*hashfile_error_func)(const char *message);
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
/* opens a hash file; if is_preload is non-zero, the entire file is preloaded */
hash_file *hashfile_open(const char *sysname, int is_preload, hashfile_error_func error_proc);
/* opens a hash file; if is_preload is non-zero, the entire file is preloaded */
hash_file *hashfile_open_options(core_options *opts, const char *sysname, int is_preload,
hashfile_error_func error_proc);
/* closes a hash file and associated resources */
void hashfile_close(hash_file *hashfile);
/* looks up information in a hash file */
const hash_info *hashfile_lookup(hash_file *hashfile, const char *hash);
/* performs a syntax check on a hash file */
int hashfile_verify(const char *sysname, void (*error_proc)(const char *message));
/* returns the functions used in this hash file */
unsigned int hashfile_functions_used(hash_file *hashfile, iodevice_t devtype);
#endif /* __HASHFILE_H__ */