mame/src/emu/driver.c
Aaron Giles 3accee936b New module: devintrf.c/.h. Implements a generic device interface similar
to the sound and CPU interfaces. This is still a bit WIP, but works at
a fundamental level. Currently the only example of usage is in qix.c for
the MC6845 CRTC.

New module: mconfig.c/.h. Moved all machine_config and MDRV_* macros here, 
out of driver.c/.h. Added MDRV macros for adding/removing/configuring
devices.

qix.c: Moved video part of machine driver to video/qix.c. Added MC6845
as a device in the machine driver. Removed explicit MC6845 initialization
from VIDEO_START in favor of simply retrieving the token from the device
interface code.

mc6845.c: Updated all callbacks to pass the mc6845_t * object. Updated
all drivers accordingly. Added a minimal device interface.

Deprecated the following constants because global constants that pretend
to document things but which are only guesses are dumb:

  - DEFAULT_60HZ_VBLANK_DURATION
  - DEFAULT_30HZ_VBLANK_DURATION
  - DEFAULT_REAL_60HZ_VBLANK_DURATION
  - DEFAULT_REAL_30HZ_VBLANK_DURATION
  - DEFAULT_60HZ_3S_VBLANK_WATCHDOG
  - DEFAULT_30HZ_3S_VBLANK_WATCHDOG

Updated all drivers to explicitly specify the equivalent bogus times.
Added comments for the "REAL" VBLANK durations to indicate that they are
not accurate.
2008-02-19 08:49:59 +00:00

247 lines
6.3 KiB
C

/***************************************************************************
driver.c
Driver construction helpers.
Copyright Nicola Salmoria and the MAME Team.
Visit http://mamedev.org for licensing and usage restrictions.
***************************************************************************/
#include "driver.h"
#include <ctype.h>
/***************************************************************************
CONSTANTS
***************************************************************************/
#define DRIVER_LRU_SIZE 10
/***************************************************************************
GLOBAL VARIABLES
***************************************************************************/
static int driver_lru[DRIVER_LRU_SIZE];
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
static int penalty_compare(const char *source, const char *target);
/***************************************************************************
MISC FUNCTIONS
***************************************************************************/
/*-------------------------------------------------
driver_get_name - return a pointer to a
driver given its name
-------------------------------------------------*/
const game_driver *driver_get_name(const char *name)
{
int lurnum, drvnum;
/* scan the LRU list first */
for (lurnum = 0; lurnum < DRIVER_LRU_SIZE; lurnum++)
if (mame_stricmp(drivers[driver_lru[lurnum]]->name, name) == 0)
{
/* if not first, swap with the head */
if (lurnum != 0)
{
int temp = driver_lru[0];
driver_lru[0] = driver_lru[lurnum];
driver_lru[lurnum] = temp;
}
return drivers[driver_lru[0]];
}
/* scan for a match in the drivers -- slow! */
for (drvnum = 0; drivers[drvnum] != NULL; drvnum++)
if (mame_stricmp(drivers[drvnum]->name, name) == 0)
{
memmove((void *)&driver_lru[1], (void *)&driver_lru[0], sizeof(driver_lru[0]) * (DRIVER_LRU_SIZE - 1));
driver_lru[0] = drvnum;
return drivers[drvnum];
}
return NULL;
}
/*-------------------------------------------------
driver_get_clone - return a pointer to the
clone of a game driver.
-------------------------------------------------*/
const game_driver *driver_get_clone(const game_driver *driver)
{
/* if no clone, easy out */
if (driver->parent == NULL || (driver->parent[0] == '0' && driver->parent[1] == 0))
return NULL;
/* convert the name to a game_driver */
return driver_get_name(driver->parent);
}
/*-------------------------------------------------
driver_list_get_approx_matches - find the best
n matches to a driver name.
-------------------------------------------------*/
void driver_list_get_approx_matches(const game_driver * const driverlist[], const char *name, int matches, const game_driver **list)
{
#undef rand
int matchnum, drvnum;
int *penalty;
/* if no name, pick random entries */
if (name == NULL || name[0] == 0)
{
const game_driver **templist;
int driver_count;
int shufnum;
/* allocate a temporary list */
templist = malloc_or_die(driver_list_get_count(driverlist) * sizeof(*templist));
/* build up a list of valid entries */
for (drvnum = driver_count = 0; driverlist[drvnum] != NULL; drvnum++)
if ((driverlist[drvnum]->flags & GAME_NO_STANDALONE) == 0)
templist[driver_count++] = driverlist[drvnum];
/* seed the RNG first */
srand(osd_ticks());
/* shuffle */
for (shufnum = 0; shufnum < 4 * driver_count; shufnum++)
{
int item1 = rand() % driver_count;
int item2 = rand() % driver_count;
const game_driver *temp;
temp = templist[item1];
templist[item1] = templist[item2];
templist[item2] = temp;
}
/* copy out the first few entries */
for (matchnum = 0; matchnum < matches; matchnum++)
list[matchnum] = templist[matchnum % driver_count];
free((void *)templist);
return;
}
/* allocate some temp memory */
penalty = malloc_or_die(matches * sizeof(*penalty));
/* initialize everyone's states */
for (matchnum = 0; matchnum < matches; matchnum++)
{
penalty[matchnum] = 9999;
list[matchnum] = NULL;
}
/* scan the entire drivers array */
for (drvnum = 0; driverlist[drvnum] != NULL; drvnum++)
{
int curpenalty, tmp;
/* skip things that can't run */
if ((driverlist[drvnum]->flags & GAME_NO_STANDALONE) != 0)
continue;
/* pick the best match between driver name and description */
curpenalty = penalty_compare(name, driverlist[drvnum]->description);
tmp = penalty_compare(name, driverlist[drvnum]->name);
curpenalty = MIN(curpenalty, tmp);
/* insert into the sorted table of matches */
for (matchnum = matches - 1; matchnum >= 0; matchnum--)
{
/* stop if we're worse than the current entry */
if (curpenalty >= penalty[matchnum])
break;
/* as lng as this isn't the last entry, bump this one down */
if (matchnum < matches - 1)
{
penalty[matchnum + 1] = penalty[matchnum];
list[matchnum + 1] = list[matchnum];
}
list[matchnum] = driverlist[drvnum];
penalty[matchnum] = curpenalty;
}
}
/* free our temp memory */
free(penalty);
}
/*-------------------------------------------------
penalty_compare - compare two strings for
closeness and assign a score.
-------------------------------------------------*/
static int penalty_compare(const char *source, const char *target)
{
int gaps = 1;
int last = TRUE;
/* scan the strings */
for ( ; *source && *target; target++)
{
/* do a case insensitive match */
int match = (tolower(*source) == tolower(*target));
/* if we matched, advance the source */
if (match)
source++;
/* if the match state changed, count gaps */
if (match != last)
{
last = match;
if (!match)
gaps++;
}
}
/* penalty if short string does not completely fit in */
for ( ; *source; source++)
gaps++;
/* if we matched perfectly, gaps == 0 */
if (gaps == 1 && *source == 0 && *target == 0)
gaps = 0;
return gaps;
}
/*-------------------------------------------------
driver_list_get_count - returns the amount of
drivers
-------------------------------------------------*/
int driver_list_get_count(const game_driver * const driverlist[])
{
int count;
for (count = 0; driverlist[count] != NULL; count++) ;
return count;
}