summaryrefslogblamecommitdiffstatshomepage
path: root/src/emu/save.h
blob: 8fc537e1289c31291aec00b97b621cbe7d00a183 (plain) (tree)
1
2
3
4
5
6
7
8

                                

                                                                            
          


                                    



                                                                            



                                                              

                  
 
 
 


                                                                            
 
               






                                      


 


                                                                            
 

                                                

 


                                                                              

                                                                                                                                      
 



                                                                                                                                                                                                                                       

 
                                    
                                                                   
                                                                 

                                                                                   
                                                                            

                                                                         
                                                                 

                                                                            
                                                                 
 
                                                                          
                                                                    

 
 


                                                                            
 
                  

                                                                          

                                                                                                                                                 

       
                                   
                                               

                  
                                                              

                                                                       
 




                                                                                                  

                                                           


                                                                                                                                              
 
                                                  

                                                                                                             
         

                                                                                                                              

                                                                                
 
                                                       

                                                                                                                  
         
                                                                                                                           

                                                                                         
 
                                                       

                                                                                                                     
         
                                                                                                                           

                                                                                                   
 
                                           

                                                                                                                              
         
                                                                                                                           

                                                                                       
 
                                     



                                                                                                                                                             
 
                          


                                                                                                                                                       
 



                                   
                                                                                                                                                                                   





                                           
                                                               

                          
                                                               

                        

                                                                                    








                                                                                    

                                                            



                                 





                                                                                                    


                         


                                                                                          
 


                                                                                      
  
 
 
                                                                                             















                                        
 
 
 


                                                                            
 


                                                   
 
          
                                                                                                                         
 


















                                                                                                                          
 
 
 


                                                   
 
          
                                                                                                                      





                                                                                                
 
 
                        
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************

    save.h

    Save state management functions.

***************************************************************************/

#pragma once

#ifndef __EMU_H__
#error Dont include this file directly; include emu.h instead.
#endif

#ifndef __SAVE_H__
#define __SAVE_H__



//**************************************************************************
//  CONSTANTS
//**************************************************************************

enum save_error
{
	STATERR_NONE,
	STATERR_ILLEGAL_REGISTRATIONS,
	STATERR_INVALID_HEADER,
	STATERR_READ_ERROR,
	STATERR_WRITE_ERROR
};



//**************************************************************************
//  MACROS
//**************************************************************************

// callback delegate for presave/postload
typedef delegate<void ()> save_prepost_delegate;


// use this to declare a given type is a simple, non-pointer type that can be
// saved; in general, this is intended only to be used for specific enum types
// defined by your device
#define ALLOW_SAVE_TYPE(TYPE) \
	template<> struct save_manager::type_checker<TYPE> { static const bool is_atom = true; static const bool is_pointer = false; }

// use this as above, but also to declare that dynamic_array<TYPE> is safe as well
#define ALLOW_SAVE_TYPE_AND_ARRAY(TYPE) \
	ALLOW_SAVE_TYPE(TYPE); \
	template<> inline void save_manager::save_item(const char *module, const char *tag, int index, dynamic_array<TYPE> &value, const char *name) { save_memory(module, tag, index, name, &value[0], sizeof(TYPE), value.count()); }


