diff --git a/src/emu/devcb.c b/src/emu/devcb.c index 5907abc7a3f..d603156dfff 100644 --- a/src/emu/devcb.c +++ b/src/emu/devcb.c @@ -361,3 +361,162 @@ void devcb_resolve_write8(devcb_resolved_write8 *resolved, const devcb_write8 *c } } } + + +/*------------------------------------------------- + devcb_resolve_read16 - convert a static + 16-bit read definition to a live definition +-------------------------------------------------*/ + +static READ16_DEVICE_HANDLER( trampoline_read_port_to_read16 ) +{ + return input_port_read_direct((const input_port_config *)device); +} + +static READ16_DEVICE_HANDLER( trampoline_read_line_to_read16 ) +{ + const devcb_resolved_read16 *resolved = (const devcb_resolved_read16 *)device; + return (*resolved->real.readline)((device_t *)resolved->realtarget); +} + +void devcb_resolve_read16(devcb_resolved_read16 *resolved, const devcb_read16 *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_read16: unable to find input port '%s' (requested by %s '%s')", config->tag, device->name(), device->tag()); + resolved->read = trampoline_read_port_to_read16; + } + + /* address space handlers */ + else if (config->type >= DEVCB_TYPE_MEMORY(AS_PROGRAM) && config->type < DEVCB_TYPE_MEMORY(ADDRESS_SPACES) && config->readspace != NULL) + { + FPTR spacenum = (FPTR)config->type - (FPTR)DEVCB_TYPE_MEMORY(AS_PROGRAM); + + device_t *targetdev = device->siblingdevice(config->tag); + if (targetdev == NULL) + fatalerror("devcb_resolve_read16: 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_read16: device '%s' (requested by %s '%s') has no memory", config->tag, device->name(), device->tag()); + + resolved->target = targetdev->memory().space(spacenum); + if (resolved->target == NULL) + fatalerror("devcb_resolve_read16: unable to find device '%s' space %d (requested by %s '%s')", config->tag, (int)spacenum, device->name(), device->tag()); + resolved->read = (read16_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_read16: unable to find device '%s' (requested by %s '%s')", config->tag, device->name(), device->tag()); + + /* read16 to read16 is direct */ + if (config->readdevice != NULL) + resolved->read = config->readdevice; + + /* read16 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_read16; + } + } +} + + +/*------------------------------------------------- + devcb_resolve_write16 - convert a static + 16-bit write definition to a live definition +-------------------------------------------------*/ + +static WRITE16_DEVICE_HANDLER( trampoline_write_port_to_write16 ) +{ + input_port_write_direct((const input_port_config *)device, data, 0xff); +} + +static WRITE16_DEVICE_HANDLER( trampoline_write_line_to_write16 ) +{ + const devcb_resolved_write16 *resolved = (const devcb_resolved_write16 *)device; + (*resolved->real.writeline)((device_t *)resolved->realtarget, (data & 1) ? ASSERT_LINE : CLEAR_LINE); +} + +void devcb_resolve_write16(devcb_resolved_write16 *resolved, const devcb_write16 *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_write16; + } + + /* address space handlers */ + else if (config->type >= DEVCB_TYPE_MEMORY(AS_PROGRAM) && config->type < DEVCB_TYPE_MEMORY(ADDRESS_SPACES) && config->writespace != NULL) + { + FPTR spacenum = (FPTR)config->type - (FPTR)DEVCB_TYPE_MEMORY(AS_PROGRAM); + + device_t *targetdev = device->siblingdevice(config->tag); + if (targetdev == NULL) + fatalerror("devcb_resolve_write16: 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_write16: device '%s' (requested by %s '%s') has no memory", config->tag, device->name(), device->tag()); + + resolved->target = targetdev->memory().space(spacenum); + if (resolved->target == NULL) + fatalerror("devcb_resolve_write16: unable to find device '%s' space %d (requested by %s '%s')", config->tag, (int)spacenum, device->name(), device->tag()); + resolved->write = (write16_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_write16: unable to find device '%s' (requested by %s '%s')", config->tag, device->name(), device->tag()); + + /* write16 to write16 is direct */ + if (config->writedevice != NULL) + resolved->write = config->writedevice; + + /* write16 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_write16; + } + } +} diff --git a/src/emu/devcb.h b/src/emu/devcb.h index 6641c2fdaf1..2fb37a3c1fa 100644 --- a/src/emu/devcb.h +++ b/src/emu/devcb.h @@ -20,6 +20,8 @@ write_line_device_func: (device, data) read8_device_func: (device, offset) write8_device_func: (device, offset, data) + read16_device_func: (device, offset) + write16_device_func: (device, offset, data) The adapted callback types supported are: @@ -31,6 +33,10 @@ write8_device_func: (device, offset, data) read8_space_func: (space, offset) write8_space_func: (space, offset, data) + read16_device_func: (device, offset) + write16_device_func: (device, offset, data) + read16_space_func: (space, offset) + write16_space_func: (space, offset, data) ***************************************************************************/ @@ -78,6 +84,14 @@ UINT8 devcb_stub(device_t *device, offs_t offset) return (target->*_Function)(*memory_nonspecific_space(device->machine()), offset, 0xff); } +// static template for a read16 stub function that calls through a given READ16_MEMBER +template +UINT16 devcb_stub(device_t *device, offs_t offset) +{ + _Class *target = downcast<_Class *>(device); + return (target->*_Function)(*memory_nonspecific_space(device->machine()), offset, 0xffff); +} + // static template for a write_line stub function that calls through a given WRITE_LINE_MEMBER template void devcb_line_stub(device_t *device, int state) @@ -94,6 +108,14 @@ void devcb_stub(device_t *device, offs_t offset, UINT8 data) (target->*_Function)(*memory_nonspecific_space(device->machine()), offset, data, 0xff); } +// static template for a write16 stub function that calls through a given WRITE16_MEMBER +template +void devcb_stub(device_t *device, offs_t offset, UINT16 data) +{ + _Class *target = downcast<_Class *>(device); + (target->*_Function)(*memory_nonspecific_space(device->machine()), offset, data, 0xffff); +} + #define DEVCB_NULL { DEVCB_TYPE_NULL } /* standard line or read/write handlers with the calling device passed */ @@ -261,6 +283,57 @@ struct _devcb_resolved_write8 }; +/* static structure used for device configuration when the desired callback type is a read16_device_func */ +typedef struct _devcb_read16 devcb_read16; +struct _devcb_read16 +{ + UINT32 type; /* one of the special DEVCB_TYPE values */ + const char * tag; /* tag of target, where appropriate */ + read_line_device_func readline; /* read line function */ + read16_device_func readdevice; /* read device function */ + read16_space_func readspace; /* read space function */ +}; + +typedef struct _devcb_resolved_read16 devcb_resolved_read16; +struct _devcb_resolved_read16 +{ + const void * target; /* target object */ + read16_device_func read; /* read function */ + const void * realtarget; /* real target object for stubs */ + union + { + read16_device_func readdevice; + read16_space_func readspace; + read_line_device_func readline; + } real; /* real read function for stubs */ +}; + + +/* static structure used for device configuration when the desired callback type is a write16_device_func */ +typedef struct _devcb_write16 devcb_write16; +struct _devcb_write16 +{ + UINT32 type; /* one of the special DEVCB_TYPE values */ + const char * tag; /* tag of target, where appropriate */ + write_line_device_func writeline; /* write line function */ + write16_device_func writedevice; /* write device function */ + write16_space_func writespace; /* write space function */ +}; + +typedef struct _devcb_resolved_write16 devcb_resolved_write16; +struct _devcb_resolved_write16 +{ + const void * target; /* target object */ + write16_device_func write; /* write function */ + const void * realtarget; /* real target object for stubs */ + union + { + write16_device_func writedevice; + write16_space_func writespace; + write_line_device_func writeline; + } real; /* real write function for stubs */ +}; + /*************************************************************************** FUNCTION PROTOTYPES @@ -281,6 +354,12 @@ void devcb_resolve_read8(devcb_resolved_read8 *resolved, const devcb_read8 *conf /* convert a static 8-bit write definition to a live definition */ void devcb_resolve_write8(devcb_resolved_write8 *resolved, const devcb_write8 *config, device_t *device); +/* convert a static 16-bit read definition to a live definition */ +void devcb_resolve_read16(devcb_resolved_read16 *resolved, const devcb_read16 *config, device_t *device); + +/* convert a static 16-bit write definition to a live definition */ +void devcb_resolve_write16(devcb_resolved_write16 *resolved, const devcb_write16 *config, device_t *device); + /*************************************************************************** @@ -309,6 +388,17 @@ INLINE int devcb_call_read8(const devcb_resolved_read8 *resolved, offs_t offset) } +/*------------------------------------------------- + devcb_call_read16 - call through a + resolved read16 handler +-------------------------------------------------*/ + +INLINE int devcb_call_read16(const devcb_resolved_read16 *resolved, offs_t offset) +{ + return (resolved->read != NULL) ? (*resolved->read)((device_t *)resolved->target, offset, 0xffff) : 0; +} + + /*------------------------------------------------- devcb_call_write_line - call through a resolved write_line handler @@ -332,6 +422,19 @@ INLINE void devcb_call_write8(const devcb_resolved_write8 *resolved, offs_t offs (*resolved->write)((device_t *)resolved->target, offset, data); } + +/*------------------------------------------------- + devcb_call_write16 - call through a + resolved write16 handler +-------------------------------------------------*/ + +INLINE void devcb_call_write16(const devcb_resolved_write16 *resolved, offs_t offset, UINT16 data) +{ + if (resolved->write != NULL) + (*resolved->write)((device_t *)resolved->target, offset, data, 0xffff); +} + + /*------------------------------------------------- devcb_line_gnd_r - input tied to GND -------------------------------------------------*/ @@ -341,6 +444,7 @@ INLINE READ_LINE_DEVICE_HANDLER( devcb_line_gnd_r ) return 0; } + /*------------------------------------------------- devcb_line_vcc_r - input tied to Vcc -------------------------------------------------*/