trunk/src/mame/drivers/pong.c
| r26783 | r26784 | |
| 370 | 370 | // ---------------------------------------------------------------------------------------- |
| 371 | 371 | |
| 372 | 372 | NETDEV_POT(ic_b9_POT, RES_K(1)) // This is a guess!! |
| 373 | NETDEV_PARAM(ic_b9_POT.DIALLOG, 1) // Log Dial ... |
| 373 | 374 | NETDEV_R(ic_b9_RPRE, 470) |
| 374 | 375 | |
| 375 | 376 | NET_C(ic_b9_POT.1, V5) |
| r26783 | r26784 | |
| 377 | 378 | NET_C(ic_b9_POT.2, ic_b9_RPRE.1) |
| 378 | 379 | NET_C(ic_b9_RPRE.2, ic_b9.CONT) |
| 379 | 380 | |
| 380 | | NETDEV_R(ic_b9_R, RES_K(71)) |
| 381 | NETDEV_R(ic_b9_R, RES_K(81)) // Adjustment pot |
| 381 | 382 | NETDEV_C(ic_b9_C, CAP_U(.1)) |
| 382 | 383 | NETDEV_D(ic_b9_D, 1N914) |
| 383 | 384 | NETDEV_NE555(ic_b9) |
| r26783 | r26784 | |
| 409 | 410 | // ---------------------------------------------------------------------------------------- |
| 410 | 411 | |
| 411 | 412 | NETDEV_POT(ic_a9_POT, RES_K(1)) // This is a guess!! |
| 413 | NETDEV_PARAM(ic_a9_POT.DIALLOG, 1) // Log Dial ... |
| 412 | 414 | NETDEV_R(ic_a9_RPRE, 470) |
| 413 | 415 | |
| 414 | 416 | NET_C(ic_a9_POT.1, V5) |
| r26783 | r26784 | |
| 416 | 418 | NET_C(ic_a9_POT.2, ic_a9_RPRE.1) |
| 417 | 419 | NET_C(ic_a9_RPRE.2, ic_a9.CONT) |
| 418 | 420 | |
| 419 | | NETDEV_R(ic_a9_R, RES_K(71)) |
| 421 | NETDEV_R(ic_a9_R, RES_K(81)) // Adjustment pot |
| 420 | 422 | NETDEV_C(ic_a9_C, CAP_U(.1)) |
| 421 | 423 | NETDEV_D(ic_a9_D, 1N914) |
| 422 | 424 | NETDEV_NE555(ic_a9) |
| r26783 | r26784 | |
| 792 | 794 | m_video(*this, "fixfreq"), |
| 793 | 795 | |
| 794 | 796 | m_dac(*this, "dac"), /* just to have a sound device */ |
| 795 | | m_srst(*this, "maincpu", "SRST"), |
| 796 | | m_p_P0(*this, "maincpu", "ic_b9_POT.DIAL"), |
| 797 | | m_p_P1(*this, "maincpu", "ic_a9_POT.DIAL"), |
| 798 | | m_sw1a(*this, "maincpu", "sw1a.POS"), |
| 799 | | m_sw1b(*this, "maincpu", "sw1b.POS"), |
| 800 | | m_p_R0(*this, "maincpu", "ic_a9_R.R"), |
| 801 | | m_p_R1(*this, "maincpu", "ic_b9_R.R") |
| 797 | m_sw1a(*this, "maincpu:sw1a"), |
| 798 | m_sw1b(*this, "maincpu:sw1b") |
| 802 | 799 | { |
| 803 | 800 | } |
| 804 | 801 | |
| 805 | 802 | // devices |
| 806 | | required_device<netlist_mame_device> m_maincpu; |
| 803 | required_device<netlist_mame_device_t> m_maincpu; |
| 807 | 804 | required_device<fixedfreq_device> m_video; |
| 808 | 805 | required_device<dac_device> m_dac; /* just to have a sound device */ |
| 809 | 806 | |
| 810 | 807 | // sub devices |
| 811 | | netlist_mame_device::required_output<netlist_logic_output_t> m_srst; |
| 812 | | netlist_mame_device::required_param<netlist_param_double_t> m_p_P0; |
| 813 | | netlist_mame_device::required_param<netlist_param_double_t> m_p_P1; |
| 814 | | netlist_mame_device::required_param<netlist_param_int_t> m_sw1a; |
| 815 | | netlist_mame_device::required_param<netlist_param_int_t> m_sw1b; |
| 816 | | netlist_mame_device::required_param<netlist_param_double_t> m_p_R0; |
| 817 | | netlist_mame_device::required_param<netlist_param_double_t> m_p_R1; |
| 808 | required_device<netlist_mame_logic_input_t> m_sw1a; |
| 809 | required_device<netlist_mame_logic_input_t> m_sw1b; |
| 818 | 810 | |
| 819 | 811 | UINT32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); |
| 820 | 812 | |
| r26783 | r26784 | |
| 827 | 819 | m_dac->write_unsigned8(64*data); |
| 828 | 820 | } |
| 829 | 821 | |
| 830 | | NETDEV_ANALOG_CALLBACK_MEMBER(video_cb) |
| 831 | | { |
| 832 | | m_video->update_vid(data, time); |
| 833 | | //printf("%20.15f\n", newval); |
| 834 | | } |
| 835 | | |
| 836 | 822 | protected: |
| 837 | 823 | |
| 838 | 824 | // driver_device overrides |
| r26783 | r26784 | |
| 851 | 837 | NETLIST_MEMREGION("maincpu") |
| 852 | 838 | |
| 853 | 839 | NETDEV_ANALOG_CALLBACK(sound_cb, sound, pong_state, sound_cb, "") |
| 854 | | NETDEV_ANALOG_CALLBACK(video_cb, videomix, pong_state, video_cb, "") |
| 840 | NETDEV_ANALOG_CALLBACK(video_cb, videomix, fixedfreq_device, update_vid, "fixfreq") |
| 855 | 841 | NETLIST_END |
| 856 | 842 | |
| 857 | 843 | static NETLIST_START(pong_fast) |
| r26783 | r26784 | |
| 859 | 845 | NETLIST_INCLUDE(pong_schematics) |
| 860 | 846 | |
| 861 | 847 | NETDEV_ANALOG_CALLBACK(sound_cb, sound, pong_state, sound_cb, "") |
| 862 | | NETDEV_ANALOG_CALLBACK(video_cb, videomix, pong_state, video_cb, "") |
| 848 | NETDEV_ANALOG_CALLBACK(video_cb, videomix, fixedfreq_device, update_vid, "fixfreq") |
| 863 | 849 | |
| 864 | 850 | NETLIST_END |
| 865 | 851 | |
| r26783 | r26784 | |
| 879 | 865 | |
| 880 | 866 | INPUT_CHANGED_MEMBER(pong_state::input_changed) |
| 881 | 867 | { |
| 882 | | double pad; |
| 883 | 868 | int numpad = (FPTR) (param); |
| 884 | 869 | |
| 885 | 870 | switch (numpad) |
| 886 | 871 | { |
| 887 | | case IC_PADDLE1: |
| 888 | | case IC_PADDLE2: |
| 889 | | { |
| 890 | | // http://ion.chem.usu.edu/~sbialkow/Classes/564/Thevenin/Thevenin.html |
| 891 | | |
| 892 | | double fac = (double) newval / (double) 256; |
| 893 | | fac = (exp(fac) - 1.0) / (exp(1.0) -1.0) ; |
| 894 | | switch (numpad) |
| 895 | | { |
| 896 | | case IC_PADDLE1: m_p_P0->setTo(fac); break; |
| 897 | | case IC_PADDLE2: m_p_P1->setTo(fac); break; |
| 898 | | } |
| 899 | | break; |
| 900 | | } |
| 901 | 872 | case IC_SWITCH: |
| 902 | | m_sw1a->setTo(newval ? 1 : 0); |
| 903 | | m_sw1b->setTo(newval ? 1 : 0); |
| 873 | m_sw1a->write(newval ? 1 : 0); |
| 874 | m_sw1b->write(newval ? 1 : 0); |
| 904 | 875 | break; |
| 905 | | case IC_COIN: |
| 906 | | m_srst->set_Q(newval & 1, NLTIME_FROM_US(500)); |
| 907 | | break; |
| 908 | | case IC_VR1: |
| 909 | | case IC_VR2: |
| 910 | | pad = (double) newval / (double) 100 * RES_K(50) + RES_K(56); |
| 911 | | switch (numpad) |
| 912 | | { |
| 913 | | case IC_VR1: m_p_R0->setTo(pad); break; |
| 914 | | case IC_VR2: m_p_R1->setTo(pad); break; |
| 915 | | } |
| 916 | | break; |
| 917 | 876 | } |
| 918 | | |
| 919 | | |
| 920 | 877 | } |
| 921 | 878 | |
| 922 | 879 | static INPUT_PORTS_START( pong ) |
| 923 | 880 | PORT_START( "PADDLE0" ) /* fake input port for player 1 paddle */ |
| 924 | | PORT_BIT( 0xff, 0x00, IPT_PADDLE ) PORT_SENSITIVITY(2) PORT_KEYDELTA(100) PORT_CENTERDELTA(0) PORT_CHANGED_MEMBER(DEVICE_SELF, pong_state, input_changed,IC_PADDLE1) |
| 881 | PORT_BIT( 0xff, 0x00, IPT_PADDLE ) PORT_SENSITIVITY(2) PORT_KEYDELTA(100) PORT_CENTERDELTA(0) NETLIST_ANALOG_PORT_CHANGED("maincpu", "pot0") |
| 925 | 882 | |
| 926 | 883 | PORT_START( "PADDLE1" ) /* fake input port for player 2 paddle */ |
| 927 | | PORT_BIT( 0xff, 0x00, IPT_PADDLE ) PORT_SENSITIVITY(2) PORT_KEYDELTA(100) PORT_CENTERDELTA(0) PORT_PLAYER(2) PORT_CHANGED_MEMBER(DEVICE_SELF, pong_state, input_changed, IC_PADDLE2) |
| 884 | PORT_BIT( 0xff, 0x00, IPT_PADDLE ) PORT_SENSITIVITY(2) PORT_KEYDELTA(100) PORT_CENTERDELTA(0) PORT_PLAYER(2) NETLIST_ANALOG_PORT_CHANGED("maincpu", "pot1") |
| 928 | 885 | |
| 929 | 886 | PORT_START("IN0") /* fake as well */ |
| 930 | | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, pong_state, input_changed, IC_COIN) |
| 887 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) NETLIST_LOGIC_PORT_CHANGED("maincpu", "srst") |
| 931 | 888 | PORT_DIPNAME( 0x06, 0x00, "Game Won" ) PORT_DIPLOCATION("SW1A:1,SW1B:1") PORT_CHANGED_MEMBER(DEVICE_SELF, pong_state, input_changed, IC_SWITCH) |
| 932 | 889 | PORT_DIPSETTING( 0x00, "11" ) |
| 933 | 890 | PORT_DIPSETTING( 0x06, "15" ) |
| 934 | 891 | |
| 935 | 892 | PORT_START("VR1") |
| 936 | | PORT_ADJUSTER( 50, "VR1 - 50k, Paddle 1 adjustment" ) PORT_CHANGED_MEMBER(DEVICE_SELF, pong_state, input_changed, IC_VR1) |
| 893 | PORT_ADJUSTER( 50, "VR1 - 50k, Paddle 1 adjustment" ) NETLIST_ANALOG_PORT_CHANGED("maincpu", "vr0") |
| 937 | 894 | PORT_START("VR2") |
| 938 | | PORT_ADJUSTER( 50, "VR2 - 50k, Paddle 2 adjustment" ) PORT_CHANGED_MEMBER(DEVICE_SELF, pong_state, input_changed, IC_VR2) |
| 895 | PORT_ADJUSTER( 50, "VR2 - 50k, Paddle 2 adjustment" ) NETLIST_ANALOG_PORT_CHANGED("maincpu", "vr1") |
| 939 | 896 | //PORT_START("GATESPEED") |
| 940 | 897 | //PORT_ADJUSTER( 100, "Logic Gate Delay" ) PORT_MINMAX(10, 200) PORT_CHANGED_MEMBER(DEVICE_SELF, pong_state, input_changed, IC_GATEDELAY) |
| 941 | 898 | |
| r26783 | r26784 | |
| 945 | 902 | |
| 946 | 903 | /* basic machine hardware */ |
| 947 | 904 | MCFG_NETLIST_ADD("maincpu", pong) |
| 905 | MCFG_NETLIST_ANALOG_INPUT("maincpu", "vr0", "ic_b9_R.R") |
| 906 | MCFG_NETLIST_ANALOG_INPUT_MULT_OFFSET(1.0 / 100.0 * RES_K(50), RES_K(56) ) |
| 907 | MCFG_NETLIST_ANALOG_INPUT("maincpu", "vr1", "ic_a9_R.R") |
| 908 | MCFG_NETLIST_ANALOG_INPUT_MULT_OFFSET(1.0 / 100.0 * RES_K(50), RES_K(56) ) |
| 909 | MCFG_NETLIST_ANALOG_INPUT("maincpu", "pot0", "ic_b9_POT.DIAL") |
| 910 | MCFG_NETLIST_ANALOG_INPUT("maincpu", "pot1", "ic_a9_POT.DIAL") |
| 911 | MCFG_NETLIST_LOGIC_INPUT("maincpu", "sw1a", "sw1a.POS", 0, 0x01) |
| 912 | MCFG_NETLIST_LOGIC_INPUT("maincpu", "sw1b", "sw1b.POS", 0, 0x01) |
| 913 | MCFG_NETLIST_LOGIC_INPUT("maincpu", "srst", "SRST.OUT", 0, 0x01) |
| 948 | 914 | |
| 949 | 915 | /* video hardware */ |
| 950 | 916 | |
| r26783 | r26784 | |
| 962 | 928 | static MACHINE_CONFIG_DERIVED( pongf, pong ) |
| 963 | 929 | |
| 964 | 930 | /* basic machine hardware */ |
| 965 | | MCFG_NETLIST_REPLACE("maincpu", pong_fast) |
| 931 | MCFG_DEVICE_MODIFY("maincpu") |
| 932 | MCFG_NETLIST_SETUP(pong_fast) |
| 966 | 933 | |
| 967 | 934 | MACHINE_CONFIG_END |
| 968 | 935 | |
trunk/src/emu/machine/netlist.c
| r26783 | r26784 | |
| 54 | 54 | //#define LOG_DEV_CALLS(x) printf x |
| 55 | 55 | #define LOG_DEV_CALLS(x) do { } while (0) |
| 56 | 56 | |
| 57 | const device_type NETLIST = &device_creator<netlist_mame_device_t>; |
| 58 | const device_type NETLIST_ANALOG_INPUT = &device_creator<netlist_mame_analog_input_t>; |
| 59 | const device_type NETLIST_LOGIC_INPUT = &device_creator<netlist_mame_logic_input_t>; |
| 60 | |
| 61 | netlist_mame_analog_input_t::netlist_mame_analog_input_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 62 | : device_t(mconfig, NETLIST_ANALOG_INPUT, "netlist analog input", tag, owner, clock, "netlist_analog_input", __FILE__), |
| 63 | netlist_mame_sub_interface(*this), |
| 64 | m_offset(0.0), |
| 65 | m_mult(1.0), |
| 66 | m_auto_port(true), |
| 67 | m_param_name("") |
| 68 | { |
| 69 | } |
| 70 | |
| 71 | void netlist_mame_analog_input_t::static_set_name(device_t &device, const char *param_name) |
| 72 | { |
| 73 | netlist_mame_analog_input_t &netlist = downcast<netlist_mame_analog_input_t &>(device); |
| 74 | netlist.m_param_name = param_name; |
| 75 | } |
| 76 | |
| 77 | void netlist_mame_analog_input_t::static_set_mult_offset(device_t &device, const double mult, const double offset) |
| 78 | { |
| 79 | netlist_mame_analog_input_t &netlist = downcast<netlist_mame_analog_input_t &>(device); |
| 80 | netlist.m_mult = mult; |
| 81 | netlist.m_offset = offset; |
| 82 | // disable automatic scaling for ioports |
| 83 | netlist.m_auto_port = false; |
| 84 | } |
| 85 | |
| 86 | void netlist_mame_analog_input_t::device_start() |
| 87 | { |
| 88 | LOG_DEV_CALLS(("start %s\n", tag())); |
| 89 | netlist_param_t *p = downcast<netlist_mame_device_t *>(this->owner())->setup().find_param(m_param_name); |
| 90 | m_param = dynamic_cast<netlist_param_double_t *>(p); |
| 91 | if (m_param == NULL) |
| 92 | { |
| 93 | fatalerror("device %s wrong parameter type for %s\n", basetag(), m_param_name.cstr()); |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | netlist_mame_logic_input_t::netlist_mame_logic_input_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 98 | : device_t(mconfig, NETLIST_ANALOG_INPUT, "netlist analog input", tag, owner, clock, "netlist_analog_input", __FILE__), |
| 99 | netlist_mame_sub_interface(*this), |
| 100 | m_mask(0xffffffff), |
| 101 | m_shift(0), |
| 102 | m_param_name("") |
| 103 | { |
| 104 | } |
| 105 | |
| 106 | void netlist_mame_logic_input_t::static_set_params(device_t &device, const char *param_name, const UINT32 mask, const UINT32 shift) |
| 107 | { |
| 108 | netlist_mame_logic_input_t &netlist = downcast<netlist_mame_logic_input_t &>(device); |
| 109 | netlist.m_param_name = param_name; |
| 110 | netlist.m_shift = shift; |
| 111 | netlist.m_mask = mask; |
| 112 | } |
| 113 | |
| 114 | void netlist_mame_logic_input_t::device_start() |
| 115 | { |
| 116 | LOG_DEV_CALLS(("start %s\n", tag())); |
| 117 | netlist_param_t *p = downcast<netlist_mame_device_t *>(this->owner())->setup().find_param(m_param_name); |
| 118 | m_param = dynamic_cast<netlist_param_int_t *>(p); |
| 119 | if (m_param == NULL) |
| 120 | { |
| 121 | fatalerror("device %s wrong parameter type for %s\n", basetag(), m_param_name.cstr()); |
| 122 | } |
| 123 | } |
| 124 | |
| 125 | |
| 57 | 126 | // ---------------------------------------------------------------------------------------- |
| 58 | 127 | // netlist_mame_device |
| 59 | 128 | // ---------------------------------------------------------------------------------------- |
| 60 | 129 | |
| 61 | | const device_type NETLIST = &device_creator<netlist_mame_device>; |
| 62 | | |
| 63 | | static ADDRESS_MAP_START(program_dummy, AS_PROGRAM, 8, netlist_mame_device) |
| 64 | | AM_RANGE(0x000, 0x3ff) AM_ROM |
| 130 | static ADDRESS_MAP_START(program_dummy, AS_PROGRAM, 8, netlist_mame_device_t) |
| 131 | AM_RANGE(0x000, 0x3ff) AM_ROM |
| 65 | 132 | ADDRESS_MAP_END |
| 66 | 133 | |
| 67 | | netlist_mame_device::netlist_mame_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 134 | netlist_mame_device_t::netlist_mame_device_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 68 | 135 | : device_t(mconfig, NETLIST, "netlist", tag, owner, clock, "netlist_mame", __FILE__), |
| 69 | 136 | device_execute_interface(mconfig, *this), |
| 70 | | device_state_interface(mconfig, *this), |
| 71 | | device_disasm_interface(mconfig, *this), |
| 72 | | device_memory_interface(mconfig, *this), |
| 73 | | m_device_start_list(100), |
| 74 | | m_program_config("program", ENDIANNESS_LITTLE, 8, 12, 0, ADDRESS_MAP_NAME(program_dummy)), |
| 137 | device_state_interface(mconfig, *this), |
| 138 | device_disasm_interface(mconfig, *this), |
| 139 | device_memory_interface(mconfig, *this), |
| 140 | m_program_config("program", ENDIANNESS_LITTLE, 8, 12, 0, ADDRESS_MAP_NAME(program_dummy)), |
| 75 | 141 | m_netlist(NULL), |
| 76 | 142 | m_setup(NULL), |
| 77 | 143 | m_setup_func(NULL), |
| r26783 | r26784 | |
| 80 | 146 | { |
| 81 | 147 | } |
| 82 | 148 | |
| 83 | | void netlist_mame_device::static_set_constructor(device_t &device, void (*setup_func)(netlist_setup_t &)) |
| 149 | void netlist_mame_device_t::static_set_constructor(device_t &device, void (*setup_func)(netlist_setup_t &)) |
| 84 | 150 | { |
| 85 | | netlist_mame_device &netlist = downcast<netlist_mame_device &>(device); |
| 151 | LOG_DEV_CALLS(("static_set_constructor\n")); |
| 152 | netlist_mame_device_t &netlist = downcast<netlist_mame_device_t &>(device); |
| 86 | 153 | netlist.m_setup_func = setup_func; |
| 87 | | LOG_DEV_CALLS(("static_set_constructor\n")); |
| 88 | 154 | } |
| 89 | 155 | |
| 90 | | void netlist_mame_device::device_config_complete() |
| 156 | void netlist_mame_device_t::device_config_complete() |
| 91 | 157 | { |
| 92 | 158 | LOG_DEV_CALLS(("device_config_complete\n")); |
| 93 | 159 | } |
| 94 | 160 | |
| 95 | | void netlist_mame_device::device_start() |
| 161 | void netlist_mame_device_t::device_start() |
| 96 | 162 | { |
| 97 | | LOG_DEV_CALLS(("device_start\n")); |
| 163 | LOG_DEV_CALLS(("device_start %s\n", tag())); |
| 98 | 164 | |
| 99 | 165 | m_netlist = global_alloc_clear(netlist_mame_t(*this)); |
| 100 | 166 | m_setup = global_alloc_clear(netlist_setup_t(*m_netlist)); |
| r26783 | r26784 | |
| 109 | 175 | |
| 110 | 176 | m_setup_func(*m_setup); |
| 111 | 177 | |
| 178 | /* let sub-devices tweak the netlist */ |
| 179 | for( device_t *d = this->first_subdevice(); d != NULL; d = d->next() ) |
| 180 | { |
| 181 | netlist_mame_sub_interface *sdev = dynamic_cast<netlist_mame_sub_interface *>(d); |
| 182 | if( sdev != NULL ) |
| 183 | { |
| 184 | LOG_DEV_CALLS(("Found subdevice %s/%s\n", d->name(), d->shortname())); |
| 185 | sdev->custom_netlist_additions(*m_netlist); |
| 186 | } |
| 187 | } |
| 188 | |
| 112 | 189 | m_setup->start_devices(); |
| 113 | 190 | m_setup->resolve_inputs(); |
| 114 | 191 | |
| 115 | | bool allok = true; |
| 116 | | for (device_start_list_t::entry_t *ods = m_device_start_list.first(); ods != NULL; ods = m_device_start_list.next(ods)) |
| 117 | | allok &= ods->object()->OnDeviceStart(); |
| 118 | | |
| 119 | | if (!allok) |
| 120 | | m_netlist->xfatalerror("required elements not found\n"); |
| 121 | | |
| 122 | 192 | save_state(); |
| 123 | 193 | |
| 124 | 194 | // State support |
| 125 | 195 | |
| 126 | | state_add(STATE_GENPC, "curpc", m_genPC).noshow(); |
| 196 | state_add(STATE_GENPC, "curpc", m_genPC).noshow(); |
| 127 | 197 | |
| 128 | | for (int i=0; i < m_netlist->m_nets.count(); i++) |
| 129 | | { |
| 130 | | netlist_net_t *n = m_netlist->m_nets[i]; |
| 131 | | if (n->isRailNet()) |
| 132 | | { |
| 133 | | state_add(i*2, n->name(), n->m_cur.Q); |
| 134 | | } |
| 135 | | else |
| 136 | | { |
| 137 | | state_add(i*2+1, n->name(), n->m_cur.Analog).formatstr("%20s"); |
| 138 | | } |
| 139 | | } |
| 198 | for (int i=0; i < m_netlist->m_nets.count(); i++) |
| 199 | { |
| 200 | netlist_net_t *n = m_netlist->m_nets[i]; |
| 201 | if (n->isRailNet()) |
| 202 | { |
| 203 | state_add(i*2, n->name(), n->m_cur.Q); |
| 204 | } |
| 205 | else |
| 206 | { |
| 207 | state_add(i*2+1, n->name(), n->m_cur.Analog).formatstr("%20s"); |
| 208 | } |
| 209 | } |
| 140 | 210 | |
| 141 | 211 | // set our instruction counter |
| 142 | 212 | m_icountptr = &m_icount; |
| 143 | 213 | } |
| 144 | 214 | |
| 145 | | void netlist_mame_device::device_reset() |
| 215 | void netlist_mame_device_t::device_reset() |
| 146 | 216 | { |
| 147 | 217 | LOG_DEV_CALLS(("device_reset\n")); |
| 148 | 218 | m_netlist->reset(); |
| 149 | 219 | } |
| 150 | 220 | |
| 151 | | void netlist_mame_device::device_stop() |
| 221 | void netlist_mame_device_t::device_stop() |
| 152 | 222 | { |
| 153 | 223 | LOG_DEV_CALLS(("device_stop\n")); |
| 154 | 224 | m_setup->print_stats(); |
| r26783 | r26784 | |
| 159 | 229 | m_netlist = NULL; |
| 160 | 230 | } |
| 161 | 231 | |
| 162 | | ATTR_COLD void netlist_mame_device::device_post_load() |
| 232 | ATTR_COLD void netlist_mame_device_t::device_post_load() |
| 163 | 233 | { |
| 164 | | LOG_DEV_CALLS(("device_post_load\n")); |
| 234 | LOG_DEV_CALLS(("device_post_load\n")); |
| 165 | 235 | |
| 166 | | m_netlist->post_load(); |
| 236 | m_netlist->post_load(); |
| 167 | 237 | } |
| 168 | 238 | |
| 169 | | ATTR_COLD void netlist_mame_device::device_pre_save() |
| 239 | ATTR_COLD void netlist_mame_device_t::device_pre_save() |
| 170 | 240 | { |
| 171 | 241 | LOG_DEV_CALLS(("device_pre_save\n")); |
| 172 | 242 | |
| 173 | 243 | m_netlist->pre_save(); |
| 174 | 244 | } |
| 175 | 245 | |
| 176 | | void netlist_mame_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) |
| 246 | void netlist_mame_device_t::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) |
| 177 | 247 | { |
| 178 | 248 | } |
| 179 | 249 | |
| 180 | 250 | |
| 181 | 251 | |
| 182 | | ATTR_COLD void netlist_mame_device::save_state() |
| 252 | ATTR_COLD void netlist_mame_device_t::save_state() |
| 183 | 253 | { |
| 184 | | for (pstate_entry_t::list_t::entry_t *p = m_netlist->save_list().first(); p != NULL; p = m_netlist->save_list().next(p)) |
| 185 | | { |
| 186 | | pstate_entry_t *s = p->object(); |
| 187 | | NL_VERBOSE_OUT(("saving state for %s\n", s->m_name.cstr())); |
| 188 | | switch (s->m_dt) |
| 189 | | { |
| 190 | | case DT_DOUBLE: |
| 191 | | save_pointer((double *) s->m_ptr, s->m_name, s->m_count); |
| 192 | | break; |
| 193 | | case DT_INT64: |
| 194 | | save_pointer((INT64 *) s->m_ptr, s->m_name, s->m_count); |
| 195 | | break; |
| 196 | | case DT_INT8: |
| 197 | | save_pointer((INT8 *) s->m_ptr, s->m_name, s->m_count); |
| 198 | | break; |
| 199 | | case DT_INT: |
| 200 | | save_pointer((int *) s->m_ptr, s->m_name, s->m_count); |
| 201 | | break; |
| 202 | | case DT_BOOLEAN: |
| 203 | | save_pointer((bool *) s->m_ptr, s->m_name, s->m_count); |
| 204 | | break; |
| 205 | | case DT_CUSTOM: |
| 206 | | case NOT_SUPPORTED: |
| 207 | | default: |
| 208 | | m_netlist->xfatalerror("found unsupported save element %s\n", s->m_name.cstr()); |
| 209 | | break; |
| 210 | | } |
| 211 | | } |
| 254 | for (pstate_entry_t::list_t::entry_t *p = m_netlist->save_list().first(); p != NULL; p = m_netlist->save_list().next(p)) |
| 255 | { |
| 256 | pstate_entry_t *s = p->object(); |
| 257 | NL_VERBOSE_OUT(("saving state for %s\n", s->m_name.cstr())); |
| 258 | switch (s->m_dt) |
| 259 | { |
| 260 | case DT_DOUBLE: |
| 261 | save_pointer((double *) s->m_ptr, s->m_name, s->m_count); |
| 262 | break; |
| 263 | case DT_INT64: |
| 264 | save_pointer((INT64 *) s->m_ptr, s->m_name, s->m_count); |
| 265 | break; |
| 266 | case DT_INT8: |
| 267 | save_pointer((INT8 *) s->m_ptr, s->m_name, s->m_count); |
| 268 | break; |
| 269 | case DT_INT: |
| 270 | save_pointer((int *) s->m_ptr, s->m_name, s->m_count); |
| 271 | break; |
| 272 | case DT_BOOLEAN: |
| 273 | save_pointer((bool *) s->m_ptr, s->m_name, s->m_count); |
| 274 | break; |
| 275 | case DT_CUSTOM: |
| 276 | case NOT_SUPPORTED: |
| 277 | default: |
| 278 | m_netlist->xfatalerror("found unsupported save element %s\n", s->m_name.cstr()); |
| 279 | break; |
| 280 | } |
| 281 | } |
| 212 | 282 | |
| 213 | 283 | } |
| 214 | 284 | |
| 215 | | ATTR_COLD UINT64 netlist_mame_device::execute_clocks_to_cycles(UINT64 clocks) const |
| 285 | ATTR_COLD UINT64 netlist_mame_device_t::execute_clocks_to_cycles(UINT64 clocks) const |
| 216 | 286 | { |
| 217 | 287 | return clocks; |
| 218 | 288 | } |
| 219 | 289 | |
| 220 | | ATTR_COLD UINT64 netlist_mame_device::execute_cycles_to_clocks(UINT64 cycles) const |
| 290 | ATTR_COLD UINT64 netlist_mame_device_t::execute_cycles_to_clocks(UINT64 cycles) const |
| 221 | 291 | { |
| 222 | 292 | return cycles; |
| 223 | 293 | } |
| 224 | 294 | |
| 225 | | ATTR_COLD offs_t netlist_mame_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) |
| 295 | ATTR_COLD offs_t netlist_mame_device_t::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) |
| 226 | 296 | { |
| 227 | | //char tmp[16]; |
| 228 | | unsigned startpc = pc; |
| 229 | | int relpc = pc - m_genPC; |
| 230 | | //UINT16 opcode = (oprom[pc - startpc] << 8) | oprom[pc+1 - startpc]; |
| 231 | | //UINT8 inst = opcode >> 13; |
| 297 | //char tmp[16]; |
| 298 | unsigned startpc = pc; |
| 299 | int relpc = pc - m_genPC; |
| 300 | //UINT16 opcode = (oprom[pc - startpc] << 8) | oprom[pc+1 - startpc]; |
| 301 | //UINT8 inst = opcode >> 13; |
| 232 | 302 | |
| 233 | | if (relpc >= 0 && relpc < m_netlist->queue().count()) |
| 234 | | { |
| 235 | | // sprintf(buffer, "%04x %02d %s", pc, relpc, m_netlist->queue()[m_netlist->queue().count() - relpc - 1].object().name().cstr()); |
| 236 | | int dpc = m_netlist->queue().count() - relpc - 1; |
| 237 | | sprintf(buffer, "%c %s @%10.7f", (relpc == 0) ? '*' : ' ', m_netlist->queue()[dpc].object().name().cstr(), |
| 238 | | m_netlist->queue()[dpc].time().as_double()); |
| 239 | | } |
| 240 | | else |
| 241 | | sprintf(buffer, "%s", ""); |
| 242 | | pc+=1; |
| 243 | | return (pc - startpc); |
| 303 | if (relpc >= 0 && relpc < m_netlist->queue().count()) |
| 304 | { |
| 305 | // sprintf(buffer, "%04x %02d %s", pc, relpc, m_netlist->queue()[m_netlist->queue().count() - relpc - 1].object().name().cstr()); |
| 306 | int dpc = m_netlist->queue().count() - relpc - 1; |
| 307 | sprintf(buffer, "%c %s @%10.7f", (relpc == 0) ? '*' : ' ', m_netlist->queue()[dpc].object().name().cstr(), |
| 308 | m_netlist->queue()[dpc].time().as_double()); |
| 309 | } |
| 310 | else |
| 311 | sprintf(buffer, "%s", ""); |
| 312 | pc+=1; |
| 313 | return (pc - startpc); |
| 244 | 314 | } |
| 245 | 315 | |
| 246 | | ATTR_HOT void netlist_mame_device::execute_run() |
| 316 | ATTR_HOT void netlist_mame_device_t::execute_run() |
| 247 | 317 | { |
| 248 | 318 | bool check_debugger = ((device_t::machine().debug_flags & DEBUG_FLAG_ENABLED) != 0); |
| 249 | 319 | // debugging |
| 250 | 320 | //m_ppc = m_pc; // copy PC to previous PC |
| 251 | 321 | if (check_debugger) |
| 252 | 322 | { |
| 253 | | while (m_icount > 0) |
| 254 | | { |
| 255 | | int m_temp = 1; |
| 256 | | m_genPC++; |
| 257 | | m_genPC &= 255; |
| 258 | | debugger_instruction_hook(this, m_genPC); |
| 259 | | m_netlist->process_queue(m_temp); |
| 260 | | m_icount -= (1 - m_temp); |
| 261 | | } |
| 323 | while (m_icount > 0) |
| 324 | { |
| 325 | int m_temp = 1; |
| 326 | m_genPC++; |
| 327 | m_genPC &= 255; |
| 328 | debugger_instruction_hook(this, m_genPC); |
| 329 | m_netlist->process_queue(m_temp); |
| 330 | m_icount -= (1 - m_temp); |
| 331 | } |
| 262 | 332 | } |
| 263 | 333 | else |
| 264 | | m_netlist->process_queue(m_icount); |
| 334 | m_netlist->process_queue(m_icount); |
| 265 | 335 | } |
| 266 | | |
trunk/src/emu/machine/netlist.h
| r26783 | r26784 | |
| 59 | 59 | #define MCFG_NETLIST_ADD(_tag, _setup ) \ |
| 60 | 60 | MCFG_DEVICE_ADD(_tag, NETLIST, NETLIST_CLOCK) \ |
| 61 | 61 | MCFG_NETLIST_SETUP(_setup) |
| 62 | |
| 62 | 63 | #define MCFG_NETLIST_REPLACE(_tag, _setup) \ |
| 63 | 64 | MCFG_DEVICE_REPLACE(_tag, NETLIST, NETLIST_CLOCK) \ |
| 64 | 65 | MCFG_NETLIST_SETUP(_setup) |
| 66 | |
| 65 | 67 | #define MCFG_NETLIST_SETUP(_setup) \ |
| 66 | | netlist_mame_device::static_set_constructor(*device, NETLIST_NAME(_setup)); |
| 68 | netlist_mame_device_t::static_set_constructor(*device, NETLIST_NAME(_setup)); |
| 67 | 69 | |
| 70 | #define MCFG_NETLIST_ANALOG_INPUT(_basetag, _tag, _name) \ |
| 71 | MCFG_DEVICE_ADD(_basetag ":" _tag, NETLIST_ANALOG_INPUT, 0) \ |
| 72 | netlist_mame_analog_input_t::static_set_name(*device, _name); |
| 73 | |
| 74 | #define MCFG_NETLIST_ANALOG_INPUT_MULT_OFFSET(_mult, _offset) \ |
| 75 | netlist_mame_analog_input_t::static_set_mult_offset(*device, _mult, _offset); |
| 76 | |
| 77 | #define NETLIST_ANALOG_PORT_CHANGED(_base, _tag) \ |
| 78 | PORT_CHANGED_MEMBER(_base ":" _tag, netlist_mame_analog_input_t, input_changed, 0) |
| 79 | |
| 80 | #define MCFG_NETLIST_LOGIC_INPUT(_basetag, _tag, _name, _shift, _mask) \ |
| 81 | MCFG_DEVICE_ADD(_basetag ":" _tag, NETLIST_LOGIC_INPUT, 0) \ |
| 82 | netlist_mame_logic_input_t::static_set_params(*device, _name, _mask, _shift); |
| 83 | |
| 84 | #define NETLIST_LOGIC_PORT_CHANGED(_base, _tag) \ |
| 85 | PORT_CHANGED_MEMBER(_base ":" _tag, netlist_mame_logic_input_t, input_changed, 0) |
| 86 | |
| 68 | 87 | // ---------------------------------------------------------------------------------------- |
| 69 | 88 | // Extensions to interface netlist with MAME code .... |
| 70 | 89 | // ---------------------------------------------------------------------------------------- |
| r26783 | r26784 | |
| 83 | 102 | #define NETDEV_ANALOG_CALLBACK_MEMBER(_name) \ |
| 84 | 103 | void _name(const double data, const attotime &time) |
| 85 | 104 | |
| 86 | | class netlist_mame_device; |
| 105 | class netlist_mame_device_t; |
| 87 | 106 | |
| 88 | 107 | class netlist_mame_t : public netlist_base_t |
| 89 | 108 | { |
| 90 | 109 | public: |
| 91 | 110 | |
| 92 | | netlist_mame_t(netlist_mame_device &parent) |
| 111 | netlist_mame_t(netlist_mame_device_t &parent) |
| 93 | 112 | : netlist_base_t(), |
| 94 | 113 | m_parent(parent) |
| 95 | 114 | {} |
| r26783 | r26784 | |
| 97 | 116 | |
| 98 | 117 | inline running_machine &machine(); |
| 99 | 118 | |
| 100 | | netlist_mame_device &parent() { return m_parent; } |
| 119 | netlist_mame_device_t &parent() { return m_parent; } |
| 101 | 120 | |
| 102 | 121 | protected: |
| 103 | 122 | |
| r26783 | r26784 | |
| 108 | 127 | } |
| 109 | 128 | |
| 110 | 129 | private: |
| 111 | | netlist_mame_device &m_parent; |
| 130 | netlist_mame_device_t &m_parent; |
| 112 | 131 | }; |
| 113 | 132 | |
| 114 | 133 | // ---------------------------------------------------------------------------------------- |
| 115 | | // MAME glue classes |
| 134 | // netlist_mame_device_t |
| 116 | 135 | // ---------------------------------------------------------------------------------------- |
| 117 | 136 | |
| 118 | | |
| 119 | | |
| 120 | | |
| 121 | | // ======================> netlist_mame_device |
| 122 | | |
| 123 | | class netlist_mame_device : public device_t, |
| 124 | | public device_execute_interface, |
| 125 | | public device_state_interface, |
| 126 | | public device_disasm_interface, |
| 127 | | public device_memory_interface |
| 137 | class netlist_mame_device_t : public device_t, |
| 138 | public device_execute_interface, |
| 139 | public device_state_interface, |
| 140 | public device_disasm_interface, |
| 141 | public device_memory_interface |
| 128 | 142 | { |
| 129 | 143 | public: |
| 130 | 144 | |
| 131 | | template<bool _Required, class _NETClass> |
| 132 | | class output_finder; |
| 133 | | template<class C> |
| 134 | | class optional_output; |
| 135 | | template<class C> |
| 136 | | class required_output; |
| 137 | | template<class C> |
| 138 | | class optional_param; |
| 139 | | template<class C> |
| 140 | | class required_param; |
| 141 | | class on_device_start; |
| 142 | | |
| 143 | 145 | // construction/destruction |
| 144 | | netlist_mame_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 145 | | virtual ~netlist_mame_device() {} |
| 146 | netlist_mame_device_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 147 | virtual ~netlist_mame_device_t() {} |
| 146 | 148 | |
| 147 | 149 | static void static_set_constructor(device_t &device, void (*setup_func)(netlist_setup_t &)); |
| 148 | 150 | |
| 149 | 151 | netlist_setup_t &setup() { return *m_setup; } |
| 150 | 152 | netlist_mame_t &netlist() { return *m_netlist; } |
| 151 | 153 | |
| 152 | | typedef netlist_list_t<on_device_start *> device_start_list_t; |
| 153 | | |
| 154 | | device_start_list_t m_device_start_list; |
| 155 | | |
| 156 | 154 | protected: |
| 157 | 155 | // device-level overrides |
| 158 | 156 | virtual void device_config_complete(); |
| r26783 | r26784 | |
| 167 | 165 | |
| 168 | 166 | ATTR_HOT virtual void execute_run(); |
| 169 | 167 | |
| 170 | | // device_disasm_interface overrides |
| 171 | | ATTR_COLD virtual UINT32 disasm_min_opcode_bytes() const { return 1; } |
| 172 | | ATTR_COLD virtual UINT32 disasm_max_opcode_bytes() const { return 1; } |
| 173 | | ATTR_COLD virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options); |
| 168 | // device_disasm_interface overrides |
| 169 | ATTR_COLD virtual UINT32 disasm_min_opcode_bytes() const { return 1; } |
| 170 | ATTR_COLD virtual UINT32 disasm_max_opcode_bytes() const { return 1; } |
| 171 | ATTR_COLD virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options); |
| 174 | 172 | |
| 175 | | // device_memory_interface overrides |
| 173 | // device_memory_interface overrides |
| 176 | 174 | |
| 177 | | address_space_config m_program_config; |
| 175 | address_space_config m_program_config; |
| 178 | 176 | |
| 179 | | virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const |
| 180 | | { |
| 181 | | switch (spacenum) |
| 182 | | { |
| 183 | | case AS_PROGRAM: return &m_program_config; |
| 184 | | case AS_IO: return NULL; |
| 185 | | default: return NULL; |
| 186 | | } |
| 187 | | } |
| 177 | virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const |
| 178 | { |
| 179 | switch (spacenum) |
| 180 | { |
| 181 | case AS_PROGRAM: return &m_program_config; |
| 182 | case AS_IO: return NULL; |
| 183 | default: return NULL; |
| 184 | } |
| 185 | } |
| 188 | 186 | |
| 189 | | virtual void state_string_export(const device_state_entry &entry, astring &string) |
| 190 | | { |
| 191 | | if (entry.index() >= 0) |
| 192 | | { |
| 193 | | if (entry.index() & 1) |
| 194 | | string.format("%10.6f", *((double *) entry.dataptr())); |
| 195 | | else |
| 196 | | string.format("%d", *((netlist_sig_t *) entry.dataptr())); |
| 197 | | } |
| 198 | | } |
| 187 | virtual void state_string_export(const device_state_entry &entry, astring &string) |
| 188 | { |
| 189 | if (entry.index() >= 0) |
| 190 | { |
| 191 | if (entry.index() & 1) |
| 192 | string.format("%10.6f", *((double *) entry.dataptr())); |
| 193 | else |
| 194 | string.format("%d", *((netlist_sig_t *) entry.dataptr())); |
| 195 | } |
| 196 | } |
| 199 | 197 | |
| 200 | 198 | |
| 201 | 199 | netlist_mame_t *m_netlist; |
| r26783 | r26784 | |
| 208 | 206 | void (*m_setup_func)(netlist_setup_t &); |
| 209 | 207 | |
| 210 | 208 | int m_icount; |
| 211 | | int m_genPC; |
| 209 | int m_genPC; |
| 212 | 210 | |
| 213 | | |
| 214 | | |
| 215 | 211 | }; |
| 216 | 212 | |
| 217 | 213 | inline running_machine &netlist_mame_t::machine() |
| r26783 | r26784 | |
| 220 | 216 | } |
| 221 | 217 | |
| 222 | 218 | // ---------------------------------------------------------------------------------------- |
| 219 | // netlist_mame_sub_interface |
| 220 | // ---------------------------------------------------------------------------------------- |
| 221 | |
| 222 | class netlist_mame_sub_interface |
| 223 | { |
| 224 | public: |
| 225 | // construction/destruction |
| 226 | netlist_mame_sub_interface(netlist_mame_device_t &obj) : m_object(obj) {} |
| 227 | virtual ~netlist_mame_sub_interface() { } |
| 228 | |
| 229 | virtual void custom_netlist_additions(netlist_base_t &netlist) { } |
| 230 | |
| 231 | inline netlist_mame_device_t &object() { return m_object; } |
| 232 | private: |
| 233 | netlist_mame_device_t &m_object; |
| 234 | }; |
| 235 | |
| 236 | // ---------------------------------------------------------------------------------------- |
| 237 | // netlist_mame_analog_input_t |
| 238 | // ---------------------------------------------------------------------------------------- |
| 239 | |
| 240 | class netlist_mame_analog_input_t : public device_t, |
| 241 | public netlist_mame_sub_interface |
| 242 | { |
| 243 | public: |
| 244 | |
| 245 | // construction/destruction |
| 246 | netlist_mame_analog_input_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 247 | virtual ~netlist_mame_analog_input_t() { } |
| 248 | |
| 249 | static void static_set_name(device_t &device, const char *param_name); |
| 250 | static void static_set_mult_offset(device_t &device, const double mult, const double offset); |
| 251 | |
| 252 | inline void write(const double val) { m_param->setTo(val * m_mult + m_offset); } |
| 253 | |
| 254 | inline DECLARE_INPUT_CHANGED_MEMBER(input_changed) |
| 255 | { |
| 256 | if (m_auto_port) |
| 257 | write(((double) newval - (double) field.minval())/((double) (field.maxval()-field.minval()) ) ); |
| 258 | else |
| 259 | write(newval); |
| 260 | } |
| 261 | inline DECLARE_WRITE_LINE_MEMBER(write_line) { write(state); } |
| 262 | inline DECLARE_WRITE8_MEMBER(write8) { write(data); } |
| 263 | inline DECLARE_WRITE16_MEMBER(write16) { write(data); } |
| 264 | inline DECLARE_WRITE32_MEMBER(write32) { write(data); } |
| 265 | inline DECLARE_WRITE64_MEMBER(write64) { write(data); } |
| 266 | |
| 267 | protected: |
| 268 | // device-level overrides |
| 269 | virtual void device_start(); |
| 270 | |
| 271 | private: |
| 272 | netlist_param_double_t *m_param; |
| 273 | double m_offset; |
| 274 | double m_mult; |
| 275 | bool m_auto_port; |
| 276 | pstring m_param_name; |
| 277 | }; |
| 278 | |
| 279 | // ---------------------------------------------------------------------------------------- |
| 280 | // netlist_mame_logic_input_t |
| 281 | // ---------------------------------------------------------------------------------------- |
| 282 | |
| 283 | class netlist_mame_logic_input_t : public device_t, |
| 284 | public netlist_mame_sub_interface |
| 285 | { |
| 286 | public: |
| 287 | |
| 288 | // construction/destruction |
| 289 | netlist_mame_logic_input_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 290 | virtual ~netlist_mame_logic_input_t() { } |
| 291 | |
| 292 | static void static_set_params(device_t &device, const char *param_name, const UINT32 mask, const UINT32 shift); |
| 293 | |
| 294 | inline void write(const UINT32 val) { m_param->setTo((val >> m_shift) & m_mask); } |
| 295 | |
| 296 | inline DECLARE_INPUT_CHANGED_MEMBER(input_changed) { write(newval); } |
| 297 | DECLARE_WRITE_LINE_MEMBER(write_line) { write(state); } |
| 298 | DECLARE_WRITE8_MEMBER(write8) { write(data); } |
| 299 | DECLARE_WRITE16_MEMBER(write16) { write(data); } |
| 300 | DECLARE_WRITE32_MEMBER(write32) { write(data); } |
| 301 | DECLARE_WRITE64_MEMBER(write64) { write(data); } |
| 302 | |
| 303 | protected: |
| 304 | // device-level overrides |
| 305 | virtual void device_start(); |
| 306 | |
| 307 | private: |
| 308 | netlist_param_int_t *m_param; |
| 309 | UINT32 m_mask; |
| 310 | UINT32 m_shift; |
| 311 | pstring m_param_name; |
| 312 | }; |
| 313 | |
| 314 | // ---------------------------------------------------------------------------------------- |
| 223 | 315 | // netdev_callback |
| 224 | 316 | // ---------------------------------------------------------------------------------------- |
| 225 | 317 | |
| r26783 | r26784 | |
| 300 | 392 | }; |
| 301 | 393 | |
| 302 | 394 | |
| 303 | | // ======================> netlist_output_finder |
| 304 | | |
| 305 | | class netlist_mame_device::on_device_start |
| 306 | | { |
| 307 | | public: |
| 308 | | virtual bool OnDeviceStart() = 0; |
| 309 | | virtual ~on_device_start() {} |
| 310 | | }; |
| 311 | | |
| 312 | | // device finder template |
| 313 | | template<bool _Required, class _NETClass> |
| 314 | | class netlist_mame_device::output_finder : public object_finder_base<_NETClass>, |
| 315 | | netlist_mame_device::on_device_start |
| 316 | | { |
| 317 | | public: |
| 318 | | // construction/destruction |
| 319 | | output_finder(device_t &base, const char *tag, const char *output) |
| 320 | | : object_finder_base<_NETClass>(base, tag), m_netlist(NULL), m_output(output) { } |
| 321 | | |
| 322 | | // finder |
| 323 | | virtual bool findit(bool isvalidation = false) |
| 324 | | { |
| 325 | | if (isvalidation) return true; |
| 326 | | device_t *device = this->m_base.subdevice(this->m_tag); |
| 327 | | m_netlist = dynamic_cast<netlist_mame_device *>(device); |
| 328 | | if (device != NULL && m_netlist == NULL) |
| 329 | | { |
| 330 | | void mame_printf_warning(const char *format, ...) ATTR_PRINTF(1,2); |
| 331 | | mame_printf_warning("Device '%s' found but is not netlist\n", this->m_tag); |
| 332 | | } |
| 333 | | m_netlist->m_device_start_list.add(this); |
| 334 | | return this->report_missing(m_netlist != NULL, "device", _Required); |
| 335 | | } |
| 336 | | |
| 337 | | protected: |
| 338 | | netlist_mame_device *m_netlist; |
| 339 | | const char *m_output; |
| 340 | | }; |
| 341 | | |
| 342 | | // optional device finder |
| 343 | | template<class C> |
| 344 | | class netlist_mame_device::optional_output : public netlist_mame_device::output_finder<false, C> |
| 345 | | { |
| 346 | | public: |
| 347 | | optional_output(device_t &base, const char *tag, const char *output) : output_finder<false, C>(base, tag, output) { } |
| 348 | | |
| 349 | | virtual ~optional_output() {}; |
| 350 | | |
| 351 | | virtual bool OnDeviceStart() |
| 352 | | { |
| 353 | | this->m_target = dynamic_cast<C *>(this->m_netlist->setup().find_terminal(this->m_output, netlist_object_t::OUTPUT, false)); |
| 354 | | return this->report_missing(this->m_target != NULL, "output", false); |
| 355 | | } |
| 356 | | |
| 357 | | }; |
| 358 | | |
| 359 | | // required devices are similar but throw an error if they are not found |
| 360 | | template<class C> |
| 361 | | class netlist_mame_device::required_output : public netlist_mame_device::output_finder<true, C> |
| 362 | | { |
| 363 | | public: |
| 364 | | required_output(device_t &base, const char *tag, const char *output) : output_finder<true, C>(base, tag, output) { } |
| 365 | | |
| 366 | | virtual ~required_output() {}; |
| 367 | | |
| 368 | | virtual bool OnDeviceStart() |
| 369 | | { |
| 370 | | this->m_target = dynamic_cast<C *>(this->m_netlist->setup().find_terminal(this->m_output, netlist_object_t::OUTPUT)); |
| 371 | | return this->report_missing(this->m_target != NULL, "output", true); |
| 372 | | } |
| 373 | | |
| 374 | | }; |
| 375 | | |
| 376 | | // optional device finder |
| 377 | | template<class C> |
| 378 | | class netlist_mame_device::optional_param : public netlist_mame_device::output_finder<false, C> |
| 379 | | { |
| 380 | | public: |
| 381 | | optional_param(device_t &base, const char *tag, const char *output) : output_finder<false, C>(base, tag, output) { } |
| 382 | | |
| 383 | | virtual bool OnDeviceStart() |
| 384 | | { |
| 385 | | this->m_target = dynamic_cast<C *>(this->m_netlist->setup().find_param(this->m_output, false)); |
| 386 | | return this->report_missing(this->m_target != NULL, "parameter", false); |
| 387 | | } |
| 388 | | |
| 389 | | }; |
| 390 | | |
| 391 | | // required devices are similar but throw an error if they are not found |
| 392 | | template<class C> |
| 393 | | class netlist_mame_device::required_param : public netlist_mame_device::output_finder<true, C> |
| 394 | | { |
| 395 | | public: |
| 396 | | required_param(device_t &base, const char *tag, const char *output) : output_finder<true, C>(base, tag, output) { } |
| 397 | | |
| 398 | | virtual bool OnDeviceStart() |
| 399 | | { |
| 400 | | this->m_target = dynamic_cast<C *>( this->m_netlist->setup().find_param(this->m_output)); |
| 401 | | return this->report_missing(this->m_target != NULL, "parameter", true); |
| 402 | | } |
| 403 | | }; |
| 404 | | |
| 405 | | |
| 406 | 395 | // device type definition |
| 407 | 396 | extern const device_type NETLIST; |
| 397 | extern const device_type NETLIST_ANALOG_INPUT; |
| 398 | extern const device_type NETLIST_LOGIC_INPUT; |
| 408 | 399 | |
| 409 | 400 | #endif |
trunk/src/emu/netlist/devices/nld_74107.c
| r26783 | r26784 | |
| 7 | 7 | |
| 8 | 8 | NETLIB_START(nic74107Asub) |
| 9 | 9 | { |
| 10 | | register_input("CLK", m_clk, netlist_input_t::STATE_INP_HL); |
| 11 | | register_output("Q", m_Q); |
| 12 | | register_output("QQ", m_QQ); |
| 10 | register_input("CLK", m_clk, netlist_input_t::STATE_INP_HL); |
| 11 | register_output("Q", m_Q); |
| 12 | register_output("QQ", m_QQ); |
| 13 | 13 | |
| 14 | | m_Q.initial(0); |
| 15 | | m_QQ.initial(1); |
| 14 | m_Q.initial(0); |
| 15 | m_QQ.initial(1); |
| 16 | 16 | |
| 17 | | m_Q1 = 0; |
| 18 | | m_Q2 = 0; |
| 19 | | m_F = 0; |
| 17 | m_Q1 = 0; |
| 18 | m_Q2 = 0; |
| 19 | m_F = 0; |
| 20 | 20 | |
| 21 | | save(NAME(m_Q1)); |
| 22 | | save(NAME(m_Q2)); |
| 23 | | save(NAME(m_F)); |
| 21 | save(NAME(m_Q1)); |
| 22 | save(NAME(m_Q2)); |
| 23 | save(NAME(m_F)); |
| 24 | 24 | } |
| 25 | 25 | |
| 26 | 26 | NETLIB_START(nic74107A) |
| 27 | 27 | { |
| 28 | | register_sub(sub, "sub"); |
| 28 | register_sub(sub, "sub"); |
| 29 | 29 | |
| 30 | | register_subalias("CLK", sub.m_clk); |
| 31 | | register_input("J", m_J); |
| 32 | | register_input("K", m_K); |
| 33 | | register_input("CLRQ", m_clrQ); |
| 34 | | register_subalias("Q", sub.m_Q); |
| 35 | | register_subalias("QQ", sub.m_QQ); |
| 30 | register_subalias("CLK", sub.m_clk); |
| 31 | register_input("J", m_J); |
| 32 | register_input("K", m_K); |
| 33 | register_input("CLRQ", m_clrQ); |
| 34 | register_subalias("Q", sub.m_Q); |
| 35 | register_subalias("QQ", sub.m_QQ); |
| 36 | 36 | |
| 37 | 37 | } |
| 38 | 38 | |
| 39 | 39 | ATTR_HOT inline void NETLIB_NAME(nic74107Asub)::newstate(const netlist_sig_t state) |
| 40 | 40 | { |
| 41 | | const netlist_time delay[2] = { NLTIME_FROM_NS(40), NLTIME_FROM_NS(25) }; |
| 41 | const netlist_time delay[2] = { NLTIME_FROM_NS(40), NLTIME_FROM_NS(25) }; |
| 42 | 42 | |
| 43 | | OUTLOGIC(m_Q, state, delay[state ^ 1]); |
| 44 | | OUTLOGIC(m_QQ, state ^ 1, delay[state]); |
| 43 | OUTLOGIC(m_Q, state, delay[state ^ 1]); |
| 44 | OUTLOGIC(m_QQ, state ^ 1, delay[state]); |
| 45 | 45 | } |
| 46 | 46 | |
| 47 | 47 | NETLIB_UPDATE(nic74107Asub) |
| 48 | 48 | { |
| 49 | | const netlist_sig_t t = m_Q.net().Q(); |
| 50 | | newstate((!t & m_Q1) | (t & m_Q2) | m_F); |
| 51 | | if (!m_Q1) |
| 52 | | m_clk.inactivate(); |
| 49 | const netlist_sig_t t = m_Q.net().Q(); |
| 50 | newstate((!t & m_Q1) | (t & m_Q2) | m_F); |
| 51 | if (!m_Q1) |
| 52 | m_clk.inactivate(); |
| 53 | 53 | } |
| 54 | 54 | |
| 55 | 55 | NETLIB_UPDATE(nic74107A) |
| 56 | 56 | { |
| 57 | | const UINT8 JK = (INPLOGIC(m_J) << 1) | INPLOGIC(m_K); |
| 57 | const UINT8 JK = (INPLOGIC(m_J) << 1) | INPLOGIC(m_K); |
| 58 | 58 | |
| 59 | | switch (JK) |
| 60 | | { |
| 61 | | case 0: |
| 62 | | sub.m_Q1 = 0; |
| 63 | | sub.m_Q2 = 1; |
| 64 | | sub.m_F = 0; |
| 65 | | sub.m_clk.inactivate(); |
| 66 | | break; |
| 67 | | case 1: // (!INPLOGIC(m_J) & INPLOGIC(m_K)) |
| 68 | | sub.m_Q1 = 0; |
| 69 | | sub.m_Q2 = 0; |
| 70 | | sub.m_F = 0; |
| 71 | | break; |
| 72 | | case 2: // (INPLOGIC(m_J) & !INPLOGIC(m_K)) |
| 73 | | sub.m_Q1 = 0; |
| 74 | | sub.m_Q2 = 0; |
| 75 | | sub.m_F = 1; |
| 76 | | break; |
| 77 | | case 3: // (INPLOGIC(m_J) & INPLOGIC(m_K)) |
| 78 | | sub.m_Q1 = 1; |
| 79 | | sub.m_Q2 = 0; |
| 80 | | sub.m_F = 0; |
| 81 | | break; |
| 82 | | default: |
| 83 | | break; |
| 84 | | } |
| 59 | switch (JK) |
| 60 | { |
| 61 | case 0: |
| 62 | sub.m_Q1 = 0; |
| 63 | sub.m_Q2 = 1; |
| 64 | sub.m_F = 0; |
| 65 | sub.m_clk.inactivate(); |
| 66 | break; |
| 67 | case 1: // (!INPLOGIC(m_J) & INPLOGIC(m_K)) |
| 68 | sub.m_Q1 = 0; |
| 69 | sub.m_Q2 = 0; |
| 70 | sub.m_F = 0; |
| 71 | break; |
| 72 | case 2: // (INPLOGIC(m_J) & !INPLOGIC(m_K)) |
| 73 | sub.m_Q1 = 0; |
| 74 | sub.m_Q2 = 0; |
| 75 | sub.m_F = 1; |
| 76 | break; |
| 77 | case 3: // (INPLOGIC(m_J) & INPLOGIC(m_K)) |
| 78 | sub.m_Q1 = 1; |
| 79 | sub.m_Q2 = 0; |
| 80 | sub.m_F = 0; |
| 81 | break; |
| 82 | default: |
| 83 | break; |
| 84 | } |
| 85 | 85 | |
| 86 | | if (!INPLOGIC(m_clrQ)) |
| 87 | | { |
| 88 | | sub.m_clk.inactivate(); |
| 89 | | sub.newstate(0); |
| 90 | | } |
| 91 | | else if (!sub.m_Q2) |
| 92 | | sub.m_clk.activate_hl(); |
| 86 | if (!INPLOGIC(m_clrQ)) |
| 87 | { |
| 88 | sub.m_clk.inactivate(); |
| 89 | sub.newstate(0); |
| 90 | } |
| 91 | else if (!sub.m_Q2) |
| 92 | sub.m_clk.activate_hl(); |
| 93 | 93 | } |
trunk/src/emu/netlist/nl_base.c
| r26783 | r26784 | |
| 15 | 15 | // ---------------------------------------------------------------------------------------- |
| 16 | 16 | |
| 17 | 17 | netlist_queue_t::netlist_queue_t(netlist_base_t &nl) |
| 18 | | : netlist_timed_queue<netlist_net_t, netlist_time, 512>(), pstate_callback_t(), |
| 19 | | m_netlist(nl), |
| 20 | | m_qsize(0) |
| 18 | : netlist_timed_queue<netlist_net_t, netlist_time, 512>(), pstate_callback_t(), |
| 19 | m_netlist(nl), |
| 20 | m_qsize(0) |
| 21 | 21 | { } |
| 22 | 22 | |
| 23 | 23 | void netlist_queue_t::register_state(pstate_manager_t &manager, const pstring &module) |
| 24 | 24 | { |
| 25 | | NL_VERBOSE_OUT(("register_state\n")); |
| 26 | | manager.save_manager(m_qsize, module + "." + "qsize"); |
| 27 | | manager.save_manager(m_times, module + "." + "times"); |
| 28 | | manager.save_manager(&(m_name[0][0]), module + "." + "names", sizeof(m_name)); |
| 25 | NL_VERBOSE_OUT(("register_state\n")); |
| 26 | manager.save_item(m_qsize, module + "." + "qsize"); |
| 27 | manager.save_item(m_times, module + "." + "times"); |
| 28 | manager.save_item(&(m_name[0][0]), module + "." + "names", sizeof(m_name)); |
| 29 | 29 | } |
| 30 | 30 | void netlist_queue_t::on_pre_save() |
| 31 | 31 | { |
| 32 | | NL_VERBOSE_OUT(("on_pre_save\n")); |
| 33 | | m_qsize = this->count(); |
| 34 | | NL_VERBOSE_OUT(("current time %f qsize %d\n", m_netlist->time().as_double(), qsize)); |
| 35 | | for (int i = 0; i < m_qsize; i++ ) |
| 36 | | { |
| 37 | | m_times[i] = this->listptr()[i].time().as_raw(); |
| 38 | | const char *p = this->listptr()[i].object().name().cstr(); |
| 39 | | int n = MIN(63, strlen(p)); |
| 40 | | strncpy(&(m_name[i][0]), p, n); |
| 41 | | m_name[i][n] = 0; |
| 42 | | } |
| 32 | NL_VERBOSE_OUT(("on_pre_save\n")); |
| 33 | m_qsize = this->count(); |
| 34 | NL_VERBOSE_OUT(("current time %f qsize %d\n", m_netlist->time().as_double(), qsize)); |
| 35 | for (int i = 0; i < m_qsize; i++ ) |
| 36 | { |
| 37 | m_times[i] = this->listptr()[i].time().as_raw(); |
| 38 | const char *p = this->listptr()[i].object().name().cstr(); |
| 39 | int n = MIN(63, strlen(p)); |
| 40 | strncpy(&(m_name[i][0]), p, n); |
| 41 | m_name[i][n] = 0; |
| 42 | } |
| 43 | 43 | } |
| 44 | 44 | |
| 45 | 45 | |
| 46 | 46 | void netlist_queue_t::on_post_load() |
| 47 | 47 | { |
| 48 | | this->clear(); |
| 49 | | NL_VERBOSE_OUT(("current time %f qsize %d\n", m_netlist->time().as_double(), qsize)); |
| 50 | | for (int i = 0; i < m_qsize; i++ ) |
| 51 | | { |
| 52 | | netlist_net_t *n = m_netlist.find_net(&(m_name[i][0])); |
| 53 | | NL_VERBOSE_OUT(("Got %s ==> %p\n", qtemp[i].m_name, n)); |
| 54 | | NL_VERBOSE_OUT(("schedule time %f (%f)\n", n->time().as_double(), qtemp[i].m_time.as_double())); |
| 55 | | this->push(netlist_queue_t::entry_t(netlist_time::from_raw(m_times[i]), *n)); |
| 56 | | } |
| 48 | this->clear(); |
| 49 | NL_VERBOSE_OUT(("current time %f qsize %d\n", m_netlist->time().as_double(), qsize)); |
| 50 | for (int i = 0; i < m_qsize; i++ ) |
| 51 | { |
| 52 | netlist_net_t *n = m_netlist.find_net(&(m_name[i][0])); |
| 53 | NL_VERBOSE_OUT(("Got %s ==> %p\n", qtemp[i].m_name, n)); |
| 54 | NL_VERBOSE_OUT(("schedule time %f (%f)\n", n->time().as_double(), qtemp[i].m_time.as_double())); |
| 55 | this->push(netlist_queue_t::entry_t(netlist_time::from_raw(m_times[i]), *n)); |
| 56 | } |
| 57 | 57 | } |
| 58 | 58 | |
| 59 | 59 | // ---------------------------------------------------------------------------------------- |
| r26783 | r26784 | |
| 108 | 108 | // ---------------------------------------------------------------------------------------- |
| 109 | 109 | |
| 110 | 110 | netlist_base_t::netlist_base_t() |
| 111 | | : netlist_object_t(NETLIST, GENERIC), |
| 112 | | m_time_ps(netlist_time::zero), |
| 113 | | m_queue(*this), |
| 114 | | m_rem(0), |
| 115 | | m_div(NETLIST_DIV), |
| 116 | | m_mainclock(NULL), |
| 117 | | m_solver(NULL) |
| 111 | : netlist_object_t(NETLIST, GENERIC), |
| 112 | m_time_ps(netlist_time::zero), |
| 113 | m_queue(*this), |
| 114 | m_rem(0), |
| 115 | m_div(NETLIST_DIV), |
| 116 | m_mainclock(NULL), |
| 117 | m_solver(NULL) |
| 118 | 118 | { |
| 119 | 119 | } |
| 120 | 120 | |
| r26783 | r26784 | |
| 216 | 216 | |
| 217 | 217 | ATTR_HOT ATTR_ALIGN void netlist_base_t::process_queue(INT32 &atime) |
| 218 | 218 | { |
| 219 | | if (m_mainclock == NULL) |
| 220 | | { |
| 221 | | while ( (atime > 0) && (m_queue.is_not_empty())) |
| 222 | | { |
| 223 | | const netlist_queue_t::entry_t &e = m_queue.pop(); |
| 224 | | update_time(e.time(), atime); |
| 219 | if (m_mainclock == NULL) |
| 220 | { |
| 221 | while ( (atime > 0) && (m_queue.is_not_empty())) |
| 222 | { |
| 223 | const netlist_queue_t::entry_t &e = m_queue.pop(); |
| 224 | update_time(e.time(), atime); |
| 225 | 225 | |
| 226 | 226 | //if (FATAL_ERROR_AFTER_NS) |
| 227 | 227 | // NL_VERBOSE_OUT(("%s\n", e.object().netdev()->name().cstr()); |
| r26783 | r26784 | |
| 254 | 254 | |
| 255 | 255 | NETLIB_NAME(mainclock)::mc_update(mcQ, time() + inc); |
| 256 | 256 | |
| 257 | | } |
| 258 | | const netlist_queue_t::entry_t &e = m_queue.pop(); |
| 257 | } |
| 258 | const netlist_queue_t::entry_t &e = m_queue.pop(); |
| 259 | 259 | |
| 260 | 260 | update_time(e.time(), atime); |
| 261 | 261 | |
trunk/src/emu/netlist/pstate.h
| r26783 | r26784 | |
| 16 | 16 | // ---------------------------------------------------------------------------------------- |
| 17 | 17 | |
| 18 | 18 | #define PSTATE_INTERFACE_DECL() \ |
| 19 | | template<typename C> ATTR_COLD void save(C &state, const pstring &stname); |
| 19 | template<typename C> ATTR_COLD void save(C &state, const pstring &stname); |
| 20 | 20 | |
| 21 | 21 | #define PSTATE_INTERFACE(obj, manager, module) \ |
| 22 | | template<typename C> ATTR_COLD void obj::save(C &state, const pstring &stname) \ |
| 23 | | { \ |
| 24 | | manager->save_manager(state, module + "." + stname); \ |
| 25 | | } |
| 22 | template<typename C> ATTR_COLD void obj::save(C &state, const pstring &stname) \ |
| 23 | { \ |
| 24 | manager->save_item(state, module + "." + stname); \ |
| 25 | } |
| 26 | 26 | |
| 27 | 27 | enum pstate_data_type_e { |
| 28 | | NOT_SUPPORTED, |
| 29 | | DT_CUSTOM, |
| 30 | | DT_DOUBLE, |
| 31 | | DT_INT64, |
| 32 | | DT_INT8, |
| 33 | | DT_INT, |
| 34 | | DT_BOOLEAN |
| 28 | NOT_SUPPORTED, |
| 29 | DT_CUSTOM, |
| 30 | DT_DOUBLE, |
| 31 | DT_INT64, |
| 32 | DT_INT8, |
| 33 | DT_INT, |
| 34 | DT_BOOLEAN |
| 35 | 35 | }; |
| 36 | 36 | |
| 37 | 37 | template<typename _ItemType> struct nl_datatype { static const pstate_data_type_e type = pstate_data_type_e(NOT_SUPPORTED); }; |
| r26783 | r26784 | |
| 54 | 54 | { |
| 55 | 55 | typedef netlist_list_t<pstate_entry_t *> list_t; |
| 56 | 56 | |
| 57 | | pstate_entry_t(const pstring &stname, const pstate_data_type_e dt, const int size, const int count, void *ptr) : |
| 58 | | m_name(stname), m_dt(dt), m_size(size), m_count(count), m_ptr(ptr) { } |
| 59 | | pstring m_name; |
| 60 | | pstate_data_type_e m_dt; |
| 61 | | int m_size; |
| 62 | | int m_count; |
| 63 | | void *m_ptr; |
| 57 | pstate_entry_t(const pstring &stname, const pstate_data_type_e dt, const int size, const int count, void *ptr) : |
| 58 | m_name(stname), m_dt(dt), m_size(size), m_count(count), m_ptr(ptr) { } |
| 59 | pstring m_name; |
| 60 | pstate_data_type_e m_dt; |
| 61 | int m_size; |
| 62 | int m_count; |
| 63 | void *m_ptr; |
| 64 | 64 | }; |
| 65 | 65 | |
| 66 | 66 | class pstate_manager_t; |
| r26783 | r26784 | |
| 68 | 68 | class pstate_callback_t |
| 69 | 69 | { |
| 70 | 70 | public: |
| 71 | | typedef netlist_list_t<pstate_callback_t *> list_t; |
| 71 | typedef netlist_list_t<pstate_callback_t *> list_t; |
| 72 | 72 | |
| 73 | | virtual ~pstate_callback_t() { }; |
| 73 | virtual ~pstate_callback_t() { }; |
| 74 | 74 | |
| 75 | | virtual void register_state(pstate_manager_t &manager, const pstring &module) = 0; |
| 76 | | virtual void on_pre_save() = 0; |
| 77 | | virtual void on_post_load() = 0; |
| 75 | virtual void register_state(pstate_manager_t &manager, const pstring &module) = 0; |
| 76 | virtual void on_pre_save() = 0; |
| 77 | virtual void on_post_load() = 0; |
| 78 | 78 | protected: |
| 79 | 79 | }; |
| 80 | 80 | |
| r26783 | r26784 | |
| 84 | 84 | |
| 85 | 85 | ATTR_COLD ~pstate_manager_t(); |
| 86 | 86 | |
| 87 | | template<typename C> ATTR_COLD void save_manager(C &state, const pstring &stname) |
| 88 | | { |
| 89 | | save_state_ptr(stname, nl_datatype<C>::type, sizeof(C), 1, &state); |
| 90 | | } |
| 87 | template<typename C> ATTR_COLD void save_item(C &state, const pstring &stname) |
| 88 | { |
| 89 | save_state_ptr(stname, nl_datatype<C>::type, sizeof(C), 1, &state); |
| 90 | } |
| 91 | 91 | |
| 92 | | template<typename C, std::size_t N> ATTR_COLD void save_manager(C (&state)[N], const pstring &stname) |
| 93 | | { |
| 94 | | save_state_ptr(stname, nl_datatype<C>::type, sizeof(state[0]), N, &(state[0])); |
| 95 | | } |
| 92 | template<typename C, std::size_t N> ATTR_COLD void save_item(C (&state)[N], const pstring &stname) |
| 93 | { |
| 94 | save_state_ptr(stname, nl_datatype<C>::type, sizeof(state[0]), N, &(state[0])); |
| 95 | } |
| 96 | 96 | |
| 97 | | template<typename C> ATTR_COLD void save_manager(C *state, const pstring &stname, const int count) |
| 98 | | { |
| 99 | | save_state_ptr(stname, nl_datatype<C>::type, sizeof(C), count, state); |
| 100 | | } |
| 97 | template<typename C> ATTR_COLD void save_item(C *state, const pstring &stname, const int count) |
| 98 | { |
| 99 | save_state_ptr(stname, nl_datatype<C>::type, sizeof(C), count, state); |
| 100 | } |
| 101 | 101 | |
| 102 | | ATTR_COLD void pre_save(); |
| 103 | | ATTR_COLD void post_load(); |
| 102 | ATTR_COLD void pre_save(); |
| 103 | ATTR_COLD void post_load(); |
| 104 | 104 | |
| 105 | 105 | inline const pstate_entry_t::list_t &save_list() const { return m_save; } |
| 106 | 106 | |
| 107 | 107 | protected: |
| 108 | | ATTR_COLD void save_state_ptr(const pstring &stname, const pstate_data_type_e, const int size, const int count, void *ptr); |
| 108 | ATTR_COLD void save_state_ptr(const pstring &stname, const pstate_data_type_e, const int size, const int count, void *ptr); |
| 109 | 109 | |
| 110 | 110 | private: |
| 111 | 111 | pstate_entry_t::list_t m_save; |
| 112 | 112 | pstate_callback_t::list_t m_callback; |
| 113 | 113 | }; |
| 114 | 114 | |
| 115 | | template<> ATTR_COLD inline void pstate_manager_t::save_manager(pstate_callback_t &state, const pstring &stname) |
| 115 | template<> ATTR_COLD inline void pstate_manager_t::save_item(pstate_callback_t &state, const pstring &stname) |
| 116 | 116 | { |
| 117 | | //save_state_ptr(stname, DT_CUSTOM, 0, 1, &state); |
| 118 | | m_callback.add(&state); |
| 119 | | state.register_state(*this, stname); |
| 117 | //save_state_ptr(stname, DT_CUSTOM, 0, 1, &state); |
| 118 | m_callback.add(&state); |
| 119 | state.register_state(*this, stname); |
| 120 | 120 | } |
| 121 | 121 | |
| 122 | | template<> ATTR_COLD inline void pstate_manager_t::save_manager(netlist_time &nlt, const pstring &stname) |
| 122 | template<> ATTR_COLD inline void pstate_manager_t::save_item(netlist_time &nlt, const pstring &stname) |
| 123 | 123 | { |
| 124 | 124 | save_state_ptr(stname, DT_INT64, sizeof(netlist_time::INTERNALTYPE), 1, nlt.get_internaltype_ptr()); |
| 125 | 125 | } |
trunk/src/emu/netlist/nl_base.h
| r26783 | r26784 | |
| 185 | 185 | //#define NETLIB_CONSTRUCTOR(_chip) ATTR_COLD _chip :: _chip (netlist_setup_t &setup, const char *name) |
| 186 | 186 | // : net_device_t(setup, name) |
| 187 | 187 | |
| 188 | | #define NETLIB_UPDATE_PARAM(_chip) ATTR_COLD ATTR_ALIGN void NETLIB_NAME(_chip) :: update_param(void) |
| 188 | #define NETLIB_UPDATE_PARAM(_chip) ATTR_HOT ATTR_ALIGN void NETLIB_NAME(_chip) :: update_param(void) |
| 189 | 189 | #define NETLIB_FUNC_VOID(_chip, _name, _params) ATTR_HOT ATTR_ALIGN void NETLIB_NAME(_chip) :: _name _params |
| 190 | 190 | |
| 191 | 191 | #define NETLIB_UPDATE_TERMINALS() ATTR_HOT ATTR_ALIGN inline void update_terminals(void) |
| r26783 | r26784 | |
| 370 | 370 | protected: |
| 371 | 371 | ATTR_COLD virtual void save_register() |
| 372 | 372 | { |
| 373 | | save(NAME(m_state)); |
| 374 | | netlist_owned_object_t::save_register(); |
| 373 | save(NAME(m_state)); |
| 374 | netlist_owned_object_t::save_register(); |
| 375 | 375 | } |
| 376 | 376 | |
| 377 | 377 | private: |
| r26783 | r26784 | |
| 462 | 462 | class netlist_logic_input_t : public netlist_input_t |
| 463 | 463 | { |
| 464 | 464 | public: |
| 465 | | ATTR_COLD netlist_logic_input_t() |
| 465 | ATTR_COLD netlist_logic_input_t() |
| 466 | 466 | : netlist_input_t(INPUT, LOGIC) |
| 467 | 467 | { |
| 468 | 468 | // default to TTL |
| r26783 | r26784 | |
| 487 | 487 | class netlist_ttl_input_t : public netlist_logic_input_t |
| 488 | 488 | { |
| 489 | 489 | public: |
| 490 | | ATTR_COLD netlist_ttl_input_t() |
| 490 | ATTR_COLD netlist_ttl_input_t() |
| 491 | 491 | : netlist_logic_input_t() { set_thresholds(0.8 , 2.0); } |
| 492 | 492 | }; |
| 493 | 493 | |
| r26783 | r26784 | |
| 498 | 498 | class netlist_analog_input_t : public netlist_input_t |
| 499 | 499 | { |
| 500 | 500 | public: |
| 501 | | ATTR_COLD netlist_analog_input_t() |
| 501 | ATTR_COLD netlist_analog_input_t() |
| 502 | 502 | : netlist_input_t(INPUT, ANALOG) { } |
| 503 | 503 | |
| 504 | 504 | ATTR_HOT inline const double Q_Analog() const; |
| r26783 | r26784 | |
| 596 | 596 | hybrid_t m_cur; |
| 597 | 597 | hybrid_t m_new; |
| 598 | 598 | |
| 599 | /* use this to register state.... */ |
| 600 | ATTR_COLD virtual void late_save_register() |
| 601 | { |
| 602 | save(NAME(m_last.Analog)); |
| 603 | save(NAME(m_cur.Analog)); |
| 604 | save(NAME(m_new.Analog)); |
| 605 | save(NAME(m_last.Q)); |
| 606 | save(NAME(m_cur.Q)); |
| 607 | save(NAME(m_new.Q)); |
| 608 | save(NAME(m_time)); |
| 609 | save(NAME(m_active)); |
| 610 | save(NAME(m_in_queue)); |
| 611 | netlist_object_t::save_register(); |
| 612 | } |
| 613 | |
| 599 | 614 | protected: |
| 600 | 615 | UINT32 m_num_cons; |
| 601 | 616 | |
| 617 | /* we don't use this to save state |
| 618 | * because we may get deleted again ... |
| 619 | */ |
| 602 | 620 | ATTR_COLD virtual void save_register() |
| 603 | 621 | { |
| 604 | | save(NAME(m_last.Analog)); |
| 605 | | save(NAME(m_cur.Analog)); |
| 606 | | save(NAME(m_new.Analog)); |
| 607 | | save(NAME(m_last.Q)); |
| 608 | | save(NAME(m_cur.Q)); |
| 609 | | save(NAME(m_new.Q)); |
| 610 | | save(NAME(m_time)); |
| 611 | | save(NAME(m_active)); |
| 612 | | save(NAME(m_in_queue)); |
| 613 | | netlist_object_t::save_register(); |
| 622 | //assert_always(false, "trying too early to register state in netlist_net_t"); |
| 614 | 623 | } |
| 615 | 624 | |
| 625 | |
| 616 | 626 | private: |
| 617 | 627 | ATTR_HOT void update_dev(const netlist_core_terminal_t *inp, const UINT32 mask) const; |
| 618 | 628 | |
| r26783 | r26784 | |
| 950 | 960 | // ---------------------------------------------------------------------------------------- |
| 951 | 961 | |
| 952 | 962 | class netlist_queue_t : public netlist_timed_queue<netlist_net_t, netlist_time, 512>, |
| 953 | | public pstate_callback_t |
| 963 | public pstate_callback_t |
| 954 | 964 | { |
| 955 | 965 | public: |
| 956 | 966 | |
| 957 | | netlist_queue_t(netlist_base_t &nl); |
| 967 | netlist_queue_t(netlist_base_t &nl); |
| 958 | 968 | |
| 959 | | void register_state(pstate_manager_t &manager, const pstring &module); |
| 960 | | void on_pre_save(); |
| 961 | | void on_post_load(); |
| 969 | void register_state(pstate_manager_t &manager, const pstring &module); |
| 970 | void on_pre_save(); |
| 971 | void on_post_load(); |
| 962 | 972 | |
| 963 | | pstate_callback_t &callback() { return *this; } |
| 973 | pstate_callback_t &callback() { return *this; } |
| 964 | 974 | |
| 965 | 975 | private: |
| 966 | | netlist_base_t &m_netlist; |
| 967 | | int m_qsize; |
| 968 | | netlist_time::INTERNALTYPE m_times[512]; |
| 969 | | char m_name[512][64]; |
| 976 | netlist_base_t &m_netlist; |
| 977 | int m_qsize; |
| 978 | netlist_time::INTERNALTYPE m_times[512]; |
| 979 | char m_name[512][64]; |
| 970 | 980 | }; |
| 971 | 981 | |
| 972 | 982 | // ---------------------------------------------------------------------------------------- |
| r26783 | r26784 | |
| 984 | 994 | netlist_base_t(); |
| 985 | 995 | virtual ~netlist_base_t(); |
| 986 | 996 | |
| 987 | | ATTR_HOT inline const netlist_queue_t &queue() const { return m_queue; } |
| 988 | | ATTR_HOT inline netlist_queue_t &queue() { return m_queue; } |
| 997 | ATTR_HOT inline const netlist_queue_t &queue() const { return m_queue; } |
| 998 | ATTR_HOT inline netlist_queue_t &queue() { return m_queue; } |
| 989 | 999 | |
| 990 | 1000 | ATTR_HOT inline void push_to_queue(netlist_net_t &out, const netlist_time &attime) |
| 991 | 1001 | { |
| r26783 | r26784 | |
| 1020 | 1030 | virtual void vfatalerror(const char *format, va_list ap) const = 0; |
| 1021 | 1031 | |
| 1022 | 1032 | protected: |
| 1023 | | ATTR_COLD virtual void save_register() |
| 1024 | | { |
| 1025 | | save(NAME(m_queue.callback())); |
| 1026 | | save(NAME(m_time_ps)); |
| 1027 | | save(NAME(m_rem)); |
| 1028 | | save(NAME(m_div)); |
| 1029 | | netlist_object_t::save_register(); |
| 1030 | | } |
| 1033 | ATTR_COLD virtual void save_register() |
| 1034 | { |
| 1035 | save(NAME(m_queue.callback())); |
| 1036 | save(NAME(m_time_ps)); |
| 1037 | save(NAME(m_rem)); |
| 1038 | save(NAME(m_div)); |
| 1039 | netlist_object_t::save_register(); |
| 1040 | } |
| 1031 | 1041 | |
| 1032 | 1042 | #if (NL_KEEP_STATISTICS) |
| 1033 | 1043 | // performance |
| r26783 | r26784 | |
| 1039 | 1049 | private: |
| 1040 | 1050 | ATTR_HOT void update_time(const netlist_time t, INT32 &atime); |
| 1041 | 1051 | |
| 1042 | | netlist_time m_time_ps; |
| 1043 | | netlist_queue_t m_queue; |
| 1052 | netlist_time m_time_ps; |
| 1053 | netlist_queue_t m_queue; |
| 1044 | 1054 | UINT32 m_rem; |
| 1045 | 1055 | UINT32 m_div; |
| 1046 | 1056 | |
| r26783 | r26784 | |
| 1298 | 1308 | { |
| 1299 | 1309 | public: |
| 1300 | 1310 | |
| 1301 | | ATTR_COLD netlist_factory(); |
| 1302 | | ATTR_COLD ~netlist_factory(); |
| 1311 | ATTR_COLD netlist_factory(); |
| 1312 | ATTR_COLD ~netlist_factory(); |
| 1303 | 1313 | |
| 1304 | | ATTR_COLD void initialize(); |
| 1314 | ATTR_COLD void initialize(); |
| 1305 | 1315 | |
| 1306 | | template<class _C> |
| 1307 | | ATTR_COLD void register_device(const pstring &name, const pstring &classname) |
| 1316 | template<class _C> |
| 1317 | ATTR_COLD void register_device(const pstring &name, const pstring &classname) |
| 1308 | 1318 | { |
| 1309 | 1319 | m_list.add(new net_device_t_factory< _C >(name, classname) ); |
| 1310 | 1320 | } |
| 1311 | 1321 | |
| 1312 | | ATTR_COLD netlist_device_t *new_device_by_classname(const pstring &classname, netlist_setup_t &setup) const; |
| 1313 | | ATTR_COLD netlist_device_t *new_device_by_name(const pstring &name, netlist_setup_t &setup) const; |
| 1322 | ATTR_COLD netlist_device_t *new_device_by_classname(const pstring &classname, netlist_setup_t &setup) const; |
| 1323 | ATTR_COLD netlist_device_t *new_device_by_name(const pstring &name, netlist_setup_t &setup) const; |
| 1314 | 1324 | |
| 1315 | 1325 | private: |
| 1316 | 1326 | typedef netlist_list_t<net_device_t_base_factory *> list_t; |