/* 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 #include #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; }