mame/src/emu/devcb.c
2011-03-25 16:14:09 +00:00

364 lines
14 KiB
C

/***************************************************************************
devcb.c
Device callback interface helpers.
Copyright Nicola Salmoria and the MAME Team.
Visit http://mamedev.org for licensing and usage restrictions.
***************************************************************************/
#include "emu.h"
/***************************************************************************
STATIC-TO-LIVE CONVERSION
***************************************************************************/
/*-------------------------------------------------
devcb_resolve_read_line - convert a static
read line definition to a live definition
-------------------------------------------------*/
static READ_LINE_DEVICE_HANDLER( trampoline_read_port_to_read_line )
{
return (input_port_read_direct((const input_port_config *)device) & 1) ? ASSERT_LINE : CLEAR_LINE;
}
static READ_LINE_DEVICE_HANDLER( trampoline_read8_to_read_line )
{
const devcb_resolved_read_line *resolved = (const devcb_resolved_read_line *)device;
return ((*resolved->real.readdevice)((device_t *)resolved->realtarget, 0) & 1) ? ASSERT_LINE : CLEAR_LINE;
}
void devcb_resolve_read_line(devcb_resolved_read_line *resolved, const devcb_read_line *config, device_t *device)
{
/* reset the resolved structure */
memset(resolved, 0, sizeof(*resolved));
/* input port handlers */
if (config->type == DEVCB_TYPE_INPUT)
{
resolved->target = device->machine->port(config->tag);
if (resolved->target == NULL)
fatalerror("devcb_resolve_read_line: unable to find input port '%s' (requested by %s '%s')", config->tag, device->name(), device->tag());
resolved->read = trampoline_read_port_to_read_line;
}
/* address space handlers */
else if (config->type >= DEVCB_TYPE_MEMORY(ADDRESS_SPACE_PROGRAM) && config->type < DEVCB_TYPE_MEMORY(ADDRESS_SPACES) && config->readspace != NULL)
{
FPTR spacenum = (FPTR)config->type - (FPTR)DEVCB_TYPE_MEMORY(ADDRESS_SPACE_PROGRAM);
device_t *targetdev = device->siblingdevice(config->tag);
if (targetdev == NULL)
fatalerror("devcb_resolve_read_line: unable to find device '%s' (requested by %s '%s')", config->tag, device->name(), device->tag());
device_memory_interface *memory;
if (!targetdev->interface(memory))
fatalerror("devcb_resolve_read_line: device '%s' (requested by %s '%s') has no memory", config->tag, device->name(), device->tag());
resolved->target = resolved;
resolved->read = trampoline_read8_to_read_line;
resolved->realtarget = device_get_space(targetdev, spacenum);
if (resolved->realtarget == NULL)
fatalerror("devcb_resolve_read_line: unable to find device '%s' space %d (requested by %s '%s')", config->tag, (int)spacenum, device->name(), device->tag());
resolved->real.readspace = config->readspace;
}
/* device handlers */
else if ((config->type == DEVCB_TYPE_DEVICE || config->type == DEVCB_TYPE_SELF || config->type == DEVCB_TYPE_DRIVER) && (config->readline != NULL || config->readdevice != NULL))
{
/* locate the device */
if (config->type == DEVCB_TYPE_SELF)
resolved->target = device;
else if (config->type == DEVCB_TYPE_DRIVER)
resolved->target = device->machine->driver_data();
else
if (strcmp(config->tag, DEVICE_SELF_OWNER) == 0)
resolved->target = device->owner();
else
resolved->target = device->siblingdevice(config->tag);
if (resolved->target == NULL)
fatalerror("devcb_resolve_read_line: unable to find device '%s' (requested by %s '%s')", config->tag, device->name(), device->tag());
/* read_line to read_line is direct */
if (config->readline != NULL)
resolved->read = config->readline;
/* read_line to handler goes through a trampoline */
else
{
resolved->realtarget = resolved->target;
resolved->real.readdevice = config->readdevice;
resolved->target = resolved;
resolved->read = trampoline_read8_to_read_line;
}
}
}
/*-------------------------------------------------
devcb_resolve_write_line - convert a static
write line definition to a live definition
-------------------------------------------------*/
static WRITE_LINE_DEVICE_HANDLER( trampoline_write_port_to_write_line )
{
input_port_write_direct((const input_port_config *)device, state, 0xffffffff);
}
static WRITE_LINE_DEVICE_HANDLER( trampoline_write8_to_write_line )
{
const devcb_resolved_write_line *resolved = (const devcb_resolved_write_line *)device;
(*resolved->real.writedevice)((device_t *)resolved->realtarget, 0, state);
}
static WRITE_LINE_DEVICE_HANDLER( trampoline_writecpu_to_write_line )
{
const devcb_resolved_write_line *resolved = (const devcb_resolved_write_line *)device;
device_t *targetdev = (device_t *)resolved->realtarget;
cpu_set_input_line(targetdev, resolved->real.writeline, state ? ASSERT_LINE : CLEAR_LINE);
}
void devcb_resolve_write_line(devcb_resolved_write_line *resolved, const devcb_write_line *config, device_t *device)
{
/* reset the resolved structure */
memset(resolved, 0, sizeof(*resolved));
if (config->type == DEVCB_TYPE_INPUT)
{
resolved->target = device->machine->port(config->tag);
if (resolved->target == NULL)
fatalerror("devcb_resolve_write_line: unable to find input port '%s' (requested by %s '%s')", config->tag, device->name(), device->tag());
resolved->write = trampoline_write_port_to_write_line;
}
/* address space handlers */
else if (config->type >= DEVCB_TYPE_MEMORY(ADDRESS_SPACE_PROGRAM) && config->type < DEVCB_TYPE_MEMORY(ADDRESS_SPACES) && config->writespace != NULL)
{
FPTR spacenum = (FPTR)config->type - (FPTR)DEVCB_TYPE_MEMORY(ADDRESS_SPACE_PROGRAM);
device_t *targetdev = device->siblingdevice(config->tag);
if (targetdev == NULL)
fatalerror("devcb_resolve_write_line: unable to find device '%s' (requested by %s '%s')", config->tag, device->name(), device->tag());
device_memory_interface *memory;
if (!targetdev->interface(memory))
fatalerror("devcb_resolve_write_line: device '%s' (requested by %s '%s') has no memory", config->tag, device->name(), device->tag());
resolved->target = resolved;
resolved->write = trampoline_write8_to_write_line;
resolved->realtarget = device_get_space(targetdev, spacenum);
if (resolved->realtarget == NULL)
fatalerror("devcb_resolve_write_line: unable to find device '%s' space %d (requested by %s '%s')", config->tag, (int)spacenum, device->name(), device->tag());
resolved->real.writespace = config->writespace;
}
/* cpu line handlers */
else if (config->type >= DEVCB_TYPE_CPU_LINE(0) && config->type < DEVCB_TYPE_CPU_LINE(MAX_INPUT_LINES))
{
FPTR line = (FPTR)config->type - (FPTR)DEVCB_TYPE_CPU_LINE(0);
device_t *targetdev = device->siblingdevice(config->tag);
if (targetdev == NULL)
fatalerror("devcb_resolve_write_line: unable to find device '%s' (requested by %s '%s')", config->tag, device->name(), device->tag());
resolved->target = resolved;
resolved->write = trampoline_writecpu_to_write_line;
resolved->realtarget = targetdev;
resolved->real.writeline = (int) line;
}
/* device handlers */
else if ((config->type == DEVCB_TYPE_DEVICE || config->type == DEVCB_TYPE_SELF || config->type == DEVCB_TYPE_DRIVER) && (config->writeline != NULL || config->writedevice != NULL))
{
/* locate the device */
if (config->type == DEVCB_TYPE_SELF)
resolved->target = device;
else if (config->type == DEVCB_TYPE_DRIVER)
resolved->target = device->machine->driver_data();
else
if (strcmp(config->tag, DEVICE_SELF_OWNER) == 0)
resolved->target = device->owner();
else
resolved->target = device->siblingdevice(config->tag);
if (resolved->target == NULL)
fatalerror("devcb_resolve_write_line: unable to find device '%s' (requested by %s '%s')", config->tag, device->name(), device->tag());
/* write_line to write_line is direct */
if (config->writeline != NULL)
resolved->write = config->writeline;
/* write_line to handler goes through a trampoline */
else
{
resolved->realtarget = resolved->target;
resolved->real.writedevice = config->writedevice;
resolved->target = resolved;
resolved->write = trampoline_write8_to_write_line;
}
}
}
/*-------------------------------------------------
devcb_resolve_read8 - convert a static
8-bit read definition to a live definition
-------------------------------------------------*/
static READ8_DEVICE_HANDLER( trampoline_read_port_to_read8 )
{
return input_port_read_direct((const input_port_config *)device);
}
static READ8_DEVICE_HANDLER( trampoline_read_line_to_read8 )
{
const devcb_resolved_read8 *resolved = (const devcb_resolved_read8 *)device;
return (*resolved->real.readline)((device_t *)resolved->realtarget);
}
void devcb_resolve_read8(devcb_resolved_read8 *resolved, const devcb_read8 *config, device_t *device)
{
/* reset the resolved structure */
memset(resolved, 0, sizeof(*resolved));
/* input port handlers */
if (config->type == DEVCB_TYPE_INPUT)
{
resolved->target = device->machine->port(config->tag);
if (resolved->target == NULL)
fatalerror("devcb_resolve_read8: unable to find input port '%s' (requested by %s '%s')", config->tag, device->name(), device->tag());
resolved->read = trampoline_read_port_to_read8;
}
/* address space handlers */
else if (config->type >= DEVCB_TYPE_MEMORY(ADDRESS_SPACE_PROGRAM) && config->type < DEVCB_TYPE_MEMORY(ADDRESS_SPACES) && config->readspace != NULL)
{
FPTR spacenum = (FPTR)config->type - (FPTR)DEVCB_TYPE_MEMORY(ADDRESS_SPACE_PROGRAM);
device_t *targetdev = device->siblingdevice(config->tag);
if (targetdev == NULL)
fatalerror("devcb_resolve_read8: unable to find device '%s' (requested by %s '%s')", config->tag, device->name(), device->tag());
device_memory_interface *memory;
if (!targetdev->interface(memory))
fatalerror("devcb_resolve_read8: device '%s' (requested by %s '%s') has no memory", config->tag, device->name(), device->tag());
resolved->target = device_get_space(targetdev, spacenum);
if (resolved->target == NULL)
fatalerror("devcb_resolve_read8: unable to find device '%s' space %d (requested by %s '%s')", config->tag, (int)spacenum, device->name(), device->tag());
resolved->read = (read8_device_func)config->readspace;
}
/* device handlers */
else if ((config->type == DEVCB_TYPE_DEVICE || config->type == DEVCB_TYPE_SELF || config->type == DEVCB_TYPE_DRIVER) && (config->readline != NULL || config->readdevice != NULL))
{
if (config->type == DEVCB_TYPE_SELF)
resolved->target = device;
else if (config->type == DEVCB_TYPE_DRIVER)
resolved->target = device->machine->driver_data();
else
if (strcmp(config->tag, DEVICE_SELF_OWNER) == 0)
resolved->target = device->owner();
else
resolved->target = device->siblingdevice(config->tag);
if (resolved->target == NULL)
fatalerror("devcb_resolve_read8: unable to find device '%s' (requested by %s '%s')", config->tag, device->name(), device->tag());
/* read8 to read8 is direct */
if (config->readdevice != NULL)
resolved->read = config->readdevice;
/* read8 to read_line goes through a trampoline */
else
{
resolved->realtarget = resolved->target;
resolved->real.readline = config->readline;
resolved->target = resolved;
resolved->read = trampoline_read_line_to_read8;
}
}
}
/*-------------------------------------------------
devcb_resolve_write8 - convert a static
8-bit write definition to a live definition
-------------------------------------------------*/
static WRITE8_DEVICE_HANDLER( trampoline_write_port_to_write8 )
{
input_port_write_direct((const input_port_config *)device, data, 0xff);
}
static WRITE8_DEVICE_HANDLER( trampoline_write_line_to_write8 )
{
const devcb_resolved_write8 *resolved = (const devcb_resolved_write8 *)device;
(*resolved->real.writeline)((device_t *)resolved->realtarget, (data & 1) ? ASSERT_LINE : CLEAR_LINE);
}
void devcb_resolve_write8(devcb_resolved_write8 *resolved, const devcb_write8 *config, device_t *device)
{
/* reset the resolved structure */
memset(resolved, 0, sizeof(*resolved));
if (config->type == DEVCB_TYPE_INPUT)
{
resolved->target = device->machine->port(config->tag);
if (resolved->target == NULL)
fatalerror("devcb_resolve_read_line: unable to find input port '%s' (requested by %s '%s')", config->tag, device->name(), device->tag());
resolved->write = trampoline_write_port_to_write8;
}
/* address space handlers */
else if (config->type >= DEVCB_TYPE_MEMORY(ADDRESS_SPACE_PROGRAM) && config->type < DEVCB_TYPE_MEMORY(ADDRESS_SPACES) && config->writespace != NULL)
{
FPTR spacenum = (FPTR)config->type - (FPTR)DEVCB_TYPE_MEMORY(ADDRESS_SPACE_PROGRAM);
device_t *targetdev = device->siblingdevice(config->tag);
if (targetdev == NULL)
fatalerror("devcb_resolve_write8: unable to find device '%s' (requested by %s '%s')", config->tag, device->name(), device->tag());
device_memory_interface *memory;
if (!targetdev->interface(memory))
fatalerror("devcb_resolve_write8: device '%s' (requested by %s '%s') has no memory", config->tag, device->name(), device->tag());
resolved->target = device_get_space(targetdev, spacenum);
if (resolved->target == NULL)
fatalerror("devcb_resolve_write8: unable to find device '%s' space %d (requested by %s '%s')", config->tag, (int)spacenum, device->name(), device->tag());
resolved->write = (write8_device_func)config->writespace;
}
/* device handlers */
else if ((config->type == DEVCB_TYPE_DEVICE || config->type == DEVCB_TYPE_SELF || config->type == DEVCB_TYPE_DRIVER) && (config->writeline != NULL || config->writedevice != NULL))
{
if (config->type == DEVCB_TYPE_SELF)
resolved->target = device;
else if (config->type == DEVCB_TYPE_DRIVER)
resolved->target = device->machine->driver_data();
else
if (strcmp(config->tag, DEVICE_SELF_OWNER) == 0)
resolved->target = device->owner();
else
resolved->target = device->siblingdevice(config->tag);
if (resolved->target == NULL)
fatalerror("devcb_resolve_write8: unable to find device '%s' (requested by %s '%s')", config->tag, device->name(), device->tag());
/* write8 to write8 is direct */
if (config->writedevice != NULL)
resolved->write = config->writedevice;
/* write8 to write_line goes through a trampoline */
else
{
resolved->realtarget = resolved->target;
resolved->real.writeline = config->writeline;
resolved->target = resolved;
resolved->write = trampoline_write_line_to_write8;
}
}
}