mirror of
https://github.com/holub/mame
synced 2025-04-25 09:50:04 +03:00
Updated netlist implementation:
- Now supports any resolution fitting reasonably into a UINT64 - Execution now uses a list sorted by execution time - Implementation now supports analog and digital inputs / outputs - First step in a move to "terminals" being both input / output - Improved object model Pong: - Rewrote video code, now emulates a monitor by analyzing the analog video signal and identifying vsync and hysnc pulses. - Removed all hacks. Overall performance increase of about 10% over the previous "pongf" implementation.
This commit is contained in:
parent
4a73f8bcfb
commit
5280005bfa
File diff suppressed because it is too large
Load Diff
@ -54,12 +54,14 @@
|
||||
// Special chips
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
#define NETDEV_CONST(_name, _v) \
|
||||
NET_REGISTER_DEV(netdev_const, _name) \
|
||||
NETDEV_PARAM(_name.CONST, _v) \
|
||||
#define NETDEV_CLOCK(_name) \
|
||||
NET_REGISTER_DEV(netdev_clock, _name) \
|
||||
|
||||
#define NETDEV_INPUT(_name) \
|
||||
NET_REGISTER_DEV(netdev_input, _name) \
|
||||
#define NETDEV_LOGIC_INPUT(_name) \
|
||||
NET_REGISTER_DEV(netdev_logic_input, _name) \
|
||||
|
||||
#define NETDEV_ANALOG_INPUT(_name) \
|
||||
NET_REGISTER_DEV(netdev_analog_input, _name) \
|
||||
|
||||
#define NETDEV_CALLBACK(_name, _IN) \
|
||||
NET_REGISTER_DEV(netdev_callback, _name) \
|
||||
@ -92,7 +94,7 @@
|
||||
|
||||
#define TTL_7402_NOR(_name, _I1, _I2) \
|
||||
NET_REGISTER_DEV(nic7402, _name) \
|
||||
NET_CONNECT(_name, I1, _I1) \
|
||||
NET_CONNECT(_name, I1, _I1) \
|
||||
NET_CONNECT(_name, I2, _I2) \
|
||||
|
||||
#define TTL_7404_INVERT(_name, _I1) \
|
||||
@ -145,7 +147,7 @@
|
||||
|
||||
#define TTL_7486_XOR(_name, _I1, _I2) \
|
||||
NET_REGISTER_DEV(nic7486, _name) \
|
||||
NET_CONNECT(_name, I1, _I1) \
|
||||
NET_CONNECT(_name, I1, _I1) \
|
||||
NET_CONNECT(_name, I2, _I2) \
|
||||
|
||||
#define TTL_7448(_name, _A0, _A1, _A2, _A3, _LTQ, _BIQ, _RBIQ) \
|
||||
@ -185,9 +187,10 @@
|
||||
NET_CONNECT(_name, R91, _R91) \
|
||||
NET_CONNECT(_name, R92, _R92) \
|
||||
|
||||
#define TTL_7493(_name, _CLK, _R1, _R2) \
|
||||
#define TTL_7493(_name, _CLKA, _CLKB, _R1, _R2) \
|
||||
NET_REGISTER_DEV(nic7493, _name) \
|
||||
NET_CONNECT(_name, CLK, _CLK) \
|
||||
NET_CONNECT(_name, CLKA, _CLKA) \
|
||||
NET_CONNECT(_name, CLKB, _CLKB) \
|
||||
NET_CONNECT(_name, R1, _R1) \
|
||||
NET_CONNECT(_name, R2, _R2) \
|
||||
|
||||
@ -198,7 +201,7 @@
|
||||
NET_CONNECT(_name, K, _K) \
|
||||
NET_CONNECT(_name, CLRQ, _CLRQ) \
|
||||
|
||||
#define TTL_74107(_name, _CLK, _J, _K, _CLRQ) \
|
||||
#define TTL_74107(_name, _CLK, _J, _K, _CLRQ) \
|
||||
TTL_74107A(_name, _CLK, _J, _K, _CLRQ)
|
||||
|
||||
#define TTL_74153(_name, _A1, _A2, _A3, _A4, _A, _B, _GA) \
|
||||
@ -224,46 +227,50 @@
|
||||
NET_CONNECT(_name, D, _D) \
|
||||
|
||||
|
||||
#define NE555N_MSTABLE(_name, _TRIG) \
|
||||
#define NE555N_MSTABLE(_name, _TRIG, _CV) \
|
||||
NET_REGISTER_DEV(nicNE555N_MSTABLE, _name) \
|
||||
NET_CONNECT(_name, TRIG, _TRIG) \
|
||||
NET_CONNECT(_name, CV, _CV) \
|
||||
|
||||
#define NETDEV_MIXER3(_name, _I1, _I2, _I3) \
|
||||
NET_REGISTER_DEV(nicMixer8, _name) \
|
||||
NET_CONNECT(_name, I1, _I1) \
|
||||
NET_CONNECT(_name, I2, _I2) \
|
||||
NET_CONNECT(_name, I3, _I3) \
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// Special support devices ...
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
NETLIB_DEVICE_WITH_PARAMS(netdev_const,
|
||||
net_output_t m_Q;
|
||||
net_param_t m_const;
|
||||
NETLIB_DEVICE(netdev_logic_input,
|
||||
ttl_output_t m_Q;
|
||||
);
|
||||
|
||||
NETLIB_DEVICE(netdev_input,
|
||||
net_output_t m_Q;
|
||||
NETLIB_DEVICE(netdev_analog_input,
|
||||
analog_output_t m_Q;
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// Special devices ...
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
/* This class is an artificial delay circuit delaying a signal until the next low to high transition
|
||||
* this is needed by pong to model delays in the hblank circuit
|
||||
*/
|
||||
|
||||
NETLIB_DEVICE(netdev_delay_lh,
|
||||
net_input_t m_clk;
|
||||
net_input_t m_D;
|
||||
NETLIB_DEVICE_WITH_PARAMS(netdev_clock,
|
||||
ttl_input_t m_feedback;
|
||||
ttl_output_t m_Q;
|
||||
|
||||
net_sig_t m_lastclk;
|
||||
|
||||
net_output_t m_Q;
|
||||
net_param_t m_freq;
|
||||
netlist_time m_inc;
|
||||
);
|
||||
|
||||
NETLIB_DEVICE_WITH_PARAMS(nicMultiSwitch,
|
||||
net_input_t m_I[8];
|
||||
analog_input_t m_I[8];
|
||||
|
||||
net_output_t m_Q;
|
||||
net_output_t m_low;
|
||||
analog_output_t m_Q;
|
||||
analog_output_t m_low;
|
||||
|
||||
net_param_t m_POS;
|
||||
|
||||
@ -271,11 +278,22 @@ NETLIB_DEVICE_WITH_PARAMS(nicMultiSwitch,
|
||||
);
|
||||
|
||||
NETLIB_DEVICE(nicRSFF,
|
||||
net_input_t m_S;
|
||||
net_input_t m_R;
|
||||
ttl_input_t m_S;
|
||||
ttl_input_t m_R;
|
||||
|
||||
net_output_t m_Q;
|
||||
net_output_t m_QQ;
|
||||
ttl_output_t m_Q;
|
||||
ttl_output_t m_QQ;
|
||||
);
|
||||
|
||||
NETLIB_DEVICE_WITH_PARAMS(nicMixer8,
|
||||
analog_input_t m_I[8];
|
||||
|
||||
analog_output_t m_Q;
|
||||
analog_output_t m_low;
|
||||
|
||||
net_param_t m_R[8];
|
||||
|
||||
double m_w[8];
|
||||
);
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -284,186 +302,252 @@ NETLIB_DEVICE(nicRSFF,
|
||||
|
||||
NETLIB_DEVICE_WITH_PARAMS(nicNE555N_MSTABLE,
|
||||
|
||||
ATTR_HOT void timer_cb(INT32 timer_id);
|
||||
//ATTR_HOT void timer_cb(INT32 timer_id);
|
||||
|
||||
net_input_t m_trigger;
|
||||
analog_input_t m_trigger;
|
||||
analog_input_t m_CV;
|
||||
analog_input_t m_THRESHOLD; /* internal */
|
||||
|
||||
UINT8 m_last;
|
||||
UINT8 m_fired;
|
||||
double m_time;
|
||||
bool m_last;
|
||||
|
||||
net_output_t m_Q;
|
||||
analog_output_t m_Q;
|
||||
analog_output_t m_THRESHOLD_OUT; /* internal */
|
||||
|
||||
netlist_base_timer_t *m_timer;
|
||||
//netlist_base_timer_t *m_timer;
|
||||
net_param_t m_R;
|
||||
net_param_t m_C;
|
||||
net_param_t m_VS;
|
||||
net_param_t m_VL;
|
||||
net_param_t m_VT;
|
||||
);
|
||||
|
||||
NETLIB_SIGNAL(nic7400, 2)
|
||||
NETLIB_SIGNAL(nic7402, 2)
|
||||
NETLIB_SIGNAL(nic7404, 1)
|
||||
NETLIB_SIGNAL(nic7410, 3)
|
||||
NETLIB_SIGNAL(nic7420, 4)
|
||||
NETLIB_SIGNAL(nic7425, 4)
|
||||
NETLIB_SIGNAL(nic7427, 3)
|
||||
NETLIB_SIGNAL(nic7430, 8)
|
||||
NETLIB_SIGNAL(nic7450, 4)
|
||||
NETLIB_SIGNAL(nic7400, 2, 0)
|
||||
NETLIB_SIGNAL(nic7402, 2, 1)
|
||||
NETLIB_SIGNAL(nic7410, 3, 0)
|
||||
NETLIB_SIGNAL(nic7420, 4, 0)
|
||||
NETLIB_SIGNAL(nic7425, 4, 1)
|
||||
NETLIB_SIGNAL(nic7427, 3, 1)
|
||||
NETLIB_SIGNAL(nic7430, 8, 0)
|
||||
|
||||
NETLIB_DEVICE(nic7404,
|
||||
ttl_input_t m_I;
|
||||
ttl_output_t m_Q;
|
||||
);
|
||||
|
||||
NETLIB_DEVICE(nic7450,
|
||||
ttl_input_t m_I0;
|
||||
ttl_input_t m_I1;
|
||||
ttl_input_t m_I2;
|
||||
ttl_input_t m_I3;
|
||||
ttl_output_t m_Q;
|
||||
);
|
||||
|
||||
#if 0
|
||||
NETLIB_DEVICE(nic7474,
|
||||
net_input_t m_clk;
|
||||
net_input_t m_D;
|
||||
net_input_t m_clrQ;
|
||||
net_input_t m_preQ;
|
||||
ttl_input_t m_clk;
|
||||
ttl_input_t m_D;
|
||||
ttl_input_t m_clrQ;
|
||||
ttl_input_t m_preQ;
|
||||
|
||||
net_sig_t m_lastclk;
|
||||
|
||||
net_output_t m_Q;
|
||||
net_output_t m_QQ;
|
||||
ttl_output_t m_Q;
|
||||
ttl_output_t m_QQ;
|
||||
);
|
||||
|
||||
NETLIB_SIGNAL(nic7486, 2)
|
||||
#else
|
||||
NETLIB_SUBDEVICE(nic7474sub,
|
||||
ttl_input_t m_clk;
|
||||
|
||||
UINT8 m_nextD;
|
||||
ttl_output_t m_Q;
|
||||
ttl_output_t m_QQ;
|
||||
);
|
||||
|
||||
NETLIB_DEVICE(nic7474,
|
||||
nic7474sub sub;
|
||||
|
||||
ttl_input_t m_D;
|
||||
ttl_input_t m_clrQ;
|
||||
ttl_input_t m_preQ;
|
||||
);
|
||||
#endif
|
||||
|
||||
NETLIB_DEVICE(nic7486,
|
||||
ttl_input_t m_I0;
|
||||
ttl_input_t m_I1;
|
||||
ttl_output_t m_Q;
|
||||
);
|
||||
|
||||
/* 74107 does latch data during high !
|
||||
* For modelling purposes, we assume 74107 and 74107A are the same
|
||||
*/
|
||||
|
||||
|
||||
NETLIB_SUBDEVICE(nic74107Asub,
|
||||
ttl_input_t m_clk;
|
||||
|
||||
UINT8 m_Q1;
|
||||
UINT8 m_Q2;
|
||||
UINT8 m_F;
|
||||
|
||||
ttl_output_t m_Q;
|
||||
ttl_output_t m_QQ;
|
||||
|
||||
);
|
||||
|
||||
NETLIB_DEVICE(nic74107A,
|
||||
net_input_t m_clk;
|
||||
net_input_t m_J;
|
||||
net_input_t m_K;
|
||||
net_input_t m_clrQ;
|
||||
nic74107Asub sub;
|
||||
|
||||
net_sig_t m_lastclk;
|
||||
ttl_input_t m_J;
|
||||
ttl_input_t m_K;
|
||||
ttl_input_t m_clrQ;
|
||||
|
||||
net_output_t m_Q;
|
||||
net_output_t m_QQ;
|
||||
);
|
||||
|
||||
class nic74107 : public nic74107A
|
||||
{
|
||||
public:
|
||||
nic74107(netlist_setup_t *parent, const char *name)
|
||||
: nic74107A(parent, name) {}
|
||||
nic74107()
|
||||
: nic74107A() {}
|
||||
|
||||
};
|
||||
|
||||
|
||||
NETLIB_SUBDEVICE(nic7493ff,
|
||||
ttl_input_t m_I;
|
||||
ttl_output_t m_Q;
|
||||
UINT8 m_active;
|
||||
);
|
||||
|
||||
#if 1
|
||||
NETLIB_DEVICE(nic7493,
|
||||
ttl_input_t m_R1;
|
||||
ttl_input_t m_R2;
|
||||
|
||||
nic7493ff A;
|
||||
nic7493ff B;
|
||||
nic7493ff C;
|
||||
nic7493ff D;
|
||||
|
||||
);
|
||||
#else
|
||||
|
||||
NETLIB_DEVICE(nic7493,
|
||||
ATTR_HOT void update_outputs();
|
||||
|
||||
net_input_t m_R1;
|
||||
net_input_t m_R2;
|
||||
net_input_t m_clk;
|
||||
ttl_input_t m_clk;
|
||||
ttl_input_t m_R1;
|
||||
ttl_input_t m_R2;
|
||||
|
||||
ttl_output_t m_QA;
|
||||
ttl_output_t m_QB;
|
||||
ttl_output_t m_QC;
|
||||
ttl_output_t m_QD;
|
||||
|
||||
UINT8 m_lastclk;
|
||||
UINT8 m_cnt;
|
||||
|
||||
net_output_t m_QA;
|
||||
net_output_t m_QB;
|
||||
net_output_t m_QC;
|
||||
net_output_t m_QD;
|
||||
);
|
||||
#endif
|
||||
|
||||
NETLIB_DEVICE(nic7490,
|
||||
ATTR_HOT void update_outputs();
|
||||
|
||||
net_input_t m_R1;
|
||||
net_input_t m_R2;
|
||||
net_input_t m_R91;
|
||||
net_input_t m_R92;
|
||||
net_input_t m_clk;
|
||||
ttl_input_t m_R1;
|
||||
ttl_input_t m_R2;
|
||||
ttl_input_t m_R91;
|
||||
ttl_input_t m_R92;
|
||||
ttl_input_t m_clk;
|
||||
|
||||
net_sig_t m_lastclk;
|
||||
UINT8 m_cnt;
|
||||
|
||||
net_output_t m_QA;
|
||||
net_output_t m_QB;
|
||||
net_output_t m_QC;
|
||||
net_output_t m_QD;
|
||||
ttl_output_t m_QA;
|
||||
ttl_output_t m_QB;
|
||||
ttl_output_t m_QC;
|
||||
ttl_output_t m_QD;
|
||||
);
|
||||
|
||||
/* ripple-carry counter on low-high clock transition */
|
||||
NETLIB_DEVICE(nic9316,
|
||||
|
||||
NETLIB_SUBDEVICE(nic9316sub,
|
||||
ATTR_HOT void update_outputs_all();
|
||||
ATTR_HOT void update_outputs();
|
||||
|
||||
net_input_t m_clk;
|
||||
net_input_t m_ENP;
|
||||
net_input_t m_ENT;
|
||||
net_input_t m_CLRQ;
|
||||
net_input_t m_LOADQ;
|
||||
net_input_t m_A;
|
||||
net_input_t m_B;
|
||||
net_input_t m_C;
|
||||
net_input_t m_D;
|
||||
ttl_input_t m_clk;
|
||||
|
||||
ttl_input_t m_LOADQ;
|
||||
ttl_input_t m_ENT;
|
||||
ttl_input_t m_A;
|
||||
ttl_input_t m_B;
|
||||
ttl_input_t m_C;
|
||||
ttl_input_t m_D;
|
||||
|
||||
UINT8 m_lastclk;
|
||||
UINT8 m_cnt;
|
||||
|
||||
net_output_t m_QA;
|
||||
net_output_t m_QB;
|
||||
net_output_t m_QC;
|
||||
net_output_t m_QD;
|
||||
net_output_t m_RC;
|
||||
ttl_output_t m_QA;
|
||||
ttl_output_t m_QB;
|
||||
ttl_output_t m_QC;
|
||||
ttl_output_t m_QD;
|
||||
ttl_output_t m_RC;
|
||||
);
|
||||
|
||||
NETLIB_DEVICE(nic9316,
|
||||
nic9316sub sub;
|
||||
ttl_input_t m_ENP;
|
||||
ttl_input_t m_CLRQ;
|
||||
);
|
||||
|
||||
NETLIB_DEVICE(nic7483,
|
||||
net_input_t m_CI;
|
||||
net_input_t m_A1;
|
||||
net_input_t m_A2;
|
||||
net_input_t m_A3;
|
||||
net_input_t m_A4;
|
||||
net_input_t m_B1;
|
||||
net_input_t m_B2;
|
||||
net_input_t m_B3;
|
||||
net_input_t m_B4;
|
||||
net_input_t m_clk;
|
||||
ttl_input_t m_CI;
|
||||
ttl_input_t m_A1;
|
||||
ttl_input_t m_A2;
|
||||
ttl_input_t m_A3;
|
||||
ttl_input_t m_A4;
|
||||
ttl_input_t m_B1;
|
||||
ttl_input_t m_B2;
|
||||
ttl_input_t m_B3;
|
||||
ttl_input_t m_B4;
|
||||
ttl_input_t m_clk;
|
||||
|
||||
UINT8 m_lastr;
|
||||
|
||||
net_output_t m_SA;
|
||||
net_output_t m_SB;
|
||||
net_output_t m_SC;
|
||||
net_output_t m_SD;
|
||||
net_output_t m_CO;
|
||||
ttl_output_t m_SA;
|
||||
ttl_output_t m_SB;
|
||||
ttl_output_t m_SC;
|
||||
ttl_output_t m_SD;
|
||||
ttl_output_t m_CO;
|
||||
|
||||
);
|
||||
|
||||
/* one half of a nic74153 */
|
||||
|
||||
NETLIB_DEVICE(nic74153,
|
||||
net_input_t m_I[4];
|
||||
net_input_t m_A;
|
||||
net_input_t m_B;
|
||||
net_input_t m_GA;
|
||||
ttl_input_t m_I[4];
|
||||
ttl_input_t m_A;
|
||||
ttl_input_t m_B;
|
||||
ttl_input_t m_GA;
|
||||
|
||||
net_output_t m_AY;
|
||||
ttl_output_t m_AY;
|
||||
);
|
||||
|
||||
NETLIB_DEVICE(nic7448,
|
||||
static const UINT8 tab7448[16][7];
|
||||
|
||||
net_input_t m_A0;
|
||||
net_input_t m_A1;
|
||||
net_input_t m_A2;
|
||||
net_input_t m_A3;
|
||||
net_input_t m_LTQ;
|
||||
net_input_t m_RBIQ;
|
||||
net_input_t m_BIQ;
|
||||
ttl_input_t m_A0;
|
||||
ttl_input_t m_A1;
|
||||
ttl_input_t m_A2;
|
||||
ttl_input_t m_A3;
|
||||
ttl_input_t m_LTQ;
|
||||
ttl_input_t m_RBIQ;
|
||||
ttl_input_t m_BIQ;
|
||||
|
||||
UINT8 m_state;
|
||||
|
||||
net_output_t m_a;
|
||||
net_output_t m_b;
|
||||
net_output_t m_c;
|
||||
net_output_t m_d;
|
||||
net_output_t m_e;
|
||||
net_output_t m_f;
|
||||
net_output_t m_g;
|
||||
ttl_output_t m_a;
|
||||
ttl_output_t m_b;
|
||||
ttl_output_t m_c;
|
||||
ttl_output_t m_d;
|
||||
ttl_output_t m_e;
|
||||
ttl_output_t m_f;
|
||||
ttl_output_t m_g;
|
||||
);
|
||||
|
||||
|
||||
|
@ -42,10 +42,10 @@
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#include "netlist.h"
|
||||
#include "net_lib.h"
|
||||
|
||||
//============================================================
|
||||
// DEBUGGING
|
||||
@ -54,11 +54,6 @@
|
||||
#define VERBOSE (0)
|
||||
#define KEEP_STATISTICS (0)
|
||||
|
||||
|
||||
#if KEEP_STATISTICS && USE_DELEGATES
|
||||
#error "Statistics only work without delegates!"
|
||||
#endif
|
||||
|
||||
#if (VERBOSE)
|
||||
|
||||
#define VERBOSE_OUT(x) printf x
|
||||
@ -71,9 +66,9 @@
|
||||
//============================================================
|
||||
|
||||
#if KEEP_STATISTICS
|
||||
#define add_to_stat(v,x) do { atomic_add32((v), (x)); } while (0)
|
||||
#define add_to_stat(v,x) do { v += (x); } while (0)
|
||||
#define inc_stat(v) add_to_stat(v, 1)
|
||||
#define begin_timing(v) do { (v) -= get_profile_ticks(); } while (0)
|
||||
#define begin_timing(v) do { (v) -= get_profile_ticks(); } while (0)
|
||||
#define end_timing(v) do { (v) += get_profile_ticks(); } while (0)
|
||||
#else
|
||||
#define add_to_stat(v,x) do { } while (0)
|
||||
@ -82,6 +77,9 @@
|
||||
#define end_timing(v) do { } while (0)
|
||||
#endif
|
||||
|
||||
|
||||
const netlist_time netlist_time::zero = netlist_time::from_raw(0);
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// A netlist parser
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -103,86 +101,96 @@ public:
|
||||
n = getname('(');
|
||||
VERBOSE_OUT(("Parser: Device: %s\n", n));
|
||||
if (strcmp(n,"NET_ALIAS") == 0)
|
||||
{
|
||||
char *alias;
|
||||
char *out;
|
||||
m_p++;
|
||||
skipws();
|
||||
alias = getname(',');
|
||||
m_p++;
|
||||
skipws();
|
||||
out = getname(')');
|
||||
m_p++;
|
||||
VERBOSE_OUT(("Parser: Alias: %s %s\n", alias, out));
|
||||
m_setup.register_alias(alias, out);
|
||||
}
|
||||
net_alias();
|
||||
else if (strcmp(n,"NETDEV_PARAM") == 0)
|
||||
{
|
||||
char *param;
|
||||
double val;
|
||||
m_p++;
|
||||
skipws();
|
||||
param = getname(',');
|
||||
m_p++;
|
||||
skipws();
|
||||
val = eval_param();
|
||||
m_p++;
|
||||
VERBOSE_OUT(("Parser: Param: %s %f\n", param, val));
|
||||
m_setup.find_param(param)->setTo(val);
|
||||
}
|
||||
else if (strcmp(n,"NETDEV_CONST") == 0)
|
||||
{
|
||||
char *devname;
|
||||
net_dev_t *dev;
|
||||
char paramfq[30];
|
||||
double val;
|
||||
m_p++;
|
||||
skipws();
|
||||
devname = getname(',');
|
||||
dev = net_create_device_by_name(n, &m_setup, devname);
|
||||
m_setup.register_dev(dev);
|
||||
m_p++;
|
||||
skipws();
|
||||
val = eval_param();
|
||||
m_p++;
|
||||
strcpy(paramfq, devname);
|
||||
strcat(paramfq, ".CONST");
|
||||
VERBOSE_OUT(("Parser: Const: %s %f\n", devname, val));
|
||||
m_setup.find_param(paramfq)->setTo(val);
|
||||
}
|
||||
netdev_param();
|
||||
else if ((strcmp(n,"NETDEV_TTL_CONST") == 0) || (strcmp(n,"NETDEV_ANALOG_CONST") == 0))
|
||||
netdev_const(n);
|
||||
else
|
||||
{
|
||||
char *devname;
|
||||
net_dev_t *dev;
|
||||
int cnt;
|
||||
|
||||
m_p++;
|
||||
skipws();
|
||||
devname = getname2(',', ')');
|
||||
dev = net_create_device_by_name(n, &m_setup, devname);
|
||||
m_setup.register_dev(dev);
|
||||
skipws();
|
||||
VERBOSE_OUT(("Parser: IC: %s\n", n));
|
||||
cnt = 0;
|
||||
while (*m_p != ')')
|
||||
{
|
||||
m_p++;
|
||||
skipws();
|
||||
n = getname2(',', ')');
|
||||
VERBOSE_OUT(("Parser: ID: %s %s\n", n, dev->m_inputs.item(cnt)));
|
||||
m_setup.register_link(dev->m_inputs.item(cnt), n);
|
||||
skipws();
|
||||
cnt++;
|
||||
//return 0;
|
||||
}
|
||||
if (cnt != dev->m_inputs.count() && !dev->variable_input_count())
|
||||
fatalerror("netlist: input count mismatch for %s - expected %d found %d\n", devname, dev->m_inputs.count(), cnt);
|
||||
m_p++;
|
||||
}
|
||||
netdev_device(n);
|
||||
}
|
||||
}
|
||||
|
||||
void net_alias()
|
||||
{
|
||||
char *alias;
|
||||
char *out;
|
||||
skipws();
|
||||
alias = getname(',');
|
||||
skipws();
|
||||
out = getname(')');
|
||||
VERBOSE_OUT(("Parser: Alias: %s %s\n", alias, out));
|
||||
m_setup.register_alias(alias, out);
|
||||
}
|
||||
|
||||
void netdev_param()
|
||||
{
|
||||
char *param;
|
||||
double val;
|
||||
skipws();
|
||||
param = getname(',');
|
||||
skipws();
|
||||
val = eval_param();
|
||||
VERBOSE_OUT(("Parser: Param: %s %f\n", param, val));
|
||||
m_setup.find_param(param).initial(val);
|
||||
check_char(')');
|
||||
}
|
||||
|
||||
void netdev_const(const char *dev_name)
|
||||
{
|
||||
char *devname;
|
||||
net_device_t *dev;
|
||||
char paramfq[30];
|
||||
double val;
|
||||
|
||||
skipws();
|
||||
devname = getname(',');
|
||||
dev = net_create_device_by_name(dev_name, &m_setup, devname);
|
||||
m_setup.register_dev(dev);
|
||||
skipws();
|
||||
val = eval_param();
|
||||
check_char(')');
|
||||
strcpy(paramfq, devname);
|
||||
strcat(paramfq, ".CONST");
|
||||
VERBOSE_OUT(("Parser: Const: %s %f\n", devname, val));
|
||||
m_setup.find_param(paramfq).setTo(val);
|
||||
}
|
||||
|
||||
void netdev_device(const char *dev_type)
|
||||
{
|
||||
char *devname;
|
||||
net_device_t *dev;
|
||||
int cnt;
|
||||
|
||||
skipws();
|
||||
devname = getname2(',', ')');
|
||||
dev = net_create_device_by_name(dev_type, &m_setup, devname);
|
||||
m_setup.register_dev(dev);
|
||||
skipws();
|
||||
VERBOSE_OUT(("Parser: IC: %s\n", n));
|
||||
cnt = 0;
|
||||
while (*m_p != ')')
|
||||
{
|
||||
m_p++;
|
||||
skipws();
|
||||
char *output_name = getname2(',', ')');
|
||||
VERBOSE_OUT(("Parser: ID: %s %s\n", output_name, dev->m_inputs.item(cnt)));
|
||||
m_setup.register_link(dev->m_inputs.item(cnt), output_name);
|
||||
skipws();
|
||||
cnt++;
|
||||
}
|
||||
if (cnt != dev->m_inputs.count() && !dev->variable_input_count())
|
||||
fatalerror("netlist: input count mismatch for %s - expected %d found %d\n", devname, dev->m_inputs.count(), cnt);
|
||||
check_char(')');
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
char *cdup(const char *s)
|
||||
{
|
||||
return core_strdup(s);
|
||||
}
|
||||
|
||||
void skipeol()
|
||||
{
|
||||
while (*m_p)
|
||||
@ -190,6 +198,8 @@ private:
|
||||
if (*m_p == 10)
|
||||
{
|
||||
m_p++;
|
||||
if (*m_p && *m_p == 13)
|
||||
m_p++;
|
||||
return;
|
||||
}
|
||||
m_p++;
|
||||
@ -226,7 +236,8 @@ private:
|
||||
while (*m_p != sep)
|
||||
*p1++ = *m_p++;
|
||||
*p1 = 0;
|
||||
return core_strdup(buf);
|
||||
m_p++;
|
||||
return cdup(buf);
|
||||
}
|
||||
|
||||
char *getname2(char sep1, char sep2)
|
||||
@ -237,7 +248,18 @@ private:
|
||||
while ((*m_p != sep1) && (*m_p != sep2))
|
||||
*p1++ = *m_p++;
|
||||
*p1 = 0;
|
||||
return core_strdup(buf);
|
||||
return cdup(buf);
|
||||
}
|
||||
|
||||
void check_char(char ctocheck)
|
||||
{
|
||||
skipws();
|
||||
if (*m_p == ctocheck)
|
||||
{
|
||||
m_p++;
|
||||
return;
|
||||
}
|
||||
fatalerror("Parser: expected '%c' found '%c'", ctocheck, *m_p);
|
||||
}
|
||||
|
||||
double eval_param()
|
||||
@ -255,7 +277,7 @@ private:
|
||||
f = i;
|
||||
ret = strtod(s+strlen(macs[f]), &e);
|
||||
if ((f>0) && (*e != ')'))
|
||||
exit(0);
|
||||
fatalerror("Parser: Error with parameter ...");
|
||||
if (f>0)
|
||||
e++;
|
||||
m_p = e;
|
||||
@ -268,83 +290,142 @@ private:
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netdev_a_to_d
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
class netdev_a_to_d_proxy : public net_device_t
|
||||
{
|
||||
public:
|
||||
netdev_a_to_d_proxy(net_input_t &in_proxied) : net_device_t()
|
||||
{
|
||||
assert_always(in_proxied.object_type(SIGNAL_MASK) == SIGNAL_DIGITAL, "Digital signal expected");
|
||||
m_I.m_high_thresh_V = in_proxied.m_high_thresh_V;
|
||||
m_I.m_low_thresh_V = in_proxied.m_low_thresh_V;
|
||||
}
|
||||
|
||||
ATTR_HOT void update()
|
||||
{
|
||||
if (m_I.Q_Analog() > m_I.m_high_thresh_V)
|
||||
m_Q.setToPS(1, NLTIME_FROM_NS(1));
|
||||
else if (m_I.Q_Analog() < m_I.m_low_thresh_V)
|
||||
m_Q.setToPS(0, NLTIME_FROM_NS(1));
|
||||
}
|
||||
|
||||
ATTR_COLD void start()
|
||||
{
|
||||
m_I.init(this);
|
||||
m_Q.set_netdev(this);
|
||||
|
||||
m_Q.initial(1);
|
||||
}
|
||||
|
||||
analog_input_t m_I;
|
||||
ttl_output_t m_Q;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netdev_const
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
NETLIB_START(netdev_ttl_const)
|
||||
{
|
||||
register_output("Q", m_Q);
|
||||
register_param("CONST", m_const, 0.0);
|
||||
}
|
||||
|
||||
NETLIB_UPDATE(netdev_ttl_const)
|
||||
{
|
||||
}
|
||||
|
||||
NETLIB_UPDATE_PARAM(netdev_ttl_const)
|
||||
{
|
||||
m_Q.setToPS(m_const.ValueInt(), NLTIME_IMMEDIATE);
|
||||
}
|
||||
|
||||
NETLIB_START(netdev_analog_const)
|
||||
{
|
||||
register_output("Q", m_Q);
|
||||
register_param("CONST", m_const, 0.0);
|
||||
}
|
||||
|
||||
NETLIB_UPDATE(netdev_analog_const)
|
||||
{
|
||||
}
|
||||
|
||||
NETLIB_UPDATE_PARAM(netdev_analog_const)
|
||||
{
|
||||
m_Q.initial(m_const.Value());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netlist_base_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
netlist_base_t::netlist_base_t(bool sub_cycle_exact)
|
||||
netlist_base_t::netlist_base_t()
|
||||
//m_output_list(ttl_list_t<output_t *>(2048)),
|
||||
: m_current(0), m_divisor(32), m_sub_cycle_exact(sub_cycle_exact), m_gatedelay(100), m_clockfreq(1000000)
|
||||
//: m_divisor(32), m_gatedelay(100), m_clockfreq(1000000)
|
||||
: m_div(1024)
|
||||
{
|
||||
m_netlist_mask = NET_LIST_MASK;
|
||||
reset_lists();
|
||||
}
|
||||
|
||||
netlist_base_t::~netlist_base_t()
|
||||
{
|
||||
}
|
||||
|
||||
void netlist_base_t::set_clock_freq(int clockfreq)
|
||||
void netlist_base_t::set_clock_freq(UINT64 clockfreq)
|
||||
{
|
||||
m_clockfreq = clockfreq;
|
||||
m_divisor = U64(100000000000) / m_clockfreq / m_gatedelay;
|
||||
VERBOSE_OUT(("Divisor %d\n", m_divisor));
|
||||
m_div = netlist_time::from_hz(clockfreq).as_raw();
|
||||
VERBOSE_OUT(("Setting clock %lld and divisor %d\n", clockfreq, m_div));
|
||||
}
|
||||
|
||||
void netlist_base_t::set_gatedelay(int gatedelay)
|
||||
ATTR_HOT ATTR_ALIGN void netlist_base_t::process_list(INT32 &atime)
|
||||
{
|
||||
m_gatedelay = gatedelay;
|
||||
m_divisor = U64(100000000000) / m_clockfreq / m_gatedelay;
|
||||
VERBOSE_OUT(("Divisor %d\n", m_divisor));
|
||||
}
|
||||
|
||||
ATTR_HOT inline void netlist_base_t::process_list(void)
|
||||
{
|
||||
net_list_t<net_output_t *, 512> &list = m_output_list[m_sub_cycle_exact ? m_current : 0];
|
||||
#if 0
|
||||
net_output_t * RESTRICT * RESTRICT first;
|
||||
net_output_t * RESTRICT * RESTRICT last;
|
||||
|
||||
first = list.first();
|
||||
last = list.last();
|
||||
while (first <= last)
|
||||
while ( (atime > 0) && (m_queue.is_not_empty()))
|
||||
{
|
||||
net_output_t * RESTRICT * RESTRICT out = first;
|
||||
while (out <= last)
|
||||
{
|
||||
(*out)->update_out();
|
||||
(*out)->update_devs();
|
||||
out++;
|
||||
}
|
||||
first = last + 1;
|
||||
last = list.last();
|
||||
}
|
||||
#else
|
||||
net_output_t * RESTRICT * RESTRICT out;
|
||||
queue_t::entry_t e = m_queue.pop();
|
||||
netlist_time delta = e.time() - m_time_ps + netlist_time::from_raw(m_rem);
|
||||
|
||||
out = list.first();
|
||||
while (out <= list.last())
|
||||
atime -= divu_64x32_rem(delta.as_raw(), m_div, &m_rem);
|
||||
m_time_ps = e.time();
|
||||
|
||||
e.object()->update_devs();
|
||||
|
||||
add_to_stat(m_perf_out_processed, 1);
|
||||
add_to_stat(m_perf_list_len, m_end);
|
||||
}
|
||||
|
||||
if (atime > 0)
|
||||
{
|
||||
(*out)->update_out();
|
||||
(*out)->update_devs();
|
||||
out++;
|
||||
m_time_ps += netlist_time::from_raw(atime * m_div);
|
||||
atime = 0;
|
||||
}
|
||||
#endif
|
||||
reset_list();
|
||||
|
||||
if (m_sub_cycle_exact)
|
||||
m_current = (m_current + 1) & m_netlist_mask;
|
||||
if (KEEP_STATISTICS)
|
||||
printf("%f\n", (double) m_perf_list_len / (double) m_perf_out_processed);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// Default netlist elements ...
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
static NETLIST_START(base)
|
||||
NETDEV_TTL_CONST(ttlhigh, 1)
|
||||
NETDEV_TTL_CONST(ttllow, 0)
|
||||
NETDEV_ANALOG_CONST(NC, NETLIST_HIGHIMP_V)
|
||||
NETLIST_END
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netlist_setup_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
netlist_setup_t::netlist_setup_t(netlist_base_t &netlist)
|
||||
//m_output_list(ttl_list_t<output_t *>(2048)),
|
||||
: m_netlist(netlist)
|
||||
{
|
||||
NETLIST_NAME(base)(*this);
|
||||
}
|
||||
|
||||
netlist_setup_t::~netlist_setup_t()
|
||||
@ -352,7 +433,7 @@ netlist_setup_t::~netlist_setup_t()
|
||||
}
|
||||
|
||||
|
||||
net_dev_t *netlist_setup_t::register_dev(net_dev_t *dev)
|
||||
net_device_t *netlist_setup_t::register_dev(net_device_t *dev)
|
||||
{
|
||||
if (!(m_devices.add(dev->name(), dev, false)==TMERR_NONE))
|
||||
fatalerror("Error adding %s to device list\n", dev->name());
|
||||
@ -378,7 +459,7 @@ static void remove_start_with(T &hm, astring &sw)
|
||||
|
||||
void netlist_setup_t::remove_dev(const char *name)
|
||||
{
|
||||
net_dev_t *dev = m_devices.find(name);
|
||||
net_device_t *dev = m_devices.find(name);
|
||||
astring temp = name;
|
||||
if (dev == NULL)
|
||||
fatalerror("Device %s does not exist\n", name);
|
||||
@ -413,11 +494,10 @@ void netlist_setup_t::register_output(const char *name, net_output_t *out)
|
||||
fatalerror("Error adding output %s to output list\n", name);
|
||||
}
|
||||
|
||||
void netlist_setup_t::register_input(const char *name, net_input_t *inp, net_input_type type)
|
||||
void netlist_setup_t::register_input(const char *name, net_input_t *inp)
|
||||
{
|
||||
net_input_setup_t *setup_inp = new net_input_setup_t(inp, type);
|
||||
VERBOSE_OUT(("input %s\n", name));
|
||||
if (!(m_inputs.add(name, setup_inp, false) == TMERR_NONE))
|
||||
if (!(m_inputs.add(name, inp, false) == TMERR_NONE))
|
||||
fatalerror("Error adding input %s to input list\n", name);
|
||||
}
|
||||
|
||||
@ -431,7 +511,7 @@ void netlist_setup_t::register_link(const char *sin, const char *sout)
|
||||
|
||||
void netlist_setup_t::register_param(const char *sname, net_param_t *param)
|
||||
{
|
||||
astring temp = param->ttl_dev()->name();
|
||||
astring temp = param->netdev().name();
|
||||
temp.cat(".");
|
||||
temp.cat(sname);
|
||||
if (!(m_params.add(temp, param, false)==TMERR_NONE))
|
||||
@ -454,7 +534,7 @@ net_output_t *netlist_setup_t::find_output_exact(const char *outname_in)
|
||||
return ret;
|
||||
}
|
||||
|
||||
net_output_t *netlist_setup_t::find_output(const char *outname_in)
|
||||
net_output_t &netlist_setup_t::find_output(const char *outname_in)
|
||||
{
|
||||
const char *outname = resolve_alias(outname_in);
|
||||
net_output_t *ret;
|
||||
@ -471,10 +551,10 @@ net_output_t *netlist_setup_t::find_output(const char *outname_in)
|
||||
if (ret == NULL)
|
||||
fatalerror("output %s(%s) not found!", outname_in, outname);
|
||||
VERBOSE_OUT(("Found input %s\n", outname));
|
||||
return ret;
|
||||
return *ret;
|
||||
}
|
||||
|
||||
net_param_t *netlist_setup_t::find_param(const char *param_in)
|
||||
net_param_t &netlist_setup_t::find_param(const char *param_in)
|
||||
{
|
||||
const char *outname = resolve_alias(param_in);
|
||||
net_param_t *ret;
|
||||
@ -483,7 +563,7 @@ net_param_t *netlist_setup_t::find_param(const char *param_in)
|
||||
if (ret == NULL)
|
||||
fatalerror("parameter %s(%s) not found!", param_in, outname);
|
||||
VERBOSE_OUT(("Found parameter %s\n", outname));
|
||||
return ret;
|
||||
return *ret;
|
||||
}
|
||||
|
||||
void netlist_setup_t::resolve_inputs(void)
|
||||
@ -493,39 +573,47 @@ void netlist_setup_t::resolve_inputs(void)
|
||||
{
|
||||
const astring *sout = entry->object();
|
||||
astring sin = entry->tag();
|
||||
net_input_setup_t *in = m_inputs.find(sin);
|
||||
int p = sin.find(".");
|
||||
const char *devname = sin.substr(0, p);
|
||||
net_dev_t *dev = m_devices.find(devname);
|
||||
net_output_t *out = find_output(sout->cstr() );
|
||||
net_input_t *in = m_inputs.find(sin);
|
||||
|
||||
(*in->inp()).o = GETINPPTR(*out);
|
||||
//in->inp()->v = out->Q_ptr();
|
||||
if (in->type() == NET_INP_TYPE_ACTIVE)
|
||||
out->register_con(dev);
|
||||
net_output_t &out = find_output(sout->cstr());
|
||||
if (out.object_type(net_output_t::SIGNAL_MASK) == net_output_t::SIGNAL_ANALOG
|
||||
&& in->object_type(net_output_t::SIGNAL_MASK) == net_output_t::SIGNAL_DIGITAL)
|
||||
{
|
||||
// fatalerror("connecting analog output %s with %s\n", out.netdev()->name(), in->netdev()->name());
|
||||
// fatalerror("connecting analog output %s with %s\n", out.netdev()->name(), in->netdev()->name());
|
||||
netdev_a_to_d_proxy *proxy = new netdev_a_to_d_proxy(*in);
|
||||
proxy->init(this, "abc");
|
||||
proxy->start();
|
||||
in->set_output(proxy->GETINPPTR(proxy->m_Q));
|
||||
//Next check would not work with dynamic activation
|
||||
//if (in->state() != net_input_t::INP_STATE_PASSIVE)
|
||||
proxy->m_Q.register_con(*in);
|
||||
proxy->m_I.set_output(&out);
|
||||
//if (proxy->m_I.state() != net_input_t::INP_STATE_PASSIVE)
|
||||
out.register_con(proxy->m_I);
|
||||
}
|
||||
else
|
||||
{
|
||||
in->set_output(out.netdev()->GETINPPTR(out));
|
||||
|
||||
//Next check would not work with dynamic activation
|
||||
//if (in->state() != net_input_t::INP_STATE_PASSIVE)
|
||||
out.register_con(*in);
|
||||
}
|
||||
}
|
||||
/* make sure params are set now .. */
|
||||
for (tagmap_param_t::entry_t *entry = m_params.first(); entry != NULL; entry = m_params.next(entry))
|
||||
{
|
||||
entry->object()->netdev().update_param();
|
||||
}
|
||||
|
||||
step_all_devices();
|
||||
//reset_list();
|
||||
//process_list();
|
||||
}
|
||||
|
||||
void netlist_setup_t::step_all_devices()
|
||||
{
|
||||
m_netlist.reset_list();
|
||||
|
||||
for (tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry))
|
||||
/* make sure all outputs are triggered once */
|
||||
for (tagmap_output_t::entry_t *entry = m_outputs.first(); entry != NULL; entry = m_outputs.next(entry))
|
||||
{
|
||||
net_dev_t &dev = *entry->object();
|
||||
dev.update_param();
|
||||
dev.update();
|
||||
|
||||
for (tagmap_output_t::entry_t *entry = m_outputs.first(); entry != NULL; entry = m_outputs.next(entry))
|
||||
{
|
||||
net_output_t &out = *entry->object();
|
||||
out.update_out();
|
||||
}
|
||||
m_netlist.reset_lists();
|
||||
net_output_t *out = entry->object();
|
||||
out->update_devs_force();
|
||||
INT32 time = 1000;
|
||||
m_netlist.process_list(time);
|
||||
}
|
||||
}
|
||||
|
||||
@ -547,119 +635,238 @@ void netlist_setup_t::print_stats()
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// net_core_device_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
net_core_device_t::net_core_device_t()
|
||||
: net_object_t(DEVICE)
|
||||
{
|
||||
}
|
||||
|
||||
net_core_device_t::~net_core_device_t()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ATTR_COLD void net_core_device_t::init_core(netlist_base_t *anetlist, const char *name)
|
||||
{
|
||||
m_netlist = anetlist;
|
||||
m_name = name;
|
||||
#if USE_DELEGATES_A
|
||||
h = net_update_delegate(&net_core_device_t::update, "update", this);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
ATTR_COLD void net_core_device_t::register_subdevice(net_core_device_t &subdev)
|
||||
{
|
||||
m_subdevs.add(&subdev);
|
||||
subdev.init_core(m_netlist, this->name());
|
||||
//subdev.start();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// net_dev_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
net_dev_t::~net_dev_t()
|
||||
|
||||
net_device_t::net_device_t()
|
||||
: net_core_device_t(), m_variable_input_count(false)
|
||||
{
|
||||
}
|
||||
|
||||
ATTR_HOT void net_dev_t::update_timed()
|
||||
net_device_t::~net_device_t()
|
||||
{
|
||||
inc_stat(&stat_count);
|
||||
begin_timing(total_time);
|
||||
update();
|
||||
end_timing(total_time);
|
||||
}
|
||||
|
||||
void net_dev_t::register_output(const char *name, net_output_t *port)
|
||||
ATTR_COLD void net_device_t::init(netlist_setup_t *setup, const char *name)
|
||||
{
|
||||
astring temp = this->name();
|
||||
m_setup = setup;
|
||||
init_core(&setup->netlist(), name);
|
||||
}
|
||||
|
||||
void net_device_t::register_output(const net_core_device_t &dev, const char *name, net_output_t &port)
|
||||
{
|
||||
astring temp = dev.name();
|
||||
temp.cat(".");
|
||||
temp.cat(name);
|
||||
port->set_ttl_dev(this);
|
||||
m_setup->register_output(temp, port);
|
||||
port.set_netdev(&dev);
|
||||
m_setup->register_output(temp, &port);
|
||||
}
|
||||
|
||||
void net_dev_t::register_input(const char *name, net_input_t *inp, net_input_type type)
|
||||
void net_device_t::register_output(const char *name, net_output_t &port)
|
||||
{
|
||||
astring temp = this->name();
|
||||
register_output(*this, name, port);
|
||||
}
|
||||
|
||||
void net_device_t::register_input(net_core_device_t &dev, const char *name, net_input_t &inp, int type)
|
||||
{
|
||||
astring temp = dev.name();
|
||||
temp.cat(".");
|
||||
temp.cat(name);
|
||||
inp.init(&dev, type);
|
||||
m_inputs.add(core_strdup(temp.cstr()));
|
||||
m_setup->register_input(temp, inp, type);
|
||||
m_setup->register_input(temp, &inp);
|
||||
}
|
||||
|
||||
void net_dev_t::register_param(const char *name, net_param_t *param, double initialVal)
|
||||
void net_device_t::register_input(const char *name, net_input_t &inp, int type)
|
||||
{
|
||||
param->set_ttl_dev(this);
|
||||
param->initial(initialVal);
|
||||
m_setup->register_param(name, param);
|
||||
register_input(*this, name, inp, type);
|
||||
}
|
||||
|
||||
void net_device_t::register_link_internal(net_core_device_t &dev, net_input_t &in, net_output_t &out)
|
||||
{
|
||||
in.set_output(GETINPPTR(out));
|
||||
in.init(&dev);
|
||||
//if (in.state() != net_input_t::INP_STATE_PASSIVE)
|
||||
out.register_con(in);
|
||||
}
|
||||
|
||||
void net_device_t::register_link_internal(net_input_t &in, net_output_t &out)
|
||||
{
|
||||
register_link_internal(*this, in, out);
|
||||
}
|
||||
|
||||
void net_device_t::register_param(net_core_device_t &dev, const char *name, net_param_t ¶m, double initialVal)
|
||||
{
|
||||
param.set_netdev(dev);
|
||||
param.initial(initialVal);
|
||||
m_setup->register_param(name, ¶m);
|
||||
}
|
||||
|
||||
void net_device_t::register_param(const char *name, net_param_t ¶m, double initialVal)
|
||||
{
|
||||
register_param(*this,name, param, initialVal);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// net_input_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
ATTR_COLD void net_input_t::init(net_core_device_t *dev, int astate)
|
||||
{
|
||||
m_netdev = dev;
|
||||
m_state = astate;
|
||||
#if USE_DELEGATES
|
||||
h = net_update_delegate(&net_core_device_t::update, "update", dev);
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// net_output_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
net_output_t::net_output_t()
|
||||
net_output_t::net_output_t(int atype)
|
||||
: net_object_t(atype)
|
||||
{
|
||||
#if USE_DELEGATES
|
||||
//m_cons = global_alloc_array_clear(net_update_delegate, 32);
|
||||
#else
|
||||
// m_cons = global_alloc_array_clear(net_dev_t *, 32);
|
||||
#endif
|
||||
//m_Q = parent.alloc_sig();
|
||||
//m_new_Q = parent.alloc_sig();
|
||||
m_num_cons = 0;
|
||||
m_last_Q = 1;
|
||||
m_Q = 0;
|
||||
m_new_Q = m_Q;
|
||||
m_active = 0;
|
||||
m_in_queue = 2;
|
||||
}
|
||||
|
||||
ATTR_COLD void net_output_t::set_ttl_dev(net_dev_t *dev)
|
||||
ATTR_COLD void net_output_t::set_netdev(const net_core_device_t *dev)
|
||||
{
|
||||
m_ttldev = dev;
|
||||
m_netlist = &dev->setup()->netlist();
|
||||
m_netdev = dev;
|
||||
m_netlist = dev->netlist();
|
||||
}
|
||||
|
||||
|
||||
ATTR_COLD void net_output_t::register_con(net_dev_t *dev)
|
||||
static inline void update_dev(const net_input_t *inp, const UINT32 mask)
|
||||
{
|
||||
assert(m_num_cons<32);
|
||||
if ((inp->state() & mask) != 0)
|
||||
{
|
||||
begin_timing(inp->netdev()->total_time);
|
||||
inc_stat(inp->netdev()->stat_count);
|
||||
#if USE_DELEGATES
|
||||
net_update_delegate aDelegate = net_update_delegate(&net_dev_t::update, "update", dev);
|
||||
for (int i=0; i < m_num_cons; i++)
|
||||
if (m_cons[i] == aDelegate)
|
||||
return;
|
||||
m_cons[m_num_cons++] = aDelegate;
|
||||
inp->h();
|
||||
#else
|
||||
for (int i=0; i < m_num_cons; i++)
|
||||
if (m_cons[i] == dev)
|
||||
return;
|
||||
m_cons[m_num_cons++] = dev;
|
||||
inp->netdev()->update_device();
|
||||
#endif
|
||||
end_timing(inp->netdev()->total_time);
|
||||
}
|
||||
}
|
||||
|
||||
ATTR_HOT inline void net_output_t::update_devs()
|
||||
{
|
||||
#if USE_DELEGATES
|
||||
|
||||
net_update_delegate *s = m_cons;
|
||||
net_update_delegate *e = s + m_num_cons;
|
||||
const UINT32 masks[4] = { 1, 5, 3, 1 };
|
||||
m_Q = m_new_Q;
|
||||
m_Q_analog = m_new_Q_analog;
|
||||
|
||||
while (s<e)
|
||||
//UINT32 mask = 1 | ((m_last_Q & (m_Q ^ 1)) << 1) | (((m_last_Q ^ 1) & m_Q) << 2);
|
||||
const UINT32 mask = masks[ (m_last_Q << 1) | m_Q ];
|
||||
|
||||
switch (m_num_cons)
|
||||
{
|
||||
(*s++)();
|
||||
case 2:
|
||||
update_dev(m_cons[1], mask);
|
||||
case 1:
|
||||
update_dev(m_cons[0], mask);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
for (int i=0; i < m_num_cons; i++)
|
||||
update_dev(m_cons[i], mask);
|
||||
}
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
#else
|
||||
net_dev_t **s = m_cons;
|
||||
net_dev_t **e = s + m_num_cons;
|
||||
|
||||
#if KEEP_STATISTICS
|
||||
while (s<e)
|
||||
(*s++)->update_timed();
|
||||
m_in_queue = 2; /* mark as taken ... */
|
||||
m_last_Q = m_Q;
|
||||
}
|
||||
|
||||
ATTR_COLD void net_output_t::update_devs_force()
|
||||
{
|
||||
net_input_t **s = m_cons;
|
||||
int i = m_num_cons;
|
||||
|
||||
m_Q = m_new_Q;
|
||||
m_Q_analog = m_new_Q_analog;
|
||||
while (i-- > 0)
|
||||
{
|
||||
if (((*s)->state() & net_input_t::INP_STATE_ACTIVE) != 0)
|
||||
#if USE_DELEGATES
|
||||
(*s)->h();
|
||||
#else
|
||||
while (s<e)
|
||||
(*s++)->update();
|
||||
(*s)->netdev()->update_device();
|
||||
#endif
|
||||
s++;
|
||||
}
|
||||
|
||||
m_last_Q = m_Q;
|
||||
}
|
||||
|
||||
ATTR_COLD void net_output_t::register_con(net_input_t &input)
|
||||
{
|
||||
int i;
|
||||
if (m_num_cons >= ARRAY_LENGTH(m_cons))
|
||||
fatalerror("Connections exceeded for %s\n", m_netdev->name());
|
||||
|
||||
/* keep similar devices together */
|
||||
for (i = 0; i < m_num_cons; i++)
|
||||
#if USE_DELEGATES
|
||||
if (m_cons[i]->h == input.h)
|
||||
break;
|
||||
#else
|
||||
if (m_cons[i]->netdev() == input.netdev())
|
||||
break;
|
||||
#endif
|
||||
for (int j = m_num_cons; j > i; j--)
|
||||
m_cons[j] = m_cons[j - 1];
|
||||
m_cons[i] = &input;
|
||||
m_num_cons++;
|
||||
if (input.state() != net_input_t::INP_STATE_PASSIVE)
|
||||
m_active++;
|
||||
}
|
||||
|
||||
NETLIB_UPDATE(netdev_callback)
|
||||
{
|
||||
// FIXME: Remove after device cleanup
|
||||
if (!m_callback.isnull())
|
||||
m_callback(INPVAL(m_in));
|
||||
m_callback(INPANALOG(m_in));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -674,17 +881,6 @@ netlist_mame_device::netlist_mame_device(const machine_config &mconfig, const ch
|
||||
: device_t(mconfig, NETLIST, "netlist", tag, owner, clock),
|
||||
device_execute_interface(mconfig, *this)
|
||||
{
|
||||
m_clock = clock;
|
||||
}
|
||||
|
||||
void netlist_mame_device::static_set_subcycles(device_t &device, int subcycles)
|
||||
{
|
||||
netlist_mame_device &netlist = downcast<netlist_mame_device &>(device);
|
||||
|
||||
assert((subcycles & 1) == 0);
|
||||
assert( subcycles > 0);
|
||||
|
||||
netlist.m_subcycles = subcycles;
|
||||
}
|
||||
|
||||
void netlist_mame_device::static_set_constructor(device_t &device, void (*setup_func)(netlist_setup_t &))
|
||||
@ -701,8 +897,8 @@ void netlist_mame_device::device_start()
|
||||
{
|
||||
|
||||
//double dt = clocks_to_attotime(1).as_double();
|
||||
m_netlist = global_alloc_clear(netlist_t(*this, m_subcycles > 2));
|
||||
m_netlist->set_clock_freq(m_clock * m_subcycles);
|
||||
m_netlist = global_alloc_clear(netlist_t(*this));
|
||||
m_netlist->set_clock_freq(this->clock());
|
||||
|
||||
m_setup = global_alloc_clear(netlist_setup_t(*m_netlist));
|
||||
|
||||
@ -717,18 +913,12 @@ void netlist_mame_device::device_start()
|
||||
|
||||
m_setup->resolve_inputs();
|
||||
|
||||
//m_clockcnt = 0;
|
||||
|
||||
m_clock_input = m_setup->find_output("clk");
|
||||
|
||||
//save_item(NAME(m_clockcnt));
|
||||
save_state();
|
||||
/* TODO: we have to save the round robin queue as well */
|
||||
|
||||
// set our instruction counter
|
||||
m_icountptr = &m_icount;
|
||||
m_ss = SubCycles() / 2;
|
||||
m_clk = 0;
|
||||
}
|
||||
|
||||
void netlist_mame_device::device_reset()
|
||||
@ -761,37 +951,25 @@ void netlist_mame_device::save_state()
|
||||
|
||||
UINT64 netlist_mame_device::execute_clocks_to_cycles(UINT64 clocks) const
|
||||
{
|
||||
return clocks * SubCycles();
|
||||
return clocks;
|
||||
}
|
||||
|
||||
UINT64 netlist_mame_device::execute_cycles_to_clocks(UINT64 cycles) const
|
||||
{
|
||||
return cycles / SubCycles();
|
||||
return cycles;
|
||||
}
|
||||
|
||||
ATTR_HOT void netlist_mame_device::execute_run()
|
||||
{
|
||||
//bool check_debugger = ((device_t::machine().debug_flags & DEBUG_FLAG_ENABLED) != 0);
|
||||
osd_ticks_t a = -osd_ticks();
|
||||
UINT8 ssdiv2 = (SubCycles() / 2);
|
||||
//int p = m_icount;
|
||||
do
|
||||
{
|
||||
// debugging
|
||||
//m_ppc = m_pc; // copy PC to previous PC
|
||||
//if (check_debugger)
|
||||
// debugger_instruction_hook(this, 0); //m_pc);
|
||||
if (--m_ss == 0)
|
||||
{
|
||||
m_ss = ssdiv2;
|
||||
m_clk = !m_clk;
|
||||
m_clock_input->setTo(m_clk);
|
||||
}
|
||||
m_netlist->process_list();
|
||||
m_icount--;
|
||||
} while (m_icount > 0);
|
||||
a+=osd_ticks();
|
||||
//printf("%ld %d %ld\n", (long) a, p, (long) (a * 1000 / p));
|
||||
|
||||
// debugging
|
||||
//m_ppc = m_pc; // copy PC to previous PC
|
||||
//if (check_debugger)
|
||||
// debugger_instruction_hook(this, 0); //m_pc);
|
||||
|
||||
m_netlist->process_list(m_icount);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -46,7 +46,7 @@ TODO:
|
||||
* http://www.youtube.com/watch?v=pDrRnJOCKZc
|
||||
*/
|
||||
|
||||
#define MASTER_CLOCK 7139000
|
||||
#define MASTER_CLOCK 7159000
|
||||
#define V_TOTAL (0x105+1)
|
||||
#define H_TOTAL (0x1C6+1) // 454
|
||||
|
||||
@ -55,7 +55,7 @@ TODO:
|
||||
#define VBSTART (V_TOTAL)
|
||||
#define VBEND (16)
|
||||
|
||||
#define HRES_MULT (2)
|
||||
#define HRES_MULT (1)
|
||||
|
||||
enum input_changed_enum
|
||||
{
|
||||
@ -64,15 +64,17 @@ enum input_changed_enum
|
||||
IC_COIN,
|
||||
IC_SWITCH,
|
||||
IC_VR1,
|
||||
IC_VR2,
|
||||
IC_GATEDELAY
|
||||
IC_VR2
|
||||
};
|
||||
|
||||
static NETLIST_START(pong_schematics)
|
||||
NETDEV_CONST(high, 1)
|
||||
NETDEV_CONST(low, 0)
|
||||
NETDEV_INPUT(clk)
|
||||
NETDEV_INPUT(SRST)
|
||||
NETDEV_TTL_CONST(high, 1)
|
||||
NETDEV_TTL_CONST(low, 0)
|
||||
NETDEV_CLOCK(clk)
|
||||
NETDEV_PARAM(clk.FREQ, 7159000.0)
|
||||
NETDEV_LOGIC_INPUT(SRST)
|
||||
NETDEV_ANALOG_INPUT(P1)
|
||||
NETDEV_ANALOG_INPUT(P2)
|
||||
|
||||
TTL_7404_INVERT(hitQ, hit)
|
||||
TTL_7400_NAND(hit, hit1Q, hit2Q)
|
||||
@ -111,9 +113,9 @@ static NETLIST_START(pong_schematics)
|
||||
TTL_7427_NOR(ic_g2a, ic_g3c.Q, 256HQ, vpad2Q)
|
||||
NET_ALIAS(pad2, ic_g2a.Q)
|
||||
|
||||
/* horizontal counter */
|
||||
TTL_7493(ic_f8, clk, ic_e7b.QQ, ic_e7b.QQ) /* f8, f9, f6b */
|
||||
TTL_7493(ic_f9, ic_f8.QD, ic_e7b.QQ, ic_e7b.QQ) /* f8, f9, f6b */
|
||||
// horizontal counter
|
||||
TTL_7493(ic_f8, clk, ic_f8.QA, ic_e7b.QQ, ic_e7b.QQ) // f8, f9, f6b
|
||||
TTL_7493(ic_f9, ic_f8.QD, ic_f9.QA, ic_e7b.QQ, ic_e7b.QQ) // f8, f9, f6b
|
||||
TTL_74107(ic_f6b, ic_f9.QD, high, high, ic_e7b.Q)
|
||||
TTL_7430_NAND(ic_f7, ic_f8.QB, ic_f8.QC, ic_f9.QC, ic_f9.QD, ic_f6b.Q, high, high, high)
|
||||
TTL_7474(ic_e7b, clk, ic_f7, high, high)
|
||||
@ -129,9 +131,9 @@ static NETLIST_START(pong_schematics)
|
||||
NET_ALIAS(256H, ic_f6b.Q)
|
||||
NET_ALIAS(256HQ, ic_f6b.QQ)
|
||||
|
||||
/* vertical counter */
|
||||
TTL_7493(ic_e8, hreset, ic_e7a.QQ, ic_e7a.QQ) /* e8, e9, d9b */
|
||||
TTL_7493(ic_e9, ic_e8.QD, ic_e7a.QQ, ic_e7a.QQ) /* e8, e9, d9b */
|
||||
// vertical counter
|
||||
TTL_7493(ic_e8, hreset, ic_e8.QA, ic_e7a.QQ, ic_e7a.QQ) // e8, e9, d9b
|
||||
TTL_7493(ic_e9, ic_e8.QD,ic_e9.QA, ic_e7a.QQ, ic_e7a.QQ) // e8, e9, d9b
|
||||
TTL_74107(ic_d9b, ic_e9.QD, high, high, ic_e7a.Q)
|
||||
TTL_7474(ic_e7a, hreset, e7a_data, high, high)
|
||||
TTL_7410_NAND(e7a_data, ic_e8.QA, ic_e8.QC, ic_d9b.Q)
|
||||
@ -147,11 +149,11 @@ static NETLIST_START(pong_schematics)
|
||||
NET_ALIAS(256VQ, ic_d9b.QQ)
|
||||
|
||||
|
||||
/* hblank flip flop */
|
||||
// hblank flip flop
|
||||
|
||||
TTL_7400_NAND(ic_g5b, 16H, 64H)
|
||||
|
||||
/* the time critical one */
|
||||
// the time critical one
|
||||
TTL_7400_NAND(ic_h5c, ic_h5b.Q, hresetQ)
|
||||
TTL_7400_NAND(ic_h5b, ic_h5c.Q, ic_g5b.Q)
|
||||
|
||||
@ -159,7 +161,7 @@ static NETLIST_START(pong_schematics)
|
||||
NET_ALIAS(hblankQ, ic_h5b.Q)
|
||||
TTL_7400_NAND(hsyncQ, hblank, 32H)
|
||||
|
||||
/* vblank flip flop */
|
||||
// vblank flip flop
|
||||
TTL_7402_NOR(ic_f5c, ic_f5d.Q, vreset)
|
||||
TTL_7402_NOR(ic_f5d, ic_f5c.Q, 16V)
|
||||
|
||||
@ -170,11 +172,11 @@ static NETLIST_START(pong_schematics)
|
||||
TTL_7410_NAND(ic_g5a, vblank, 4V, ic_h5a.Q)
|
||||
NET_ALIAS(vsyncQ, ic_g5a.Q)
|
||||
|
||||
/* move logic */
|
||||
// move logic
|
||||
|
||||
TTL_7400_NAND(ic_e1d, hit_sound, ic_e1c.Q)
|
||||
TTL_7400_NAND(ic_e1c, ic_f1.QC, ic_f1.QD)
|
||||
TTL_7493(ic_f1, ic_e1d.Q, rstspeed, rstspeed)
|
||||
TTL_7493(ic_f1, ic_e1d.Q, ic_f1.QA, rstspeed, rstspeed)
|
||||
|
||||
TTL_7402_NOR(ic_g1d, ic_f1.QC, ic_f1.QD)
|
||||
TTL_7400_NAND(ic_h1a, ic_g1d.Q, ic_g1d.Q)
|
||||
@ -199,7 +201,7 @@ static NETLIST_START(pong_schematics)
|
||||
NET_ALIAS(Aa, ic_h4c.Q)
|
||||
NET_ALIAS(Ba, ic_h4b.Q)
|
||||
|
||||
/* hvid circuit */
|
||||
// hvid circuit
|
||||
|
||||
TTL_7400_NAND(hball_resetQ, Serve, attractQ)
|
||||
|
||||
@ -210,19 +212,19 @@ static NETLIST_START(pong_schematics)
|
||||
TTL_7420_NAND(ic_h6b, ic_g6b.Q, ic_h7.RC, ic_g7.QC, ic_g7.QD)
|
||||
NET_ALIAS(hvidQ, ic_h6b.Q)
|
||||
|
||||
/* vvid circuit */
|
||||
// vvid circuit
|
||||
|
||||
TTL_9316(ic_b3, hsyncQ, high, vblankQ, high, ic_b2b.Q, a6, b6, c6, d6)
|
||||
TTL_9316(ic_a3, hsyncQ, ic_b3.RC, high, high, ic_b2b.Q, low, low, low, low)
|
||||
TTL_7400_NAND(ic_b2b, ic_a3.RC, ic_b3.RC)
|
||||
TTL_7410_NAND(ic_e2b, ic_a3.RC, ic_b3.QC, ic_b3.QD)
|
||||
NET_ALIAS(vvidQ, ic_e2b.Q)
|
||||
TTL_7404_INVERT(vvid, vvidQ) /* D2D */
|
||||
TTL_7404_INVERT(vvid, vvidQ) // D2D
|
||||
NET_ALIAS(vpos256, ic_a3.RC)
|
||||
NET_ALIAS(vpos32, ic_a3.QB)
|
||||
NET_ALIAS(vpos16, ic_a3.QA)
|
||||
|
||||
/* vball ctrl circuit */
|
||||
// vball ctrl circuit
|
||||
|
||||
TTL_7450_ANDORINVERT(ic_a6a, b1, 256HQ, b2, 256H)
|
||||
TTL_7450_ANDORINVERT(ic_a6b, c1, 256HQ, c2, 256H)
|
||||
@ -231,7 +233,7 @@ static NETLIST_START(pong_schematics)
|
||||
TTL_7474(ic_a5b, hit, ic_a6a, attractQ, high)
|
||||
TTL_7474(ic_a5a, hit, ic_a6b, attractQ, high)
|
||||
TTL_7474(ic_b5a, hit, ic_b6b, attractQ, high)
|
||||
TTL_74107(ic_h2x, vblank, vvid, vvid, hitQ) /* two marked at position h2a ==> this h2x */
|
||||
TTL_74107(ic_h2x, vblank, vvid, vvid, hitQ) // two marked at position h2a ==> this h2x
|
||||
|
||||
TTL_7486_XOR(ic_a4c, ic_a5b.Q, ic_h2x.Q)
|
||||
TTL_7486_XOR(ic_a4b, ic_a5a.Q, ic_h2x.Q)
|
||||
@ -246,9 +248,9 @@ static NETLIST_START(pong_schematics)
|
||||
NET_ALIAS(c6, ic_b4.SC)
|
||||
NET_ALIAS(d6, ic_b4.SD)
|
||||
|
||||
/* serve monoflop */
|
||||
// serve monoflop
|
||||
TTL_7404_INVERT(f4_trig, rstspeed)
|
||||
NE555N_MSTABLE(ic_f4_serve, f4_trig)
|
||||
NE555N_MSTABLE(ic_f4_serve, f4_trig, NC)
|
||||
NETDEV_PARAM(ic_f4_serve.R, RES_K(330))
|
||||
NETDEV_PARAM(ic_f4_serve.C, CAP_U(4.7))
|
||||
|
||||
@ -258,15 +260,15 @@ static NETLIST_START(pong_schematics)
|
||||
NET_ALIAS(Serve, ic_b5b_serve.QQ)
|
||||
NET_ALIAS(ServeQ, ic_b5b_serve.Q)
|
||||
|
||||
/* score logic */
|
||||
// score logic
|
||||
|
||||
TTL_7474(ic_h3a, 4H, 128H, high, attractQ)
|
||||
|
||||
/* sound logic */
|
||||
// sound logic
|
||||
TTL_7474(ic_c2a, vpos256, high, hitQ, high)
|
||||
TTL_74107(ic_f3_topbot, vblank, vvid, vvidQ, ServeQ)
|
||||
NE555N_MSTABLE(ic_g4_sc, MissQ)
|
||||
NET_ALIAS(SC, ic_g4_sc.Q) /* monoflop with NE555 determines score sound */
|
||||
NE555N_MSTABLE(ic_g4_sc, MissQ, NC)
|
||||
NET_ALIAS(SC, ic_g4_sc.Q) // monoflop with NE555 determines score sound
|
||||
NETDEV_PARAM(ic_g4_sc.R, RES_K(220))
|
||||
NETDEV_PARAM(ic_g4_sc.C, CAP_U(1))
|
||||
|
||||
@ -280,15 +282,15 @@ static NETLIST_START(pong_schematics)
|
||||
NET_ALIAS(sound, ic_c1b.Q)
|
||||
|
||||
|
||||
/* paddle1 logic 1 */
|
||||
// paddle1 logic 1
|
||||
|
||||
NE555N_MSTABLE(ic_b9, 256VQ)
|
||||
NE555N_MSTABLE(ic_b9, 256VQ, P1)
|
||||
NETDEV_PARAM(ic_b9.R, RES_K(90))
|
||||
NETDEV_PARAM(ic_b9.C, CAP_U(.1))
|
||||
NETDEV_PARAM(ic_b9.VL, 0.7)
|
||||
TTL_7404_INVERT(ic_c9b, ic_b9.Q)
|
||||
TTL_7400_NAND(ic_b7b, ic_a7b.Q, hsyncQ)
|
||||
TTL_7493(ic_b8, ic_b7b.Q, ic_b9.Q, ic_b9.Q)
|
||||
TTL_7493(ic_b8, ic_b7b.Q, ic_b8.QA, ic_b9.Q, ic_b9.Q)
|
||||
TTL_7400_NAND(ic_b7a, ic_c9b.Q, ic_a7b.Q)
|
||||
TTL_7420_NAND(ic_a7b, ic_b8.QA, ic_b8.QB, ic_b8.QC, ic_b8.QD)
|
||||
NET_ALIAS(vpad1Q, ic_b7a.Q)
|
||||
@ -297,15 +299,15 @@ static NETLIST_START(pong_schematics)
|
||||
NET_ALIAS(c1, ic_b8.QC)
|
||||
NET_ALIAS(d1, ic_b8.QD)
|
||||
|
||||
/* paddle1 logic 2 */
|
||||
// paddle1 logic 2
|
||||
|
||||
NE555N_MSTABLE(ic_a9, 256VQ)
|
||||
NE555N_MSTABLE(ic_a9, 256VQ, P2)
|
||||
NETDEV_PARAM(ic_a9.R, RES_K(90))
|
||||
NETDEV_PARAM(ic_a9.C, CAP_U(.1))
|
||||
NETDEV_PARAM(ic_a9.VL, 0.7)
|
||||
TTL_7404_INVERT(ic_c9a, ic_a9.Q)
|
||||
TTL_7400_NAND(ic_b7c, ic_a7a.Q, hsyncQ)
|
||||
TTL_7493(ic_a8, ic_b7c.Q, ic_a9.Q, ic_a9.Q)
|
||||
TTL_7493(ic_a8, ic_b7c.Q, ic_a8.QA, ic_a9.Q, ic_a9.Q)
|
||||
TTL_7400_NAND(ic_b7d, ic_c9a.Q, ic_a7a.Q)
|
||||
TTL_7420_NAND(ic_a7a, ic_a8.QA, ic_a8.QB, ic_a8.QC, ic_a8.QD)
|
||||
NET_ALIAS(vpad2Q, ic_b7d.Q)
|
||||
@ -314,7 +316,7 @@ static NETLIST_START(pong_schematics)
|
||||
NET_ALIAS(c2, ic_a8.QC)
|
||||
NET_ALIAS(d2, ic_a8.QD)
|
||||
|
||||
/* C5-EN Logic */
|
||||
// C5-EN Logic
|
||||
|
||||
TTL_7404_INVERT(ic_e3a, 128H)
|
||||
TTL_7427_NOR( ic_e3b, 256H, 64H, ic_e3a.Q)
|
||||
@ -325,14 +327,14 @@ static NETLIST_START(pong_schematics)
|
||||
TTL_7425_NOR(ic_f2a, ic_g1a.Q, 64V, 128V, ic_d2c.Q)
|
||||
NET_ALIAS(c5-en, ic_f2a.Q)
|
||||
|
||||
/* Score logic ... */
|
||||
// Score logic ...
|
||||
|
||||
TTL_7402_NOR(ic_f5b, L, Missed)
|
||||
TTL_7490(ic_c7, ic_f5b, SRST, SRST, low, low)
|
||||
TTL_74107(ic_c8a, ic_c7.QD, high, high, SRSTQ)
|
||||
NETDEV_SWITCH2(sw1a, high, ic_c7.QC)
|
||||
NETDEV_PARAM(sw1a.POS, 0)
|
||||
TTL_7410_NAND(ic_d8a, ic_c7.QA, sw1a.Q, ic_c8a.Q) /* would be nand2 for 11 instead of 15 points, need a switch dev! */
|
||||
TTL_7410_NAND(ic_d8a, ic_c7.QA, sw1a.Q, ic_c8a.Q) // would be nand2 for 11 instead of 15 points, need a switch dev!
|
||||
|
||||
NET_ALIAS(StopG1Q, ic_d8a.Q)
|
||||
NET_ALIAS(score1_1, ic_c7.QA)
|
||||
@ -347,7 +349,7 @@ static NETLIST_START(pong_schematics)
|
||||
TTL_74107(ic_c8b, ic_d7.QD, high, high, SRSTQ)
|
||||
NETDEV_SWITCH2(sw1b, high, ic_d7.QC)
|
||||
NETDEV_PARAM(sw1b.POS, 0)
|
||||
TTL_7410_NAND(ic_d8b, ic_d7.QA, sw1b.Q, ic_c8b.Q) /* would be nand2 for 11 instead of 15 points, need a switch dev! */
|
||||
TTL_7410_NAND(ic_d8b, ic_d7.QA, sw1b.Q, ic_c8b.Q) // would be nand2 for 11 instead of 15 points, need a switch dev!
|
||||
|
||||
NET_ALIAS(StopG2Q, ic_d8b.Q)
|
||||
NET_ALIAS(score2_1, ic_d7.QA)
|
||||
@ -357,7 +359,7 @@ static NETLIST_START(pong_schematics)
|
||||
NET_ALIAS(score2_10, ic_c8b.Q)
|
||||
NET_ALIAS(score2_10Q, ic_c8b.QQ)
|
||||
|
||||
/* Score display */
|
||||
// Score display
|
||||
|
||||
TTL_74153(ic_d6a, score1_10Q, score1_4, score2_10Q, score2_4, 32H, 64H, low)
|
||||
TTL_74153(ic_d6b, score1_10Q, score1_8, score2_10Q, score2_8, 32H, 64H, low)
|
||||
@ -395,18 +397,26 @@ static NETLIST_START(pong_schematics)
|
||||
TTL_7430_NAND(ic_d3, ic_d4a, ic_d5c, ic_c4c, ic_d5a, ic_d4c, ic_d4b, ic_d5b, high)
|
||||
NET_ALIAS(score, ic_d3.Q) //FIXME
|
||||
|
||||
/* net */
|
||||
// net
|
||||
TTL_74107(ic_f3b, clk, 256H, 256HQ, high)
|
||||
TTL_7400_NAND(ic_g3b, ic_f3b.QQ, 256H)
|
||||
TTL_7427_NOR(ic_g2b, ic_g3b.Q, vblank, 4V)
|
||||
NET_ALIAS(net, ic_g2b.Q)
|
||||
|
||||
/* video */
|
||||
// video
|
||||
TTL_7402_NOR(ic_g1b, hvidQ, vvidQ)
|
||||
TTL_7425_NOR(ic_f2b, ic_g1b.Q, pad1, pad2, net)
|
||||
TTL_7404_INVERT(ic_e4e, ic_f2b.Q)
|
||||
NET_ALIAS(video, ic_e4e.Q)
|
||||
|
||||
TTL_7486_XOR(ic_a4d, hsyncQ, vsyncQ)
|
||||
TTL_7404_INVERT(ic_e4f, ic_a4d.Q)
|
||||
|
||||
NETDEV_MIXER3(videomix, video, score, ic_e4f.Q)
|
||||
NETDEV_PARAM(videomix.R1, RES_K(1))
|
||||
NETDEV_PARAM(videomix.R2, RES_K(1.2))
|
||||
NETDEV_PARAM(videomix.R3, RES_K(22))
|
||||
|
||||
NETLIST_END
|
||||
|
||||
static NETLIST_START(pong)
|
||||
@ -414,8 +424,7 @@ static NETLIST_START(pong)
|
||||
//NETLIST_INCLUDE(pong_schematics)
|
||||
NETLIST_MEMREGION("maincpu")
|
||||
NETDEV_CALLBACK(sound_cb, sound)
|
||||
NETDEV_CALLBACK(video_cb, video)
|
||||
NETDEV_CALLBACK(score_cb, score)
|
||||
NETDEV_CALLBACK(video_cb, videomix)
|
||||
|
||||
NETLIST_END
|
||||
|
||||
@ -425,13 +434,12 @@ static NETLIST_START(pong_fast)
|
||||
/* the signal above is delayed on pong due to counter at gate delays.
|
||||
* This is approximated by the following circuit ...
|
||||
*/
|
||||
NET_REMOVE_DEV(ic_h5b)
|
||||
NETDEV_DELAY_RISE(ic_g5b_D, clk, ic_g5b.Q)
|
||||
TTL_7400_NAND(ic_h5b, ic_h5c.Q, ic_g5b_D.Q)
|
||||
//NET_REMOVE_DEV(ic_h5b)
|
||||
//NETDEV_DELAY_RISE(ic_g5b_D, clk, ic_g5b.Q)
|
||||
//TTL_7400_NAND(ic_h5b, ic_h5c.Q, ic_g5b_D.Q)
|
||||
|
||||
NETDEV_CALLBACK(sound_cb, sound)
|
||||
NETDEV_CALLBACK(video_cb, video)
|
||||
NETDEV_CALLBACK(score_cb, score)
|
||||
NETDEV_CALLBACK(video_cb, videomix)
|
||||
|
||||
NETLIST_END
|
||||
|
||||
@ -443,10 +451,10 @@ public:
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_dac(*this, "dac"), /* just to have a sound device */
|
||||
m_srst(*this, "maincpu", "SRST"),
|
||||
m_p_V0(*this, "maincpu", "P1"),
|
||||
m_p_V1(*this, "maincpu", "P2"),
|
||||
m_sw1a(*this, "maincpu", "sw1a.POS"),
|
||||
m_sw1b(*this, "maincpu", "sw1b.POS"),
|
||||
m_p_V0(*this, "maincpu", "ic_a9.VT"),
|
||||
m_p_V1(*this, "maincpu", "ic_b9.VT"),
|
||||
m_p_R0(*this, "maincpu", "ic_a9.R"),
|
||||
m_p_R1(*this, "maincpu", "ic_b9.R")
|
||||
{
|
||||
@ -457,11 +465,11 @@ public:
|
||||
required_device<dac_device> m_dac; /* just to have a sound device */
|
||||
|
||||
// sub devices
|
||||
netlist_mame_device::required_output m_srst;
|
||||
netlist_mame_device::required_output<logic_output_t> m_srst;
|
||||
netlist_mame_device::required_output<analog_output_t> m_p_V0;
|
||||
netlist_mame_device::required_output<analog_output_t> m_p_V1;
|
||||
netlist_mame_device::required_param m_sw1a;
|
||||
netlist_mame_device::required_param m_sw1b;
|
||||
netlist_mame_device::required_param m_p_V0;
|
||||
netlist_mame_device::required_param m_p_V1;
|
||||
netlist_mame_device::required_param m_p_R0;
|
||||
netlist_mame_device::required_param m_p_R1;
|
||||
|
||||
@ -469,21 +477,21 @@ public:
|
||||
|
||||
DECLARE_INPUT_CHANGED_MEMBER(input_changed);
|
||||
|
||||
void sound_cb(net_sig_t newval)
|
||||
void sound_cb(double newval)
|
||||
{
|
||||
m_dac->write_unsigned8(128*(!newval));
|
||||
//printf("snd %f\n", newval);
|
||||
//dac_w(m_dac, 0, newval*64);
|
||||
m_dac->write_unsigned8(64*newval);
|
||||
}
|
||||
|
||||
void video_cb(net_sig_t newval)
|
||||
void video_cb(double newval)
|
||||
{
|
||||
update_vid();
|
||||
m_vid = (m_vid & 2) | (UINT8) newval;
|
||||
}
|
||||
|
||||
void score_cb(net_sig_t newval)
|
||||
{
|
||||
update_vid();
|
||||
m_vid = (m_vid & 1) | ((UINT8) newval<<1);
|
||||
//printf("%f\n", newval);
|
||||
if (newval != m_vid)
|
||||
{
|
||||
update_vid();
|
||||
m_vid = newval;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -498,29 +506,75 @@ private:
|
||||
|
||||
void update_vid()
|
||||
{
|
||||
const netlist_time clock_period = netlist_time::from_hz(NETLIST_CLOCK);
|
||||
const netlist_time hsync_min_time = netlist_time::from_us(4);
|
||||
const netlist_time vsync_min_time = netlist_time::from_us(50); /* usec */
|
||||
const int vsync_min_pulses = 4;
|
||||
|
||||
UINT64 clocks = m_maincpu->total_cycles(); // m_maincpu->attotime_to_cycles(m_maincpu->local_time());
|
||||
int new_x = clocks % ( m_maincpu->SubCycles() * H_TOTAL);
|
||||
int new_y = (clocks / (m_maincpu->SubCycles() * H_TOTAL)) % V_TOTAL;
|
||||
if (m_vid > 0)
|
||||
int pw = NETLIST_CLOCK / ((UINT64)MASTER_CLOCK) / HRES_MULT;
|
||||
netlist_time time = clock_period * (clocks - m_last_clock);
|
||||
|
||||
//UINT64 clocks = m_maincpu->netlist().time().as_raw() >> 10; // m_maincpu->attotime_to_cycles(m_maincpu->local_time());
|
||||
//int pw = (NETLIST_INTERNAL_CLOCK / ((UINT64)MASTER_CLOCK) / HRES_MULT) >> 8;
|
||||
|
||||
if (m_last_y < m_bitmap->height())
|
||||
{
|
||||
rgb_t col = MAKE_RGB(255,255,255);
|
||||
if (new_y > m_last_y)
|
||||
new_x = m_maincpu->SubCycles() * H_TOTAL-1;
|
||||
int delta = (new_x - m_last_x);
|
||||
if (delta < m_maincpu->SubCycles())
|
||||
col = MAKE_RGB(255 * delta /( m_maincpu->SubCycles()),255 * delta /( m_maincpu->SubCycles()),255 * delta /( m_maincpu->SubCycles()));
|
||||
for (int i = m_last_x / ( m_maincpu->SubCycles() / HRES_MULT); i < new_x / ( m_maincpu->SubCycles()/HRES_MULT); i++)
|
||||
int colv = (int) (m_vid / 3.5 * 255.0);
|
||||
rgb_t col = MAKE_RGB(colv, colv, colv);
|
||||
int pixels = (clocks - m_line_clock) / pw;
|
||||
|
||||
while (pixels >= m_bitmap->width())
|
||||
{
|
||||
for (int i = m_last_x ; i < m_bitmap->width() - 1; i++)
|
||||
m_bitmap->pix(m_last_y, i) = col;
|
||||
pixels -= m_bitmap->width();
|
||||
m_last_x = 0;
|
||||
}
|
||||
for (int i = m_last_x ; i < pixels; i++)
|
||||
m_bitmap->pix(m_last_y, i) = col;
|
||||
m_last_x = pixels;
|
||||
}
|
||||
m_last_x = new_x;
|
||||
m_last_y = new_y;
|
||||
if (m_vid <= 0.34)
|
||||
{
|
||||
if (time >= vsync_min_time)
|
||||
{
|
||||
m_vsync_cnt++;
|
||||
if (m_vsync_cnt >= vsync_min_pulses)
|
||||
{
|
||||
m_vsync_cnt = 0;
|
||||
m_last_y = 0;
|
||||
attoseconds_t new_refresh = DOUBLE_TO_ATTOSECONDS((double) (clocks - m_vsync_clock) / (double) NETLIST_CLOCK);
|
||||
if (new_refresh != m_refresh)
|
||||
{
|
||||
m_refresh = new_refresh;
|
||||
rectangle visarea(0, H_TOTAL * HRES_MULT - 1, 0, V_TOTAL-1);
|
||||
this->mconfig().first_screen()->configure(H_TOTAL * HRES_MULT, V_TOTAL, visarea, m_refresh);
|
||||
m_vsync_clock = clocks;
|
||||
}
|
||||
}
|
||||
m_last_y++;
|
||||
m_last_x = 0;
|
||||
}
|
||||
else if (time >= hsync_min_time)
|
||||
{
|
||||
m_last_x = 0; // hsync
|
||||
m_last_y++;
|
||||
m_line_clock = clocks;
|
||||
}
|
||||
}
|
||||
m_last_clock = clocks;
|
||||
}
|
||||
|
||||
UINT8 m_vid;
|
||||
double m_vid;
|
||||
int m_last_x;
|
||||
int m_last_y;
|
||||
UINT64 m_last_clock;
|
||||
UINT64 m_line_clock;
|
||||
UINT64 m_vsync_clock;
|
||||
attoseconds_t m_refresh;
|
||||
int m_vsync_cnt;
|
||||
bitmap_rgb32 *m_bitmap;
|
||||
|
||||
};
|
||||
|
||||
void pong_state::machine_start()
|
||||
@ -530,13 +584,10 @@ void pong_state::machine_start()
|
||||
|
||||
m_maincpu->setup().register_callback("sound_cb", net_output_delegate(&pong_state::sound_cb, "pong_state::sound_cb", this));
|
||||
m_maincpu->setup().register_callback("video_cb", net_output_delegate(&pong_state::video_cb, "pong_state::video_cb", this));
|
||||
m_maincpu->setup().register_callback("score_cb", net_output_delegate(&pong_state::score_cb, "pong_state::score_cb", this));
|
||||
}
|
||||
|
||||
void pong_state::machine_reset()
|
||||
{
|
||||
// m_sound_nmi_enabled = FALSE;
|
||||
// m_nmi_enable = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -549,7 +600,7 @@ void pong_state::video_start()
|
||||
UINT32 pong_state::screen_update( screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect )
|
||||
{
|
||||
copybitmap(bitmap, *m_bitmap, 0, 0, 0, 0, cliprect);
|
||||
m_bitmap->fill(MAKE_RGB(0,0,0));
|
||||
//m_bitmap->fill(MAKE_RGB(0,0,0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -579,8 +630,8 @@ INPUT_CHANGED_MEMBER(pong_state::input_changed)
|
||||
double pad = vA + (vB - vA)*PRE_R / (Req + PRE_R);
|
||||
switch (numpad)
|
||||
{
|
||||
case IC_PADDLE1: m_p_V0->setTo(pad); break;
|
||||
case IC_PADDLE2: m_p_V1->setTo(pad); break;
|
||||
case IC_PADDLE1: m_p_V0->setToPS(pad, NLTIME_FROM_NS(0)); break;
|
||||
case IC_PADDLE2: m_p_V1->setToPS(pad, NLTIME_FROM_NS(0)); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -589,7 +640,7 @@ INPUT_CHANGED_MEMBER(pong_state::input_changed)
|
||||
m_sw1b->setTo(newval ? 1 : 0);
|
||||
break;
|
||||
case IC_COIN:
|
||||
m_srst->setTo(newval & 1);
|
||||
m_srst->setToPS(newval & 1, NLTIME_FROM_US(500));
|
||||
break;
|
||||
case IC_VR1:
|
||||
case IC_VR2:
|
||||
@ -600,9 +651,6 @@ INPUT_CHANGED_MEMBER(pong_state::input_changed)
|
||||
case IC_VR2: m_p_R1->setTo(pad); break;
|
||||
}
|
||||
break;
|
||||
case IC_GATEDELAY:
|
||||
m_maincpu->netlist().set_gatedelay(newval);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@ -626,15 +674,15 @@ static INPUT_PORTS_START( pong )
|
||||
PORT_ADJUSTER( 63, "VR1 - 50k, Paddle 1 adjustment" ) PORT_CHANGED_MEMBER(DEVICE_SELF, pong_state, input_changed, IC_VR1)
|
||||
PORT_START("VR2")
|
||||
PORT_ADJUSTER( 63, "VR2 - 50k, Paddle 2 adjustment" ) PORT_CHANGED_MEMBER(DEVICE_SELF, pong_state, input_changed, IC_VR2)
|
||||
PORT_START("GATESPEED")
|
||||
PORT_ADJUSTER( 100, "Logic Gate Delay" ) PORT_MINMAX(10, 200) PORT_CHANGED_MEMBER(DEVICE_SELF, pong_state, input_changed, IC_GATEDELAY)
|
||||
//PORT_START("GATESPEED")
|
||||
//PORT_ADJUSTER( 100, "Logic Gate Delay" ) PORT_MINMAX(10, 200) PORT_CHANGED_MEMBER(DEVICE_SELF, pong_state, input_changed, IC_GATEDELAY)
|
||||
|
||||
INPUT_PORTS_END
|
||||
|
||||
static MACHINE_CONFIG_START( pong, pong_state )
|
||||
|
||||
/* basic machine hardware */
|
||||
MCFG_NETLIST_ADD("maincpu", MASTER_CLOCK, pong, 10)
|
||||
MCFG_NETLIST_ADD("maincpu", pong)
|
||||
|
||||
/* video hardware */
|
||||
MCFG_SCREEN_ADD("screen", RASTER)
|
||||
@ -651,7 +699,8 @@ MACHINE_CONFIG_END
|
||||
static MACHINE_CONFIG_DERIVED( pongf, pong )
|
||||
|
||||
/* basic machine hardware */
|
||||
MCFG_NETLIST_REPLACE("maincpu", MASTER_CLOCK, pong_fast, 2)
|
||||
//MCFG_NETLIST_REPLACE("maincpu", MASTER_CLOCK, pong_fast, 100)
|
||||
MCFG_NETLIST_REPLACE("maincpu", pong_fast)
|
||||
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
@ -663,7 +712,7 @@ MACHINE_CONFIG_END
|
||||
|
||||
ROM_START( pong ) /* dummy to satisfy game entry*/
|
||||
ROM_REGION( 0x10000, "maincpu", 0 ) /* enough for netlist */
|
||||
ROM_LOAD( "pong.netlist", 0x00000, 10306, CRC(bb92b267) SHA1(0dd6b3209ac1335a97cfe159502d24556f531007) )
|
||||
ROM_LOAD( "pong.netlist", 0x000000, 0x0029e4, CRC(e9c409a1) SHA1(1dc99437f49261c3cb3f46153c6258043bc720a0) )
|
||||
ROM_END
|
||||
|
||||
ROM_START( pongf ) /* dummy to satisfy game entry*/
|
||||
|
Loading…
Reference in New Issue
Block a user