summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Couriersud <couriersud@users.noreply.github.com>2013-12-20 15:54:48 +0000
committer Couriersud <couriersud@users.noreply.github.com>2013-12-20 15:54:48 +0000
commitf46847e487f4ea9eda52c6e3189deabaf0f3e34e (patch)
tree819ce92808aff399eb4b905660ab03baebc7e82b
parent5eb4f5530b1544324fd7e209d036d67991abd195 (diff)
Netlist and Pong:
- Added save-state support. - Fixed a compile issue with MSVC The state saving is now 80% generic. This still needs some polishing, but works.
-rw-r--r--src/emu/machine/netlist.c114
-rw-r--r--src/emu/machine/netlist.h12
-rw-r--r--src/emu/netlist/devices/net_lib.c6
-rw-r--r--src/emu/netlist/devices/nld_7483.c2
-rw-r--r--src/emu/netlist/devices/nld_7490.c3
-rw-r--r--src/emu/netlist/devices/nld_7493.c4
-rw-r--r--src/emu/netlist/devices/nld_9316.c3
-rw-r--r--src/emu/netlist/devices/nld_legacy.c8
-rw-r--r--src/emu/netlist/devices/nld_log.c2
-rw-r--r--src/emu/netlist/devices/nld_ne555.c2
-rw-r--r--src/emu/netlist/devices/nld_signal.h9
-rw-r--r--src/emu/netlist/devices/nld_solver.c38
-rw-r--r--src/emu/netlist/devices/nld_solver.h2
-rw-r--r--src/emu/netlist/devices/nld_twoterm.c9
-rw-r--r--src/emu/netlist/devices/nld_twoterm.h8
-rw-r--r--src/emu/netlist/nl_base.c64
-rw-r--r--src/emu/netlist/nl_base.h118
-rw-r--r--src/emu/netlist/nl_lists.h18
-rw-r--r--src/emu/netlist/nl_setup.c48
-rw-r--r--src/emu/netlist/nl_setup.h24
-rw-r--r--src/emu/netlist/nl_time.h3
-rw-r--r--src/emu/video/fixfreq.c26
-rw-r--r--src/mame/drivers/pong.c4
23 files changed, 450 insertions, 77 deletions
diff --git a/src/emu/machine/netlist.c b/src/emu/machine/netlist.c
index 5e5b5e67d7f..e7bebcfdee4 100644
--- a/src/emu/machine/netlist.c
+++ b/src/emu/machine/netlist.c
@@ -50,7 +50,8 @@
#include "netlist/nl_setup.h"
#include "netlist/devices/net_lib.h"
-#define LOG_DEV_CALLS(x) do { } while (0);
+//#define LOG_DEV_CALLS(x) printf x
+#define LOG_DEV_CALLS(x) do { } while (0)
// ----------------------------------------------------------------------------------------
// netlist_mame_device
@@ -61,6 +62,7 @@ const device_type NETLIST = &device_creator<netlist_mame_device>;
netlist_mame_device::netlist_mame_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, NETLIST, "netlist", tag, owner, clock, "netlist_mame", __FILE__),
device_execute_interface(mconfig, *this),
+ //device_state_interface(mconfig, *this),
m_device_start_list(100),
m_netlist(NULL),
m_setup(NULL),
@@ -86,11 +88,13 @@ void netlist_mame_device::device_start()
LOG_DEV_CALLS(("device_start\n"));
m_netlist = global_alloc_clear(netlist_mame_t(*this));
- m_netlist->set_clock_freq(this->clock());
-
m_setup = global_alloc_clear(netlist_setup_t(*m_netlist));
+ m_netlist->init_object(*m_netlist, "netlist");
+ m_setup->init();
+
+ m_netlist->set_clock_freq(this->clock());
- // register additional devices
+ // register additional devices
m_setup->factory().register_device<nld_analog_callback>( "NETDEV_CALLBACK", "nld_analog_callback");
@@ -107,7 +111,6 @@ void netlist_mame_device::device_start()
m_netlist->xfatalerror("required elements not found\n");
save_state();
- /* TODO: we have to save the round robin queue as well */
// set our instruction counter
m_icountptr = &m_icount;
@@ -130,31 +133,113 @@ void netlist_mame_device::device_stop()
m_netlist = NULL;
}
-void netlist_mame_device::device_post_load()
+ATTR_COLD void netlist_mame_device::device_post_load()
{
+ LOG_DEV_CALLS(("device_post_load\n"));
+ m_netlist->queue().clear();
+ NL_VERBOSE_OUT(("current time %f qsize %d\n", m_netlist->time().as_double(), qsize));
+ for (int i = 0; i < qsize; i++ )
+ {
+ netlist_net_t *n = m_netlist->find_net(qtemp[i].m_name);
+ NL_VERBOSE_OUT(("Got %s ==> %p\n", qtemp[i].m_name, n));
+ NL_VERBOSE_OUT(("schedule time %f (%f)\n", n->time().as_double(), qtemp[i].m_time.as_double()));
+ m_netlist->queue().push(netlist_base_t::queue_t::entry_t(qtemp[i].m_time, *n));
+ }
+}
+
+ATTR_COLD void netlist_mame_device::device_pre_save()
+{
+ LOG_DEV_CALLS(("device_pre_save\n"));
+
+ qsize = m_netlist->queue().count();
+ NL_VERBOSE_OUT(("current time %f qsize %d\n", m_netlist->time().as_double(), qsize));
+ for (int i = 0; i < qsize; i++ )
+ {
+ qtemp[i].m_time = m_netlist->queue().listptr()[i].time();
+ const char *p = m_netlist->queue().listptr()[i].object().name().cstr();
+ int n = MIN(63, strlen(p));
+ strncpy(qtemp[i].m_name, p, n);
+ qtemp[i].m_name[n] = 0;
+ }
+#if 0
+
+ netlist_time *nlt = (netlist_time *) ;
+ netlist_base_t::queue_t::entry_t *p = m_netlist->queue().listptr()[i];
+ netlist_time *nlt = (netlist_time *) p->time_ptr();
+ save_pointer(nlt->get_internaltype_ptr(), "queue", 1, i);
+#endif
}
void netlist_mame_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
}
-void netlist_mame_device::save_state()
+
+
+ATTR_COLD void netlist_mame_device::save_state()
{
+ for (netlist_setup_t::save_entry_list_t::entry_t *p = setup().m_save.first(); p != NULL; p = setup().m_save.next(p))
+ {
+ netlist_setup_t::save_entry_t *s = p->object();
+ NL_VERBOSE_OUT(("saving state for %s\n", s->m_name.cstr()));
+ switch (s->m_dt)
+ {
+ case DT_DOUBLE:
+ save_pointer((double *) s->m_ptr, s->m_name, 1);
+ break;
+ case DT_INT64:
+ save_pointer((INT64 *) s->m_ptr, s->m_name, 1);
+ break;
+ case DT_INT8:
+ save_pointer((INT8 *) s->m_ptr, s->m_name, 1);
+ break;
+ case DT_INT:
+ save_pointer((int *) s->m_ptr, s->m_name, 1);
+ break;
+ case DT_BOOLEAN:
+ save_pointer((bool *) s->m_ptr, s->m_name, 1);
+ break;
#if 0
- for (netlist_setup_t::tagmap_output_t::entry_t *entry = m_setup->m_outputs.first(); entry != NULL; entry = m_setup->m_outputs.next(entry))
- {
- save_item(*entry->object()->Q_ptr(), entry->tag().cstr(), 0);
- save_item(*entry->object()->new_Q_ptr(), entry->tag().cstr(), 1);
- }
+ case DT_NLTIME:
+ {
+ netlist_time *nlt = (netlist_time *) s->m_ptr;
+ //save_pointer((netlist_time::INTERNALTYPE *) s->m_ptr, s->m_name, 1);
+ //save_pointer(nlt->get_internaltype_ptr(), s->m_name, 1);
+ save_item(*nlt->get_internaltype_ptr(), s->m_name.cstr());
+ }
+ break;
+#endif
+ case NOT_SUPPORTED:
+ default:
+ m_netlist->xfatalerror("found unsupported save element %s\n", s->m_name.cstr());
+ break;
+ }
+ }
+
+ // handle the queue
+
+ save_item(NAME(qsize));
+ for (int i = 0; i < m_netlist->queue().capacity(); i++ )
+ {
+ save_pointer(qtemp[i].m_time.get_internaltype_ptr(), "queue_time", 1, i);
+ save_pointer(qtemp[i].m_name, "queue_name", sizeof(qtemp[i].m_name), i);
+
+ }
+#if 0
+
+ netlist_time *nlt = (netlist_time *) ;
+ netlist_base_t::queue_t::entry_t *p = m_netlist->queue().listptr()[i];
+ netlist_time *nlt = (netlist_time *) p->time_ptr();
+ save_pointer(nlt->get_internaltype_ptr(), "queue", 1, i);
#endif
}
-UINT64 netlist_mame_device::execute_clocks_to_cycles(UINT64 clocks) const
+ATTR_COLD UINT64 netlist_mame_device::execute_clocks_to_cycles(UINT64 clocks) const
{
return clocks;
}
-UINT64 netlist_mame_device::execute_cycles_to_clocks(UINT64 cycles) const
+ATTR_COLD UINT64 netlist_mame_device::execute_cycles_to_clocks(UINT64 cycles) const
{
return cycles;
}
@@ -169,5 +254,4 @@ ATTR_HOT void netlist_mame_device::execute_run()
// debugger_instruction_hook(this, 0); //m_pc);
m_netlist->process_queue(m_icount);
-
}
diff --git a/src/emu/machine/netlist.h b/src/emu/machine/netlist.h
index 9389838beab..1ad5588bb00 100644
--- a/src/emu/machine/netlist.h
+++ b/src/emu/machine/netlist.h
@@ -122,6 +122,7 @@ private:
class netlist_mame_device : public device_t,
public device_execute_interface
+ //public device_state_interface
//, public device_memory_interface
{
public:
@@ -158,6 +159,7 @@ protected:
virtual void device_stop();
virtual void device_reset();
virtual void device_post_load();
+ virtual void device_pre_save();
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
virtual UINT64 execute_clocks_to_cycles(UINT64 clocks) const;
virtual UINT64 execute_cycles_to_clocks(UINT64 cycles) const;
@@ -168,6 +170,16 @@ protected:
netlist_setup_t *m_setup;
+// more save state ... needs to go somewhere else
+
+ struct qentry {
+ netlist_time m_time;
+ char m_name[64];
+ };
+
+ qentry qtemp[1024];
+ int qsize;
+
private:
void save_state();
diff --git a/src/emu/netlist/devices/net_lib.c b/src/emu/netlist/devices/net_lib.c
index 93694000426..81a375bfd27 100644
--- a/src/emu/netlist/devices/net_lib.c
+++ b/src/emu/netlist/devices/net_lib.c
@@ -118,6 +118,8 @@ NETLIB_START(nic7448_sub)
register_output("e", m_e);
register_output("f", m_f);
register_output("g", m_g);
+
+ save(NAME(m_state));
}
NETLIB_UPDATE(nic7448_sub)
@@ -225,6 +227,10 @@ NETLIB_START(nic74107Asub)
m_Q.initial(0);
m_QQ.initial(1);
+
+ save(NAME(m_Q1));
+ save(NAME(m_Q2));
+ save(NAME(m_F));
}
NETLIB_START(nic74107A)
diff --git a/src/emu/netlist/devices/nld_7483.c b/src/emu/netlist/devices/nld_7483.c
index 4bf89303fda..eca61846241 100644
--- a/src/emu/netlist/devices/nld_7483.c
+++ b/src/emu/netlist/devices/nld_7483.c
@@ -24,6 +24,8 @@ NETLIB_START(7483)
register_output("SC", m_SC);
register_output("SD", m_SD);
register_output("C4", m_C4);
+
+ save(NAME(m_lastr));
}
NETLIB_UPDATE(7483)
diff --git a/src/emu/netlist/devices/nld_7490.c b/src/emu/netlist/devices/nld_7490.c
index 56dddf21d7a..48b8bbc6b5c 100644
--- a/src/emu/netlist/devices/nld_7490.c
+++ b/src/emu/netlist/devices/nld_7490.c
@@ -19,6 +19,9 @@ NETLIB_START(7490)
register_output("QB", m_Q[1]);
register_output("QC", m_Q[2]);
register_output("QD", m_Q[3]);
+
+ save(NAME(m_cnt));
+
}
NETLIB_UPDATE(7490)
diff --git a/src/emu/netlist/devices/nld_7493.c b/src/emu/netlist/devices/nld_7493.c
index 96d955e2fce..a8c218de5a8 100644
--- a/src/emu/netlist/devices/nld_7493.c
+++ b/src/emu/netlist/devices/nld_7493.c
@@ -28,8 +28,12 @@ NETLIB_START(7493)
NETLIB_START(7493ff)
{
+ m_reset = 0;
+
register_input("CLK", m_I, netlist_input_t::STATE_INP_HL);
register_output("Q", m_Q);
+
+ save(NAME(m_reset));
}
NETLIB_UPDATE(7493ff)
diff --git a/src/emu/netlist/devices/nld_9316.c b/src/emu/netlist/devices/nld_9316.c
index 0406609d902..ede8e0c0e68 100644
--- a/src/emu/netlist/devices/nld_9316.c
+++ b/src/emu/netlist/devices/nld_9316.c
@@ -48,6 +48,9 @@ NETLIB_START(9316_sub)
register_output("QD", m_QD);
register_output("RC", m_RC);
+ save(NAME(m_cnt));
+ save(NAME(m_loadq));
+ save(NAME(m_ent));
}
NETLIB_UPDATE(9316_sub)
diff --git a/src/emu/netlist/devices/nld_legacy.c b/src/emu/netlist/devices/nld_legacy.c
index 990112ff02a..4afe74a45d8 100644
--- a/src/emu/netlist/devices/nld_legacy.c
+++ b/src/emu/netlist/devices/nld_legacy.c
@@ -21,6 +21,9 @@ NETLIB_START(nicMultiSwitch)
}
register_param("POS", m_POS, 0);
register_output("Q", m_Q);
+
+ save(NAME(m_position));
+
}
NETLIB_UPDATE(nicMultiSwitch)
@@ -116,11 +119,14 @@ NETLIB_START(nicNE555N_MSTABLE)
register_param("VS", m_VS, 5.0);
register_param("VL", m_VL, 0.0 *5.0);
- m_THRESHOLD_OUT.init_object(*this, "THRESHOLD");
+ m_THRESHOLD_OUT.init_object(*this, name() + "THRESHOLD");
register_link_internal(m_THRESHOLD, m_THRESHOLD_OUT, netlist_input_t::STATE_INP_ACTIVE);
m_Q.initial(5.0 * 0.4);
m_last = false;
+
+ save(NAME(m_last));
+
}
inline double NETLIB_NAME(nicNE555N_MSTABLE)::nicNE555N_cv()
diff --git a/src/emu/netlist/devices/nld_log.c b/src/emu/netlist/devices/nld_log.c
index 2101b0deb07..e175c4670a8 100644
--- a/src/emu/netlist/devices/nld_log.c
+++ b/src/emu/netlist/devices/nld_log.c
@@ -6,6 +6,8 @@
#include "nld_log.h"
#include "sound/wavwrite.h"
+//FIXME: what to do with save states?
+
NETLIB_START(log)
{
register_input("I", m_I);
diff --git a/src/emu/netlist/devices/nld_ne555.c b/src/emu/netlist/devices/nld_ne555.c
index 312c5984f1a..06a616f2bb9 100644
--- a/src/emu/netlist/devices/nld_ne555.c
+++ b/src/emu/netlist/devices/nld_ne555.c
@@ -48,6 +48,8 @@ NETLIB_START(NE555)
setup().connect(m_RDIS.m_N, m_R3.m_N);
m_last_out = false;
+
+ save(NAME(m_last_out));
}
NETLIB_UPDATE(NE555)
diff --git a/src/emu/netlist/devices/nld_signal.h b/src/emu/netlist/devices/nld_signal.h
index 461b071b4c7..a9e99ec381d 100644
--- a/src/emu/netlist/devices/nld_signal.h
+++ b/src/emu/netlist/devices/nld_signal.h
@@ -43,6 +43,7 @@ public:
register_input(sIN[i], m_i[i], netlist_input_t::STATE_INP_ACTIVE);
}
m_Q.initial(1);
+ save(NAME(m_active));
}
#if (USE_DEACTIVE_DEVICE)
@@ -69,7 +70,7 @@ public:
public:
netlist_ttl_input_t m_i[_numdev];
netlist_ttl_output_t m_Q;
- INT8 m_active;
+ INT32 m_active;
};
@@ -92,6 +93,7 @@ public:
{
register_input(sIN[i], m_i[i]);
}
+ save(NAME(m_active));
}
#if (USE_DEACTIVE_DEVICE)
@@ -142,7 +144,7 @@ public:
public:
netlist_ttl_input_t m_i[_numdev];
netlist_ttl_output_t m_Q;
- INT8 m_active;
+ INT32 m_active;
};
#if 1
@@ -165,6 +167,7 @@ public:
{
register_input(sIN[i], m_i[i], netlist_input_t::STATE_INP_ACTIVE);
}
+ save(NAME(m_active));
}
#if (USE_DEACTIVE_DEVICE)
@@ -214,7 +217,7 @@ public:
public:
netlist_ttl_input_t m_i[2];
netlist_ttl_output_t m_Q;
- INT8 m_active;
+ INT32 m_active;
};
#endif
diff --git a/src/emu/netlist/devices/nld_solver.c b/src/emu/netlist/devices/nld_solver.c
index 78f82c8bd1b..b02f5e4d701 100644
--- a/src/emu/netlist/devices/nld_solver.c
+++ b/src/emu/netlist/devices/nld_solver.c
@@ -187,6 +187,8 @@ static bool already_processed(net_groups_t groups, int &cur_group, netlist_net_t
static void process_net(net_groups_t groups, int &cur_group, netlist_net_t *net)
{
/* add the net */
+ if (net->m_head == NULL)
+ return;
groups[cur_group].add(net);
for (netlist_core_terminal_t *p = net->m_head; p != NULL; p = p->m_update_list_next)
{
@@ -216,10 +218,18 @@ NETLIB_START(solver)
register_param("ACCURACY", m_accuracy, 1e-3);
register_param("CONVERG", m_convergence, 0.3);
- register_link_internal(m_fb_sync, m_Q_sync, netlist_input_t::STATE_INP_ACTIVE);
- register_link_internal(m_fb_step, m_Q_step, netlist_input_t::STATE_INP_ACTIVE);
+ // internal staff
+
+ register_input("FB_sync", m_fb_sync, netlist_input_t::STATE_INP_ACTIVE);
+ register_input("FB_step", m_fb_step, netlist_input_t::STATE_INP_ACTIVE);
+
+ setup().connect(m_fb_sync, m_Q_sync);
+ setup().connect(m_fb_step, m_Q_step);
+
m_last_step = netlist_time::zero;
+ save(NAME(m_last_step));
+
}
NETLIB_UPDATE_PARAM(solver)
@@ -237,13 +247,6 @@ NETLIB_NAME(solver)::~NETLIB_NAME(solver)()
e = en;
}
- netlist_net_t::list_t::entry_t *p = m_nets.first();
- while (p != NULL)
- {
- netlist_net_t::list_t::entry_t *pn = m_nets.next(p);
- delete p->object();
- p = pn;
- }
}
NETLIB_FUNC_VOID(solver, post_start, ())
@@ -251,24 +254,9 @@ NETLIB_FUNC_VOID(solver, post_start, ())
netlist_net_t::list_t groups[100];
int cur_group = -1;
- NL_VERBOSE_OUT(("post start solver ...\n"));
-
- // delete empty nets ...
- for (netlist_net_t::list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
- {
- if (pn->object()->m_head == NULL)
- {
- NL_VERBOSE_OUT(("Deleting net ...\n"));
- netlist_net_t *to_delete = pn->object();
- m_nets.remove(to_delete);
- delete to_delete;
- pn--;
- }
- }
-
SOLVER_VERBOSE_OUT(("Scanning net groups ...\n"));
// determine net groups
- for (netlist_net_t::list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
+ for (netlist_net_t::list_t::entry_t *pn = netlist().m_nets.first(); pn != NULL; pn = netlist().m_nets.next(pn))
{
if (!already_processed(groups, cur_group, pn->object()))
{
diff --git a/src/emu/netlist/devices/nld_solver.h b/src/emu/netlist/devices/nld_solver.h
index 2598e4632f4..55216f70143 100644
--- a/src/emu/netlist/devices/nld_solver.h
+++ b/src/emu/netlist/devices/nld_solver.h
@@ -74,8 +74,6 @@ public:
~NETLIB_NAME(solver)();
- netlist_net_t::list_t m_nets;
-
ATTR_HOT inline void schedule();
ATTR_COLD void post_start();
diff --git a/src/emu/netlist/devices/nld_twoterm.c b/src/emu/netlist/devices/nld_twoterm.c
index 39ac2b6e422..ddf7fc128cd 100644
--- a/src/emu/netlist/devices/nld_twoterm.c
+++ b/src/emu/netlist/devices/nld_twoterm.c
@@ -124,6 +124,9 @@ NETLIB_START(D)
register_param("model", m_model, "");
m_Vd = 0.7;
+
+ save(NAME(m_Vd));
+
}
@@ -197,6 +200,8 @@ NETLIB_START(QBJT_switch<_type>)
setup().connect(m_RB.m_N, m_RC.m_N);
setup().connect(m_RB.m_P, m_BV);
setup().connect(m_RB.m_N, m_EV);
+
+ save(NAME(m_state_on));
}
NETLIB_UPDATE(Q)
@@ -256,8 +261,8 @@ ATTR_COLD void NETLIB_NAME(VCCS)::configure(const double Gfac, const double GI)
register_terminal("OP", m_OP);
register_terminal("ON", m_ON);
- m_OP1.init_object(*this, "OP1", netlist_core_terminal_t::STATE_INP_ACTIVE);
- m_ON1.init_object(*this, "ON1", netlist_core_terminal_t::STATE_INP_ACTIVE);
+ m_OP1.init_object(*this, name() + ".OP1", netlist_core_terminal_t::STATE_INP_ACTIVE);
+ m_ON1.init_object(*this, name() + ".ON1", netlist_core_terminal_t::STATE_INP_ACTIVE);
const double m_mult = m_G.Value() * Gfac; // 1.0 ==> 1V ==> 1A
m_IP.set(GI);
diff --git a/src/emu/netlist/devices/nld_twoterm.h b/src/emu/netlist/devices/nld_twoterm.h
index 4e4b7073ed7..b5cb54f9aa1 100644
--- a/src/emu/netlist/devices/nld_twoterm.h
+++ b/src/emu/netlist/devices/nld_twoterm.h
@@ -219,9 +219,11 @@ public:
}
else
{
- //m_Vd = m_Vd + log((nVd - m_Vd) * m_VtInv + 1.0) * m_Vt;
+#if defined(_MSC_VER) && _MSC_VER < 1200
+ m_Vd = m_Vd + log((nVd - m_Vd) * m_VtInv + 1.0) * m_Vt;
+#else
m_Vd = m_Vd + log1p((nVd - m_Vd) * m_VtInv) * m_Vt;
-
+#endif
const double eVDVt = exp(m_Vd * m_VtInv);
Id = m_Is * (eVDVt - 1.0);
@@ -348,7 +350,7 @@ protected:
double m_gB; // base conductance / switch on
double m_gC; // collector conductance / switch on
double m_V; // internal voltage source
- int m_state_on;
+ UINT8 m_state_on;
private:
};
diff --git a/src/emu/netlist/nl_base.c b/src/emu/netlist/nl_base.c
index e2999ce0146..23d89fac573 100644
--- a/src/emu/netlist/nl_base.c
+++ b/src/emu/netlist/nl_base.c
@@ -29,6 +29,7 @@ ATTR_COLD void netlist_object_t::init_object(netlist_base_t &nl, const pstring &
{
m_netlist = &nl;
m_name = aname;
+ save_register();
}
ATTR_COLD const pstring &netlist_object_t::name() const
@@ -38,6 +39,23 @@ ATTR_COLD const pstring &netlist_object_t::name() const
return m_name;
}
+ATTR_COLD void netlist_object_t::save_state_ptr(const pstring &stname, const netlist_data_type_e dt, const int size, void *ptr)
+{
+ pstring fullname = name() + "." + stname;
+ // do nothing for now;
+ ATTR_UNUSED pstring ts[] = {
+ "NOT_SUPPORTED",
+ "DT_DOUBLE",
+ "DT_INT64",
+ "DT_INT8",
+ "DT_INT",
+ "DT_BOOLEAN"
+ };
+
+ NL_VERBOSE_OUT(("SAVE: <%s> %s(%d) %p\n", fullname.cstr(), ts[dt].cstr(), size, ptr));
+ netlist().setup().save_state_ptr(fullname, dt, size, ptr);
+}
+
// ----------------------------------------------------------------------------------------
// netlist_owned_object_t
// ----------------------------------------------------------------------------------------
@@ -61,7 +79,8 @@ ATTR_COLD void netlist_owned_object_t::init_object(netlist_core_device_t &dev,
// ----------------------------------------------------------------------------------------
netlist_base_t::netlist_base_t()
- : m_time_ps(netlist_time::zero),
+ : netlist_object_t(NETLIST, GENERIC),
+ m_time_ps(netlist_time::zero),
m_rem(0),
m_div(NETLIST_DIV),
m_mainclock(NULL),
@@ -82,9 +101,30 @@ static void tagmap_free_entries(T &tm)
netlist_base_t::~netlist_base_t()
{
tagmap_free_entries<tagmap_devices_t>(m_devices);
+
+ netlist_net_t::list_t::entry_t *p = m_nets.first();
+ while (p != NULL)
+ {
+ netlist_net_t::list_t::entry_t *pn = m_nets.next(p);
+ if (!p->object()->isRailNet())
+ delete p->object();
+ p = pn;
+ }
+
+ m_nets.reset();
pstring::resetmem();
}
+ATTR_COLD netlist_net_t *netlist_base_t::find_net(const pstring &name)
+{
+ for (netlist_net_t::list_t::entry_t *p = m_nets.first(); p != NULL; p = m_nets.next(p))
+ {
+ if (p->object()->name() == name)
+ return p->object();
+ }
+ return NULL;
+}
+
ATTR_COLD void netlist_base_t::set_mainclock_dev(NETLIB_NAME(mainclock) *dev)
{
m_mainclock = dev;
@@ -339,6 +379,7 @@ ATTR_COLD void netlist_device_t::register_input(const pstring &name, netlist_inp
setup().register_object(*this, *this, name, inp, type);
}
+//FIXME: Get rid of this
static void init_term(netlist_core_device_t &dev, netlist_core_terminal_t &term, netlist_input_t::state_e aState)
{
if (!term.isInitalized())
@@ -346,13 +387,13 @@ static void init_term(netlist_core_device_t &dev, netlist_core_terminal_t &term,
switch (term.type())
{
case netlist_terminal_t::OUTPUT:
- dynamic_cast<netlist_output_t &>(term).init_object(dev, "internal output");
+ dynamic_cast<netlist_output_t &>(term).init_object(dev, dev.name() + ".INTOUT");
break;
case netlist_terminal_t::INPUT:
- dynamic_cast<netlist_input_t &>(term).init_object(dev, "internal input", aState);
+ dynamic_cast<netlist_input_t &>(term).init_object(dev, dev.name() + ".INTINP", aState);
break;
case netlist_terminal_t::TERMINAL:
- dynamic_cast<netlist_terminal_t &>(term).init_object(dev, "internal terminal", aState);
+ dynamic_cast<netlist_terminal_t &>(term).init_object(dev, dev.name() + ".INTTERM", aState);
break;
default:
dev.netlist().xfatalerror("Unknown terminal type");
@@ -362,6 +403,7 @@ static void init_term(netlist_core_device_t &dev, netlist_core_terminal_t &term,
}
// FIXME: Revise internal links ...
+//FIXME: Get rid of this
ATTR_COLD void netlist_device_t::register_link_internal(netlist_core_device_t &dev, netlist_input_t &in, netlist_output_t &out, const netlist_input_t::state_e aState)
{
init_term(dev, in, aState);
@@ -377,9 +419,11 @@ ATTR_COLD void netlist_device_t::register_link_internal(netlist_input_t &in, net
template <class C, class T>
ATTR_COLD void netlist_device_t::register_param(netlist_core_device_t &dev, const pstring &sname, C &param, const T initialVal)
{
- param.init_object(dev, sname);
+ pstring fullname = dev.name() + "." + sname;
+ param.init_object(dev, fullname);
param.initial(initialVal);
- setup().register_object(*this, *this, sname, param, netlist_terminal_t::STATE_NONEX);
+ //FIXME: pass fullname from above
+ setup().register_object(*this, *this, fullname, param, netlist_terminal_t::STATE_NONEX);
}
template ATTR_COLD void netlist_device_t::register_param(netlist_core_device_t &dev, const pstring &sname, netlist_param_double_t &param, const double initialVal);
@@ -405,6 +449,12 @@ ATTR_COLD netlist_net_t::netlist_net_t(const type_t atype, const family_t afamil
{
};
+ATTR_COLD void netlist_net_t::init_object(netlist_base_t &nl, const pstring &aname)
+{
+ netlist_object_t::init_object(nl, aname);
+ nl.m_nets.add(this);
+}
+
ATTR_COLD void netlist_net_t::register_railterminal(netlist_output_t &mr)
{
assert(m_railterminal == NULL);
@@ -551,7 +601,7 @@ netlist_output_t::netlist_output_t(const type_t atype, const family_t afamily)
ATTR_COLD void netlist_output_t::init_object(netlist_core_device_t &dev, const pstring &aname)
{
netlist_core_terminal_t::init_object(dev, aname, STATE_OUT);
- net().init_object(dev.netlist(), aname);
+ net().init_object(dev.netlist(), aname + ".net");
net().register_railterminal(*this);
}
diff --git a/src/emu/netlist/nl_base.h b/src/emu/netlist/nl_base.h
index 66efe4e7345..9134f4e4c51 100644
--- a/src/emu/netlist/nl_base.h
+++ b/src/emu/netlist/nl_base.h
@@ -247,6 +247,33 @@ class NETLIB_NAME(solver);
class NETLIB_NAME(mainclock);
// ----------------------------------------------------------------------------------------
+// state saving ...
+// ----------------------------------------------------------------------------------------
+
+enum netlist_data_type_e {
+ NOT_SUPPORTED,
+ DT_DOUBLE,
+ DT_INT64,
+ DT_INT8,
+ DT_INT,
+ DT_BOOLEAN
+};
+
+template<typename _ItemType> struct nl_datatype { static const netlist_data_type_e type = netlist_data_type_e(NOT_SUPPORTED); };
+//template<typename _ItemType> struct type_checker<_ItemType*> { static const bool is_atom = false; static const bool is_pointer = true; };
+
+#define NETLIST_SAVE_TYPE(TYPE, TYPEDESC) template<> struct nl_datatype<TYPE>{ static const netlist_data_type_e type = netlist_data_type_e(TYPEDESC); }
+
+NETLIST_SAVE_TYPE(double, DT_DOUBLE);
+NETLIST_SAVE_TYPE(INT8, DT_INT8);
+NETLIST_SAVE_TYPE(UINT8, DT_INT8);
+NETLIST_SAVE_TYPE(INT64, DT_INT64);
+NETLIST_SAVE_TYPE(UINT64, DT_INT64);
+NETLIST_SAVE_TYPE(bool, DT_BOOLEAN);
+NETLIST_SAVE_TYPE(UINT32, DT_INT);
+NETLIST_SAVE_TYPE(INT32, DT_INT);
+
+// ----------------------------------------------------------------------------------------
// netlist_object_t
// ----------------------------------------------------------------------------------------
@@ -261,6 +288,7 @@ public:
PARAM = 3,
NET = 4,
DEVICE = 5,
+ NETLIST = 6,
};
enum family_t {
// Terminal families
@@ -285,6 +313,12 @@ public:
ATTR_COLD const pstring &name() const;
+ ATTR_COLD void save_state_ptr(const pstring &stname, const netlist_data_type_e, const int size, void *ptr);
+ template<class C> ATTR_COLD void save(C &state, const pstring &stname)
+ {
+ save_state_ptr(stname, nl_datatype<C>::type, sizeof(C), &state);
+ }
+
ATTR_HOT inline const type_t type() const { return m_objtype; }
ATTR_HOT inline const family_t family() const { return m_family; }
@@ -294,6 +328,11 @@ public:
ATTR_HOT inline netlist_base_t & RESTRICT netlist() { return *m_netlist; }
ATTR_HOT inline const netlist_base_t & RESTRICT netlist() const { return *m_netlist; }
+protected:
+
+ // must call parent save_register !
+ ATTR_COLD virtual void save_register() { };
+
private:
pstring m_name;
const type_t m_objtype;
@@ -301,6 +340,11 @@ private:
netlist_base_t * RESTRICT m_netlist;
};
+template<> ATTR_COLD inline void netlist_object_t::save(netlist_time &state, const pstring &stname)
+{
+ save_state_ptr(stname, DT_INT64, sizeof(netlist_time::INTERNALTYPE), state.get_internaltype_ptr());
+}
+
// ----------------------------------------------------------------------------------------
// netlist_owned_object_t
// ----------------------------------------------------------------------------------------
@@ -338,6 +382,7 @@ public:
STATE_NONEX = 256
};
+
ATTR_COLD netlist_core_terminal_t(const type_t atype, const family_t afamily);
ATTR_COLD void init_object(netlist_core_device_t &dev, const pstring &aname, const state_e astate);
@@ -357,11 +402,17 @@ public:
netlist_core_terminal_t *m_update_list_next;
+protected:
+ ATTR_COLD virtual void save_register() { save(NAME(m_state)); netlist_owned_object_t::save_register(); }
+
private:
netlist_net_t * RESTRICT m_net;
state_e m_state;
};
+NETLIST_SAVE_TYPE(netlist_core_terminal_t::state_e, DT_INT);
+
+
class netlist_terminal_t : public netlist_core_terminal_t
{
NETLIST_PREVENT_COPYING(netlist_terminal_t)
@@ -394,6 +445,16 @@ public:
netlist_terminal_t *m_otherterm;
+
+protected:
+ ATTR_COLD virtual void save_register()
+ {
+ save(NAME(m_Idr));
+ save(NAME(m_go));
+ save(NAME(m_gt));
+ netlist_core_terminal_t::save_register();
+ }
+
};
@@ -502,6 +563,7 @@ public:
};
ATTR_COLD netlist_net_t(const type_t atype, const family_t afamily);
+ ATTR_COLD void init_object(netlist_base_t &nl, const pstring &aname);
ATTR_COLD void register_con(netlist_core_terminal_t &terminal);
ATTR_COLD void merge_net(netlist_net_t *othernet);
@@ -568,6 +630,21 @@ protected:
UINT32 m_num_cons;
+protected:
+ ATTR_COLD virtual void save_register()
+ {
+ save(NAME(m_last.Analog));
+ save(NAME(m_cur.Analog));
+ save(NAME(m_new.Analog));
+ save(NAME(m_last.Q));
+ save(NAME(m_cur.Q));
+ save(NAME(m_new.Q));
+ save(NAME(m_time));
+ save(NAME(m_active));
+ save(NAME(m_in_queue));
+ netlist_object_t::save_register();
+ }
+
private:
ATTR_HOT void update_dev(const netlist_core_terminal_t *inp, const UINT32 mask) const;
@@ -688,6 +765,13 @@ public:
ATTR_COLD inline void initial(const double val) { m_param = val; }
ATTR_HOT inline const double Value() const { return m_param; }
+protected:
+ ATTR_COLD virtual void save_register()
+ {
+ save(NAME(m_param));
+ netlist_param_t::save_register();
+ }
+
private:
double m_param;
};
@@ -703,6 +787,13 @@ public:
ATTR_HOT inline const int Value() const { return m_param; }
+protected:
+ ATTR_COLD virtual void save_register()
+ {
+ save(NAME(m_param));
+ netlist_param_t::save_register();
+ }
+
private:
int m_param;
};
@@ -832,7 +923,7 @@ public:
protected:
ATTR_HOT virtual void update() { }
- ATTR_HOT virtual void start() { }
+ ATTR_COLD virtual void start() { }
private:
};
@@ -892,7 +983,7 @@ private:
typedef tagmap_t<netlist_device_t *, 393> tagmap_devices_t;
-class netlist_base_t
+class netlist_base_t : public netlist_object_t
{
NETLIST_PREVENT_COPYING(netlist_base_t)
public:
@@ -920,6 +1011,8 @@ public:
ATTR_COLD void set_solver_dev(NETLIB_NAME(solver) *dev);
ATTR_COLD void set_setup(netlist_setup_t *asetup) { m_setup = asetup; }
+ ATTR_COLD netlist_net_t *find_net(const pstring &name);
+
ATTR_COLD void set_clock_freq(UINT64 clockfreq);
ATTR_COLD netlist_setup_t &setup() { return *m_setup; }
@@ -928,11 +1021,23 @@ public:
ATTR_COLD void xfatalerror(const char *format, ...) const;
tagmap_devices_t m_devices;
+ netlist_net_t::list_t m_nets;
protected:
// any derived netlist must override this ...
virtual void vfatalerror(const char *format, va_list ap) const = 0;
+
+protected:
+ ATTR_COLD virtual void save_register()
+ {
+ //queue_t m_queue;
+ save(NAME(m_time_ps));
+ save(NAME(m_rem));
+ save(NAME(m_div));
+ netlist_object_t::save_register();
+ }
+
#if (NL_KEEP_STATISTICS)
// performance
int m_perf_out_processed;
@@ -978,9 +1083,8 @@ public:
protected:
ATTR_COLD void start()
{
- m_I.init_object(*this, "I", netlist_terminal_t::STATE_INP_ACTIVE);
-
- m_Q.init_object(*this, "Q");
+ register_input("I", m_I, netlist_terminal_t::STATE_INP_ACTIVE);
+ register_output("Q", m_Q);
m_Q.initial(1);
}
@@ -1020,8 +1124,8 @@ public:
protected:
ATTR_COLD void start()
{
- m_I.init_object(*this, "I", netlist_terminal_t::STATE_INP_ACTIVE);
- m_Q.init_object(*this, "Q");
+ register_input("I", m_I, netlist_terminal_t::STATE_INP_ACTIVE);
+ register_output("Q", m_Q);
m_Q.initial(0);
}
diff --git a/src/emu/netlist/nl_lists.h b/src/emu/netlist/nl_lists.h
index c2882248787..3d4d70c0231 100644
--- a/src/emu/netlist/nl_lists.h
+++ b/src/emu/netlist/nl_lists.h
@@ -113,6 +113,15 @@ public:
ATTR_HOT inline bool empty() const { return (m_ptr < m_list); }
ATTR_HOT inline void reset() { m_ptr = m_list - 1; }
+ ATTR_COLD void reset_and_free()
+ {
+ for (entry_t *i = m_list; i <= m_ptr; i++)
+ {
+ delete i->object();
+ }
+ reset();
+ }
+
//ATTR_HOT inline entry_t *item(int i) const { return &m_list[i]; }
ATTR_HOT inline _ListClass& operator[](const int & index) { return m_list[index].m_obj; }
ATTR_HOT inline const _ListClass& operator[](const int & index) const { return m_list[index].m_obj; }
@@ -142,6 +151,9 @@ public:
inline entry_t(const _Time atime, _Element &elem) : m_time(atime), m_object(&elem) {}
ATTR_HOT inline const _Time &time() const { return m_time; }
ATTR_HOT inline _Element & object() const { return *m_object; }
+
+ ATTR_HOT inline const _Time *time_ptr() const { return &m_time; }
+ ATTR_HOT inline _Element *object_ptr() const { return m_object; }
private:
_Time m_time;
_Element *m_object;
@@ -153,6 +165,7 @@ public:
clear();
}
+ ATTR_HOT inline int capacity() const { return _Size; }
ATTR_HOT inline bool is_empty() const { return (m_end == &m_list[0]); }
ATTR_HOT inline bool is_not_empty() const { return (m_end > &m_list[0]); }
@@ -193,6 +206,11 @@ public:
m_end = &m_list[0];
}
+ // save state support
+
+ ATTR_COLD entry_t *listptr() { return &m_list[0]; }
+ ATTR_COLD int count() const { return m_end - m_list; }
+
#if (NL_KEEP_STATISTICS)
// profiling
INT32 m_prof_start;
diff --git a/src/emu/netlist/nl_setup.c b/src/emu/netlist/nl_setup.c
index d1f513c88c8..d17e83990b4 100644
--- a/src/emu/netlist/nl_setup.c
+++ b/src/emu/netlist/nl_setup.c
@@ -33,6 +33,10 @@ netlist_setup_t::netlist_setup_t(netlist_base_t &netlist)
, m_proxy_cnt(0)
{
netlist.set_setup(this);
+}
+
+void netlist_setup_t::init()
+{
m_factory.initialize();
NETLIST_NAME(base)(*this);
}
@@ -45,6 +49,7 @@ netlist_setup_t::~netlist_setup_t()
m_params.reset();
m_terminals.reset();
m_params_temp.reset();
+ m_save.reset_and_free();
netlist().set_setup(NULL);
@@ -132,6 +137,9 @@ pstring netlist_setup_t::objtype_as_astr(netlist_object_t &in)
case netlist_terminal_t::DEVICE:
return "DEVICE";
break;
+ case netlist_terminal_t::NETLIST:
+ return "NETLIST";
+ break;
}
// FIXME: noreturn
netlist().xfatalerror("Unknown object type %d\n", in.type());
@@ -161,10 +169,8 @@ void netlist_setup_t::register_object(netlist_device_t &dev, netlist_core_device
break;
case netlist_terminal_t::PARAM:
{
-
netlist_param_t &param = dynamic_cast<netlist_param_t &>(obj);
- pstring temp = param.netdev().name() + "." + name;
- const pstring val = m_params_temp.find(temp);
+ const pstring val = m_params_temp.find(name);
if (val != "")
{
switch (param.param_type())
@@ -174,17 +180,17 @@ void netlist_setup_t::register_object(netlist_device_t &dev, netlist_core_device
NL_VERBOSE_OUT(("Found parameter ... %s : %s\n", temp.cstr(), val->cstr()));
double vald = 0;
if (sscanf(val.cstr(), "%lf", &vald) != 1)
- netlist().xfatalerror("Invalid number conversion %s : %s\n", temp.cstr(), val.cstr());
+ netlist().xfatalerror("Invalid number conversion %s : %s\n", name.cstr(), val.cstr());
dynamic_cast<netlist_param_double_t &>(param).initial(vald);
}
break;
case netlist_param_t::INTEGER:
case netlist_param_t::LOGIC:
{
- NL_VERBOSE_OUT(("Found parameter ... %s : %s\n", temp.cstr(), val->cstr()));
+ NL_VERBOSE_OUT(("Found parameter ... %s : %s\n", name.cstr(), val->cstr()));
int vald = 0;
if (sscanf(val.cstr(), "%d", &vald) != 1)
- netlist().xfatalerror("Invalid number conversion %s : %s\n", temp.cstr(), val.cstr());
+ netlist().xfatalerror("Invalid number conversion %s : %s\n", name.cstr(), val.cstr());
dynamic_cast<netlist_param_int_t &>(param).initial(vald);
}
break;
@@ -213,14 +219,18 @@ void netlist_setup_t::register_object(netlist_device_t &dev, netlist_core_device
}
break;
default:
- netlist().xfatalerror("Parameter is not supported %s : %s\n", temp.cstr(), val.cstr());
+ netlist().xfatalerror("Parameter is not supported %s : %s\n", name.cstr(), val.cstr());
}
}
- if (!(m_params.add(temp, &param, false)==TMERR_NONE))
+ if (!(m_params.add(name, &param, false)==TMERR_NONE))
netlist().xfatalerror("Error adding parameter %s to parameter list\n", name.cstr());
}
break;
case netlist_terminal_t::DEVICE:
+ netlist().xfatalerror("Device registration not yet supported - \n", name.cstr());
+ break;
+ case netlist_terminal_t::NETLIST:
+ netlist().xfatalerror("Netlist registration not yet supported - \n", name.cstr());
break;
}
}
@@ -462,9 +472,9 @@ void netlist_setup_t::connect_terminals(netlist_core_terminal_t &t1, netlist_cor
NL_VERBOSE_OUT(("adding net ...\n"));
netlist_net_t *anet = new netlist_net_t(netlist_object_t::NET, netlist_object_t::ANALOG);
t1.set_net(*anet);
- m_netlist.solver()->m_nets.add(anet);
+ //m_netlist.solver()->m_nets.add(anet);
// FIXME: Nets should have a unique name
- t1.net().init_object(netlist(),"some net");
+ t1.net().init_object(netlist(),"net." + t1.name() );
t1.net().register_con(t2);
t1.net().register_con(t1);
}
@@ -533,6 +543,23 @@ void netlist_setup_t::resolve_inputs()
//VERBOSE_OUT(("%s %d\n", out->netdev()->name(), *out->Q_ptr()));
}
+#if 0
+ NL_VERBOSE_OUT(("deleting empty nets ...\n"));
+
+ // delete empty nets ...
+ for (netlist_net_t::list_t::entry_t *pn = netlist().m_nets.first(); pn != NULL; pn = netlist().m_nets.next(pn))
+ {
+ if (pn->object()->m_head == NULL)
+ {
+ NL_VERBOSE_OUT(("Deleting net ...\n"));
+ netlist_net_t *to_delete = pn->object();
+ netlist().m_nets.remove(to_delete);
+ if (!to_delete->isRailNet())
+ delete to_delete;
+ pn--;
+ }
+ }
+#endif
if (m_netlist.solver() != NULL)
m_netlist.solver()->post_start();
@@ -578,6 +605,7 @@ void netlist_setup_t::start_devices()
netlist_device_t *dev = entry->object();
dev->init(netlist(), entry->tag().cstr());
}
+
}
void netlist_setup_t::parse(const char *buf)
diff --git a/src/emu/netlist/nl_setup.h b/src/emu/netlist/nl_setup.h
index 8d9c0eefa4d..401a9921f8f 100644
--- a/src/emu/netlist/nl_setup.h
+++ b/src/emu/netlist/nl_setup.h
@@ -102,6 +102,8 @@ public:
netlist_setup_t(netlist_base_t &netlist);
~netlist_setup_t();
+ void init();
+
netlist_base_t &netlist() { return m_netlist; }
const netlist_base_t &netlist() const { return m_netlist; }
netlist_factory &factory() { return m_factory; }
@@ -133,6 +135,28 @@ public:
void print_stats();
+ /* save state */
+
+ struct save_entry_t
+ {
+ save_entry_t(const pstring &stname, const netlist_data_type_e dt, const int size, void *ptr) :
+ m_name(stname), m_dt(dt), m_size(size), m_ptr(ptr) { }
+ pstring m_name;
+ netlist_data_type_e m_dt;
+ int m_size;
+ void *m_ptr;
+ };
+
+ typedef netlist_list_t<save_entry_t *> save_entry_list_t;
+
+ void save_state_ptr(const pstring &stname, const netlist_data_type_e dt, const int size, void *ptr)
+ {
+ save_entry_t *p = new save_entry_t(stname, dt, size, ptr);
+ m_save.add(p);
+ }
+
+ save_entry_list_t m_save;
+
protected:
private:
diff --git a/src/emu/netlist/nl_time.h b/src/emu/netlist/nl_time.h
index 36f7d26fd7b..bfdeda38c32 100644
--- a/src/emu/netlist/nl_time.h
+++ b/src/emu/netlist/nl_time.h
@@ -50,6 +50,9 @@ public:
ATTR_HOT inline const INTERNALTYPE as_raw() const { return m_time; }
ATTR_HOT inline const double as_double() const { return (double) m_time / (double) RESOLUTION; }
+ // for save states ....
+ ATTR_HOT inline INTERNALTYPE *get_internaltype_ptr() { return &m_time; }
+
ATTR_HOT static inline const netlist_time from_nsec(const int ns) { return netlist_time((UINT64) ns * (RESOLUTION / U64(1000000000))); }
ATTR_HOT static inline const netlist_time from_usec(const int us) { return netlist_time((UINT64) us * (RESOLUTION / U64(1000000))); }
ATTR_HOT static inline const netlist_time from_msec(const int ms) { return netlist_time((UINT64) ms * (RESOLUTION / U64(1000))); }
diff --git a/src/emu/video/fixfreq.c b/src/emu/video/fixfreq.c
index 3a9e60c9537..0ab0c7f7b88 100644
--- a/src/emu/video/fixfreq.c
+++ b/src/emu/video/fixfreq.c
@@ -113,6 +113,31 @@ void fixedfreq_device::device_start()
m_bitmap[1] = NULL;
//m_vblank_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(vga_device::vblank_timer_cb),this));
recompute_parameters(false);
+
+ save_item(NAME(m_vid));
+ save_item(NAME(m_last_x));
+ save_item(NAME(m_last_y));
+ save_item(NAME(m_last_time));
+ save_item(NAME(m_line_time));
+ save_item(NAME(m_last_hsync_time));
+ save_item(NAME(m_last_vsync_time));
+ save_item(NAME(m_refresh));
+ save_item(NAME(m_clock_period));
+ //save_item(NAME(m_bitmap[0]));
+ //save_item(NAME(m_bitmap[1]));
+ save_item(NAME(m_cur_bm));
+
+ /* sync separator */
+ save_item(NAME(m_vint));
+ save_item(NAME(m_int_trig));
+ save_item(NAME(m_mult));
+
+ save_item(NAME(m_sig_vsync));
+ save_item(NAME(m_sig_composite));
+ save_item(NAME(m_sig_field));
+
+
+
}
void fixedfreq_device::device_reset()
@@ -122,6 +147,7 @@ void fixedfreq_device::device_reset()
m_last_hsync_time = attotime::zero;
m_last_vsync_time = attotime::zero;
m_vint = 0;
+
}
diff --git a/src/mame/drivers/pong.c b/src/mame/drivers/pong.c
index 2ac1cf0c82d..c88c6e51bbd 100644
--- a/src/mame/drivers/pong.c
+++ b/src/mame/drivers/pong.c
@@ -982,5 +982,5 @@ ROM_START( pongf ) /* dummy to satisfy game entry*/
ROM_END
-GAME( 1972, pong, 0, pong, pong, driver_device, 0, ROT0, "Atari", "Pong (Rev E)", 0 )
-GAME( 1972, pongf, 0, pongf, pong, driver_device, 0, ROT0, "Atari", "Pong (Rev E), no subcycles", 0 )
+GAME( 1972, pong, 0, pong, pong, driver_device, 0, ROT0, "Atari", "Pong (Rev E)", GAME_SUPPORTS_SAVE )
+GAME( 1972, pongf, 0, pongf, pong, driver_device, 0, ROT0, "Atari", "Pong (Rev E), no subcycles", GAME_SUPPORTS_SAVE )