// NES block-oriented file access // Nes_Emu 0.7.0 #ifndef NES_FILE_H #define NES_FILE_H #include "blargg_common.h" #include "abstract_file.h" #include "nes_data.h" // Writes a structured file class Nes_File_Writer : public Data_Writer { public: Nes_File_Writer(); ~Nes_File_Writer(); // Begin writing file with specified signature tag const char * begin( Auto_File_Writer, nes_tag_t ); // Begin tagged group const char * begin_group( nes_tag_t ); // Write tagged block const char * write_block( nes_tag_t, void const*, long size ); // Write tagged block header. 'Size' bytes must be written before next block. const char * write_block_header( nes_tag_t, long size ); // Write data to current block const char *write( void const*, long ); // End tagged group const char * end_group(); // End file const char * end(); private: Auto_File_Writer out; long write_remain; int depth_; const char * write_header( nes_tag_t tag, long size ); }; // Reads a structured file class Nes_File_Reader : public Data_Reader { public: Nes_File_Reader(); ~Nes_File_Reader(); // If true, verify checksums of any blocks that have them void enable_checksums( bool = true ); // Begin reading file. Until next_block() is called, block_tag() yields tag for file. const char * begin( Auto_File_Reader ); // Read header of next block in current group const char * next_block(); // Type of current block enum block_type_t { data_block, group_begin, group_end, invalid }; block_type_t block_type() const { return block_type_; } // Tag of current block nes_tag_t block_tag() const { return h.tag; } // Read at most s bytes from block and skip any remaining bytes const char * read_block_data( void*, long s ); // Read at most 's' bytes from current block and return number of bytes actually read virtual const char * read_v( void*, int n ); // Skip 's' bytes in current block virtual const char * skip_v( int s ); // Read first sub-block of current group block const char * enter_group(); // Skip past current group const char * exit_group(); // Current depth, where 0 is top-level in file and higher is deeper int depth() const { return depth_; } // True if all data has been read bool done() const { return depth() == 0 && block_type() == group_end; } private: Auto_File_Reader in; nes_block_t h; block_type_t block_type_; int depth_; const char * read_header(); }; template inline const char * read_nes_state( Nes_File_Reader& in, T* out ) { const char * err = in.read_block_data( out, sizeof *out ); out->swap(); return err; } template inline const char * write_nes_state( Nes_File_Writer& out, T& in ) { in.swap(); const char * err = out.write_block( in.tag, &in, sizeof in ); in.swap(); return err; } template inline const char * write_nes_state( Nes_File_Writer& out, const T& in ) { T copy = in; copy.swap(); return out.write_block( copy.tag, ©, sizeof copy ); } #endif