// register items with explicit tags
#define state_save_register_item(_mach, _mod, _tag, _index, _val) \
	(_mach).save().save_item(_mod, _tag, _index, _val, #_val)

#define state_save_register_item_pointer(_mach, _mod, _tag, _index, _val, _count) \
	(_mach).save().save_pointer(_mod, _tag, _index, _val, #_val, _count)

#define state_save_register_item_array(_mach, _mod, _tag, _index, _val) \
	(_mach).save().save_item(_mod, _tag, _index, _val, #_val)

#define state_save_register_item_2d_array(_mach, _mod, _tag, _index, _val) \
	(_mach).save().save_item(_mod, _tag, _index, _val, #_val)

#define state_save_register_item_bitmap(_mach, _mod, _tag, _index, _val) \
	(_mach).save().save_item(_mod, _tag, _index, *(_val), #_val)



//**************************************************************************
//  TYPE DEFINITIONS
//**************************************************************************

class save_manager
{
	// type_checker is a set of templates to identify valid save types
	template<typename _ItemType> struct type_checker { static const bool is_atom = false; static const bool is_pointer = false; };
	template<typename _ItemType> struct type_checker<_ItemType*> { static const bool is_atom = false; static const bool is_pointer = true; };

public:
	// construction/destruction
	save_manager(running_machine &machine);

	// getters
	running_machine &machine() const { return m_machine; }
	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(save_prepost_delegate func);
	void register_postload(save_prepost_delegate func);

	// 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 _ItemType>
	void save_item(const char *module, const char *tag, int index, _ItemType &value, const char *valname)
	{
		if (type_checker<_ItemType>::is_pointer) throw emu_fatalerror("Called save_item on a pointer with no count!");
		if (!type_checker<_ItemType>::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 _ItemType, std::size_t N>
	void save_item(const char *module, const char *tag, int index, _ItemType (&value)[N], const char *valname)
	{
		if (!type_checker<_ItemType>::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 _ItemType, std::size_t M, std::size_t N>
	void save_item(const char *module, const char *tag, int index, _ItemType (&value)[M][N], const char *valname)
	{
		if (!type_checker<_ItemType>::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 _ItemType>
	void save_pointer(const char *module, const char *tag, int index, _ItemType *value, const char *valname, UINT32 count)
	{
		if (!type_checker<_ItemType>::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 _ItemType>
	void save_item(_ItemType &value, const char *valname, int index = 0) { save_item("global", NULL, index, value, valname); }
	template<typename _ItemType>
	void save_pointer(_ItemType *value, const char *valname, UINT32 count, int index = 0) { save_pointer("global", NULL, index, value, valname, count); }

	// file processing
	static save_error check_file(running_machine &machine, emu_file &file, const char *gamename, void (CLIB_DECL *errormsg)(const char *fmt, ...));
	save_error write_file(emu_file &file);
	save_error read_file(emu_file &file);

private:
	// internal helpers
	UINT32 signature() const;
	void dump_registry() const;
	static 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(save_prepost_delegate callback);

		// getters
		state_callback *next() const { return m_next; }

		// state
		state_callback *    m_next;                 // pointer to next entry
		save_prepost_delegate m_func;               // delegate
	};

	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
};


// template specializations to enumerate the fundamental atomic types you are allowed to save
ALLOW_SAVE_TYPE_AND_ARRAY(char);
ALLOW_SAVE_TYPE_AND_ARRAY(bool);
ALLOW_SAVE_TYPE_AND_ARRAY(INT8);
ALLOW_SAVE_TYPE_AND_ARRAY(UINT8);
ALLOW_SAVE_TYPE_AND_ARRAY(INT16);
ALLOW_SAVE_TYPE_AND_ARRAY(UINT16);
ALLOW_SAVE_TYPE_AND_ARRAY(INT32);
ALLOW_SAVE_TYPE_AND_ARRAY(UINT32);
ALLOW_SAVE_TYPE_AND_ARRAY(INT64);
ALLOW_SAVE_TYPE_AND_ARRAY(UINT64);
ALLOW_SAVE_TYPE_AND_ARRAY(PAIR);
ALLOW_SAVE_TYPE_AND_ARRAY(PAIR64);
ALLOW_SAVE_TYPE_AND_ARRAY(float);
ALLOW_SAVE_TYPE_AND_ARRAY(double);
ALLOW_SAVE_TYPE_AND_ARRAY(endianness_t);
ALLOW_SAVE_TYPE_AND_ARRAY(rgb_t);



//**************************************************************************
//  INLINE FUNCTIONS
//**************************************************************************

//-------------------------------------------------
//  save_item - specialized save_item for bitmaps
//-------------------------------------------------

template<>
inline void save_manager::save_item(const char *module, const char *tag, int index, bitmap_ind8 &value, const char *name)
{
	save_memory(module, tag, index, name, &value.pix(0), value.bpp() / 8, value.rowpixels() * value.height());
}

template<>
inline void save_manager::save_item(const char *module, const char *tag, int index, bitmap_ind16 &value, const char *name)
{
	save_memory(module, tag, index, name, &value.pix(0), value.bpp() / 8, value.rowpixels() * value.height());
}

template<>
inline void save_manager::save_item(const char *module, const char *tag, int index, bitmap_ind32 &value, const char *name)
{
	save_memory(module, tag, index, name, &value.pix(0), value.bpp() / 8, value.rowpixels() * value.height());
}

template<>
inline void save_manager::save_item(const char *module, const char *tag, int index, bitmap_rgb32 &value, const char *name)
{
	save_memory(module, tag, index, name, &value.pix(0), value.bpp() / 8, value.rowpixels() * value.height());
}


//-------------------------------------------------
//  save_item - specialized save_item for attotimes
//-------------------------------------------------

template<>
inline void save_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  /* __SAVE_H__ */