static int write_snapshot( libspectrum_snap *snap, const char *filename ) { unsigned char *buffer = NULL; size_t length = 0; int error, flags; libspectrum_id_t type; libspectrum_class_t class; 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; error = libspectrum_snap_write( &buffer, &length, &flags, snap, type, creator, 0 ); if( error ) return error; error = write_file( buffer, length, filename ); if( error ) { free( buffer ); return error; } free( buffer ); 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; }
static libspectrum_error rzx_write_snapshot( libspectrum_byte **buffer, libspectrum_byte **ptr, size_t *length, libspectrum_snap *snap, libspectrum_id_t snap_format, libspectrum_creator *creator, int compress ) { libspectrum_error error; libspectrum_byte *snap_buffer = NULL; size_t snap_length; libspectrum_byte *gzsnap = NULL; size_t gzlength = 0; int flags, done; snapshot_string_t *type; snap_length = 0; if( snap_format == LIBSPECTRUM_ID_UNKNOWN ) { /* If not given a snap format, try using .z80. If that would result in major information loss, use .szx instead */ snap_format = LIBSPECTRUM_ID_SNAPSHOT_Z80; error = libspectrum_snap_write( &snap_buffer, &snap_length, &flags, snap, snap_format, creator, 0 ); if( error ) return error; if( flags & LIBSPECTRUM_FLAG_SNAPSHOT_MAJOR_INFO_LOSS ) { libspectrum_free( snap_buffer ); snap_length = 0; snap_format = LIBSPECTRUM_ID_SNAPSHOT_SZX; error = libspectrum_snap_write( &snap_buffer, &snap_length, &flags, snap, snap_format, creator, 0 ); if( error ) return error; } } else { error = libspectrum_snap_write( &snap_buffer, &snap_length, &flags, snap, snap_format, creator, 0 ); if( error ) return error; } if( flags & LIBSPECTRUM_FLAG_SNAPSHOT_MAJOR_INFO_LOSS ) { libspectrum_print_error( LIBSPECTRUM_ERROR_WARNING, "%s:rzx_write_snapshot: embedded snapshot has lost a significant amount of information", __FILE__ ); } if( compress ) { #ifdef HAVE_ZLIB_H error = libspectrum_zlib_compress( snap_buffer, snap_length, &gzsnap, &gzlength ); if( error != LIBSPECTRUM_ERROR_NONE ) { libspectrum_free( snap_buffer ); return error; } libspectrum_make_room( buffer, 17 + gzlength, ptr, length ); #else /* #ifdef HAVE_ZLIB_H */ libspectrum_print_error( LIBSPECTRUM_ERROR_UNKNOWN, "rzx_write_snapshot: compression needs zlib" ); return LIBSPECTRUM_ERROR_UNKNOWN; #endif /* #ifdef HAVE_ZLIB_H */ } else { libspectrum_make_room( buffer, 17 + snap_length, ptr, length ); } *(*ptr)++ = LIBSPECTRUM_RZX_SNAPSHOT_BLOCK; if( compress ) { /* Block length and flags */ libspectrum_write_dword( ptr, 17 + gzlength ); libspectrum_write_dword( ptr, 2 ); } else { libspectrum_write_dword( ptr, 17 + snap_length ); libspectrum_write_dword( ptr, 0 ); } for( type = snapshot_strings, done = 0; type->format; type++ ) { if( type->format == snap_format ) { memcpy( *ptr, type->string, 4 ); *ptr += 4; done = 1; break; } } if( !done ) { libspectrum_print_error( LIBSPECTRUM_ERROR_UNKNOWN, "%s:rzx_write_snapshot: unexpected snap type %d", __FILE__, snap_format ); return LIBSPECTRUM_ERROR_UNKNOWN; } libspectrum_write_dword( ptr, snap_length ); /* Snapshot length */ if( compress ) { memcpy( *ptr, gzsnap, gzlength ); (*ptr) += gzlength; libspectrum_free( gzsnap ); } else { memcpy( *ptr, snap_buffer, snap_length ); (*ptr) += snap_length; } libspectrum_free( snap_buffer ); return LIBSPECTRUM_ERROR_NONE; }
libspectrum_error fuse_libspectrum_snap_write( libspectrum_byte **buffer, size_t *length, int *out_flags, libspectrum_snap *snap, libspectrum_id_t type, libspectrum_creator *creator, int in_flags ) { return libspectrum_snap_write( buffer, length, out_flags, snap, type, creator, in_flags | LIBSPECTRUM_FLAG_SNAPSHOT_NO_COMPRESSION ); }
int main( int argc, char **argv ) { libspectrum_snap *snap; libspectrum_id_t type; libspectrum_class_t class; unsigned char *buffer; size_t length; libspectrum_creator *creator; int flags; int compress = 0; int fix = 0; FILE *f; int error = 0; int c; struct option long_options[] = { { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'V' }, { 0, 0, 0, 0 } }; progname = argv[0]; while( ( c = getopt_long( argc, argv, "cnfhV", long_options, NULL ) ) != -1 ) { switch( c ) { case 'c': compress = LIBSPECTRUM_FLAG_SNAPSHOT_ALWAYS_COMPRESS; break; case 'n': compress = LIBSPECTRUM_FLAG_SNAPSHOT_NO_COMPRESSION; break; case 'f': fix = 1; break; case 'h': show_help(); return 0; case 'V': show_version(); return 0; case '?': /* getopt prints an error message to stderr */ error = 1; break; default: error = 1; fprintf( stderr, "%s: unknown option `%c'\n", progname, (char) c ); break; } } argc -= optind; argv += optind; if( error ) { fprintf( stderr, "Try `%s --help' for more information.\n", progname ); return error; } if( argc < 2 ) { fprintf( stderr, "%s: usage: %s [-c] [-n] [-f] <infile> <outfile>\n", progname, progname ); fprintf( stderr, "Try `%s --help' for more information.\n", progname ); return 1; } error = init_libspectrum(); if( error ) return error; snap = libspectrum_snap_alloc(); if( read_file( argv[0], &buffer, &length ) ) { libspectrum_snap_free( snap ); return 1; } error = libspectrum_snap_read( snap, buffer, length, LIBSPECTRUM_ID_UNKNOWN, argv[0] ); if( error ) { libspectrum_snap_free( snap ); free( buffer ); return error; } free( buffer ); if( fix ) fix_snapshot( snap ); error = libspectrum_identify_file_with_class( &type, &class, argv[1], NULL, 0 ); if( error ) { libspectrum_snap_free( snap ); return error; } if( class != LIBSPECTRUM_CLASS_SNAPSHOT ) { fprintf( stderr, "%s: '%s' is not a snapshot file\n", progname, argv[1] ); libspectrum_snap_free( snap ); return 1; } error = get_creator( &creator, "snapconv" ); if( error ) { libspectrum_snap_free( snap ); return error; } length = 0; error = libspectrum_snap_write( &buffer, &length, &flags, snap, type, creator, compress ); if( error ) { libspectrum_creator_free( creator ); libspectrum_snap_free( snap ); return error; } if( flags & LIBSPECTRUM_FLAG_SNAPSHOT_MAJOR_INFO_LOSS ) { fprintf( stderr, "%s: warning: major information loss during conversion\n", progname ); } else if( flags & LIBSPECTRUM_FLAG_SNAPSHOT_MINOR_INFO_LOSS ) { fprintf( stderr, "%s: warning: minor information loss during conversion\n", progname ); } error = libspectrum_creator_free( creator ); if( error ) { free( buffer ); libspectrum_snap_free( snap ); return error; } error = libspectrum_snap_free( snap ); if( error ) { free( buffer ); return error; } f = fopen( argv[1], "wb" ); if( !f ) { fprintf( stderr, "%s: couldn't open '%s': %s\n", progname, argv[1], strerror( errno ) ); free( buffer ); return 1; } if( fwrite( buffer, 1, length, f ) != length ) { fprintf( stderr, "%s: error writing to '%s'\n", progname, argv[1] ); free( buffer ); fclose( f ); return 1; } free( buffer ); fclose( f ); return 0; }