mirror of
https://github.com/holub/mame
synced 2025-06-30 07:58:56 +03:00
Moved the state saving system to C++. For now the registration macros
are still intact. The new state_manager class has templatized methods for saving the various types, and through template specialization can save more complex system types cleanly (like bitmaps and attotimes). Added new mechanism to detect proper state save types. This is much more strict and there will likely be some games/devices that fatalerror at startup until they are remedied. Spot checking has caught the more common situations. The new state_manager is embedded directly in the running_machine, allowing objects to register state saving in their constructors now. Added NAME() macro which is a generalization of FUNC() and can be used to wrap variables that are registered when directly using the new methods as opposed to the previous macros. For example: machine->state().save_item(NAME(global_item)) Added methods in the device_t class that implicitly register state against the current device, making for a cleaner interface. Just a couple of required regexes for now: state_save_register_postload( *)\(( *)([^,;]+), * \3->state().register_postload\1\(\2 state_save_register_presave( *)\(( *)([^,;]+), * \3->state().register_presave\1\(\2
This commit is contained in:
parent
f4f3adf250
commit
4f7efb1ca4
@ -535,7 +535,6 @@ static CPU_INIT( arm )
|
||||
state_save_register_device_item_array(device, 0, cpustate->coproRegister);
|
||||
state_save_register_device_item(device, 0, cpustate->pendingIrq);
|
||||
state_save_register_device_item(device, 0, cpustate->pendingFiq);
|
||||
state_save_register_device_item(device, 0, cpustate->endian);
|
||||
}
|
||||
|
||||
|
||||
@ -552,7 +551,6 @@ static CPU_INIT( arm_be )
|
||||
state_save_register_device_item_array(device, 0, cpustate->coproRegister);
|
||||
state_save_register_device_item(device, 0, cpustate->pendingIrq);
|
||||
state_save_register_device_item(device, 0, cpustate->pendingFiq);
|
||||
state_save_register_device_item(device, 0, cpustate->endian);
|
||||
}
|
||||
|
||||
|
||||
|
@ -275,7 +275,7 @@ static void cquestsnd_state_register(device_t *device)
|
||||
state_save_register_device_item(device, 0, cpustate->prev_ipram);
|
||||
state_save_register_device_item(device, 0, cpustate->prev_ipwrt);
|
||||
|
||||
state_save_register_postload(device->machine, cquestsnd_postload, (void *)device);
|
||||
device->machine->state().register_postload(cquestsnd_postload, (void *)device);
|
||||
}
|
||||
|
||||
static CPU_INIT( cquestsnd )
|
||||
@ -349,7 +349,7 @@ static void cquestrot_state_register(device_t *device)
|
||||
state_save_register_device_item_pointer(device, 0, cpustate->dram, 16384);
|
||||
state_save_register_device_item_pointer(device, 0, cpustate->sram, 2048);
|
||||
|
||||
state_save_register_postload(device->machine, cquestrot_postload, (void *)device);
|
||||
device->machine->state().register_postload(cquestrot_postload, (void *)device);
|
||||
}
|
||||
|
||||
static CPU_INIT( cquestrot )
|
||||
@ -433,7 +433,7 @@ static void cquestlin_state_register(device_t *device)
|
||||
state_save_register_device_item_pointer(device, 0, cpustate->e_stack, 32768);
|
||||
state_save_register_device_item_pointer(device, 0, cpustate->o_stack, 32768);
|
||||
|
||||
state_save_register_postload(device->machine, cquestlin_postload, (void *)device);
|
||||
device->machine->state().register_postload(cquestlin_postload, (void *)device);
|
||||
}
|
||||
|
||||
static CPU_INIT( cquestlin )
|
||||
|
@ -365,7 +365,7 @@ static CPU_INIT( g65816 )
|
||||
state_save_register_device_item(device, 0, cpustate->irq_delay);
|
||||
state_save_register_device_item(device, 0, cpustate->stopped);
|
||||
|
||||
state_save_register_postload(device->machine, g65816_restore_state, cpustate);
|
||||
device->machine->state().register_postload(g65816_restore_state, cpustate);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -237,7 +237,7 @@ static CPU_INIT(h8)
|
||||
state_save_register_device_item(device, 0, h8->h8TSTR);
|
||||
state_save_register_device_item_array(device, 0, h8->h8TCNT);
|
||||
|
||||
state_save_register_postload(device->machine, h8_onstateload, h8);
|
||||
device->machine->state().register_postload(h8_onstateload, h8);
|
||||
|
||||
h8_itu_init(h8);
|
||||
}
|
||||
|
@ -259,7 +259,7 @@ static CPU_INIT(h8bit)
|
||||
state_save_register_device_item(device, 0, h8->h8TSTR);
|
||||
state_save_register_device_item_array(device, 0, h8->h8TCNT);
|
||||
|
||||
state_save_register_postload(h8->device->machine, h8_onstateload, h8);
|
||||
h8->device->machine->state().register_postload(h8_onstateload, h8);
|
||||
}
|
||||
|
||||
static CPU_RESET(h8bit)
|
||||
|
@ -541,7 +541,7 @@ static CPU_INIT( hd6309 )
|
||||
state_save_register_device_item(device, 0, DP);
|
||||
state_save_register_device_item(device, 0, CC);
|
||||
state_save_register_device_item(device, 0, MD);
|
||||
state_save_register_postload(device->machine, hd6309_postload, (void *) device);
|
||||
device->machine->state().register_postload(hd6309_postload, (void *) device);
|
||||
state_save_register_device_item(device, 0, m68_state->int_state);
|
||||
state_save_register_device_item(device, 0, m68_state->nmi_state);
|
||||
state_save_register_device_item(device, 0, m68_state->irq_state[0]);
|
||||
|
@ -605,7 +605,7 @@ static CPU_INIT( i386 )
|
||||
state_save_register_device_item(device, 0, cpustate->ldtr.flags);
|
||||
state_save_register_device_item(device, 0, cpustate->irq_state);
|
||||
state_save_register_device_item(device, 0, cpustate->performed_intersegment_jump);
|
||||
state_save_register_postload(device->machine, i386_postload, (void *)device);
|
||||
device->machine->state().register_postload(i386_postload, (void *)device);
|
||||
}
|
||||
|
||||
static void build_opcode_table(i386_state *cpustate, UINT32 features)
|
||||
|
@ -430,7 +430,7 @@ static void init_common(int isdsp, legacy_cpu_device *device, device_irq_callbac
|
||||
state_save_register_device_item_array(device, 0, jaguar->a);
|
||||
state_save_register_device_item_array(device, 0, jaguar->ctrl);
|
||||
state_save_register_device_item(device, 0, jaguar->ppc);
|
||||
state_save_register_postload(device->machine, jaguar_postload, (void *)device);
|
||||
device->machine->state().register_postload(jaguar_postload, (void *)device);
|
||||
}
|
||||
|
||||
|
||||
|
@ -940,24 +940,16 @@ static CPU_INIT( m37710 )
|
||||
state_save_register_device_item(device, 0, cpustate->irq_level);
|
||||
state_save_register_device_item(device, 0, cpustate->stopped);
|
||||
state_save_register_device_item_array(device, 0, cpustate->m37710_regs);
|
||||
state_save_register_device_item(device, 0, cpustate->reload[0].seconds);
|
||||
state_save_register_device_item(device, 0, cpustate->reload[0].attoseconds);
|
||||
state_save_register_device_item(device, 0, cpustate->reload[1].seconds);
|
||||
state_save_register_device_item(device, 0, cpustate->reload[1].attoseconds);
|
||||
state_save_register_device_item(device, 0, cpustate->reload[2].seconds);
|
||||
state_save_register_device_item(device, 0, cpustate->reload[2].attoseconds);
|
||||
state_save_register_device_item(device, 0, cpustate->reload[3].seconds);
|
||||
state_save_register_device_item(device, 0, cpustate->reload[3].attoseconds);
|
||||
state_save_register_device_item(device, 0, cpustate->reload[4].seconds);
|
||||
state_save_register_device_item(device, 0, cpustate->reload[4].attoseconds);
|
||||
state_save_register_device_item(device, 0, cpustate->reload[5].seconds);
|
||||
state_save_register_device_item(device, 0, cpustate->reload[5].attoseconds);
|
||||
state_save_register_device_item(device, 0, cpustate->reload[6].seconds);
|
||||
state_save_register_device_item(device, 0, cpustate->reload[6].attoseconds);
|
||||
state_save_register_device_item(device, 0, cpustate->reload[7].seconds);
|
||||
state_save_register_device_item(device, 0, cpustate->reload[7].attoseconds);
|
||||
state_save_register_device_item(device, 0, cpustate->reload[0]);
|
||||
state_save_register_device_item(device, 0, cpustate->reload[1]);
|
||||
state_save_register_device_item(device, 0, cpustate->reload[2]);
|
||||
state_save_register_device_item(device, 0, cpustate->reload[3]);
|
||||
state_save_register_device_item(device, 0, cpustate->reload[4]);
|
||||
state_save_register_device_item(device, 0, cpustate->reload[5]);
|
||||
state_save_register_device_item(device, 0, cpustate->reload[6]);
|
||||
state_save_register_device_item(device, 0, cpustate->reload[7]);
|
||||
|
||||
state_save_register_postload(device->machine, m37710_restore_state, cpustate);
|
||||
device->machine->state().register_postload(m37710_restore_state, cpustate);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -769,8 +769,8 @@ static CPU_INIT( m68k )
|
||||
state_save_register_device_item(device, 0, m68k->save_halted);
|
||||
state_save_register_device_item(device, 0, m68k->pref_addr);
|
||||
state_save_register_device_item(device, 0, m68k->pref_data);
|
||||
state_save_register_presave(device->machine, m68k_presave, m68k);
|
||||
state_save_register_postload(device->machine, m68k_postload, m68k);
|
||||
device->machine->state().register_presave(m68k_presave, m68k);
|
||||
device->machine->state().register_postload(m68k_postload, m68k);
|
||||
}
|
||||
|
||||
/* Pulse the RESET line on the CPU */
|
||||
|
@ -1627,7 +1627,7 @@ static void mips_state_register( const char *type, legacy_cpu_device *device )
|
||||
state_save_register_device_item( device, 0, psxcpu->multiplier_operation );
|
||||
state_save_register_device_item( device, 0, psxcpu->multiplier_operand1 );
|
||||
state_save_register_device_item( device, 0, psxcpu->multiplier_operand2 );
|
||||
state_save_register_postload( device->machine, mips_postload, psxcpu );
|
||||
device->machine->state().register_postload( mips_postload, psxcpu );
|
||||
}
|
||||
|
||||
static CPU_INIT( psxcpu )
|
||||
|
@ -669,7 +669,7 @@ static CPU_INIT( tms34010 )
|
||||
state_save_register_device_item(device, 0, tms->pixelshift);
|
||||
state_save_register_device_item(device, 0, tms->gfxcycles);
|
||||
state_save_register_device_item_pointer(device, 0, (&tms->regs[0].reg), ARRAY_LENGTH(tms->regs));
|
||||
state_save_register_postload(device->machine, tms34010_state_postload, tms);
|
||||
device->machine->state().register_postload(tms34010_state_postload, tms);
|
||||
}
|
||||
|
||||
static CPU_RESET( tms34010 )
|
||||
|
@ -244,7 +244,7 @@ void debug_command_init(running_machine *machine)
|
||||
void *base;
|
||||
|
||||
/* stop when we run out of items */
|
||||
name = state_save_get_indexed_item(machine, itemnum, &base, &valsize, &valcount);
|
||||
name = machine->state().indexed_item(itemnum, base, valsize, valcount);
|
||||
if (name == NULL)
|
||||
break;
|
||||
|
||||
|
@ -177,7 +177,7 @@ void debug_view_memory::enumerate_sources()
|
||||
// stop when we run out of items
|
||||
UINT32 valsize, valcount;
|
||||
void *base;
|
||||
const char *itemname = state_save_get_indexed_item(&m_machine, itemnum, &base, &valsize, &valcount);
|
||||
const char *itemname = m_machine.state().indexed_item(itemnum, base, valsize, valcount);
|
||||
if (itemname == NULL)
|
||||
break;
|
||||
|
||||
|
@ -134,8 +134,8 @@ void device_list::start_all()
|
||||
m_machine->add_notifier(MACHINE_NOTIFY_EXIT, static_exit);
|
||||
|
||||
// add pre-save and post-load callbacks
|
||||
state_save_register_presave(m_machine, static_pre_save, this);
|
||||
state_save_register_postload(m_machine, static_post_load, this);
|
||||
m_machine->state().register_presave(static_pre_save, this);
|
||||
m_machine->state().register_postload(static_post_load, this);
|
||||
|
||||
// iterate over devices to start them
|
||||
device_t *nextdevice;
|
||||
@ -535,6 +535,7 @@ void device_interface::interface_debug_setup()
|
||||
device_t::device_t(running_machine &_machine, const device_config &config)
|
||||
: machine(&_machine),
|
||||
m_machine(_machine),
|
||||
m_state_manager(_machine.state()),
|
||||
m_debug(NULL),
|
||||
m_execute(NULL),
|
||||
m_memory(NULL),
|
||||
@ -724,13 +725,13 @@ void device_t::start()
|
||||
intf->interface_pre_start();
|
||||
|
||||
// remember the number of state registrations
|
||||
int state_registrations = state_save_get_reg_count(machine);
|
||||
int state_registrations = machine->state().registration_count();
|
||||
|
||||
// start the device
|
||||
device_start();
|
||||
|
||||
// complain if nothing was registered by the device
|
||||
state_registrations = state_save_get_reg_count(machine) - state_registrations;
|
||||
state_registrations = machine->state().registration_count() - state_registrations;
|
||||
device_execute_interface *exec;
|
||||
device_sound_interface *sound;
|
||||
if (state_registrations == 0 && (interface(exec) || interface(sound)))
|
||||
|
@ -437,6 +437,12 @@ public:
|
||||
void synchronize(device_timer_id id = 0, int param = 0, void *ptr = NULL) { timer_set(attotime::zero, id, param, ptr); }
|
||||
void timer_expired(emu_timer &timer, device_timer_id id, int param, void *ptr) { device_timer(timer, id, param, ptr); }
|
||||
|
||||
// state saving interfaces
|
||||
template<typename T>
|
||||
void save_item(T &value, const char *valname, int index = 0) { m_state_manager.save_item(name(), tag(), index, value, valname); }
|
||||
template<typename T>
|
||||
void save_pointer(T *value, const char *valname, UINT32 count, int index = 0) { m_state_manager.save_pointer(name(), tag(), index, value, valname); }
|
||||
|
||||
// debugging
|
||||
device_debug *debug() const { return m_debug; }
|
||||
|
||||
@ -475,6 +481,7 @@ protected:
|
||||
//------------------- end derived class overrides
|
||||
|
||||
running_machine & m_machine;
|
||||
state_manager & m_state_manager;
|
||||
device_debug * m_debug;
|
||||
|
||||
// for speed
|
||||
|
@ -569,8 +569,7 @@ void device_execute_interface::interface_pre_start()
|
||||
state_save_register_device_item(&m_device, 0, m_nexteatcycles);
|
||||
state_save_register_device_item(&m_device, 0, m_trigger);
|
||||
state_save_register_device_item(&m_device, 0, m_totalcycles);
|
||||
state_save_register_device_item(&m_device, 0, m_localtime.seconds);
|
||||
state_save_register_device_item(&m_device, 0, m_localtime.attoseconds);
|
||||
state_save_register_device_item(&m_device, 0, m_localtime);
|
||||
state_save_register_device_item(&m_device, 0, m_iloops);
|
||||
}
|
||||
|
||||
|
@ -70,6 +70,10 @@
|
||||
#include "memory.h"
|
||||
#include "addrmap.h"
|
||||
|
||||
// machine-wide utilities
|
||||
#include "romload.h"
|
||||
#include "state.h"
|
||||
|
||||
// define machine_config_constructor here due to circular dependency
|
||||
// between devices and the machine config
|
||||
class machine_config;
|
||||
@ -103,10 +107,6 @@ typedef device_config * (*machine_config_constructor)(machine_config &config, de
|
||||
#include "mconfig.h"
|
||||
#include "driver.h"
|
||||
|
||||
// machine-wide utilities
|
||||
#include "romload.h"
|
||||
#include "state.h"
|
||||
|
||||
// image-related
|
||||
#include "softlist.h"
|
||||
#include "image.h"
|
||||
|
@ -198,6 +198,9 @@ inline void operator--(_Type &value) { value = (_Type)((int)value - 1); } \
|
||||
inline void operator--(_Type &value, int) { value = (_Type)((int)value - 1); }
|
||||
|
||||
|
||||
// this macro passes an item followed by a string version of itself as two consecutive parameters
|
||||
#define NAME(x) x, #x
|
||||
|
||||
// this macro wraps a function 'x' and can be used to pass a function followed by its name
|
||||
#define FUNC(x) x, #x
|
||||
|
||||
|
@ -143,8 +143,8 @@ void palette_init(running_machine *machine)
|
||||
palette->save_bright = auto_alloc_array(machine, float, numcolors);
|
||||
state_save_register_global_pointer(machine, palette->save_pen, numcolors);
|
||||
state_save_register_global_pointer(machine, palette->save_bright, numcolors);
|
||||
state_save_register_presave(machine, palette_presave, palette);
|
||||
state_save_register_postload(machine, palette_postload, palette);
|
||||
machine->state().register_presave(palette_presave, palette);
|
||||
machine->state().register_postload(palette_postload, palette);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,7 +154,6 @@ running_machine::running_machine(const machine_config &_config, osd_interface &o
|
||||
sample_rate(options_get_int(&options, OPTION_SAMPLERATE)),
|
||||
debug_flags(0),
|
||||
ui_active(false),
|
||||
state_data(NULL),
|
||||
memory_data(NULL),
|
||||
palette_data(NULL),
|
||||
tilemap_data(NULL),
|
||||
@ -167,6 +166,7 @@ running_machine::running_machine(const machine_config &_config, osd_interface &o
|
||||
generic_video_data(NULL),
|
||||
generic_audio_data(NULL),
|
||||
m_logerror_list(NULL),
|
||||
m_state(*this),
|
||||
m_scheduler(*this),
|
||||
m_options(options),
|
||||
m_osd(osd),
|
||||
@ -264,15 +264,11 @@ void running_machine::start()
|
||||
config_init(this);
|
||||
input_init(this);
|
||||
output_init(this);
|
||||
state_init(this);
|
||||
state_save_allow_registration(this, true);
|
||||
palette_init(this);
|
||||
m_render = auto_alloc(this, render_manager(*this));
|
||||
generic_machine_init(this);
|
||||
generic_sound_init(this);
|
||||
|
||||
m_scheduler.register_for_save();
|
||||
|
||||
// allocate a soft_reset timer
|
||||
m_soft_reset_timer = m_scheduler.timer_alloc(MSTUB(timer_expired, running_machine, soft_reset), this);
|
||||
|
||||
@ -344,7 +340,7 @@ void running_machine::start()
|
||||
m_cheat = auto_alloc(this, cheat_manager(*this));
|
||||
|
||||
// disallow save state registrations starting here
|
||||
state_save_allow_registration(this, false);
|
||||
m_state.allow_registration(false);
|
||||
}
|
||||
|
||||
|
||||
@ -798,7 +794,7 @@ void running_machine::handle_saveload()
|
||||
astring fullname(mame_file_full_name(file));
|
||||
|
||||
// read/write the save state
|
||||
state_save_error staterr = (m_saveload_schedule == SLS_LOAD) ? state_save_read_file(this, file) : state_save_write_file(this, file);
|
||||
state_save_error staterr = (m_saveload_schedule == SLS_LOAD) ? m_state.read_file(file) : m_state.write_file(file);
|
||||
|
||||
// handle the result
|
||||
switch (staterr)
|
||||
|
@ -187,7 +187,6 @@ class video_manager;
|
||||
class debug_view_manager;
|
||||
class osd_interface;
|
||||
|
||||
typedef struct _state_private state_private;
|
||||
typedef struct _memory_private memory_private;
|
||||
typedef struct _palette_private palette_private;
|
||||
typedef struct _tilemap_private tilemap_private;
|
||||
@ -356,6 +355,7 @@ public:
|
||||
bool exit_pending() const { return m_exit_pending; }
|
||||
bool new_driver_pending() const { return (m_new_driver_pending != NULL); }
|
||||
const char *new_driver_name() const { return m_new_driver_pending->name; }
|
||||
state_manager &state() { return m_state; }
|
||||
device_scheduler &scheduler() { return m_scheduler; }
|
||||
osd_interface &osd() const { return m_osd; }
|
||||
screen_device *first_screen() const { return primary_screen; }
|
||||
@ -440,7 +440,6 @@ public:
|
||||
generic_pointers generic; // generic pointers
|
||||
|
||||
// internal core information
|
||||
state_private * state_data; // internal data from state.c
|
||||
memory_private * memory_data; // internal data from memory.c
|
||||
palette_private * palette_data; // internal data from palette.c
|
||||
tilemap_private * tilemap_data; // internal data from tilemap.c
|
||||
@ -486,6 +485,7 @@ private:
|
||||
};
|
||||
logerror_callback_item *m_logerror_list;
|
||||
|
||||
state_manager m_state; // state manager
|
||||
device_scheduler m_scheduler; // scheduler object
|
||||
core_options & m_options;
|
||||
osd_interface & m_osd;
|
||||
|
@ -292,7 +292,7 @@ static DEVICE_START( pci_bus )
|
||||
state_save_register_device_item(device, 0, pcibus->devicenum);
|
||||
state_save_register_device_item(device, 0, pcibus->busnum);
|
||||
|
||||
state_save_register_postload(device->machine, pci_bus_postload, pcibus);
|
||||
device->machine->state().register_postload(pci_bus_postload, pcibus);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1105,8 +1105,7 @@ static void common_start( device_t *device, int device_type ) {
|
||||
state_save_register_device_item(device, timerno, timer->null_count);
|
||||
state_save_register_device_item(device, timerno, timer->phase);
|
||||
state_save_register_device_item(device, timerno, timer->cycles_to_output);
|
||||
state_save_register_device_item(device, timerno, timer->last_updated.seconds);
|
||||
state_save_register_device_item(device, timerno, timer->last_updated.attoseconds);
|
||||
state_save_register_device_item(device, timerno, timer->last_updated);
|
||||
state_save_register_device_item(device, timerno, timer->clock);
|
||||
}
|
||||
}
|
||||
|
@ -1590,7 +1590,7 @@ void memory_init(running_machine *machine)
|
||||
space->locate_memory();
|
||||
|
||||
// register a callback to reset banks when reloading state
|
||||
state_save_register_postload(machine, bank_reattach, NULL);
|
||||
machine->state().register_postload(bank_reattach, NULL);
|
||||
|
||||
// dump the final memory configuration
|
||||
generate_memdump(machine);
|
||||
@ -4092,7 +4092,7 @@ memory_block::memory_block(address_space &space, offs_t bytestart, offs_t byteen
|
||||
int bytes_per_element = space.data_width() / 8;
|
||||
astring name;
|
||||
name.printf("%08x-%08x", bytestart, byteend);
|
||||
state_save_register_memory(&space.m_machine, "memory", space.device().tag(), space.spacenum(), name, m_data, bytes_per_element, (UINT32)(byteend + 1 - bytestart) / bytes_per_element, __FILE__, __LINE__);
|
||||
space.m_machine.state().save_memory("memory", space.device().tag(), space.spacenum(), name, m_data, bytes_per_element, (UINT32)(byteend + 1 - bytestart) / bytes_per_element);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4142,7 +4142,7 @@ memory_bank::memory_bank(address_space &space, int index, offs_t bytestart, offs
|
||||
m_name.printf("Bank '%s'", tag);
|
||||
}
|
||||
|
||||
if (!m_anonymous && state_save_registration_allowed(&space.m_machine))
|
||||
if (!m_anonymous && space.m_machine.state().registration_allowed())
|
||||
state_save_register_item(&space.m_machine, "memory", m_tag, 0, m_curentry);
|
||||
}
|
||||
|
||||
|
@ -123,6 +123,8 @@ enum
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
||||
class machine_config;
|
||||
|
||||
typedef device_config rom_source;
|
||||
|
||||
|
||||
|
@ -283,12 +283,9 @@ void emu_timer::register_save()
|
||||
// save the bits
|
||||
state_save_register_item(m_machine, "timer", name, index, m_param);
|
||||
state_save_register_item(m_machine, "timer", name, index, m_enabled);
|
||||
state_save_register_item(m_machine, "timer", name, index, m_period.seconds);
|
||||
state_save_register_item(m_machine, "timer", name, index, m_period.attoseconds);
|
||||
state_save_register_item(m_machine, "timer", name, index, m_start.seconds);
|
||||
state_save_register_item(m_machine, "timer", name, index, m_start.attoseconds);
|
||||
state_save_register_item(m_machine, "timer", name, index, m_expire.seconds);
|
||||
state_save_register_item(m_machine, "timer", name, index, m_expire.attoseconds);
|
||||
state_save_register_item(m_machine, "timer", name, index, m_period);
|
||||
state_save_register_item(m_machine, "timer", name, index, m_start);
|
||||
state_save_register_item(m_machine, "timer", name, index, m_expire);
|
||||
}
|
||||
|
||||
|
||||
@ -336,16 +333,10 @@ device_scheduler::device_scheduler(running_machine &machine) :
|
||||
// append a single never-expiring timer so there is always one in the list
|
||||
m_timer_list = &m_timer_allocator.alloc()->init(m_machine, NULL, NULL, NULL, true);
|
||||
m_timer_list->adjust(attotime::never);
|
||||
}
|
||||
|
||||
|
||||
// remove me once save state registration is embedded
|
||||
void device_scheduler::register_for_save()
|
||||
{
|
||||
// register global states
|
||||
state_save_register_item(&m_machine, "timer", NULL, 0, m_basetime.seconds);
|
||||
state_save_register_item(&m_machine, "timer", NULL, 0, m_basetime.attoseconds);
|
||||
state_save_register_postload(&m_machine, &state_postload_stub<device_scheduler, &device_scheduler::postload>, this);
|
||||
state_save_register_item(&m_machine, "timer", NULL, 0, m_basetime);
|
||||
m_machine.state().register_postload(&state_postload_stub<device_scheduler, &device_scheduler::postload>, this);
|
||||
}
|
||||
|
||||
|
||||
|
@ -155,7 +155,6 @@ public:
|
||||
// construction/destruction
|
||||
device_scheduler(running_machine &machine);
|
||||
~device_scheduler();
|
||||
void register_for_save();
|
||||
|
||||
// getters
|
||||
attotime time() const;
|
||||
|
@ -379,22 +379,21 @@ void screen_device::device_start()
|
||||
if (overname != NULL && strcmp(overname, "none") != 0)
|
||||
load_effect_overlay(overname);
|
||||
|
||||
state_save_register_device_item(this, 0, m_width);
|
||||
state_save_register_device_item(this, 0, m_height);
|
||||
state_save_register_device_item(this, 0, m_visarea.min_x);
|
||||
state_save_register_device_item(this, 0, m_visarea.min_y);
|
||||
state_save_register_device_item(this, 0, m_visarea.max_x);
|
||||
state_save_register_device_item(this, 0, m_visarea.max_y);
|
||||
state_save_register_device_item(this, 0, m_last_partial_scan);
|
||||
state_save_register_device_item(this, 0, m_frame_period);
|
||||
state_save_register_device_item(this, 0, m_scantime);
|
||||
state_save_register_device_item(this, 0, m_pixeltime);
|
||||
state_save_register_device_item(this, 0, m_vblank_period);
|
||||
state_save_register_device_item(this, 0, m_vblank_start_time.seconds);
|
||||
state_save_register_device_item(this, 0, m_vblank_start_time.attoseconds);
|
||||
state_save_register_device_item(this, 0, m_vblank_end_time.seconds);
|
||||
state_save_register_device_item(this, 0, m_vblank_end_time.attoseconds);
|
||||
state_save_register_device_item(this, 0, m_frame_number);
|
||||
// register items for saving
|
||||
save_item(NAME(m_width));
|
||||
save_item(NAME(m_height));
|
||||
save_item(NAME(m_visarea.min_x));
|
||||
save_item(NAME(m_visarea.min_y));
|
||||
save_item(NAME(m_visarea.max_x));
|
||||
save_item(NAME(m_visarea.max_y));
|
||||
save_item(NAME(m_last_partial_scan));
|
||||
save_item(NAME(m_frame_period));
|
||||
save_item(NAME(m_scantime));
|
||||
save_item(NAME(m_pixeltime));
|
||||
save_item(NAME(m_vblank_period));
|
||||
save_item(NAME(m_vblank_start_time));
|
||||
save_item(NAME(m_vblank_end_time));
|
||||
save_item(NAME(m_frame_number));
|
||||
}
|
||||
|
||||
|
||||
|
@ -112,7 +112,7 @@ sound_stream::sound_stream(device_t &device, int inputs, int outputs, int sample
|
||||
astring state_tag;
|
||||
state_tag.printf("%d", m_device.machine->sound().m_stream_list.count());
|
||||
state_save_register_item(m_device.machine, "stream", state_tag, 0, m_sample_rate);
|
||||
state_save_register_postload(m_device.machine, state_postload_stub<sound_stream, &sound_stream::postload>, this);
|
||||
m_device.machine->state().register_postload(state_postload_stub<sound_stream, &sound_stream::postload>, this);
|
||||
|
||||
// save the gain of each input and output
|
||||
for (int inputnum = 0; inputnum < m_inputs; inputnum++)
|
||||
@ -806,8 +806,7 @@ sound_manager::sound_manager(running_machine &machine)
|
||||
machine.add_notifier(MACHINE_NOTIFY_RESET, &sound_manager::reset);
|
||||
|
||||
// register global states
|
||||
state_save_register_global(&machine, m_last_update.seconds);
|
||||
state_save_register_global(&machine, m_last_update.attoseconds);
|
||||
state_save_register_global(&machine, m_last_update);
|
||||
|
||||
// set the starting attenuation
|
||||
set_attenuation(options_get_int(machine.options(), OPTION_VOLUME));
|
||||
@ -863,7 +862,7 @@ void sound_manager::set_attenuation(int attenuation)
|
||||
bool sound_manager::indexed_speaker_input(int index, speaker_input &info) const
|
||||
{
|
||||
// scan through the speakers until we find the indexed input
|
||||
for (info.speaker = downcast<speaker_device *>(m_machine.m_devicelist.first(SPEAKER)); info.speaker != NULL; info.speaker = downcast<speaker_device *>(info.speaker->typenext()))
|
||||
for (info.speaker = downcast<speaker_device *>(m_machine.m_devicelist.first(SPEAKER)); info.speaker != NULL; info.speaker = info.speaker->next_speaker())
|
||||
{
|
||||
if (index < info.speaker->inputs())
|
||||
{
|
||||
@ -1004,7 +1003,7 @@ void sound_manager::update()
|
||||
|
||||
// force all the speaker streams to generate the proper number of samples
|
||||
int samples_this_update = 0;
|
||||
for (speaker_device *speaker = downcast<speaker_device *>(m_machine.m_devicelist.first(SPEAKER)); speaker != NULL; speaker = downcast<speaker_device *>(speaker->typenext()))
|
||||
for (speaker_device *speaker = downcast<speaker_device *>(m_machine.m_devicelist.first(SPEAKER)); speaker != NULL; speaker = speaker->next_speaker())
|
||||
speaker->mix(m_leftmix, m_rightmix, samples_this_update, (m_muted & MUTE_REASON_SYSTEM));
|
||||
|
||||
// now downmix the final result
|
||||
|
@ -61,7 +61,7 @@ static DEVICE_START( ym2151 )
|
||||
info->chip = ym2151_init(device,device->clock(),rate);
|
||||
assert_always(info->chip != NULL, "Error creating YM2151 chip");
|
||||
|
||||
state_save_register_postload(device->machine, ym2151intf_postload, info);
|
||||
device->machine->state().register_postload(ym2151intf_postload, info);
|
||||
|
||||
ym2151_set_irq_handler(info->chip,info->intf->irqhandler);
|
||||
ym2151_set_port_write_handler(info->chip,info->intf->portwritehandler);
|
||||
|
@ -144,7 +144,7 @@ static DEVICE_START( ym2203 )
|
||||
info->chip = ym2203_init(info,device,device->clock(),rate,timer_handler,IRQHandler,&psgintf);
|
||||
assert_always(info->chip != NULL, "Error creating YM2203 chip");
|
||||
|
||||
state_save_register_postload(device->machine, ym2203_intf_postload, info);
|
||||
device->machine->state().register_postload(ym2203_intf_postload, info);
|
||||
}
|
||||
|
||||
static DEVICE_STOP( ym2203 )
|
||||
|
@ -167,7 +167,7 @@ static DEVICE_START( ym2608 )
|
||||
timer_handler,IRQHandler,&psgintf);
|
||||
assert_always(info->chip != NULL, "Error creating YM2608 chip");
|
||||
|
||||
state_save_register_postload(device->machine, ym2608_intf_postload, info);
|
||||
device->machine->state().register_postload(ym2608_intf_postload, info);
|
||||
}
|
||||
|
||||
static DEVICE_STOP( ym2608 )
|
||||
|
@ -179,7 +179,7 @@ static DEVICE_START( ym2610 )
|
||||
timer_handler,IRQHandler,&psgintf);
|
||||
assert_always(info->chip != NULL, "Error creating YM2610 chip");
|
||||
|
||||
state_save_register_postload(device->machine, ym2610_intf_postload, info);
|
||||
device->machine->state().register_postload(ym2610_intf_postload, info);
|
||||
}
|
||||
|
||||
static DEVICE_STOP( ym2610 )
|
||||
|
@ -118,7 +118,7 @@ static DEVICE_START( ym2612 )
|
||||
info->chip = ym2612_init(info,device,device->clock(),rate,timer_handler,IRQHandler);
|
||||
assert_always(info->chip != NULL, "Error creating YM2612 chip");
|
||||
|
||||
state_save_register_postload(device->machine, ym2612_intf_postload, info);
|
||||
device->machine->state().register_postload(ym2612_intf_postload, info);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1704,8 +1704,7 @@ static void FMsave_state_channel(device_t *device,FM_CH *CH,int num_ch)
|
||||
static void FMsave_state_st(device_t *device,FM_ST *ST)
|
||||
{
|
||||
#if FM_BUSY_FLAG_SUPPORT
|
||||
state_save_register_device_item(device, 0, ST->busy_expiry_time.seconds );
|
||||
state_save_register_device_item(device, 0, ST->busy_expiry_time.attoseconds );
|
||||
state_save_register_device_item(device, 0, ST->busy_expiry_time );
|
||||
#endif
|
||||
state_save_register_device_item(device, 0, ST->address );
|
||||
state_save_register_device_item(device, 0, ST->irq );
|
||||
|
@ -1707,8 +1707,7 @@ static void FMsave_state_channel(device_t *device,FM_CH *CH,int num_ch)
|
||||
static void FMsave_state_st(device_t *device,FM_ST *ST)
|
||||
{
|
||||
#if FM_BUSY_FLAG_SUPPORT
|
||||
state_save_register_device_item(device, 0, ST->busy_expiry_time.seconds );
|
||||
state_save_register_device_item(device, 0, ST->busy_expiry_time.attoseconds );
|
||||
state_save_register_device_item(device, 0, ST->busy_expiry_time );
|
||||
#endif
|
||||
state_save_register_device_item(device, 0, ST->address );
|
||||
state_save_register_device_item(device, 0, ST->irq );
|
||||
|
@ -1957,7 +1957,7 @@ static void OPL_save_state(FM_OPL *OPL, device_t *device)
|
||||
state_save_register_device_item(device, 0, OPL->statusmask);
|
||||
state_save_register_device_item(device, 0, OPL->mode);
|
||||
|
||||
state_save_register_postload(device->machine, OPL_postload, OPL);
|
||||
device->machine->state().register_postload(OPL_postload, OPL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -674,7 +674,7 @@ static DEVICE_START( k054539 )
|
||||
|
||||
k054539_init_chip(device, info);
|
||||
|
||||
state_save_register_postload(device->machine, reset_zones, info);
|
||||
device->machine->state().register_postload(reset_zones, info);
|
||||
}
|
||||
|
||||
|
||||
|
@ -799,7 +799,7 @@ static DEVICE_START( msm5232 )
|
||||
chip->stream = device->machine->sound().stream_alloc(*device, 0, 11, rate, chip, MSM5232_update_one);
|
||||
|
||||
/* register with the save state system */
|
||||
state_save_register_postload(device->machine, msm5232_postload, chip);
|
||||
device->machine->state().register_postload(msm5232_postload, chip);
|
||||
state_save_register_device_item_array(device, 0, chip->EN_out16);
|
||||
state_save_register_device_item_array(device, 0, chip->EN_out8);
|
||||
state_save_register_device_item_array(device, 0, chip->EN_out4);
|
||||
|
@ -589,12 +589,9 @@ static void register_for_save(pokey_state *chip, device_t *device)
|
||||
state_save_register_device_item(device, 0, chip->r9);
|
||||
state_save_register_device_item(device, 0, chip->r17);
|
||||
state_save_register_device_item(device, 0, chip->clockmult);
|
||||
state_save_register_device_item(device, 0, chip->timer_period[0].seconds);
|
||||
state_save_register_device_item(device, 0, chip->timer_period[0].attoseconds);
|
||||
state_save_register_device_item(device, 0, chip->timer_period[1].seconds);
|
||||
state_save_register_device_item(device, 0, chip->timer_period[1].attoseconds);
|
||||
state_save_register_device_item(device, 0, chip->timer_period[2].seconds);
|
||||
state_save_register_device_item(device, 0, chip->timer_period[2].attoseconds);
|
||||
state_save_register_device_item(device, 0, chip->timer_period[0]);
|
||||
state_save_register_device_item(device, 0, chip->timer_period[1]);
|
||||
state_save_register_device_item(device, 0, chip->timer_period[2]);
|
||||
state_save_register_device_item_array(device, 0, chip->timer_param);
|
||||
state_save_register_device_item_array(device, 0, chip->AUDF);
|
||||
state_save_register_device_item_array(device, 0, chip->AUDC);
|
||||
|
@ -501,7 +501,7 @@ static DEVICE_START( samples )
|
||||
state_save_register_device_item(device, i, info->channel[i].loop);
|
||||
state_save_register_device_item(device, i, info->channel[i].paused);
|
||||
}
|
||||
state_save_register_postload(device->machine, samples_postload, info);
|
||||
device->machine->state().register_postload(samples_postload, info);
|
||||
|
||||
/* initialize any custom handlers */
|
||||
if (intf->start)
|
||||
|
@ -628,7 +628,7 @@ static void register_for_save(upd7759_state *chip, device_t *device)
|
||||
state_save_register_device_item(device, 0, chip->sample);
|
||||
|
||||
state_save_register_device_item(device, 0, chip->romoffset);
|
||||
state_save_register_postload(device->machine, upd7759_postload, chip);
|
||||
device->machine->state().register_postload(upd7759_postload, chip);
|
||||
}
|
||||
|
||||
|
||||
|
@ -726,7 +726,7 @@ static DEVICE_START( vlm5030 )
|
||||
state_save_register_device_item(device,0,chip->target_pitch);
|
||||
state_save_register_device_item_array(device,0,chip->target_k);
|
||||
state_save_register_device_item_array(device,0,chip->x);
|
||||
state_save_register_postload(device->machine, vlm5030_restore_state, chip);
|
||||
device->machine->state().register_postload(vlm5030_restore_state, chip);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1485,7 +1485,7 @@ static void ym2151_state_save_register( YM2151 *chip, device_t *device )
|
||||
|
||||
state_save_register_device_item_array(device, 0, chip->connect);
|
||||
|
||||
state_save_register_postload(device->machine, ym2151_postload, chip);
|
||||
device->machine->state().register_postload(ym2151_postload, chip);
|
||||
}
|
||||
#else
|
||||
STATE_POSTLOAD( ym2151_postload )
|
||||
|
@ -694,7 +694,7 @@ static DEVICE_START( ymz280b )
|
||||
}
|
||||
}
|
||||
|
||||
state_save_register_postload(device->machine, YMZ280B_state_save_update_step, chip);
|
||||
device->machine->state().register_postload(YMZ280B_state_save_update_step, chip);
|
||||
|
||||
#if MAKE_WAVS
|
||||
chip->wavresample = wav_open("resamp.wav", INTERNAL_SAMPLE_RATE, 2);
|
||||
|
@ -85,6 +85,7 @@ public:
|
||||
virtual device_t *alloc_device(running_machine &machine) const;
|
||||
|
||||
// inline configuration helpers
|
||||
speaker_device_config *next_speaker() const { return downcast<speaker_device_config *>(typenext()); }
|
||||
static void static_set_position(device_config *device, double x, double y, double z);
|
||||
|
||||
protected:
|
||||
@ -109,6 +110,9 @@ class speaker_device : public device_t,
|
||||
virtual ~speaker_device();
|
||||
|
||||
public:
|
||||
// getters
|
||||
speaker_device *next_speaker() const { return downcast<speaker_device *>(typenext()); }
|
||||
|
||||
// internally for use by the sound system
|
||||
void mix(INT32 *leftmix, INT32 *rightmix, int &samples_this_update, bool suppress);
|
||||
|
||||
@ -135,53 +139,4 @@ protected:
|
||||
extern const device_type SPEAKER;
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// INLINE HELPERS
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// speaker_first - return the first speaker
|
||||
// device config in a machine_config
|
||||
//-------------------------------------------------
|
||||
|
||||
inline const speaker_device_config *speaker_first(const machine_config &config)
|
||||
{
|
||||
return downcast<speaker_device_config *>(config.m_devicelist.first(SPEAKER));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// speaker_next - return the next speaker
|
||||
// device config in a machine_config
|
||||
//-------------------------------------------------
|
||||
|
||||
inline const speaker_device_config *speaker_next(const speaker_device_config *previous)
|
||||
{
|
||||
return downcast<speaker_device_config *>(previous->typenext());
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// speaker_first - return the first speaker
|
||||
// device in a machine
|
||||
//-------------------------------------------------
|
||||
|
||||
inline speaker_device *speaker_first(running_machine &machine)
|
||||
{
|
||||
return downcast<speaker_device *>(machine.m_devicelist.first(SPEAKER));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// speaker_next - return the next speaker
|
||||
// device in a machine
|
||||
//-------------------------------------------------
|
||||
|
||||
inline speaker_device *speaker_next(speaker_device *previous)
|
||||
{
|
||||
return downcast<speaker_device *>(previous->typenext());
|
||||
}
|
||||
|
||||
|
||||
#endif /* __SOUND_H__ */
|
||||
|
846
src/emu/state.c
846
src/emu/state.c
@ -4,8 +4,36 @@
|
||||
|
||||
Save state management functions.
|
||||
|
||||
Copyright Nicola Salmoria and the MAME Team.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
****************************************************************************
|
||||
|
||||
Copyright Aaron Giles
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name 'MAME' nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
****************************************************************************
|
||||
|
||||
@ -28,25 +56,24 @@
|
||||
#include <zlib.h>
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// DEBUGGING
|
||||
//**************************************************************************
|
||||
|
||||
/***************************************************************************
|
||||
DEBUGGING
|
||||
***************************************************************************/
|
||||
|
||||
#define VERBOSE 0
|
||||
#define VERBOSE 1
|
||||
|
||||
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
CONSTANTS
|
||||
***************************************************************************/
|
||||
//**************************************************************************
|
||||
// CONSTANTS
|
||||
//**************************************************************************
|
||||
|
||||
#define SAVE_VERSION 2
|
||||
#define HEADER_SIZE 32
|
||||
const int SAVE_VERSION = 2;
|
||||
const int HEADER_SIZE = 32;
|
||||
|
||||
/* Available flags */
|
||||
// Available flags
|
||||
enum
|
||||
{
|
||||
SS_MSB_FIRST = 0x02
|
||||
@ -54,394 +81,325 @@ enum
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
||||
typedef struct _state_entry state_entry;
|
||||
struct _state_entry
|
||||
{
|
||||
state_entry * next; /* pointer to next entry */
|
||||
running_machine * machine; /* pointer back to the owning machine */
|
||||
void * data; /* pointer to the memory to save/restore */
|
||||
astring name; /* full name */
|
||||
UINT8 typesize; /* size of the raw data type */
|
||||
UINT32 typecount; /* number of items */
|
||||
UINT32 offset; /* offset within the final structure */
|
||||
};
|
||||
|
||||
|
||||
typedef struct _state_callback state_callback;
|
||||
struct _state_callback
|
||||
{
|
||||
state_callback * next; /* pointer to next entry */
|
||||
running_machine * machine; /* pointer back to the owning machine */
|
||||
void * param; /* function parameter */
|
||||
union
|
||||
{
|
||||
state_presave_func presave; /* presave callback */
|
||||
state_postload_func postload; /* postload callback */
|
||||
} func; /* function pointers */
|
||||
};
|
||||
|
||||
|
||||
/* In mame.h: typedef struct _state_private state_private; */
|
||||
struct _state_private
|
||||
{
|
||||
UINT8 reg_allowed; /* are registrations allowed? */
|
||||
int illegal_regs; /* number of illegal registrations */
|
||||
|
||||
state_entry * entrylist; /* list of live entries */
|
||||
state_callback * prefunclist; /* presave function list */
|
||||
state_callback * postfunclist; /* postsave function list */
|
||||
|
||||
UINT8 * ioarray; /* array where we accumulate all the data */
|
||||
UINT32 ioarraysize; /* size of the array */
|
||||
mame_file * iofile; /* file currently in use */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
GLOBAL VARIABLES
|
||||
***************************************************************************/
|
||||
//**************************************************************************
|
||||
// GLOBAL VARIABLES
|
||||
//**************************************************************************
|
||||
|
||||
#ifdef MESS
|
||||
static const char ss_magic_num[8] = { 'M', 'E', 'S', 'S', 'S', 'A', 'V', 'E' };
|
||||
const char state_manager::s_magic_num[8] = { 'M', 'E', 'S', 'S', 'S', 'A', 'V', 'E' };
|
||||
#else
|
||||
static const char ss_magic_num[8] = { 'M', 'A', 'M', 'E', 'S', 'A', 'V', 'E' };
|
||||
const char state_manager::s_magic_num[8] = { 'M', 'A', 'M', 'E', 'S', 'A', 'V', 'E' };
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
INLINE FUNCTIONS
|
||||
***************************************************************************/
|
||||
//**************************************************************************
|
||||
// INITIALIZATION
|
||||
//**************************************************************************
|
||||
|
||||
/*-------------------------------------------------
|
||||
flip_data - reverse the endianness of a
|
||||
block of data
|
||||
-------------------------------------------------*/
|
||||
//-------------------------------------------------
|
||||
// state_manager - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
INLINE void flip_data(state_entry *entry)
|
||||
state_manager::state_manager(running_machine &machine)
|
||||
: m_machine(machine),
|
||||
m_reg_allowed(true),
|
||||
m_illegal_regs(0),
|
||||
m_entry_list(machine.m_respool),
|
||||
m_presave_list(machine.m_respool),
|
||||
m_postload_list(machine.m_respool)
|
||||
{
|
||||
UINT16 *data16;
|
||||
UINT32 *data32;
|
||||
UINT64 *data64;
|
||||
int count;
|
||||
|
||||
switch (entry->typesize)
|
||||
{
|
||||
case 2:
|
||||
data16 = (UINT16 *)entry->data;
|
||||
for (count = 0; count < entry->typecount; count++)
|
||||
data16[count] = FLIPENDIAN_INT16(data16[count]);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
data32 = (UINT32 *)entry->data;
|
||||
for (count = 0; count < entry->typecount; count++)
|
||||
data32[count] = FLIPENDIAN_INT32(data32[count]);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
data64 = (UINT64 *)entry->data;
|
||||
for (count = 0; count < entry->typecount; count++)
|
||||
data64[count] = FLIPENDIAN_INT64(data64[count]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// allow_registration - allow/disallow
|
||||
// registrations to happen
|
||||
//-------------------------------------------------
|
||||
|
||||
/***************************************************************************
|
||||
INITIALIZATION
|
||||
***************************************************************************/
|
||||
|
||||
/*-------------------------------------------------
|
||||
state_init - initialize the system and reset
|
||||
all registrations
|
||||
-------------------------------------------------*/
|
||||
|
||||
enum test_enum_type { test_val };
|
||||
|
||||
class test_class_type { public: int dummy; };
|
||||
|
||||
void state_init(running_machine *machine)
|
||||
void state_manager::allow_registration(bool allowed)
|
||||
{
|
||||
bool test_bool = false;
|
||||
INT8 test_INT8 = 0;
|
||||
UINT8 test_UINT8 = 0;
|
||||
INT16 test_INT16 = 0;
|
||||
UINT16 test_UINT16 = 0;
|
||||
INT32 test_INT32 = 0;
|
||||
UINT32 test_UINT32 = 0;
|
||||
INT64 test_INT64 = 0;
|
||||
UINT64 test_UINT64 = 0;
|
||||
float test_float = 0.0f;
|
||||
double test_double = 0.0;
|
||||
test_enum_type test_enum = test_val;
|
||||
#ifdef __GNUC__
|
||||
test_class_type test_class;
|
||||
#endif
|
||||
|
||||
assert_always(IS_VALID_SAVE_TYPE(test_bool), "bool is not a valid type for save");
|
||||
assert_always(IS_VALID_SAVE_TYPE(test_INT8), "INT8 is not a valid type for save");
|
||||
assert_always(IS_VALID_SAVE_TYPE(test_UINT8), "UINT8 is not a valid type for save");
|
||||
assert_always(IS_VALID_SAVE_TYPE(test_INT16), "INT16 is not a valid type for save");
|
||||
assert_always(IS_VALID_SAVE_TYPE(test_UINT16), "UINT16 is not a valid type for save");
|
||||
assert_always(IS_VALID_SAVE_TYPE(test_INT32), "INT32 is not a valid type for save");
|
||||
assert_always(IS_VALID_SAVE_TYPE(test_UINT32), "UINT32 is not a valid type for save");
|
||||
assert_always(IS_VALID_SAVE_TYPE(test_INT64), "INT64 is not a valid type for save");
|
||||
assert_always(IS_VALID_SAVE_TYPE(test_UINT64), "UINT64 is not a valid type for save");
|
||||
assert_always(IS_VALID_SAVE_TYPE(test_float), "float is not a valid type for save");
|
||||
assert_always(IS_VALID_SAVE_TYPE(test_double), "double is not a valid type for save");
|
||||
assert_always(IS_VALID_SAVE_TYPE(test_enum), "enums are not a valid type for save");
|
||||
#ifdef __GNUC__
|
||||
assert_always(!IS_VALID_SAVE_TYPE(test_class), "classes are a valid type for save");
|
||||
#endif
|
||||
|
||||
machine->state_data = auto_alloc_clear(machine, state_private);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
state_save_get_reg_count - return the number
|
||||
of total registrations so far
|
||||
-------------------------------------------------*/
|
||||
|
||||
int state_save_get_reg_count(running_machine *machine)
|
||||
{
|
||||
state_private *global = machine->state_data;
|
||||
state_entry *entry;
|
||||
int count = 0;
|
||||
|
||||
/* count entries */
|
||||
for (entry = global->entrylist; entry != NULL; entry = entry->next)
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
REGISTRATION HANDLING
|
||||
***************************************************************************/
|
||||
|
||||
/*-------------------------------------------------
|
||||
state_save_allow_registration - allow/disallow
|
||||
registrations to happen
|
||||
-------------------------------------------------*/
|
||||
|
||||
void state_save_allow_registration(running_machine *machine, int allowed)
|
||||
{
|
||||
/* allow/deny registration */
|
||||
machine->state_data->reg_allowed = allowed;
|
||||
// allow/deny registration
|
||||
m_reg_allowed = allowed;
|
||||
if (!allowed)
|
||||
state_save_dump_registry(machine);
|
||||
dump_registry();
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
state_save_registration_allowed - query
|
||||
whether or not registrations are allowed
|
||||
-------------------------------------------------*/
|
||||
//-------------------------------------------------
|
||||
// indexed_item - return an item with the given
|
||||
// index
|
||||
//-------------------------------------------------
|
||||
|
||||
int state_save_registration_allowed(running_machine *machine)
|
||||
const char *state_manager::indexed_item(int index, void *&base, UINT32 &valsize, UINT32 &valcount) const
|
||||
{
|
||||
return machine->state_data->reg_allowed;
|
||||
state_entry *entry = m_entry_list.find(index);
|
||||
if (entry == NULL)
|
||||
return NULL;
|
||||
|
||||
base = entry->m_data;
|
||||
valsize = entry->m_typesize;
|
||||
valcount = entry->m_typecount;
|
||||
|
||||
return entry->m_name;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
state_save_register_memory - register an
|
||||
array of data in memory
|
||||
-------------------------------------------------*/
|
||||
//-------------------------------------------------
|
||||
// register_presave - register a pre-save
|
||||
// function callback
|
||||
//-------------------------------------------------
|
||||
|
||||
void state_save_register_memory(running_machine *machine, const char *module, const char *tag, UINT32 index, const char *name, void *val, UINT32 valsize, UINT32 valcount, const char *file, int line)
|
||||
void state_manager::register_presave(prepost_func func, void *param)
|
||||
{
|
||||
state_private *global = machine->state_data;
|
||||
state_entry **entryptr, *next;
|
||||
astring totalname;
|
||||
// check for invalid timing
|
||||
if (!m_reg_allowed)
|
||||
fatalerror("Attempt to register callback function after state registration is closed!");
|
||||
|
||||
// scan for duplicates and push through to the end
|
||||
for (state_callback *cb = m_presave_list.first(); cb != NULL; cb = cb->next())
|
||||
if (cb->m_func == func && cb->m_param == param)
|
||||
fatalerror("Duplicate save state function (%p, %p)", param, func);
|
||||
|
||||
// allocate a new entry
|
||||
m_presave_list.append(*auto_alloc(&m_machine, state_callback(func, param)));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// state_save_register_postload -
|
||||
// register a post-load function callback
|
||||
//-------------------------------------------------
|
||||
|
||||
void state_manager::register_postload(prepost_func func, void *param)
|
||||
{
|
||||
// check for invalid timing
|
||||
if (!m_reg_allowed)
|
||||
fatalerror("Attempt to register callback function after state registration is closed!");
|
||||
|
||||
// scan for duplicates and push through to the end
|
||||
for (state_callback *cb = m_postload_list.first(); cb != NULL; cb = cb->next())
|
||||
if (cb->m_func == func && cb->m_param == param)
|
||||
fatalerror("Duplicate save state function (%p, %p)", param, func);
|
||||
|
||||
// allocate a new entry
|
||||
m_postload_list.append(*auto_alloc(&m_machine, state_callback(func, param)));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// save_memory - register an array of data in
|
||||
// memory
|
||||
//-------------------------------------------------
|
||||
|
||||
void state_manager::save_memory(const char *module, const char *tag, UINT32 index, const char *name, void *val, UINT32 valsize, UINT32 valcount)
|
||||
{
|
||||
assert(valsize == 1 || valsize == 2 || valsize == 4 || valsize == 8);
|
||||
|
||||
/* check for invalid timing */
|
||||
if (!global->reg_allowed)
|
||||
// check for invalid timing
|
||||
if (!m_reg_allowed)
|
||||
{
|
||||
logerror("Attempt to register save state entry after state registration is closed!\nFile: %s, line %d, module %s tag %s name %s\n", file, line, module, tag, name);
|
||||
if (machine->gamedrv->flags & GAME_SUPPORTS_SAVE)
|
||||
fatalerror("Attempt to register save state entry after state registration is closed!\nFile: %s, line %d, module %s tag %s name %s\n", file, line, module, tag, name);
|
||||
global->illegal_regs++;
|
||||
logerror("Attempt to register save state entry after state registration is closed!\nModule %s tag %s name %s\n", module, tag, name);
|
||||
if (m_machine.gamedrv->flags & GAME_SUPPORTS_SAVE)
|
||||
fatalerror("Attempt to register save state entry after state registration is closed!\nModule %s tag %s name %s\n", module, tag, name);
|
||||
m_illegal_regs++;
|
||||
return;
|
||||
}
|
||||
|
||||
/* create the full name */
|
||||
// create the full name
|
||||
astring totalname;
|
||||
if (tag != NULL)
|
||||
totalname.printf("%s/%s/%X/%s", module, tag, index, name);
|
||||
else
|
||||
totalname.printf("%s/%X/%s", module, index, name);
|
||||
|
||||
/* look for duplicates and an entry to insert in front of */
|
||||
for (entryptr = &global->entrylist; *entryptr != NULL; entryptr = &(*entryptr)->next)
|
||||
// look for duplicates and an entry to insert in front of
|
||||
state_entry *insert_after = NULL;
|
||||
for (state_entry *entry = m_entry_list.first(); entry != NULL; entry = entry->next())
|
||||
{
|
||||
/* stop if the next guy's string is greater than ours */
|
||||
int cmpval = (*entryptr)->name.cmp(totalname);
|
||||
if (cmpval > 0)
|
||||
// stop when we find an entry whose name is after ours
|
||||
if (entry->m_name > totalname)
|
||||
break;
|
||||
insert_after = entry;
|
||||
|
||||
/* error if we are equal */
|
||||
if (cmpval == 0)
|
||||
// error if we are equal
|
||||
if (entry->m_name == totalname)
|
||||
fatalerror("Duplicate save state registration entry (%s)", totalname.cstr());
|
||||
}
|
||||
|
||||
/* didn't find one; allocate a new one */
|
||||
next = *entryptr;
|
||||
*entryptr = auto_alloc_clear(machine, state_entry);
|
||||
|
||||
/* fill in the rest */
|
||||
(*entryptr)->next = next;
|
||||
(*entryptr)->machine = machine;
|
||||
(*entryptr)->data = val;
|
||||
(*entryptr)->name = totalname;
|
||||
(*entryptr)->typesize = valsize;
|
||||
(*entryptr)->typecount = valcount;
|
||||
// insert us into the list
|
||||
m_entry_list.insert_after(*auto_alloc(&m_machine, state_entry(val, totalname, valsize, valcount)), insert_after);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
state_save_register_bitmap - register a
|
||||
bitmap to be saved
|
||||
-------------------------------------------------*/
|
||||
//-------------------------------------------------
|
||||
// check_file - check if a file is a valid save
|
||||
// state
|
||||
//-------------------------------------------------
|
||||
|
||||
void state_save_register_bitmap(running_machine *machine, const char *module, const char *tag, UINT32 index, const char *name, bitmap_t *val, const char *file, int line)
|
||||
state_save_error state_manager::check_file(running_machine *machine, mame_file *file, const char *gamename, void (CLIB_DECL *errormsg)(const char *fmt, ...))
|
||||
{
|
||||
state_save_register_memory(machine, module, tag, index, name, val->base, val->bpp / 8, val->rowpixels * val->height, file, line);
|
||||
}
|
||||
// if we want to validate the signature, compute it
|
||||
UINT32 sig = 0;
|
||||
if (machine != NULL)
|
||||
sig = machine->state().signature();
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
CALLBACK FUNCTION REGISTRATION
|
||||
***************************************************************************/
|
||||
|
||||
/*-------------------------------------------------
|
||||
state_save_register_presave -
|
||||
register a pre-save function callback
|
||||
-------------------------------------------------*/
|
||||
|
||||
void state_save_register_presave(running_machine *machine, state_presave_func func, void *param)
|
||||
{
|
||||
state_private *global = machine->state_data;
|
||||
state_callback **cbptr;
|
||||
|
||||
/* check for invalid timing */
|
||||
if (!global->reg_allowed)
|
||||
fatalerror("Attempt to register callback function after state registration is closed!");
|
||||
|
||||
/* scan for duplicates and push through to the end */
|
||||
for (cbptr = &global->prefunclist; *cbptr != NULL; cbptr = &(*cbptr)->next)
|
||||
if ((*cbptr)->func.presave == func && (*cbptr)->param == param)
|
||||
fatalerror("Duplicate save state function (%p, %p)", param, func);
|
||||
|
||||
/* allocate a new entry */
|
||||
*cbptr = auto_alloc(machine, state_callback);
|
||||
|
||||
/* fill it in */
|
||||
(*cbptr)->next = NULL;
|
||||
(*cbptr)->machine = machine;
|
||||
(*cbptr)->func.presave = func;
|
||||
(*cbptr)->param = param;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
state_save_register_postload -
|
||||
register a post-load function callback
|
||||
-------------------------------------------------*/
|
||||
|
||||
void state_save_register_postload(running_machine *machine, state_postload_func func, void *param)
|
||||
{
|
||||
state_private *global = machine->state_data;
|
||||
state_callback **cbptr;
|
||||
|
||||
/* check for invalid timing */
|
||||
if (!global->reg_allowed)
|
||||
fatalerror("Attempt to register callback function after state registration is closed!");
|
||||
|
||||
/* scan for duplicates and push through to the end */
|
||||
for (cbptr = &global->postfunclist; *cbptr != NULL; cbptr = &(*cbptr)->next)
|
||||
if ((*cbptr)->func.postload == func && (*cbptr)->param == param)
|
||||
fatalerror("Duplicate save state function (%p, %p)", param, func);
|
||||
|
||||
/* allocate a new entry */
|
||||
*cbptr = auto_alloc(machine, state_callback);
|
||||
|
||||
/* fill it in */
|
||||
(*cbptr)->next = NULL;
|
||||
(*cbptr)->machine = machine;
|
||||
(*cbptr)->func.postload = func;
|
||||
(*cbptr)->param = param;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
PROCESSING HELPERS
|
||||
***************************************************************************/
|
||||
|
||||
/*-------------------------------------------------
|
||||
get_signature - compute the signature, which
|
||||
is a CRC over the structure of the data
|
||||
-------------------------------------------------*/
|
||||
|
||||
static UINT32 get_signature(running_machine *machine)
|
||||
{
|
||||
state_private *global = machine->state_data;
|
||||
state_entry *entry;
|
||||
UINT32 crc = 0;
|
||||
|
||||
/* iterate over entries */
|
||||
for (entry = global->entrylist; entry != NULL; entry = entry->next)
|
||||
// seek to the beginning and read the header
|
||||
mame_fcompress(file, FCOMPRESS_NONE);
|
||||
mame_fseek(file, 0, SEEK_SET);
|
||||
UINT8 header[HEADER_SIZE];
|
||||
if (mame_fread(file, header, sizeof(header)) != sizeof(header))
|
||||
{
|
||||
UINT32 temp[2];
|
||||
|
||||
/* add the entry name to the CRC */
|
||||
crc = crc32(crc, (UINT8 *)entry->name.cstr(), entry->name.len());
|
||||
|
||||
/* add the type and size to the CRC */
|
||||
temp[0] = LITTLE_ENDIANIZE_INT32(entry->typecount);
|
||||
temp[1] = LITTLE_ENDIANIZE_INT32(entry->typesize);
|
||||
crc = crc32(crc, (UINT8 *)&temp[0], sizeof(temp));
|
||||
if (errormsg != NULL)
|
||||
(*errormsg)("Could not read " APPNAME " save file header");
|
||||
return STATERR_READ_ERROR;
|
||||
}
|
||||
|
||||
// let the generic header check work out the rest
|
||||
return validate_header(header, gamename, sig, errormsg, "");
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// read_file - read the data from a file
|
||||
//-------------------------------------------------
|
||||
|
||||
state_save_error state_manager::read_file(mame_file *file)
|
||||
{
|
||||
// if we have illegal registrations, return an error
|
||||
if (m_illegal_regs > 0)
|
||||
return STATERR_ILLEGAL_REGISTRATIONS;
|
||||
|
||||
// read the header and turn on compression for the rest of the file
|
||||
mame_fcompress(file, FCOMPRESS_NONE);
|
||||
mame_fseek(file, 0, SEEK_SET);
|
||||
UINT8 header[HEADER_SIZE];
|
||||
if (mame_fread(file, header, sizeof(header)) != sizeof(header))
|
||||
return STATERR_READ_ERROR;
|
||||
mame_fcompress(file, FCOMPRESS_MEDIUM);
|
||||
|
||||
// verify the header and report an error if it doesn't match
|
||||
UINT32 sig = signature();
|
||||
if (validate_header(header, m_machine.gamedrv->name, sig, popmessage, "Error: ") != STATERR_NONE)
|
||||
return STATERR_INVALID_HEADER;
|
||||
|
||||
// determine whether or not to flip the data when done
|
||||
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.first(); entry != NULL; entry = entry->next())
|
||||
{
|
||||
UINT32 totalsize = entry->m_typesize * entry->m_typecount;
|
||||
if (mame_fread(file, entry->m_data, totalsize) != totalsize)
|
||||
return STATERR_READ_ERROR;
|
||||
|
||||
// handle flipping
|
||||
if (flip)
|
||||
entry->flip_data();
|
||||
}
|
||||
|
||||
// call the post-load functions
|
||||
for (state_callback *func = m_postload_list.first(); func != NULL; func = func->next())
|
||||
(*func->m_func)(&m_machine, func->m_param);
|
||||
|
||||
return STATERR_NONE;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// write_file - writes the data to a file
|
||||
//-------------------------------------------------
|
||||
|
||||
state_save_error state_manager::write_file(mame_file *file)
|
||||
{
|
||||
// if we have illegal registrations, return an error
|
||||
if (m_illegal_regs > 0)
|
||||
return STATERR_ILLEGAL_REGISTRATIONS;
|
||||
|
||||
// generate the header
|
||||
UINT8 header[HEADER_SIZE];
|
||||
memcpy(&header[0], s_magic_num, 8);
|
||||
header[8] = SAVE_VERSION;
|
||||
header[9] = NATIVE_ENDIAN_VALUE_LE_BE(0, SS_MSB_FIRST);
|
||||
strncpy((char *)&header[0x0a], m_machine.gamedrv->name, 0x1c - 0x0a);
|
||||
UINT32 sig = signature();
|
||||
*(UINT32 *)&header[0x1c] = LITTLE_ENDIANIZE_INT32(sig);
|
||||
|
||||
// write the header and turn on compression for the rest of the file
|
||||
mame_fcompress(file, FCOMPRESS_NONE);
|
||||
mame_fseek(file, 0, SEEK_SET);
|
||||
if (mame_fwrite(file, header, sizeof(header)) != sizeof(header))
|
||||
return STATERR_WRITE_ERROR;
|
||||
mame_fcompress(file, FCOMPRESS_MEDIUM);
|
||||
|
||||
// call the pre-save functions
|
||||
for (state_callback *func = m_presave_list.first(); func != NULL; func = func->next())
|
||||
(*func->m_func)(&m_machine, func->m_param);
|
||||
|
||||
// then write all the data
|
||||
for (state_entry *entry = m_entry_list.first(); entry != NULL; entry = entry->next())
|
||||
{
|
||||
UINT32 totalsize = entry->m_typesize * entry->m_typecount;
|
||||
if (mame_fwrite(file, entry->m_data, totalsize) != totalsize)
|
||||
return STATERR_WRITE_ERROR;
|
||||
}
|
||||
return STATERR_NONE;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// signature - compute the signature, which
|
||||
// is a CRC over the structure of the data
|
||||
//-------------------------------------------------
|
||||
|
||||
UINT32 state_manager::signature() const
|
||||
{
|
||||
// iterate over entries
|
||||
UINT32 crc = 0;
|
||||
for (state_entry *entry = m_entry_list.first(); entry != NULL; entry = entry->next())
|
||||
{
|
||||
// add the entry name to the CRC
|
||||
crc = crc32(crc, (UINT8 *)entry->m_name.cstr(), entry->m_name.len());
|
||||
|
||||
// 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);
|
||||
crc = crc32(crc, (UINT8 *)&temp[0], sizeof(temp));
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// dump_registry - dump the registry to the
|
||||
// logfile
|
||||
//-------------------------------------------------
|
||||
|
||||
/***************************************************************************
|
||||
SAVE STATE FILE PROCESSING
|
||||
***************************************************************************/
|
||||
void state_manager::dump_registry() const
|
||||
{
|
||||
for (state_entry *entry = m_entry_list.first(); entry != NULL; entry = entry->next())
|
||||
LOG(("%s: %d x %d\n", entry->m_name.cstr(), entry->m_typesize, entry->m_typecount));
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
validate_header - validate the data in the
|
||||
header
|
||||
-------------------------------------------------*/
|
||||
|
||||
static state_save_error validate_header(const UINT8 *header, const char *gamename, UINT32 signature,
|
||||
//-------------------------------------------------
|
||||
// validate_header - validate the data in the
|
||||
// header
|
||||
//-------------------------------------------------
|
||||
|
||||
state_save_error state_manager::validate_header(const UINT8 *header, const char *gamename, UINT32 signature,
|
||||
void (CLIB_DECL *errormsg)(const char *fmt, ...), const char *error_prefix)
|
||||
{
|
||||
/* check magic number */
|
||||
if (memcmp(header, ss_magic_num, 8))
|
||||
// check magic number
|
||||
if (memcmp(header, s_magic_num, 8))
|
||||
{
|
||||
if (errormsg != NULL)
|
||||
(*errormsg)("%sThis is not a " APPNAME " save file", error_prefix);
|
||||
return STATERR_INVALID_HEADER;
|
||||
}
|
||||
|
||||
/* check save state version */
|
||||
// check save state version
|
||||
if (header[8] != SAVE_VERSION)
|
||||
{
|
||||
if (errormsg != NULL)
|
||||
@ -449,7 +407,7 @@ static state_save_error validate_header(const UINT8 *header, const char *gamenam
|
||||
return STATERR_INVALID_HEADER;
|
||||
}
|
||||
|
||||
/* check gamename, if we were asked to */
|
||||
// check gamename, if we were asked to
|
||||
if (gamename != NULL && strncmp(gamename, (const char *)&header[0x0a], 0x1c - 0x0a))
|
||||
{
|
||||
if (errormsg != NULL)
|
||||
@ -457,7 +415,7 @@ static state_save_error validate_header(const UINT8 *header, const char *gamenam
|
||||
return STATERR_INVALID_HEADER;
|
||||
}
|
||||
|
||||
/* check signature, if we were asked to */
|
||||
// check signature, if we were asked to
|
||||
if (signature != 0)
|
||||
{
|
||||
UINT32 rawsig = *(UINT32 *)&header[0x1c];
|
||||
@ -472,175 +430,63 @@ static state_save_error validate_header(const UINT8 *header, const char *gamenam
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
state_save_check_file - check if a file is
|
||||
a valid save state
|
||||
-------------------------------------------------*/
|
||||
//-------------------------------------------------
|
||||
// state_callback - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
state_save_error state_save_check_file(running_machine *machine, mame_file *file, const char *gamename, void (CLIB_DECL *errormsg)(const char *fmt, ...))
|
||||
state_manager::state_callback::state_callback(prepost_func callback, void *param)
|
||||
: m_next(NULL),
|
||||
m_param(param),
|
||||
m_func(callback)
|
||||
{
|
||||
UINT8 header[HEADER_SIZE];
|
||||
UINT32 signature = 0;
|
||||
}
|
||||
|
||||
/* if we want to validate the signature, compute it */
|
||||
if (machine != NULL)
|
||||
signature = get_signature(machine);
|
||||
|
||||
/* seek to the beginning and read the header */
|
||||
mame_fcompress(file, FCOMPRESS_NONE);
|
||||
mame_fseek(file, 0, SEEK_SET);
|
||||
if (mame_fread(file, header, sizeof(header)) != sizeof(header))
|
||||
//-------------------------------------------------
|
||||
// state_entry - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
state_manager::state_entry::state_entry(void *data, const char *name, UINT8 size, UINT32 count)
|
||||
: m_next(NULL),
|
||||
m_data(data),
|
||||
m_name(name),
|
||||
m_typesize(size),
|
||||
m_typecount(count),
|
||||
m_offset(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// flip_data - reverse the endianness of a
|
||||
// block of data
|
||||
//-------------------------------------------------
|
||||
|
||||
void state_manager::state_entry::flip_data()
|
||||
{
|
||||
UINT16 *data16;
|
||||
UINT32 *data32;
|
||||
UINT64 *data64;
|
||||
int count;
|
||||
|
||||
switch (m_typesize)
|
||||
{
|
||||
if (errormsg != NULL)
|
||||
(*errormsg)("Could not read " APPNAME " save file header");
|
||||
return STATERR_READ_ERROR;
|
||||
case 2:
|
||||
data16 = (UINT16 *)m_data;
|
||||
for (count = 0; count < m_typecount; count++)
|
||||
data16[count] = FLIPENDIAN_INT16(data16[count]);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
data32 = (UINT32 *)m_data;
|
||||
for (count = 0; count < m_typecount; count++)
|
||||
data32[count] = FLIPENDIAN_INT32(data32[count]);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
data64 = (UINT64 *)m_data;
|
||||
for (count = 0; count < m_typecount; count++)
|
||||
data64[count] = FLIPENDIAN_INT64(data64[count]);
|
||||
break;
|
||||
}
|
||||
|
||||
/* let the generic header check work out the rest */
|
||||
return validate_header(header, gamename, signature, errormsg, "");
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
state_save_write_file - writes the data to
|
||||
a file
|
||||
-------------------------------------------------*/
|
||||
|
||||
state_save_error state_save_write_file(running_machine *machine, mame_file *file)
|
||||
{
|
||||
state_private *global = machine->state_data;
|
||||
UINT32 signature = get_signature(machine);
|
||||
UINT8 header[HEADER_SIZE];
|
||||
state_callback *func;
|
||||
state_entry *entry;
|
||||
|
||||
/* if we have illegal registrations, return an error */
|
||||
if (global->illegal_regs > 0)
|
||||
return STATERR_ILLEGAL_REGISTRATIONS;
|
||||
|
||||
/* generate the header */
|
||||
memcpy(&header[0], ss_magic_num, 8);
|
||||
header[8] = SAVE_VERSION;
|
||||
header[9] = NATIVE_ENDIAN_VALUE_LE_BE(0, SS_MSB_FIRST);
|
||||
strncpy((char *)&header[0x0a], machine->gamedrv->name, 0x1c - 0x0a);
|
||||
*(UINT32 *)&header[0x1c] = LITTLE_ENDIANIZE_INT32(signature);
|
||||
|
||||
/* write the header and turn on compression for the rest of the file */
|
||||
mame_fcompress(file, FCOMPRESS_NONE);
|
||||
mame_fseek(file, 0, SEEK_SET);
|
||||
if (mame_fwrite(file, header, sizeof(header)) != sizeof(header))
|
||||
return STATERR_WRITE_ERROR;
|
||||
mame_fcompress(file, FCOMPRESS_MEDIUM);
|
||||
|
||||
/* call the pre-save functions */
|
||||
for (func = global->prefunclist; func != NULL; func = func->next)
|
||||
(*func->func.presave)(machine, func->param);
|
||||
|
||||
/* then write all the data */
|
||||
for (entry = global->entrylist; entry != NULL; entry = entry->next)
|
||||
{
|
||||
UINT32 totalsize = entry->typesize * entry->typecount;
|
||||
if (mame_fwrite(file, entry->data, totalsize) != totalsize)
|
||||
return STATERR_WRITE_ERROR;
|
||||
}
|
||||
return STATERR_NONE;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
state_save_read_file - read the data from a
|
||||
file
|
||||
-------------------------------------------------*/
|
||||
|
||||
state_save_error state_save_read_file(running_machine *machine, mame_file *file)
|
||||
{
|
||||
state_private *global = machine->state_data;
|
||||
UINT32 signature = get_signature(machine);
|
||||
UINT8 header[HEADER_SIZE];
|
||||
state_callback *func;
|
||||
state_entry *entry;
|
||||
int flip;
|
||||
|
||||
/* if we have illegal registrations, return an error */
|
||||
if (global->illegal_regs > 0)
|
||||
return STATERR_ILLEGAL_REGISTRATIONS;
|
||||
|
||||
/* read the header and turn on compression for the rest of the file */
|
||||
mame_fcompress(file, FCOMPRESS_NONE);
|
||||
mame_fseek(file, 0, SEEK_SET);
|
||||
if (mame_fread(file, header, sizeof(header)) != sizeof(header))
|
||||
return STATERR_READ_ERROR;
|
||||
mame_fcompress(file, FCOMPRESS_MEDIUM);
|
||||
|
||||
/* verify the header and report an error if it doesn't match */
|
||||
if (validate_header(header, machine->gamedrv->name, signature, popmessage, "Error: ") != STATERR_NONE)
|
||||
return STATERR_INVALID_HEADER;
|
||||
|
||||
/* determine whether or not to flip the data when done */
|
||||
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 (entry = global->entrylist; entry != NULL; entry = entry->next)
|
||||
{
|
||||
UINT32 totalsize = entry->typesize * entry->typecount;
|
||||
if (mame_fread(file, entry->data, totalsize) != totalsize)
|
||||
return STATERR_READ_ERROR;
|
||||
|
||||
/* handle flipping */
|
||||
if (flip)
|
||||
flip_data(entry);
|
||||
}
|
||||
|
||||
/* call the post-load functions */
|
||||
for (func = global->postfunclist; func != NULL; func = func->next)
|
||||
(*func->func.postload)(machine, func->param);
|
||||
|
||||
return STATERR_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
DEBUGGING
|
||||
***************************************************************************/
|
||||
|
||||
/*-------------------------------------------------
|
||||
state_save_get_indexed_item - return an item
|
||||
with the given index
|
||||
-------------------------------------------------*/
|
||||
|
||||
const char *state_save_get_indexed_item(running_machine *machine, int index, void **base, UINT32 *valsize, UINT32 *valcount)
|
||||
{
|
||||
state_private *global = machine->state_data;
|
||||
state_entry *ss;
|
||||
|
||||
for (ss = global->entrylist; ss != NULL; ss = ss->next)
|
||||
if (index-- == 0)
|
||||
{
|
||||
if (base != NULL)
|
||||
*base = ss->data;
|
||||
if (valsize != NULL)
|
||||
*valsize = ss->typesize;
|
||||
if (valcount != NULL)
|
||||
*valcount = ss->typecount;
|
||||
return ss->name;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
state_save_dump_registry - dump the registry
|
||||
to the logfile
|
||||
-------------------------------------------------*/
|
||||
|
||||
void state_save_dump_registry(running_machine *machine)
|
||||
{
|
||||
state_private *global = machine->state_data;
|
||||
state_entry *entry;
|
||||
|
||||
for (entry = global->entrylist; entry; entry=entry->next)
|
||||
LOG(("%s: %d x %d\n", entry->name.cstr(), entry->typesize, entry->typecount));
|
||||
}
|
||||
|
||||
|
333
src/emu/state.h
333
src/emu/state.h
@ -4,8 +4,36 @@
|
||||
|
||||
Save state management functions.
|
||||
|
||||
Copyright Nicola Salmoria and the MAME Team.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
****************************************************************************
|
||||
|
||||
Copyright Aaron Giles
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name 'MAME' nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
@ -18,25 +46,13 @@
|
||||
#ifndef __STATE_H__
|
||||
#define __STATE_H__
|
||||
|
||||
#ifdef __GNUC__
|
||||
#include <tr1/type_traits>
|
||||
#endif
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINTIONS
|
||||
***************************************************************************/
|
||||
//**************************************************************************
|
||||
// CONSTANTS
|
||||
//**************************************************************************
|
||||
|
||||
typedef void (*state_presave_func)(running_machine *machine, void *param);
|
||||
typedef void (*state_postload_func)(running_machine *machine, void *param);
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
CONSTANTS
|
||||
***************************************************************************/
|
||||
|
||||
enum _state_save_error
|
||||
enum state_save_error
|
||||
{
|
||||
STATERR_NONE,
|
||||
STATERR_ILLEGAL_REGISTRATIONS,
|
||||
@ -44,13 +60,12 @@ enum _state_save_error
|
||||
STATERR_READ_ERROR,
|
||||
STATERR_WRITE_ERROR
|
||||
};
|
||||
typedef enum _state_save_error state_save_error;
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
MACROS
|
||||
***************************************************************************/
|
||||
//**************************************************************************
|
||||
// MACROS
|
||||
//**************************************************************************
|
||||
|
||||
#define STATE_PRESAVE(name) void name(running_machine *machine, void *param)
|
||||
#define STATE_POSTLOAD(name) void name(running_machine *machine, void *param)
|
||||
@ -71,139 +86,235 @@ void state_postload_stub(running_machine *machine, void *param)
|
||||
}
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define IS_VALID_SAVE_TYPE(_var) \
|
||||
(std::tr1::is_arithmetic<typeof(_var)>::value || std::tr1::is_enum<typeof(_var)>::value || \
|
||||
std::tr1::is_same<typeof(_var), PAIR>::value || std::tr1::is_same<typeof(_var), PAIR64>::value)
|
||||
#else
|
||||
#define IS_VALID_SAVE_TYPE(_var) \
|
||||
(sizeof(_var) == 1 || sizeof(_var) == 2 || sizeof(_var) == 4 || sizeof(_var) == 8)
|
||||
#endif
|
||||
|
||||
|
||||
/* generic registration; all further registrations are based on this */
|
||||
#define state_save_register_generic(_mach, _mod, _tag, _index, _name, _val, _valsize, _count) \
|
||||
do { \
|
||||
assert_always(IS_VALID_SAVE_TYPE(_valsize), "Invalid data type supplied for state saving."); \
|
||||
state_save_register_memory(_mach, _mod, _tag, _index, _name, _val, sizeof(_valsize), _count, __FILE__, __LINE__); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* register items with explicit tags */
|
||||
// register items with explicit tags
|
||||
#define state_save_register_item(_mach, _mod, _tag, _index, _val) \
|
||||
state_save_register_generic(_mach, _mod, _tag, _index, #_val, &_val, _val, 1)
|
||||
(_mach)->state().save_item(_mod, _tag, _index, _val, #_val)
|
||||
|
||||
#define state_save_register_item_pointer(_mach, _mod, _tag, _index, _val, _count) \
|
||||
state_save_register_generic(_mach, _mod, _tag, _index, #_val, &_val[0], _val[0], _count)
|
||||
(_mach)->state().save_pointer(_mod, _tag, _index, _val, #_val, _count)
|
||||
|
||||
#define state_save_register_item_array(_mach, _mod, _tag, _index, _val) \
|
||||
state_save_register_item_pointer(_mach, _mod, _tag, _index, _val, sizeof(_val)/sizeof(_val[0]))
|
||||
(_mach)->state().save_item(_mod, _tag, _index, _val, #_val)
|
||||
|
||||
#define state_save_register_item_2d_array(_mach, _mod, _tag, _index, _val) \
|
||||
state_save_register_item_pointer(_mach, _mod, _tag, _index, _val[0], sizeof(_val)/sizeof(_val[0][0]))
|
||||
(_mach)->state().save_item(_mod, _tag, _index, _val, #_val)
|
||||
|
||||
#define state_save_register_item_bitmap(_mach, _mod, _tag, _index, _val) \
|
||||
state_save_register_bitmap(_mach, _mod, _tag, _index, #_val, _val, __FILE__, __LINE__)
|
||||
#define state_save_register_item_bitmap(_mach, _mod, _tag, _index, _val) \
|
||||
(_mach)->state().save_item(_mod, _tag, _index, *(_val), #_val)
|
||||
|
||||
|
||||
|
||||
/* register device items */
|
||||
// register device items
|
||||
#define state_save_register_device_item(_dev, _index, _val) \
|
||||
state_save_register_generic((_dev)->machine, (_dev)->name(), (_dev)->tag(), _index, #_val, &_val, _val, 1)
|
||||
(_dev)->machine->state().save_item((_dev)->name(), (_dev)->tag(), _index, _val, #_val)
|
||||
|
||||
#define state_save_register_device_item_pointer(_dev, _index, _val, _count) \
|
||||
state_save_register_generic((_dev)->machine, (_dev)->name(), (_dev)->tag(), _index, #_val, &_val[0], _val[0], _count)
|
||||
(_dev)->machine->state().save_pointer((_dev)->name(), (_dev)->tag(), _index, _val, #_val, _count)
|
||||
|
||||
#define state_save_register_device_item_array(_dev, _index, _val) \
|
||||
state_save_register_item_pointer((_dev)->machine, (_dev)->name(), (_dev)->tag(), _index, _val, sizeof(_val)/sizeof(_val[0]))
|
||||
(_dev)->machine->state().save_item((_dev)->name(), (_dev)->tag(), _index, _val, #_val)
|
||||
|
||||
#define state_save_register_device_item_2d_array(_dev, _index, _val) \
|
||||
state_save_register_item_pointer((_dev)->machine, (_dev)->name(), (_dev)->tag(), _index, _val[0], sizeof(_val)/sizeof(_val[0][0]))
|
||||
(_dev)->machine->state().save_item((_dev)->name(), (_dev)->tag(), _index, _val, #_val)
|
||||
|
||||
#define state_save_register_device_item_bitmap(_dev, _index, _val) \
|
||||
state_save_register_bitmap((_dev)->machine, (_dev)->name(), (_dev)->tag(), _index, #_val, _val, __FILE__, __LINE__)
|
||||
#define state_save_register_device_item_bitmap(_dev, _index, _val) \
|
||||
(_dev)->machine->state().save_item((_dev)->name(), (_dev)->tag(), _index, *(_val), #_val)
|
||||
|
||||
|
||||
|
||||
/* register global items */
|
||||
// register global items
|
||||
#define state_save_register_global(_mach, _val) \
|
||||
state_save_register_item(_mach, "globals", NULL, 0, _val)
|
||||
(_mach)->state().save_item(_val, #_val)
|
||||
|
||||
#define state_save_register_global_pointer(_mach, _val, _count) \
|
||||
state_save_register_item_pointer(_mach, "globals", NULL, 0, _val, _count)
|
||||
(_mach)->state().save_pointer(_val, #_val, _count)
|
||||
|
||||
#define state_save_register_global_array(_mach, _val) \
|
||||
state_save_register_item_array(_mach, "globals", NULL, 0, _val)
|
||||
(_mach)->state().save_item(_val, #_val)
|
||||
|
||||
#define state_save_register_global_2d_array(_mach, _val) \
|
||||
state_save_register_item_2d_array(_mach, "globals", NULL, 0, _val)
|
||||
(_mach)->state().save_item(_val, #_val)
|
||||
|
||||
#define state_save_register_global_bitmap(_mach, _val) \
|
||||
state_save_register_bitmap(_mach, "globals", NULL, 0, #_val, _val, __FILE__, __LINE__)
|
||||
(_mach)->state().save_item(*(_val), #_val)
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
FUNCTION PROTOTYPES
|
||||
***************************************************************************/
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
class state_manager
|
||||
{
|
||||
// type_checker is a set of templates to identify valid save types
|
||||
template<typename T> struct type_checker { static const bool is_atom = false; static const bool is_pointer = false; };
|
||||
template<typename T> struct type_checker<T*> { static const bool is_atom = false; static const bool is_pointer = true; };
|
||||
|
||||
public:
|
||||
typedef void (*prepost_func)(running_machine *machine, void *param);
|
||||
|
||||
// construction/destruction
|
||||
state_manager(running_machine &machine);
|
||||
|
||||
// getters
|
||||
int registration_count() const { return m_entry_list.count(); }
|
||||
bool registration_allowed() const { return m_reg_allowed; }
|
||||
|
||||
// registration control
|
||||
void allow_registration(bool allowed = true);
|
||||
const char *indexed_item(int index, void *&base, UINT32 &valsize, UINT32 &valcount) const;
|
||||
|
||||
// function registration
|
||||
void register_presave(prepost_func func, void *param);
|
||||
void register_postload(prepost_func func, void *param);
|
||||
|
||||
// generic memory registration
|
||||
void save_memory(const char *module, const char *tag, UINT32 index, const char *name, void *val, UINT32 valsize, UINT32 valcount = 1);
|
||||
|
||||
// templatized wrapper for general objects
|
||||
template<typename T>
|
||||
void save_item(const char *module, const char *tag, int index, T &value, const char *valname)
|
||||
{
|
||||
if (type_checker<T>::is_pointer) throw emu_fatalerror("Called save_item on a pointer with no count!");
|
||||
if (!type_checker<T>::is_atom) throw emu_fatalerror("Called save_item on a non-fundamental type!");
|
||||
save_memory(module, tag, index, valname, &value, sizeof(value));
|
||||
}
|
||||
|
||||
// templatized wrapper for 1-dimensional arrays
|
||||
template<typename T, std::size_t N>
|
||||
void save_item(const char *module, const char *tag, int index, T (&value)[N], const char *valname)
|
||||
{
|
||||
if (!type_checker<T>::is_atom) throw emu_fatalerror("Called save_item on a non-fundamental type!");
|
||||
save_memory(module, tag, index, valname, &value[0], sizeof(value[0]), N);
|
||||
}
|
||||
|
||||
// templatized wrapper for 2-dimensional arrays
|
||||
template<typename T, std::size_t M, std::size_t N>
|
||||
void save_item(const char *module, const char *tag, int index, T (&value)[M][N], const char *valname)
|
||||
{
|
||||
if (!type_checker<T>::is_atom) throw emu_fatalerror("Called save_item on a non-fundamental type!");
|
||||
save_memory(module, tag, index, valname, &value[0][0], sizeof(value[0][0]), M * N);
|
||||
}
|
||||
|
||||
// templatized wrapper for pointers
|
||||
template<typename T>
|
||||
void save_pointer(const char *module, const char *tag, int index, T *value, const char *valname, UINT32 count)
|
||||
{
|
||||
if (!type_checker<T>::is_atom) throw emu_fatalerror("Called save_item on a non-fundamental type!");
|
||||
save_memory(module, tag, index, valname, value, sizeof(*value), count);
|
||||
}
|
||||
|
||||
// global memory registration
|
||||
template<typename T>
|
||||
void save_item(T &value, const char *valname, int index = 0) { save_item("global", NULL, index, value, valname); }
|
||||
template<typename T>
|
||||
void save_pointer(T *value, const char *valname, UINT32 count, int index = 0) { save_pointer("global", NULL, index, value, valname, count); }
|
||||
|
||||
// file processing
|
||||
static state_save_error check_file(running_machine *machine, mame_file *file, const char *gamename, void (CLIB_DECL *errormsg)(const char *fmt, ...));
|
||||
state_save_error write_file(mame_file *file);
|
||||
state_save_error read_file(mame_file *file);
|
||||
|
||||
private:
|
||||
// internal helpers
|
||||
UINT32 signature() const;
|
||||
void dump_registry() const;
|
||||
static state_save_error validate_header(const UINT8 *header, const char *gamename, UINT32 signature, void (CLIB_DECL *errormsg)(const char *fmt, ...), const char *error_prefix);
|
||||
|
||||
// state callback item
|
||||
class state_callback
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
state_callback(prepost_func callback, void *param);
|
||||
|
||||
// getters
|
||||
state_callback *next() const { return m_next; }
|
||||
|
||||
// state
|
||||
state_callback * m_next; // pointer to next entry
|
||||
void * m_param; // function parameter
|
||||
prepost_func m_func; // pointer to the function
|
||||
};
|
||||
|
||||
class state_entry
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
state_entry(void *data, const char *name, 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
|
||||
astring m_name; // full name
|
||||
UINT8 m_typesize; // size of the raw data type
|
||||
UINT32 m_typecount; // number of items
|
||||
UINT32 m_offset; // offset within the final structure
|
||||
};
|
||||
|
||||
// internal state
|
||||
running_machine & m_machine; // reference to our machine
|
||||
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
|
||||
|
||||
static const char s_magic_num[8]; // magic number for header
|
||||
};
|
||||
|
||||
|
||||
/* ----- core system operations ----- */
|
||||
|
||||
/* initialize the system and reset all registrations */
|
||||
void state_init(running_machine *machine);
|
||||
|
||||
/* return the number of total registrations so far */
|
||||
int state_save_get_reg_count(running_machine *machine);
|
||||
// template specializations to enumerate the fundamental atomic types you are allowed to save
|
||||
template<> struct state_manager::type_checker<bool> { static const bool is_atom = true; static const bool is_pointer = false; };
|
||||
template<> struct state_manager::type_checker<INT8> { static const bool is_atom = true; static const bool is_pointer = false; };
|
||||
template<> struct state_manager::type_checker<UINT8> { static const bool is_atom = true; static const bool is_pointer = false; };
|
||||
template<> struct state_manager::type_checker<INT16> { static const bool is_atom = true; static const bool is_pointer = false; };
|
||||
template<> struct state_manager::type_checker<UINT16> { static const bool is_atom = true; static const bool is_pointer = false; };
|
||||
template<> struct state_manager::type_checker<INT32> { static const bool is_atom = true; static const bool is_pointer = false; };
|
||||
template<> struct state_manager::type_checker<UINT32> { static const bool is_atom = true; static const bool is_pointer = false; };
|
||||
template<> struct state_manager::type_checker<INT64> { static const bool is_atom = true; static const bool is_pointer = false; };
|
||||
template<> struct state_manager::type_checker<UINT64> { static const bool is_atom = true; static const bool is_pointer = false; };
|
||||
template<> struct state_manager::type_checker<PAIR> { static const bool is_atom = true; static const bool is_pointer = false; };
|
||||
template<> struct state_manager::type_checker<PAIR64> { static const bool is_atom = true; static const bool is_pointer = false; };
|
||||
template<> struct state_manager::type_checker<float> { static const bool is_atom = true; static const bool is_pointer = false; };
|
||||
template<> struct state_manager::type_checker<double> { static const bool is_atom = true; static const bool is_pointer = false; };
|
||||
|
||||
|
||||
|
||||
/* ----- registration handling ----- */
|
||||
//**************************************************************************
|
||||
// INLINE FUNCTIONS
|
||||
//**************************************************************************
|
||||
|
||||
/* allow/disallow registrations to happen (called by the core) */
|
||||
void state_save_allow_registration(running_machine *machine, int allowed);
|
||||
//-------------------------------------------------
|
||||
// save_item - specialized save_item for bitmaps
|
||||
//-------------------------------------------------
|
||||
|
||||
/* query whether or not registrations are allowed */
|
||||
int state_save_registration_allowed(running_machine *machine);
|
||||
|
||||
/* register an array of data in memory */
|
||||
void state_save_register_memory(running_machine *machine, const char *module, const char *tag, UINT32 index, const char *name, void *val, UINT32 valsize, UINT32 valcount, const char *file, int line);
|
||||
|
||||
/* register a bitmap to be saved */
|
||||
void state_save_register_bitmap(running_machine *machine, const char *module, const char *tag, UINT32 index, const char *name, bitmap_t *val, const char *file, int line);
|
||||
template<>
|
||||
inline void state_manager::save_item(const char *module, const char *tag, int index, bitmap_t &value, const char *name)
|
||||
{
|
||||
save_memory(module, tag, index, name, value.base, value.bpp / 8, value.rowpixels * value.height);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// save_item - specialized save_item for attotimes
|
||||
//-------------------------------------------------
|
||||
|
||||
/* ----- callback function registraton ----- */
|
||||
|
||||
/* register a pre-save function callback */
|
||||
void state_save_register_presave(running_machine *machine, state_presave_func func, void *param);
|
||||
|
||||
/* register a post-load function callback */
|
||||
void state_save_register_postload(running_machine *machine, state_postload_func func, void *param);
|
||||
|
||||
|
||||
|
||||
/* ----- save state file processing ----- */
|
||||
|
||||
/* check if a file is a valid save state */
|
||||
state_save_error state_save_check_file(running_machine *machine, mame_file *file, const char *gamename, void (CLIB_DECL *errormsg)(const char *fmt, ...));
|
||||
|
||||
/* write out the save state file */
|
||||
state_save_error state_save_write_file(running_machine *machine, mame_file *file);
|
||||
|
||||
/* read in a save state file */
|
||||
state_save_error state_save_read_file(running_machine *machine, mame_file *file);
|
||||
|
||||
|
||||
|
||||
/* ----- debugging ----- */
|
||||
|
||||
/* return an item with the given index */
|
||||
const char *state_save_get_indexed_item(running_machine *machine, int index, void **base, UINT32 *valsize, UINT32 *valcount);
|
||||
|
||||
/* dump the registry to the logfile */
|
||||
void state_save_dump_registry(running_machine *machine);
|
||||
template<>
|
||||
inline void state_manager::save_item(const char *module, const char *tag, int index, attotime &value, const char *name)
|
||||
{
|
||||
astring tempstr(name, ".attoseconds");
|
||||
save_memory(module, tag, index, tempstr, &value.attoseconds, sizeof(value.attoseconds));
|
||||
tempstr.cpy(name).cat(".seconds");
|
||||
save_memory(module, tag, index, tempstr, &value.seconds, sizeof(value.seconds));
|
||||
}
|
||||
|
||||
|
||||
#endif /* __STATE_H__ */
|
||||
|
@ -411,7 +411,7 @@ static tilemap_t *tilemap_create_common(running_machine *machine, void *get_info
|
||||
machine->tilemap_data->instance++;
|
||||
|
||||
/* reset everything after a load */
|
||||
state_save_register_postload(machine, tilemap_postload, tmap);
|
||||
machine->state().register_postload(tilemap_postload, tmap);
|
||||
return tmap;
|
||||
}
|
||||
|
||||
|
@ -286,7 +286,7 @@ void timer_device::device_start()
|
||||
m_timer = timer_alloc();
|
||||
|
||||
// register for save states
|
||||
state_save_register_device_item(this, 0, m_first_time);
|
||||
save_item(NAME(m_first_time));
|
||||
}
|
||||
|
||||
|
||||
|
@ -136,7 +136,7 @@ video_manager::video_manager(running_machine &machine)
|
||||
{
|
||||
// request a callback upon exiting
|
||||
machine.add_notifier(MACHINE_NOTIFY_EXIT, exit_static);
|
||||
state_save_register_postload(&machine, state_postload_stub<video_manager, &video_manager::postload>, this);
|
||||
machine.state().register_postload(state_postload_stub<video_manager, &video_manager::postload>, this);
|
||||
|
||||
// extract initial execution state from global configuration settings
|
||||
update_refresh_speed();
|
||||
|
@ -909,7 +909,7 @@ static void common_start(device_t *device, int device_type)
|
||||
mc6845->vert_char_total = 0x7f;
|
||||
|
||||
/* register for state saving */
|
||||
state_save_register_postload(device->machine, mc6845_state_save_postload, mc6845);
|
||||
device->machine->state().register_postload(mc6845_state_save_postload, mc6845);
|
||||
|
||||
state_save_register_device_item(device, 0, mc6845->clock);
|
||||
state_save_register_device_item(device, 0, mc6845->hpixels_per_column);
|
||||
|
@ -53,7 +53,7 @@ void pc_video_start(running_machine *machine,
|
||||
video_start_generic_bitmapped(machine);
|
||||
}
|
||||
|
||||
state_save_register_postload(machine, pc_video_postload, NULL);
|
||||
machine->state().register_postload(pc_video_postload, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -347,7 +347,7 @@ poly_manager *poly_alloc(running_machine *machine, int max_polys, size_t extra_d
|
||||
poly->queue = osd_work_queue_alloc(WORK_QUEUE_FLAG_MULTI | WORK_QUEUE_FLAG_HIGH_FREQ);
|
||||
|
||||
/* request a pre-save callback for synchronization */
|
||||
state_save_register_presave(machine, poly_state_presave, poly);
|
||||
machine->state().register_presave(poly_state_presave, poly);
|
||||
return poly;
|
||||
}
|
||||
|
||||
|
@ -283,7 +283,7 @@ static DEVICE_START( tms9927 )
|
||||
}
|
||||
|
||||
/* register for state saving */
|
||||
state_save_register_postload(device->machine, tms9927_state_save_postload, tms);
|
||||
device->machine->state().register_postload(tms9927_state_save_postload, tms);
|
||||
|
||||
state_save_register_device_item(device, 0, tms->clock);
|
||||
state_save_register_device_item_array(device, 0, tms->reg);
|
||||
|
@ -656,7 +656,7 @@ static void init_save_state(device_t *device)
|
||||
voodoo_state *v = get_safe_token(device);
|
||||
int index, subindex;
|
||||
|
||||
state_save_register_postload(device->machine, voodoo_postload, v);
|
||||
device->machine->state().register_postload(voodoo_postload, v);
|
||||
|
||||
/* register states: core */
|
||||
state_save_register_device_item(device, 0, v->extra_cycles);
|
||||
@ -669,8 +669,7 @@ static void init_save_state(device_t *device)
|
||||
state_save_register_device_item(device, 0, v->pci.init_enable);
|
||||
state_save_register_device_item(device, 0, v->pci.stall_state);
|
||||
state_save_register_device_item(device, 0, v->pci.op_pending);
|
||||
state_save_register_device_item(device, 0, v->pci.op_end_time.seconds);
|
||||
state_save_register_device_item(device, 0, v->pci.op_end_time.attoseconds);
|
||||
state_save_register_device_item(device, 0, v->pci.op_end_time);
|
||||
state_save_register_device_item_array(device, 0, v->pci.fifo_mem);
|
||||
|
||||
/* register states: dac */
|
||||
|
@ -924,7 +924,7 @@ MACHINE_START( schaser_sh )
|
||||
state_save_register_global(machine, state->schaser_effect_555_is_low);
|
||||
state_save_register_global(machine, state->schaser_effect_555_time_remain_savable);
|
||||
state_save_register_global(machine, state->port_2_last_extra);
|
||||
state_save_register_postload(machine, schaser_reinit_555_time_remain, NULL);
|
||||
machine->state().register_postload(schaser_reinit_555_time_remain, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -183,8 +183,7 @@ void cage_init(running_machine *machine, offs_t speedup)
|
||||
|
||||
state_save_register_global(machine, cpu_to_cage_ready);
|
||||
state_save_register_global(machine, cage_to_cpu_ready);
|
||||
state_save_register_global(machine, serial_period_per_word.seconds);
|
||||
state_save_register_global(machine, serial_period_per_word.attoseconds);
|
||||
state_save_register_global(machine, serial_period_per_word);
|
||||
state_save_register_global(machine, dma_enabled);
|
||||
state_save_register_global(machine, dma_timer_enabled);
|
||||
state_save_register_global_array(machine, cage_timer_enabled);
|
||||
|
@ -929,7 +929,7 @@ static void dcs_register_state(running_machine *machine)
|
||||
state_save_register_global_pointer(machine, dcs_sram, 0x8000*4 / sizeof(dcs_sram[0]));
|
||||
|
||||
if (dcs.rev == 2)
|
||||
state_save_register_postload(machine, sdrc_postload, NULL);
|
||||
machine->state().register_postload(sdrc_postload, NULL);
|
||||
}
|
||||
|
||||
void dcs_init(running_machine *machine)
|
||||
|
@ -338,7 +338,7 @@ static MACHINE_START( 20pacgal )
|
||||
|
||||
state_save_register_global(machine, state->game_selected);
|
||||
state_save_register_global_pointer(machine, state->ram_48000, 0x2000);
|
||||
state_save_register_postload(machine, postload_20pacgal, NULL);
|
||||
machine->state().register_postload(postload_20pacgal, NULL);
|
||||
}
|
||||
|
||||
static MACHINE_RESET( 20pacgal )
|
||||
|
@ -329,7 +329,7 @@ static MACHINE_START( ace )
|
||||
{
|
||||
ace_state *state = machine->driver_data<ace_state>();
|
||||
state_save_register_global_array(machine, state->objpos);
|
||||
state_save_register_postload(machine, ace_postload, NULL);
|
||||
machine->state().register_postload(ace_postload, NULL);
|
||||
}
|
||||
|
||||
static MACHINE_RESET( ace )
|
||||
|
@ -1765,7 +1765,7 @@ static DRIVER_INIT( profpac )
|
||||
|
||||
/* reset banking */
|
||||
profpac_banksw_w(iospace, 0, 0);
|
||||
state_save_register_postload(machine, profbank_banksw_restore, NULL);
|
||||
machine->state().register_postload(profbank_banksw_restore, NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -1781,7 +1781,7 @@ static DRIVER_INIT( demndrgn )
|
||||
|
||||
/* reset banking */
|
||||
profpac_banksw_w(iospace, 0, 0);
|
||||
state_save_register_postload(machine, profbank_banksw_restore, NULL);
|
||||
machine->state().register_postload(profbank_banksw_restore, NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -1802,7 +1802,7 @@ static DRIVER_INIT( tenpindx )
|
||||
|
||||
/* reset banking */
|
||||
profpac_banksw_w(iospace, 0, 0);
|
||||
state_save_register_postload(machine, profbank_banksw_restore, NULL);
|
||||
machine->state().register_postload(profbank_banksw_restore, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1176,7 +1176,7 @@ static void init_g1_common(running_machine *machine, offs_t slapstic_base, int s
|
||||
pitfightb_cheap_slapstic_init(machine);
|
||||
state_save_register_global(machine, state->bslapstic_bank);
|
||||
state_save_register_global(machine, state->bslapstic_primed);
|
||||
state_save_register_postload(machine, pitfightb_state_postload, NULL);
|
||||
machine->state().register_postload(pitfightb_state_postload, NULL);
|
||||
}
|
||||
else if (slapstic != 0)
|
||||
atarigen_slapstic_init(machine->device("maincpu"), slapstic_base, 0, slapstic);
|
||||
|
@ -230,7 +230,7 @@ static MACHINE_START( atarisy2 )
|
||||
state_save_register_global(machine, state->which_adc);
|
||||
state_save_register_global(machine, state->p2portwr_state);
|
||||
state_save_register_global(machine, state->p2portrd_state);
|
||||
state_save_register_postload(machine, bankselect_postload, NULL);
|
||||
machine->state().register_postload(bankselect_postload, NULL);
|
||||
state_save_register_global(machine, state->sound_reset_state);
|
||||
}
|
||||
|
||||
|
@ -119,7 +119,7 @@ static MACHINE_START( atetris )
|
||||
/* Set up save state */
|
||||
state_save_register_global(machine, state->current_bank);
|
||||
state_save_register_global(machine, state->nvram_write_enable);
|
||||
state_save_register_postload(machine, atetris_postload, NULL);
|
||||
machine->state().register_postload(atetris_postload, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -585,7 +585,7 @@ static MACHINE_START( crystal )
|
||||
state_save_register_global(machine, state->PIO);
|
||||
state_save_register_global_array(machine, state->DMActrl);
|
||||
state_save_register_global(machine, state->OldPort4);
|
||||
state_save_register_postload(machine, crystal_banksw_postload, NULL);
|
||||
machine->state().register_postload(crystal_banksw_postload, NULL);
|
||||
}
|
||||
|
||||
static MACHINE_RESET( crystal )
|
||||
|
@ -899,7 +899,7 @@ static MACHINE_START( darius )
|
||||
state_save_register_global(machine, state->nmi_enable);
|
||||
state_save_register_global_array(machine, state->vol);
|
||||
state_save_register_global_array(machine, state->pan);
|
||||
state_save_register_postload(machine, darius_postload, NULL);
|
||||
machine->state().register_postload(darius_postload, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1442,7 +1442,7 @@ static MACHINE_START( djmain )
|
||||
state_save_register_global(machine, v_ctrl);
|
||||
state_save_register_global_array(machine, obj_regs);
|
||||
|
||||
state_save_register_postload(machine, djmain_postload, NULL);
|
||||
machine->state().register_postload(djmain_postload, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4933,7 +4933,7 @@ static MACHINE_START( tenkai )
|
||||
{
|
||||
MACHINE_START_CALL(dynax);
|
||||
|
||||
state_save_register_postload(machine, tenkai_bank_postload, NULL);
|
||||
machine->state().register_postload(tenkai_bank_postload, NULL);
|
||||
}
|
||||
|
||||
static MACHINE_CONFIG_START( tenkai, dynax_state )
|
||||
@ -4996,7 +4996,7 @@ static MACHINE_START( gekisha )
|
||||
{
|
||||
MACHINE_START_CALL(dynax);
|
||||
|
||||
state_save_register_postload(machine, gekisha_bank_postload, NULL);
|
||||
machine->state().register_postload(gekisha_bank_postload, NULL);
|
||||
}
|
||||
|
||||
static MACHINE_RESET( gekisha )
|
||||
|
@ -107,7 +107,7 @@ static MACHINE_START( forte2 )
|
||||
|
||||
/* register for save states */
|
||||
state_save_register_global(machine, forte2_input_mask);
|
||||
state_save_register_postload(machine, forte2, NULL);
|
||||
machine->state().register_postload(forte2, NULL);
|
||||
}
|
||||
|
||||
static MACHINE_RESET( forte2 )
|
||||
|
@ -294,10 +294,8 @@ static MACHINE_START( gottlieb )
|
||||
state_save_register_global_pointer(machine, laserdisc_audio_buffer, AUDIORAM_SIZE);
|
||||
state_save_register_global(machine, laserdisc_audio_address);
|
||||
state_save_register_global_array(machine, laserdisc_last_samples);
|
||||
state_save_register_global(machine, laserdisc_last_time.seconds);
|
||||
state_save_register_global(machine, laserdisc_last_time.attoseconds);
|
||||
state_save_register_global(machine, laserdisc_last_clock.seconds);
|
||||
state_save_register_global(machine, laserdisc_last_clock.attoseconds);
|
||||
state_save_register_global(machine, laserdisc_last_time);
|
||||
state_save_register_global(machine, laserdisc_last_clock);
|
||||
state_save_register_global(machine, laserdisc_zero_seen);
|
||||
state_save_register_global(machine, laserdisc_audio_bits);
|
||||
state_save_register_global(machine, laserdisc_audio_bit_count);
|
||||
|
@ -146,9 +146,9 @@ void liberatr_state::machine_start()
|
||||
{
|
||||
atarigen_state::machine_start();
|
||||
|
||||
state_save_register_device_item(this, 0, m_trackball_offset);
|
||||
state_save_register_device_item(this, 0, m_ctrld);
|
||||
state_save_register_device_item_array(this, 0, m_videoram);
|
||||
save_item(NAME(m_trackball_offset));
|
||||
save_item(NAME(m_ctrld));
|
||||
save_item(NAME(m_videoram));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1148,7 +1148,7 @@ static DRIVER_INIT( quizf1 )
|
||||
set_m90_bank(machine);
|
||||
|
||||
state_save_register_global(machine, bankaddress);
|
||||
state_save_register_postload(machine, quizf1_postload, NULL);
|
||||
machine->state().register_postload(quizf1_postload, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -233,7 +233,7 @@ static MACHINE_START( m92 )
|
||||
state_save_register_global(machine, state->irqvector);
|
||||
state_save_register_global(machine, state->sound_status);
|
||||
state_save_register_global(machine, state->bankaddress);
|
||||
state_save_register_postload(machine, m92_postload, NULL);
|
||||
machine->state().register_postload(m92_postload, NULL);
|
||||
|
||||
state->scanline_timer = machine->scheduler().timer_alloc(FUNC(m92_scanline_interrupt));
|
||||
}
|
||||
|
@ -467,7 +467,7 @@ static MACHINE_START( mjsister )
|
||||
state_save_register_global(machine, state->dac_bank);
|
||||
state_save_register_global(machine, state->dac_adr_s);
|
||||
state_save_register_global(machine, state->dac_adr_e);
|
||||
state_save_register_postload(machine, mjsister_redraw, 0);
|
||||
machine->state().register_postload(mjsister_redraw, 0);
|
||||
}
|
||||
|
||||
static MACHINE_RESET( mjsister )
|
||||
|
@ -900,7 +900,7 @@ static MACHINE_START( maze )
|
||||
|
||||
/* setup for save states */
|
||||
state_save_register_global(machine, state->maze_tone_timing_state);
|
||||
state_save_register_postload(machine, maze_update_discrete, NULL);
|
||||
machine->state().register_postload(maze_update_discrete, NULL);
|
||||
|
||||
MACHINE_START_CALL(mw8080bw);
|
||||
}
|
||||
|
@ -865,7 +865,7 @@ static MACHINE_START( mystwarr )
|
||||
|
||||
state_save_register_global(machine, mw_irq_control);
|
||||
state_save_register_global(machine, cur_sound_region);
|
||||
state_save_register_postload(machine, mystwarr_postload, NULL);
|
||||
machine->state().register_postload(mystwarr_postload, NULL);
|
||||
}
|
||||
|
||||
static MACHINE_RESET(mystwarr)
|
||||
|
@ -1102,7 +1102,7 @@ static MACHINE_START( neogeo )
|
||||
state_save_register_global(machine, state->led2_value);
|
||||
state_save_register_global(machine, state->recurse);
|
||||
|
||||
state_save_register_postload(machine, neogeo_postload, NULL);
|
||||
machine->state().register_postload(neogeo_postload, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -783,7 +783,7 @@ static MACHINE_START( ninjaw )
|
||||
state_save_register_global(machine, state->cpua_ctrl);
|
||||
state_save_register_global(machine, state->banknum);
|
||||
state_save_register_global_array(machine, state->pandata);
|
||||
state_save_register_postload(machine, ninjaw_postload, NULL);
|
||||
machine->state().register_postload(ninjaw_postload, NULL);
|
||||
}
|
||||
|
||||
static MACHINE_RESET( ninjaw )
|
||||
|
@ -706,7 +706,7 @@ static MACHINE_START( othunder )
|
||||
state_save_register_global(machine, state->ad_irq);
|
||||
state_save_register_global(machine, state->banknum);
|
||||
state_save_register_global_array(machine, state->pan);
|
||||
state_save_register_postload(machine, othunder_postload, NULL);
|
||||
machine->state().register_postload(othunder_postload, NULL);
|
||||
}
|
||||
|
||||
static MACHINE_RESET( othunder )
|
||||
|
@ -248,7 +248,7 @@ static MACHINE_START( pengadvb )
|
||||
state_save_register_global_pointer(machine, main_mem, 0x4000);
|
||||
state_save_register_global(machine, mem_map);
|
||||
state_save_register_global_array(machine, mem_banks);
|
||||
state_save_register_postload(machine, pengadvb, NULL);
|
||||
machine->state().register_postload(pengadvb, NULL);
|
||||
}
|
||||
|
||||
static MACHINE_RESET( pengadvb )
|
||||
|
@ -1072,8 +1072,8 @@ static void install_hotgmck_pcm_bank(running_machine *machine)
|
||||
set_hotgmck_pcm_bank(machine, 1);
|
||||
|
||||
memory_install_write32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x5800008, 0x580000b, 0, 0, hotgmck_pcm_bank_w );
|
||||
state_save_register_postload(machine, hotgmck_pcm_bank_postload, (void *)0);
|
||||
state_save_register_postload(machine, hotgmck_pcm_bank_postload, (void *)1);
|
||||
machine->state().register_postload(hotgmck_pcm_bank_postload, (void *)0);
|
||||
machine->state().register_postload(hotgmck_pcm_bank_postload, (void *)1);
|
||||
}
|
||||
|
||||
static DRIVER_INIT( hotgmck )
|
||||
|
@ -265,7 +265,7 @@ static MACHINE_START( renegade )
|
||||
state_save_register_global(machine, mcu_key);
|
||||
|
||||
state_save_register_global(machine, bank);
|
||||
state_save_register_postload(machine, renegade_postload, NULL);
|
||||
machine->state().register_postload(renegade_postload, NULL);
|
||||
}
|
||||
|
||||
static DRIVER_INIT( renegade )
|
||||
|
@ -547,7 +547,7 @@ static MACHINE_START( slapshot )
|
||||
|
||||
state->banknum = 0;
|
||||
state_save_register_global(machine, state->banknum);
|
||||
state_save_register_postload(machine, slapshot_postload, NULL);
|
||||
machine->state().register_postload(slapshot_postload, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -5744,7 +5744,7 @@ static DRIVER_INIT( driveout )
|
||||
state_save_register_global(machine, state->driveout_sound_latch);
|
||||
state_save_register_global(machine, state->oki_bank);
|
||||
state_save_register_global(machine, state->nibble);
|
||||
state_save_register_postload(machine, driveout_postload, NULL);
|
||||
machine->state().register_postload(driveout_postload, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -534,7 +534,7 @@ static MACHINE_START( taitoh )
|
||||
state->tc0080vco = machine->device("tc0080vco");
|
||||
|
||||
state_save_register_global(machine, state->banknum);
|
||||
state_save_register_postload(machine, taitoh_postload, NULL);
|
||||
machine->state().register_postload(taitoh_postload, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -898,7 +898,7 @@ static MACHINE_START( taitox )
|
||||
|
||||
state->taitox_banknum = -1;
|
||||
state_save_register_global(machine, state->taitox_banknum);
|
||||
state_save_register_postload(machine, taitox_postload, NULL);
|
||||
machine->state().register_postload(taitox_postload, NULL);
|
||||
}
|
||||
|
||||
static const tc0140syt_interface taitox_tc0140syt_intf =
|
||||
|
@ -2994,7 +2994,7 @@ static MACHINE_START( taitoz )
|
||||
|
||||
memory_configure_bank(machine, "bank10", 0, banks, machine->region("audiocpu")->base() + 0xc000, 0x4000);
|
||||
|
||||
state_save_register_postload(machine, taitoz_postload, NULL);
|
||||
machine->state().register_postload(taitoz_postload, NULL);
|
||||
|
||||
MACHINE_START_CALL(bshark);
|
||||
}
|
||||
@ -4888,7 +4888,7 @@ static DRIVER_INIT( bshark )
|
||||
state->dblaxle_vibration = 0;
|
||||
state->eep_latch = 0;
|
||||
|
||||
state_save_register_postload(machine, bshark_postload, NULL);
|
||||
machine->state().register_postload(bshark_postload, NULL);
|
||||
state_save_register_global(machine, state->eep_latch);
|
||||
}
|
||||
|
||||
|
@ -630,7 +630,7 @@ static MACHINE_START( taitoair )
|
||||
state_save_register_item(machine, "globals", NULL, i, state->q.p[i].y);
|
||||
}
|
||||
|
||||
state_save_register_postload(machine, taitoair_postload, NULL);
|
||||
machine->state().register_postload(taitoair_postload, NULL);
|
||||
}
|
||||
|
||||
static MACHINE_RESET( taitoair )
|
||||
|
@ -662,7 +662,7 @@ static MACHINE_START( topspeed )
|
||||
state_save_register_global(machine, state->cpua_ctrl);
|
||||
state_save_register_global(machine, state->ioc220_port);
|
||||
state_save_register_global(machine, state->banknum);
|
||||
state_save_register_postload(machine, topspeed_postload, NULL);
|
||||
machine->state().register_postload(topspeed_postload, NULL);
|
||||
}
|
||||
|
||||
static MACHINE_RESET( topspeed )
|
||||
|
@ -565,7 +565,7 @@ static MACHINE_START( vegas )
|
||||
state_save_register_global(machine, sio_led_state);
|
||||
state_save_register_global(machine, pending_analog_read);
|
||||
state_save_register_global(machine, cmos_unlocked);
|
||||
state_save_register_postload(machine, vegas_postload, NULL);
|
||||
machine->state().register_postload(vegas_postload, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -558,7 +558,7 @@ static MACHINE_START( warriorb )
|
||||
|
||||
state_save_register_global(machine, state->banknum);
|
||||
state_save_register_global_array(machine, state->pandata);
|
||||
state_save_register_postload(machine, warriorb_postload, NULL);
|
||||
machine->state().register_postload(warriorb_postload, NULL);
|
||||
}
|
||||
|
||||
static MACHINE_RESET( taito_dualscreen )
|
||||
|
@ -964,7 +964,7 @@ static MACHINE_START( wgp )
|
||||
state_save_register_global(machine, state->cpua_ctrl);
|
||||
state_save_register_global(machine, state->banknum);
|
||||
state_save_register_global(machine, state->port_sel);
|
||||
state_save_register_postload(machine, wgp_postload, NULL);
|
||||
machine->state().register_postload(wgp_postload, NULL);
|
||||
}
|
||||
|
||||
static const tc0100scn_interface wgp_tc0100scn_intf =
|
||||
|
@ -493,7 +493,7 @@ static MACHINE_START( xexex )
|
||||
|
||||
state_save_register_global(machine, state->cur_control2);
|
||||
state_save_register_global(machine, state->cur_sound_region);
|
||||
state_save_register_postload(machine, xexex_postload, NULL);
|
||||
machine->state().register_postload(xexex_postload, NULL);
|
||||
|
||||
state->dmadelay_timer = machine->scheduler().timer_alloc(FUNC(dmaend_callback));
|
||||
}
|
||||
|
@ -330,7 +330,7 @@ static MACHINE_START( xmen )
|
||||
state_save_register_global(machine, state->sprite_colorbase);
|
||||
state_save_register_global_array(machine, state->layer_colorbase);
|
||||
state_save_register_global_array(machine, state->layerpri);
|
||||
state_save_register_postload(machine, xmen_postload, NULL);
|
||||
machine->state().register_postload(xmen_postload, NULL);
|
||||
}
|
||||
|
||||
static MACHINE_RESET( xmen )
|
||||
|
@ -165,7 +165,7 @@ void atarigen_init(running_machine *machine)
|
||||
state_save_register_global(machine, state->playfield2_latch);
|
||||
|
||||
/* need a postload to reset the state */
|
||||
state_save_register_postload(machine, slapstic_postload, NULL);
|
||||
machine->state().register_postload(slapstic_postload, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -258,8 +258,7 @@ static TIMER_CALLBACK( reset_timer )
|
||||
static void pic_register_state(running_machine *machine)
|
||||
{
|
||||
state_save_register_global(machine, pic.latch);
|
||||
state_save_register_global(machine, pic.latch_expire_time.seconds);
|
||||
state_save_register_global(machine, pic.latch_expire_time.attoseconds);
|
||||
state_save_register_global(machine, pic.latch_expire_time);
|
||||
state_save_register_global(machine, pic.state);
|
||||
state_save_register_global(machine, pic.index);
|
||||
state_save_register_global(machine, pic.total);
|
||||
|
@ -413,7 +413,7 @@ static void init_save_state(device_t *device)
|
||||
{
|
||||
naomibd_state *v = get_safe_token(device);
|
||||
|
||||
state_save_register_postload(device->machine, naomibd_postload, v);
|
||||
device->machine->state().register_postload(naomibd_postload, v);
|
||||
|
||||
/* register states */
|
||||
state_save_register_device_item(device, 0, v->rom_offset);
|
||||
|
@ -140,7 +140,7 @@ static DEVICE_START( nmk112 )
|
||||
nmk112->page_mask = ~intf->disable_page_mask;
|
||||
|
||||
state_save_register_device_item_array(device, 0, nmk112->current_bank);
|
||||
state_save_register_postload(device->machine, nmk112_postload_bankswitch, nmk112);
|
||||
device->machine->state().register_postload(nmk112_postload_bankswitch, nmk112);
|
||||
}
|
||||
|
||||
static DEVICE_RESET( nmk112 )
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user