Previous 15994 Revisions Next

r6451 Wednesday 25th November, 2009 at 08:17:36 UTC by Curt Coder
Imported AM_WRITE_PORT support from MAME.
[src/emu]inptport.c inptport.h memory.c memory.h validity.c

src/emu/memory.c
r6450r6451
368368static UINT32 input_port_read32(const input_port_config *port, offs_t offset, UINT32 mem_mask);
369369static UINT64 input_port_read64(const input_port_config *port, offs_t offset, UINT64 mem_mask);
370370
371/* output port handlers */
372static void input_port_write8(const input_port_config *port, offs_t offset, UINT8 data);
373static void input_port_write16(const input_port_config *port, offs_t offset, UINT16 data, UINT16 mem_mask);
374static void input_port_write32(const input_port_config *port, offs_t offset, UINT32 data, UINT32 mem_mask);
375static void input_port_write64(const input_port_config *port, offs_t offset, UINT64 data, UINT64 mem_mask);
371376
372377
378
373379/***************************************************************************
374380    INLINE FUNCTIONS
375381***************************************************************************/
r6450r6451
13721378
13731379
13741380
1381/*-------------------------------------------------
1382    memory_install_write_port_handler - install a
1383    new 8-bit input port handler into the given
1384    address space
1385-------------------------------------------------*/
1386
1387void memory_install_write_port_handler(const address_space *space, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, const char *tag)
1388{
1389   const input_port_config *port = input_port_by_tag(space->machine->portconfig, tag);
1390   address_space *spacerw = (address_space *)space;
1391   genf *handler = NULL;
1392
1393   if (port == NULL)
1394      fatalerror("Non-existent port referenced: '%s'\n", tag);
1395   switch (space->dbits)
1396   {
1397      case 8:      handler = (genf *)input_port_write8;    break;
1398      case 16:   handler = (genf *)input_port_write16;    break;
1399      case 32:   handler = (genf *)input_port_write32;    break;
1400      case 64:   handler = (genf *)input_port_write64;    break;
1401   }
1402   space_map_range(spacerw, ROW_WRITE, space->dbits, 0, addrstart, addrend, addrmask, addrmirror, handler, (void *)port, tag);
1403}
1404
1405
1406
13751407/***************************************************************************
13761408    DEBUGGER HELPERS
13771409***************************************************************************/
r6450r6451
17441776               space_map_range_private(space, ROW_READ, bits, entry->read_mask, entry->addrstart, entry->addrend, entry->addrmask, entry->addrmirror, handler, (void *)port, entry->read_porttag);
17451777            }
17461778
1779            /* if we have a write port tag, look it up */
1780            if (entry->write_porttag != NULL)
1781            {
1782               const input_port_config *port = input_port_by_tag(machine->portconfig, entry->write_porttag);
1783               int bits = (entry->write_bits == 0) ? space->dbits : entry->write_bits;
1784               genf *handler = NULL;
1785
1786               if (port == NULL)
1787                  fatalerror("Non-existent port referenced: '%s'\n", entry->write_porttag);
1788               switch (bits)
1789               {
1790                  case 8:      handler = (genf *)input_port_write8;    break;
1791                  case 16:   handler = (genf *)input_port_write16;    break;
1792                  case 32:   handler = (genf *)input_port_write32;    break;
1793                  case 64:   handler = (genf *)input_port_write64;    break;
1794               }
1795               space_map_range_private(space, ROW_WRITE, bits, entry->write_mask, entry->addrstart, entry->addrend, entry->addrmask, entry->addrmirror, handler, (void *)port, entry->write_porttag);
1796            }
1797
17471798            /* install the read handler if present */
17481799            if (rhandler.generic != NULL)
17491800            {
r6450r6451
21342185            entry->read_porttag = TOKEN_GET_STRING(tokens);
21352186            break;
21362187
2188         case ADDRMAP_TOKEN_WRITE_PORT:
2189            check_entry_field(write_porttag);
2190            entry->write_porttag = TOKEN_GET_STRING(tokens);
2191            break;
2192
21372193         case ADDRMAP_TOKEN_REGION:
21382194            check_entry_field(region);
21392195            TOKEN_UNGET_UINT32(tokens);
r6450r6451
35403596
35413597
35423598
3599/*-------------------------------------------------
3600    output port handlers
3601-------------------------------------------------*/
3602
3603static void input_port_write8(const input_port_config *port, offs_t offset, UINT8 data)
3604{
3605   input_port_write_direct(port, data, 0xff);
3606}
3607
3608static void input_port_write16(const input_port_config *port, offs_t offset, UINT16 data, UINT16 mem_mask)
3609{
3610   input_port_write_direct(port, data, mem_mask);
3611}
3612
3613static void input_port_write32(const input_port_config *port, offs_t offset, UINT32 data, UINT32 mem_mask)
3614{
3615   input_port_write_direct(port, data, mem_mask);
3616}
3617
3618static void input_port_write64(const input_port_config *port, offs_t offset, UINT64 data, UINT64 mem_mask)
3619{
3620   input_port_write_direct(port, data, mem_mask);
3621}
3622
3623
3624
35433625/***************************************************************************
35443626    STUB HANDLERS THAT MAP TO BYTE READS
35453627***************************************************************************/
src/emu/memory.h
r6450r6451
7272   ADDRMAP_TOKEN_DEVICE_READ,
7373   ADDRMAP_TOKEN_DEVICE_WRITE,
7474   ADDRMAP_TOKEN_READ_PORT,
75   ADDRMAP_TOKEN_WRITE_PORT,
7576   ADDRMAP_TOKEN_REGION,
7677   ADDRMAP_TOKEN_SHARE,
7778   ADDRMAP_TOKEN_BASEPTR,
r6450r6451
225226   const char *         read_name;         /* read handler callback name */
226227   const char *         read_devtag;      /* read tag for the relevant device */
227228   const char *         read_porttag;      /* tag for input port reading */
229   const char *         write_porttag;      /* tag for output port writing */
228230   write_handler          write;            /* write handler callback */
229231   UINT8               write_bits;         /* bits for the write handler callback (0=default, 1=8, 2=16, 3=32) */
230232   UINT8               write_mask;         /* mask bits indicating which subunits to process */
r6450r6451
738740   TOKEN_UINT32_PACK3(ADDRMAP_TOKEN_READ_PORT, 8, 0, 8, 0, 8), \
739741   TOKEN_STRING(_tag),
740742
743#define AM_WRITE_PORT(_tag) \
744   TOKEN_UINT32_PACK3(ADDRMAP_TOKEN_WRITE_PORT, 8, 0, 8, 0, 8), \
745   TOKEN_STRING(_tag),
746
741747#define AM_REGION(_tag, _offs) \
742748   TOKEN_UINT64_PACK2(ADDRMAP_TOKEN_REGION, 8, _offs, 32), \
743749   TOKEN_STRING(_tag),
src/emu/inptport.c
r6450r6451
196196};
197197
198198
199/* live custom/changed field information */
200typedef struct _callback_field_info callback_field_info;
201struct _callback_field_info
199/* live device field information */
200typedef struct _device_field_info device_field_info;
201struct _device_field_info
202202{
203   callback_field_info *      next;            /* linked list of info for this port */
203   device_field_info *      next;               /* linked list of info for this port */
204204   const input_field_config *   field;            /* pointer to the input field referenced */
205   const device_config *    device;               /* device */
205206   UINT8                  shift;            /* shift to apply to the final result */
206207};
207208
r6450r6451
224225struct _input_port_state
225226{
226227   analog_field_state *      analoglist;         /* pointer to list of analog port info */
227   callback_field_info *      customlist;         /* pointer to list of custom port info */
228   callback_field_info *      changedlist;      /* pointer to list of changed port info */
228   device_field_info *      readdevicelist;      /* pointer to list of input device info */
229   device_field_info *      writedevicelist;   /* pointer to list of output device info */
229230   input_port_value         defvalue;         /* combined default value across the port */
230231   input_port_value         digital;         /* current value from all digital inputs */
231232   input_port_value         vblank;            /* value of all IPT_VBLANK bits */
232233   input_port_value         lastvalue;         /* last value of the port, to detect changes */
234   input_port_value         lastwrite;         /* last value written to the port, to detect changes */
233235};
234236
235237
r6450r6451
442444static void init_port_types(running_machine *machine);
443445static void init_port_state(running_machine *machine);
444446static void init_autoselect_devices(const input_port_config *portlist, int type1, int type2, int type3, const char *option, const char *ananame);
445static callback_field_info *init_field_callback_info(const input_field_config *field);
447static device_field_info *init_field_device_info(const input_field_config *field,const char *device_name);
446448static analog_field_state *init_field_analog_state(const input_field_config *field);
447449
448450/* once-per-frame updates */
r6450r6451
622624
623625
624626/***************************************************************************
627    CUSTOM DEVICE I/O
628***************************************************************************/
629static READ_LINE_DEVICE_HANDLER( custom_read_line_device )
630{
631   const device_field_info *device_field = (const device_field_info *) device;
632
633   return (*device_field->field->custom)(device_field->field, device_field->field->custom_param);
634}
635
636static WRITE_LINE_DEVICE_HANDLER( changed_write_line_device )
637{
638   const device_field_info *device_field = (const device_field_info *) device;
639
640   /* recalculate 'oldval' as it cannot be passed directly */
641   input_port_value last = (device_field->field->type == IPT_OUTPUT) ? device_field->field->port->state->lastwrite : device_field->field->port->state->lastvalue;
642   input_port_value oldval = (last & device_field->field->mask) >> device_field->shift;
643
644   (*device_field->field->changed)(device_field->field, device_field->field->changed_param, oldval, state);
645}
646
647
648
649/***************************************************************************
625650    CORE SYSTEM MANAGEMENT
626651***************************************************************************/
627652
r6450r6451
12031228{
12041229   input_port_private *portdata = port->machine->input_port_data;
12051230   analog_field_state *analog;
1206   callback_field_info *custom;
1231   device_field_info *device_field;
12071232   input_port_value result;
12081233
12091234   assert_always(portdata->safe_to_read, "Input ports cannot be read at init time!");
r6450r6451
12121237   result = port->state->digital;
12131238
12141239   /* update custom values */
1215   for (custom = port->state->customlist; custom != NULL; custom = custom->next)
1216      if (input_condition_true(port->machine, &custom->field->condition))
1240   for (device_field = port->state->readdevicelist; device_field != NULL; device_field = device_field->next)
1241      if (input_condition_true(port->machine, &device_field->field->condition))
12171242      {
1218         /* replace the bits with bits from the custom routine */
1219         input_port_value newbits = (*custom->field->custom)(custom->field, custom->field->custom_param);
1220         result = (result & ~custom->field->mask) | ((newbits << custom->shift) & custom->field->mask);
1243         /* replace the bits with bits from the device */
1244         input_port_value newval = (*device_field->field->read_line_device)(device_field->device);
1245         result = (result & ~device_field->field->mask) | ((newval << device_field->shift) & device_field->field->mask);
12211246      }
12221247
12231248   /* update VBLANK bits */
r6450r6451
14231448
14241449
14251450/***************************************************************************
1451    PORT WRITING
1452***************************************************************************/
1453
1454/*-------------------------------------------------
1455    input_port_write_direct - write a value
1456   to a port
1457-------------------------------------------------*/
1458
1459void input_port_write_direct(const input_port_config *port, input_port_value data, input_port_value mem_mask)
1460{
1461   /* call device line changed handlers */
1462   device_field_info *device_field;
1463   input_port_value newvalue = port->state->lastwrite;
1464
1465   COMBINE_DATA(&newvalue);
1466
1467   for (device_field = port->state->writedevicelist; device_field; device_field = device_field->next)
1468      if (device_field->field->type == IPT_OUTPUT && input_condition_true(port->machine, &device_field->field->condition))
1469      {
1470         input_port_value oldval = (port->state->lastwrite & device_field->field->mask) >> device_field->shift;
1471         input_port_value newval = (newvalue & device_field->field->mask) >> device_field->shift;
1472
1473         /* if the bits have  changed, call the handler */
1474         if (oldval != newval)
1475            (*device_field->field->write_line_device)(device_field->device, newval);
1476      }
1477
1478   /* remember the last value */
1479   port->state->lastwrite = newvalue;
1480}
1481
1482/*-------------------------------------------------
1483    input_port_write - write a value to a
1484   port specified by tag
1485-------------------------------------------------*/
1486
1487void input_port_write(running_machine *machine, const char *tag, input_port_value value, input_port_value mask)
1488{
1489   const input_port_config *port = input_port_by_tag(machine->portconfig, tag);
1490   if (port == NULL)
1491      fatalerror("Unable to locate input port '%s'", tag);
1492   input_port_write_direct(port, value, mask);
1493}
1494
1495/*-------------------------------------------------
1496    input_port_read_safe - write a value to
1497   a port, ignore if the port does not exist
1498-------------------------------------------------*/
1499
1500void input_port_write_safe(running_machine *machine, const char *tag, input_port_value value, input_port_value mask)
1501{
1502   const input_port_config *port = input_port_by_tag(machine->portconfig, tag);
1503   if (port != NULL)
1504      input_port_write_direct(port, value, mask);
1505}
1506
1507
1508
1509/***************************************************************************
14261510    MISC HELPER FUNCTIONS
14271511***************************************************************************/
14281512
r6450r6451
15601644   for (port = machine->portconfig; port != NULL; port = port->next)
15611645   {
15621646      analog_field_state **analogstatetail;
1563      callback_field_info **custominfotail;
1564      callback_field_info **changedinfotail;
1647      device_field_info **readdevicetail;
1648      device_field_info **writedevicetail;
15651649      input_port_state *portstate;
15661650
15671651      /* allocate a new input_port_info structure */
r6450r6451
15711655
15721656      /* start with tail pointers to all the data */
15731657      analogstatetail = &portstate->analoglist;
1574      custominfotail = &portstate->customlist;
1575      changedinfotail = &portstate->changedlist;
1658      readdevicetail = &portstate->readdevicelist;
1659      writedevicetail = &portstate->writedevicelist;
15761660
15771661      /* iterate over fields */
15781662      for (field = port->fieldlist; field != NULL; field = field->next)
r6450r6451
16051689            fieldstate->joystick->inuse = TRUE;
16061690         }
16071691
1608         /* if this entry has custom callback, allocate memory for the tracking structure */
1609         if (field->custom != NULL)
1692         /* if this entry has device input, allocate memory for the tracking structure */
1693         if (field->read_line_device != NULL)
16101694         {
1611            *custominfotail = init_field_callback_info(field);
1612            custominfotail = &(*custominfotail)->next;
1695            *readdevicetail = init_field_device_info(field,field->read_device_name);
1696            readdevicetail = &(*readdevicetail)->next;
16131697         }
16141698
1615         /* if this entry has changed callback, allocate memory for the tracking structure */
1616         if (field->changed != NULL)
1699         /* if this entry has device output, allocate memory for the tracking structure */
1700         if (field->write_line_device != NULL)
16171701         {
1618            *changedinfotail = init_field_callback_info(field);
1619            changedinfotail = &(*changedinfotail)->next;
1702            *writedevicetail = init_field_device_info(field,field->write_device_name);
1703            writedevicetail = &(*writedevicetail)->next;
16201704         }
16211705
16221706#ifdef MESS
r6450r6451
17161800
17171801
17181802/*-------------------------------------------------
1719    init_field_callback_info - allocate and populate
1720    information about a changed or custom
1721    callback
1803    init_field_device_info - allocate and populate
1804    information about a device callback
17221805-------------------------------------------------*/
17231806
1724static callback_field_info *init_field_callback_info(const input_field_config *field)
1807static device_field_info *init_field_device_info(const input_field_config *field, const char *device_name)
17251808{
1726   callback_field_info *info;
1809   device_field_info *info;
17271810   input_port_value mask;
17281811
17291812   /* allocate memory */
1730   info = auto_alloc_clear(field->port->machine, callback_field_info);
1813   info = auto_alloc_clear(field->port->machine, device_field_info);
17311814
17321815   /* fill in the data */
17331816   info->field = field;
17341817   for (mask = field->mask; !(mask & 1); mask >>= 1)
17351818      info->shift++;
17361819
1820   if (device_name != NULL)
1821      info->device = devtag_get_device(field->port->machine, device_name);
1822   else
1823      info->device = (const device_config *) info;
1824
17371825   return info;
17381826}
17391827
r6450r6451
19752063   for (port = machine->portconfig; port != NULL; port = port->next)
19762064   {
19772065      const input_field_config *field;
1978      callback_field_info *changed;
2066      device_field_info *device_field;
19792067      input_port_value newvalue;
19802068
19812069      /* start with 0 values for the digital and VBLANK bits */
r6450r6451
20042092      mess_input_port_update_hook(machine, port, &port->state->digital);
20052093#endif /* MESS */
20062094
2007      /* call changed handlers */
2095      /* call device line changed handlers */
20082096      newvalue = input_port_read_direct(port);
2009      for (changed = port->state->changedlist; changed; changed = changed->next)
2010         if (input_condition_true(port->machine, &changed->field->condition))
2097      for (device_field = port->state->writedevicelist; device_field; device_field = device_field->next)
2098         if (device_field->field->type != IPT_OUTPUT && input_condition_true(port->machine, &device_field->field->condition))
20112099         {
2012            input_port_value oldbits = (port->state->lastvalue & changed->field->mask) >> changed->shift;
2013            input_port_value newbits = (newvalue & changed->field->mask) >> changed->shift;
2100            input_port_value oldval = (port->state->lastvalue & device_field->field->mask) >> device_field->shift;
2101            input_port_value newval = (newvalue & device_field->field->mask) >> device_field->shift;
20142102
20152103            /* if the bits have  changed, call the handler */
2016            if (oldbits != newbits)
2017               (*changed->field->changed)(changed->field, changed->field->changed_param, oldbits, newbits);
2104            if (oldval != newval)
2105               (*device_field->field->write_line_device)(device_field->device, newval);
20182106         }
20192107
20202108      /* remember the last value */
r6450r6451
25532641               TOKEN_SKIP_PTR(ipt);
25542642               break;
25552643            }
2644            curfield->read_line_device = custom_read_line_device;
2645            curfield->read_device_name = NULL;
25562646            curfield->custom = TOKEN_GET_PTR(ipt, customptr);
25572647            curfield->custom_param = (void *)TOKEN_GET_PTR(ipt, voidptr);
25582648            break;
r6450r6451
25662656               TOKEN_SKIP_PTR(ipt);
25672657               break;
25682658            }
2659            curfield->write_line_device = changed_write_line_device;
2660            curfield->write_device_name = NULL;
25692661            curfield->changed = TOKEN_GET_PTR(ipt, changedptr);
25702662            curfield->changed_param = (void *)TOKEN_GET_PTR(ipt, voidptr);
25712663            break;
r6450r6451
29483040            curfield->name = TOKEN_GET_STRING(ipt);
29493041            break;
29503042
3043         /* input device handler */
3044         case INPUT_TOKEN_READ_LINE_DEVICE:
3045            if (curfield == NULL)
3046            {
3047               error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_READ_LINE_DEVICE encountered with no active field\n");
3048               TOKEN_SKIP_STRING(ipt);
3049               TOKEN_SKIP_PTR(ipt);
3050               break;
3051            }
3052            curfield->read_device_name = TOKEN_GET_STRING(ipt);
3053            curfield->read_line_device = TOKEN_GET_PTR(ipt, read_line_device);
3054            break;
3055
3056         /* output device handler */
3057         case INPUT_TOKEN_WRITE_LINE_DEVICE:
3058            if (curfield == NULL)
3059            {
3060               error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_WRITE_LINE_DEVICE encountered with no active field\n");
3061               TOKEN_SKIP_STRING(ipt);
3062               TOKEN_SKIP_PTR(ipt);
3063               break;
3064            }
3065            curfield->write_device_name = TOKEN_GET_STRING(ipt);
3066            curfield->write_line_device = TOKEN_GET_PTR(ipt, write_line_device);
3067            break;
3068
29513069         default:
29523070            error_buf_append(errorbuf, errorbuflen, "Invalid token %d in input ports\n", entrytype);
29533071            break;
src/emu/inptport.h
r6450r6451
1616
1717#include <time.h>
1818
19#include "devcb.h"
1920#include "memory.h"
2021#include "inputseq.h"
2122#include "tokenize.h"
r6450r6451
357358
358359   /* special meaning handled by custom code */
359360   IPT_SPECIAL,
361   IPT_OUTPUT,
360362
361363   __ipt_max
362364};
r6450r6451
418420   INPUT_TOKEN_CHAR,
419421   INPUT_TOKEN_CATEGORY,
420422   INPUT_TOKEN_CATEGORY_NAME,
421   INPUT_TOKEN_CATEGORY_SETTING
423   INPUT_TOKEN_CATEGORY_SETTING,
424   INPUT_TOKEN_READ_LINE_DEVICE,
425   INPUT_TOKEN_WRITE_LINE_DEVICE,
422426};
423427
424428
r6450r6451
583587   input_field_custom_func    customptr;
584588   input_field_changed_func    changedptr;
585589   input_field_crossmap_func    crossmapptr;
590   read_line_device_func       read_line_device;
591   write_line_device_func       write_line_device;
586592};
587593
588594
r6450r6451
637643   UINT8                  impulse;      /* number of frames before reverting to defvalue */
638644   const char *            name;         /* user-friendly name to display */
639645   input_seq               seq[SEQ_TYPE_TOTAL];/* sequences of all types */
646   read_line_device_func      read_line_device;   /* input device handler */
647   const char *            read_device_name;   /* input device name */
648   write_line_device_func      write_line_device;   /* output device handler */
649   const char *            write_device_name;   /* input device name */
640650   input_field_custom_func      custom;         /* custom callback routine */
641651   void *                  custom_param;   /* parameter for custom callback routine */
642652   input_field_changed_func    changed;      /* changed callback routine */
r6450r6451
903913   TOKEN_PTR(changedptr, _callback), \
904914   TOKEN_PTR(voidptr, _param),
905915
916/* input device handler */
917#define PORT_READ_LINE_DEVICE(_device, _read_line_device) \
918   TOKEN_UINT32_PACK1(INPUT_TOKEN_READ_LINE_DEVICE, 8), \
919   TOKEN_STRING(_device), \
920   TOKEN_PTR(read_line_device, _read_line_device),
921
922/* output device handler */
923#define PORT_WRITE_LINE_DEVICE(_device, _write_line_device) \
924   TOKEN_UINT32_PACK1(INPUT_TOKEN_WRITE_LINE_DEVICE, 8), \
925   TOKEN_STRING(_device), \
926   TOKEN_PTR(write_line_device, _write_line_device),
927
906928/* dip switch definition */
907929#define PORT_DIPNAME(_mask, _default, _name) \
908930   TOKEN_UINT32_PACK1(INPUT_TOKEN_DIPNAME, 8), \
r6450r6451
10921114
10931115
10941116
1117/* ----- port writing ----- */
1118
1119/* write a value to a port */
1120void input_port_write_direct(const input_port_config *port, input_port_value value, input_port_value mask);
1121
1122/* write a value to a port specified by tag */
1123void input_port_write(running_machine *machine, const char *tag, input_port_value value, input_port_value mask);
1124
1125/* write a value to a port, ignore if the port does not exist */
1126void input_port_write_safe(running_machine *machine, const char *tag, input_port_value value, input_port_value mask);
1127
1128
1129
10951130/* ----- misc helper functions ----- */
10961131
10971132/* return the TRUE if the given condition attached is true */
src/emu/validity.c
r6450r6451
15861586               mame_printf_error("%s: %s device '%s' %s space memory map entry references nonexistant port tag '%s'\n", driver->source_file, driver->name, device->tag, address_space_names[spacenum], entry->read_porttag);
15871587               error = TRUE;
15881588            }
1589
1590            /* make sure ports exist */
1591            if (entry->write_porttag != NULL && input_port_by_tag(portlist, entry->write_porttag) == NULL)
1592            {
1593               mame_printf_error("%s: %s device '%s' %s space memory map entry references nonexistant port tag '%s'\n", driver->source_file, driver->name, device->tag, address_space_names[spacenum], entry->write_porttag);
1594               error = TRUE;
1595            }
15891596         }
15901597
15911598         /* release the address map */

Previous 15994 Revisions Next


© 1998-2018 The MESS Team