simplified memory management for save states and states (nw)

This commit is contained in:
Miodrag Milanovic 2016-07-01 18:55:17 +02:00
parent 83bc05a08b
commit 6e1adc4386
8 changed files with 77 additions and 119 deletions

View File

@ -1685,10 +1685,10 @@ device_debug::device_debug(device_t &device)
// add all registers into it
std::string tempstr;
for (const device_state_entry &entry : m_state->state_entries())
for (auto &entry : m_state->state_entries())
{
strmakelower(tempstr.assign(entry.symbol()));
m_symtable.add(tempstr.c_str(), (void *)(FPTR)entry.index(), get_state, set_state);
strmakelower(tempstr.assign(entry->symbol()));
m_symtable.add(tempstr.c_str(), (void *)(FPTR)entry->index(), get_state, set_state);
}
}

View File

@ -42,8 +42,7 @@ debug_view_state_source::debug_view_state_source(const char *name, device_t &dev
debug_view_state::debug_view_state(running_machine &machine, debug_view_osd_update_func osdupdate, void *osdprivate)
: debug_view(machine, DVT_STATE, osdupdate, osdprivate),
m_divider(0),
m_last_update(0),
m_state_list(nullptr)
m_last_update(0)
{
// fail if no available sources
enumerate_sources();
@ -92,12 +91,7 @@ void debug_view_state::enumerate_sources()
void debug_view_state::reset()
{
// free all items in the state list
while (m_state_list != nullptr)
{
state_item *oldhead = m_state_list;
m_state_list = oldhead->m_next;
global_free(oldhead);
}
m_state_list.clear();
}
@ -114,48 +108,39 @@ void debug_view_state::recompute()
reset();
// add a cycles entry: cycles:99999999
state_item **tailptr = &m_state_list;
*tailptr = global_alloc(state_item(REG_CYCLES, "cycles", 8));
tailptr = &(*tailptr)->m_next;
m_state_list.push_back(std::make_unique<state_item>(REG_CYCLES, "cycles", 8));
// add a beam entry: beamx:1234
*tailptr = global_alloc(state_item(REG_BEAMX, "beamx", 4));
tailptr = &(*tailptr)->m_next;
m_state_list.push_back(std::make_unique<state_item>(REG_BEAMX, "beamx", 4));
// add a beam entry: beamy:5678
*tailptr = global_alloc(state_item(REG_BEAMY, "beamy", 4));
tailptr = &(*tailptr)->m_next;
m_state_list.push_back(std::make_unique<state_item>(REG_BEAMY, "beamy", 4));
// add a beam entry: frame:123456
*tailptr = global_alloc(state_item(REG_FRAME, "frame", 6));
tailptr = &(*tailptr)->m_next;
m_state_list.push_back(std::make_unique<state_item>(REG_FRAME, "frame", 6));
// add a flags entry: flags:xxxxxxxx
*tailptr = global_alloc(state_item(STATE_GENFLAGS, "flags", source.m_stateintf->state_string_max_length(STATE_GENFLAGS)));
tailptr = &(*tailptr)->m_next;
m_state_list.push_back(std::make_unique<state_item>(STATE_GENFLAGS, "flags", source.m_stateintf->state_string_max_length(STATE_GENFLAGS)));
// add a divider entry
*tailptr = global_alloc(state_item(REG_DIVIDER, "", 0));
tailptr = &(*tailptr)->m_next;
m_state_list.push_back(std::make_unique<state_item>(REG_DIVIDER, "", 0));
// add all registers into it
for (const device_state_entry &entry : source.m_stateintf->state_entries())
if (entry.divider())
for (auto &entry : source.m_stateintf->state_entries())
if (entry->divider())
{
*tailptr = global_alloc(state_item(REG_DIVIDER, "", 0));
tailptr = &(*tailptr)->m_next;
m_state_list.push_back(std::make_unique<state_item>(REG_DIVIDER, "", 0));
}
else if (entry.visible())
else if (entry->visible())
{
*tailptr = global_alloc(state_item(entry.index(), entry.symbol(), source.m_stateintf->state_string_max_length(entry.index())));
tailptr = &(*tailptr)->m_next;
m_state_list.push_back(std::make_unique<state_item>(entry->index(), entry->symbol(), source.m_stateintf->state_string_max_length(entry->index())));
}
// count the entries and determine the maximum tag and value sizes
int count = 0;
int maxtaglen = 0;
int maxvallen = 0;
for (state_item *item = m_state_list; item != nullptr; item = item->m_next)
for (auto &item : m_state_list)
{
count++;
maxtaglen = MAX(maxtaglen, item->m_symbol.length());
@ -204,9 +189,7 @@ void debug_view_state::view_update()
total_cycles = source.m_execintf->total_cycles();
// find the first entry
state_item *curitem = m_state_list;
for (int index = 0; curitem != nullptr && index < m_topleft.y; index++)
curitem = curitem->m_next;
auto it = m_state_list.begin();
// loop over visible rows
screen_device *screen = machine().first_screen();
@ -214,10 +197,12 @@ void debug_view_state::view_update()
for (UINT32 row = 0; row < m_visible.y; row++)
{
UINT32 col = 0;
// if this visible row is valid, add it to the buffer
if (curitem != nullptr)
if (it != m_state_list.end())
{
state_item *curitem = it->get();
UINT32 effcol = m_topleft.x;
UINT8 attrib = DCA_NORMAL;
UINT32 len = 0;
@ -311,7 +296,7 @@ void debug_view_state::view_update()
}
// advance to the next item
curitem = curitem->m_next;
++it;
}
// fill the rest with blanks
@ -334,8 +319,7 @@ void debug_view_state::view_update()
//-------------------------------------------------
debug_view_state::state_item::state_item(int index, const char *name, UINT8 valuechars)
: m_next(nullptr),
m_lastval(0),
: m_lastval(0),
m_currval(0),
m_index(index),
m_vallen(valuechars),

View File

@ -52,7 +52,6 @@ private:
{
state_item(int index, const char *name, UINT8 valuechars);
state_item * m_next; // next item
UINT64 m_lastval; // last value
UINT64 m_currval; // current value
int m_index; // index
@ -68,7 +67,7 @@ private:
// internal state
int m_divider; // dividing column
UINT64 m_last_update; // execution counter at last update
state_item * m_state_list; // state data
std::vector<std::unique_ptr<state_item>> m_state_list; // state data
// constants
static const int REG_DIVIDER = -10;

View File

@ -51,7 +51,6 @@ const UINT64 device_state_entry::k_decimal_divisor[] =
device_state_entry::device_state_entry(int index, const char *symbol, void *dataptr, UINT8 size, device_state_interface *dev)
: m_device_state(dev),
m_next(nullptr),
m_index(index),
m_dataptr(dataptr),
m_datamask(0),
@ -89,7 +88,6 @@ device_state_entry::device_state_entry(int index, const char *symbol, void *data
device_state_entry::device_state_entry(int index, device_state_interface *dev)
: m_device_state(dev),
m_next(nullptr),
m_index(index),
m_dataptr(nullptr),
m_datamask(0),
@ -523,17 +521,14 @@ device_state_entry &device_state_interface::state_add(int index, const char *sym
assert(size == 1 || size == 2 || size == 4 || size == 8);
assert(symbol != nullptr);
// allocate new entry
auto entry = global_alloc(device_state_entry(index, symbol, data, size, this));
// append to the end of the list
m_state_list.append(*entry);
m_state_list.push_back(std::make_unique<device_state_entry>(index, symbol, data, size, this));
// set the fast entry if applicable
if (index >= FAST_STATE_MIN && index <= FAST_STATE_MAX)
m_fast_state[index - FAST_STATE_MIN] = entry;
m_fast_state[index - FAST_STATE_MIN] = m_state_list.back().get();
return *entry;
return *m_state_list.back().get();
}
//-------------------------------------------------
@ -543,13 +538,10 @@ device_state_entry &device_state_interface::state_add(int index, const char *sym
device_state_entry &device_state_interface::state_add_divider(int index)
{
// allocate new entry
auto entry = global_alloc(device_state_entry(index, this));
// append to the end of the list
m_state_list.append(*entry);
m_state_list.push_back(std::make_unique<device_state_entry>(index, this));
return *entry;
return *m_state_list.back().get();
}
//-------------------------------------------------
@ -604,7 +596,7 @@ void device_state_interface::state_string_export(const device_state_entry &entry
void device_state_interface::interface_post_start()
{
// make sure we got something during startup
if (m_state_list.count() == 0)
if (m_state_list.size() == 0)
throw emu_fatalerror("No state registered for device '%s' that supports it!", m_device.tag());
}
@ -621,9 +613,9 @@ const device_state_entry *device_state_interface::state_find_entry(int index) co
return m_fast_state[index - FAST_STATE_MIN];
// otherwise, scan the first
for (const device_state_entry *entry = m_state_list.first(); entry != nullptr; entry = entry->m_next)
for (auto &entry : m_state_list)
if (entry->m_index == index)
return entry;
return entry.get();
// handle failure by returning nullptr
return nullptr;

View File

@ -44,9 +44,7 @@ enum
class device_state_entry
{
friend class device_state_interface;
friend class simple_list<device_state_entry>;
private:
public:
// construction/destruction
device_state_entry(int index, const char *symbol, void *dataptr, UINT8 size, device_state_interface *dev);
device_state_entry(int index, device_state_interface *dev);
@ -60,9 +58,6 @@ public:
device_state_entry &callexport() { m_flags |= DSF_EXPORT; return *this; }
device_state_entry &noshow() { m_flags |= DSF_NOSHOW; return *this; }
// iteration helpers
device_state_entry *next() const { return m_next; }
// query information
int index() const { return m_index; }
void *dataptr() const { return m_dataptr.v; }
@ -99,7 +94,6 @@ protected:
// public state description
device_state_interface *m_device_state; // link to parent device state
device_state_entry * m_next; // link to next item
UINT32 m_index; // index by which this item is referred
generic_ptr m_dataptr; // pointer to where the data lives
UINT64 m_datamask; // mask that applies to the data
@ -124,7 +118,7 @@ public:
virtual ~device_state_interface();
// configuration access
const simple_list<device_state_entry> &state_entries() const { return m_state_list; }
const std::vector<std::unique_ptr<device_state_entry>> &state_entries() const { return m_state_list; }
// state getters
UINT64 state_int(int index);
@ -176,7 +170,7 @@ protected:
static const int FAST_STATE_MAX = 256; // lookups
// state
simple_list<device_state_entry> m_state_list; // head of state list
std::vector<std::unique_ptr<device_state_entry>> m_state_list; // head of state list
device_state_entry * m_fast_state[FAST_STATE_MAX + 1 - FAST_STATE_MIN];
// fast access to common entries
};

View File

@ -88,10 +88,10 @@ void save_manager::allow_registration(bool allowed)
const char *save_manager::indexed_item(int index, void *&base, UINT32 &valsize, UINT32 &valcount) const
{
state_entry *entry = m_entry_list.find(index);
if (entry == nullptr)
if (index >= m_entry_list.size() || index < 0)
return nullptr;
state_entry *entry = m_entry_list.at(index).get();
base = entry->m_data;
valsize = entry->m_typesize;
valcount = entry->m_typecount;
@ -112,12 +112,12 @@ void save_manager::register_presave(save_prepost_delegate func)
fatalerror("Attempt to register callback function after state registration is closed!\n");
// scan for duplicates and push through to the end
for (state_callback &cb : m_presave_list)
if (cb.m_func == func)
fatalerror("Duplicate save state function (%s/%s)\n", cb.m_func.name(), func.name());
for (auto &cb : m_presave_list)
if (cb->m_func == func)
fatalerror("Duplicate save state function (%s/%s)\n", cb->m_func.name(), func.name());
// allocate a new entry
m_presave_list.append(*global_alloc(state_callback(func)));
m_presave_list.push_back(std::make_unique<state_callback>(func));
}
@ -133,12 +133,12 @@ void save_manager::register_postload(save_prepost_delegate func)
fatalerror("Attempt to register callback function after state registration is closed!\n");
// scan for duplicates and push through to the end
for (state_callback &cb : m_postload_list)
if (cb.m_func == func)
fatalerror("Duplicate save state function (%s/%s)\n", cb.m_func.name(), func.name());
for (auto &cb : m_postload_list)
if (cb->m_func == func)
fatalerror("Duplicate save state function (%s/%s)\n", cb->m_func.name(), func.name());
// allocate a new entry
m_postload_list.append(*global_alloc(state_callback(func)));
m_postload_list.push_back(std::make_unique<state_callback>(func));
}
@ -169,21 +169,21 @@ void save_manager::save_memory(device_t *device, const char *module, const char
totalname = string_format("%s/%X/%s", module, index, name);
// look for duplicates and an entry to insert in front of
state_entry *insert_after = nullptr;
for (state_entry &entry : m_entry_list)
std::vector<std::unique_ptr<state_entry>>::iterator insert_after = m_entry_list.begin();
for (auto it = m_entry_list.begin(); it!= m_entry_list.end(); ++it)
{
// stop when we find an entry whose name is after ours
if (entry.m_name.compare(totalname)>0)
if (it->get()->m_name.compare(totalname)>0)
break;
insert_after = &entry;
insert_after = it;
// error if we are equal
if (entry.m_name.compare(totalname)==0)
if (it->get()->m_name.compare(totalname)==0)
fatalerror("Duplicate save state registration entry (%s)\n", totalname.c_str());
}
// insert us into the list
m_entry_list.insert_after(*global_alloc(state_entry(val, totalname.c_str(), device, module, tag ? tag : "", index, valsize, valcount)), insert_after);
m_entry_list.insert(insert_after,std::make_unique<state_entry>(val, totalname.c_str(), device, module, tag ? tag : "", index, valsize, valcount));
}
@ -221,8 +221,8 @@ save_error save_manager::check_file(running_machine &machine, emu_file &file, co
void save_manager::dispatch_postload()
{
for (state_callback &func : m_postload_list)
func.m_func();
for (auto &func : m_postload_list)
func->m_func();
}
//-------------------------------------------------
@ -252,15 +252,15 @@ save_error save_manager::read_file(emu_file &file)
bool flip = NATIVE_ENDIAN_VALUE_LE_BE((header[9] & SS_MSB_FIRST) != 0, (header[9] & SS_MSB_FIRST) == 0);
// read all the data, flipping if necessary
for (state_entry &entry : m_entry_list)
for (auto &entry : m_entry_list)
{
UINT32 totalsize = entry.m_typesize * entry.m_typecount;
if (file.read(entry.m_data, totalsize) != totalsize)
UINT32 totalsize = entry->m_typesize * entry->m_typecount;
if (file.read(entry->m_data, totalsize) != totalsize)
return STATERR_READ_ERROR;
// handle flipping
if (flip)
entry.flip_data();
entry->flip_data();
}
// call the post-load functions
@ -277,8 +277,8 @@ save_error save_manager::read_file(emu_file &file)
void save_manager::dispatch_presave()
{
for (state_callback &func : m_presave_list)
func.m_func();
for (auto &func : m_presave_list)
func->m_func();
}
//-------------------------------------------------
@ -311,10 +311,10 @@ save_error save_manager::write_file(emu_file &file)
dispatch_presave();
// then write all the data
for (state_entry &entry : m_entry_list)
for (auto &entry : m_entry_list)
{
UINT32 totalsize = entry.m_typesize * entry.m_typecount;
if (file.write(entry.m_data, totalsize) != totalsize)
UINT32 totalsize = entry->m_typesize * entry->m_typecount;
if (file.write(entry->m_data, totalsize) != totalsize)
return STATERR_WRITE_ERROR;
}
return STATERR_NONE;
@ -330,15 +330,15 @@ UINT32 save_manager::signature() const
{
// iterate over entries
UINT32 crc = 0;
for (state_entry &entry : m_entry_list)
for (auto &entry : m_entry_list)
{
// add the entry name to the CRC
crc = core_crc32(crc, (UINT8 *)entry.m_name.c_str(), entry.m_name.length());
crc = core_crc32(crc, (UINT8 *)entry->m_name.c_str(), entry->m_name.length());
// add the type and size to the CRC
UINT32 temp[2];
temp[0] = LITTLE_ENDIANIZE_INT32(entry.m_typecount);
temp[1] = LITTLE_ENDIANIZE_INT32(entry.m_typesize);
temp[0] = LITTLE_ENDIANIZE_INT32(entry->m_typecount);
temp[1] = LITTLE_ENDIANIZE_INT32(entry->m_typesize);
crc = core_crc32(crc, (UINT8 *)&temp[0], sizeof(temp));
}
return crc;
@ -352,8 +352,8 @@ UINT32 save_manager::signature() const
void save_manager::dump_registry() const
{
for (state_entry &entry : m_entry_list)
LOG(("%s: %d x %d\n", entry.m_name.c_str(), entry.m_typesize, entry.m_typecount));
for (auto &entry : m_entry_list)
LOG(("%s: %d x %d\n", entry->m_name.c_str(), entry->m_typesize, entry->m_typecount));
}
@ -409,8 +409,7 @@ save_error save_manager::validate_header(const UINT8 *header, const char *gamena
//-------------------------------------------------
save_manager::state_callback::state_callback(save_prepost_delegate callback)
: m_next(nullptr),
m_func(std::move(callback))
: m_func(std::move(callback))
{
}
@ -420,8 +419,7 @@ save_manager::state_callback::state_callback(save_prepost_delegate callback)
//-------------------------------------------------
state_entry::state_entry(void *data, const char *name, device_t *device, const char *module, const char *tag, int index, UINT8 size, UINT32 count)
: m_next(nullptr),
m_data(data),
: m_data(data),
m_name(name),
m_device(device),
m_module(module),

View File

@ -64,14 +64,10 @@ public:
// construction/destruction
state_entry(void *data, const char *name, device_t *device, const char *module, const char *tag, int index, UINT8 size, UINT32 count);
// getters
state_entry *next() const { return m_next; }
// helpers
void flip_data();
// state
state_entry * m_next; // pointer to next entry
void * m_data; // pointer to the memory to save/restore
std::string m_name; // full name
device_t * m_device; // associated device, nullptr if none
@ -95,7 +91,7 @@ public:
// getters
running_machine &machine() const { return m_machine; }
int registration_count() const { return m_entry_list.count(); }
int registration_count() const { return m_entry_list.size(); }
bool registration_allowed() const { return m_reg_allowed; }
// registration control
@ -170,11 +166,6 @@ private:
// construction/destruction
state_callback(save_prepost_delegate callback);
// getters
state_callback *next() const { return m_next; }
// state
state_callback * m_next; // pointer to next entry
save_prepost_delegate m_func; // delegate
};
@ -183,9 +174,9 @@ private:
bool m_reg_allowed; // are registrations allowed?
int m_illegal_regs; // number of illegal registrations
simple_list<state_entry> m_entry_list; // list of reigstered entries
simple_list<state_callback> m_presave_list; // list of pre-save functions
simple_list<state_callback> m_postload_list; // list of post-load functions
std::vector<std::unique_ptr<state_entry>> m_entry_list; // list of reigstered entries
std::vector<std::unique_ptr<state_callback>> m_presave_list; // list of pre-save functions
std::vector<std::unique_ptr<state_callback>> m_postload_list; // list of post-load functions
};

View File

@ -758,10 +758,10 @@ luabridge::LuaRef lua_engine::l_dev_get_states(const device_t *d)
if(!dynamic_cast<device_state_interface *>(dev))
return st_table;
for (device_state_entry &s : dev->state().state_entries())
for (auto &s : dev->state().state_entries())
{
// XXX: refrain from exporting non-visible entries?
st_table[s.symbol()] = &s;
st_table[s->symbol()] = &s;
}
return st_table;