/* snapshot.c: snapshot handling routines
Copyright (c) 1999-2012 Philip Kendall
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Author contact information:
E-mail: philip-fuse@shadowmagic.org.uk
*/
#include "config.h"
#include "libspectrum.h"
#include "fuse.h"
#include "machine.h"
#include "memory_pages.h"
#include "module.h"
#include "settings.h"
#include "snapshot.h"
#include "ui/ui.h"
#include "utils.h"
int snapshot_read( const char *filename )
{
utils_file file;
libspectrum_snap *snap = libspectrum_snap_alloc();
int error;
error = utils_read_file( filename, &file );
if( error ) { libspectrum_snap_free( snap ); return error; }
error = libspectrum_snap_read( snap, file.buffer, file.length,
LIBSPECTRUM_ID_UNKNOWN, filename );
if( error ) {
utils_close_file( &file ); libspectrum_snap_free( snap );
return error;
}
utils_close_file( &file );
error = snapshot_copy_from( snap );
if( error ) { libspectrum_snap_free( snap ); return error; }
error = libspectrum_snap_free( snap ); if( error ) return error;
return 0;
}
int
snapshot_read_buffer( const unsigned char *buffer, size_t length,
libspectrum_id_t type )
{
libspectrum_snap *snap = libspectrum_snap_alloc();
int error;
error = libspectrum_snap_read( snap, buffer, length, type, NULL );
if( error ) { libspectrum_snap_free( snap ); return error; }
error = snapshot_copy_from( snap );
if( error ) { libspectrum_snap_free( snap ); return error; }
error = libspectrum_snap_free( snap ); if( error ) return error;
return 0;
}
int
snapshot_copy_from( libspectrum_snap *snap )
{
int error;
libspectrum_machine machine;
periph_disable_optional();
module_snapshot_enabled( snap );
machine = libspectrum_snap_machine( snap );
settings_current.late_timings = libspectrum_snap_late_timings( snap );
if( machine != machine_current->machine ) {
error = machine_select( machine );
if( error ) {
ui_error( UI_ERROR_ERROR,
"Loading a %s snapshot, but that's not available",
libspectrum_machine_name( machine ) );
}
} else {
machine_reset( 0 );
}
module_snapshot_from( snap );
/* Need to reset memory_map_[read|write] after all modules have had a turn
initialising from the snapshot */
machine_current->memory_map();
return 0;
}
int snapshot_write( const char *filename )
{
libspectrum_id_t type;
libspectrum_class_t class;
libspectrum_snap *snap;
unsigned char *buffer; size_t length;
int flags;
int error;
/* Work out what sort of file we want from the filename; default to
.szx if we couldn't guess */
error = libspectrum_identify_file_with_class( &type, &class, filename, NULL,
0 );
if( error ) return error;
if( class != LIBSPECTRUM_CLASS_SNAPSHOT || type == LIBSPECTRUM_ID_UNKNOWN )
type = LIBSPECTRUM_ID_SNAPSHOT_SZX;
snap = libspectrum_snap_alloc();
error = snapshot_copy_to( snap );
if( error ) { libspectrum_snap_free( snap ); return error; }
flags = 0;
length = 0;
buffer = NULL;
error = libspectrum_snap_write( &buffer, &length, &flags, snap, type,
fuse_creator, 0 );
if( error ) { libspectrum_snap_free( snap ); return error; }
if( flags & LIBSPECTRUM_FLAG_SNAPSHOT_MAJOR_INFO_LOSS ) {
ui_error(
UI_ERROR_WARNING,
"A large amount of information has been lost in conversion; the snapshot probably won't work"
);
} else if( flags & LIBSPECTRUM_FLAG_SNAPSHOT_MINOR_INFO_LOSS ) {
ui_error(
UI_ERROR_WARNING,
"Some information has been lost in conversion; the snapshot may not work"
);
}
error = libspectrum_snap_free( snap );
if( error ) { libspectrum_free( buffer ); return 1; }
error = utils_write_file( filename, buffer, length );
if( error ) { libspectrum_free( buffer ); return error; }
libspectrum_free( buffer );
return 0;
}
int
snapshot_copy_to( libspectrum_snap *snap )
{
libspectrum_snap_set_machine( snap, machine_current->machine );
libspectrum_snap_set_late_timings( snap, settings_current.late_timings );
module_snapshot_to( snap );
return 0;
}