Ejemplo n.º 1
0
static void
rzx_write_header( libspectrum_byte **buffer, libspectrum_byte **ptr,
		  size_t *length, ptrdiff_t *sign_offset, int sign )
{
  size_t signature_length = strlen( rzx_signature );

  libspectrum_make_room( buffer, strlen( rzx_signature ) + 6, ptr, length );
  memcpy( *ptr, rzx_signature, signature_length ); *ptr += signature_length;

  *(*ptr)++ = 0;		/* Major version number */

  /* Flags */
#ifdef HAVE_GCRYPT_H
  *(*ptr)++ = sign ? 13 : 12;	/* Minor version number: 12 if we're not
				   signing, 13 if we are */
  libspectrum_write_dword( ptr, sign ? 0x01 : 0x00 );

  /* Store where to start signing data from */
  *sign_offset = *ptr - *buffer;

#else				/* #ifdef HAVE_GCRYPT_H */
  *(*ptr)++ = 12;		/* Minor version number */
  libspectrum_write_dword( ptr, 0 );
#endif				/* #ifdef HAVE_GCRYPT_H */
}
Ejemplo n.º 2
0
static libspectrum_error
rzx_write_signed_end( libspectrum_byte **buffer, libspectrum_byte **ptr,
		      size_t *length, ptrdiff_t sign_offset,
		      libspectrum_rzx_dsa_key *key )
{
#ifdef HAVE_GCRYPT_H
  libspectrum_error error;
  libspectrum_byte *signature; size_t sig_length;

  /* Get the actual signature */
  error = libspectrum_sign_data( &signature, &sig_length,
				 ( *buffer + sign_offset ),
				 (*ptr) - ( *buffer + sign_offset ), key );
  if( error ) return error;

  libspectrum_make_room( buffer, sig_length + 5, ptr, length );

  /* Block ID */
  *(*ptr)++ = LIBSPECTRUM_RZX_SIGN_END_BLOCK;

  /* Block length */
  libspectrum_write_dword( ptr, sig_length + 5 );

  /* Write the signature */
  memcpy( *ptr, signature, sig_length ); (*ptr) += sig_length;

  libspectrum_free( signature );

#endif				/* #ifdef HAVE_GCRYPT_H */

  return LIBSPECTRUM_ERROR_NONE;
}
Ejemplo n.º 3
0
static libspectrum_error
serialise_generalised_data_table( libspectrum_byte **ptr, libspectrum_tape_generalised_data_symbol_table *table )
{
  libspectrum_dword symbols_in_block;
  libspectrum_word symbols_in_table;

  symbols_in_block = libspectrum_tape_generalised_data_symbol_table_symbols_in_block( table );

  if( !symbols_in_block ) return LIBSPECTRUM_ERROR_NONE;

  libspectrum_write_dword( ptr, symbols_in_block );
  *(*ptr)++ = libspectrum_tape_generalised_data_symbol_table_max_pulses( table );

  symbols_in_table = libspectrum_tape_generalised_data_symbol_table_symbols_in_table( table );

  if( symbols_in_table == 0 || symbols_in_table > 256 ) {
    libspectrum_print_error( LIBSPECTRUM_ERROR_INVALID, "%s: invalid number of symbols in table: %d", __func__, symbols_in_table );
    return LIBSPECTRUM_ERROR_INVALID;
  } else if( symbols_in_table == 256 ) {
    symbols_in_table = 0;
  }

  *(*ptr)++ = symbols_in_table;

  return LIBSPECTRUM_ERROR_NONE;
}
Ejemplo n.º 4
0
libspectrum_error
libspectrum_csw_write( libspectrum_byte **buffer, size_t *length,
                       libspectrum_tape *tape )
{
    libspectrum_error error;
    libspectrum_dword sample_rate;
    size_t length_offset;

    libspectrum_byte *ptr = *buffer;

    size_t signature_length = strlen( csw_signature );

    /* First, write the .csw signature and the rest of the header */
    libspectrum_make_room( buffer, signature_length + 29, &ptr, length );

    memcpy( ptr, csw_signature, signature_length );
    ptr += signature_length;

    *ptr++ = 2;		/* Major version number */
    *ptr++ = 0;		/* Minor version number */

    /* sample rate */
    sample_rate = find_sample_rate( tape );
    libspectrum_write_dword( &ptr, sample_rate );

    /* Store where the total number of pulses (after decompression) will
       be written, and skip over those bytes */
    length_offset = ptr - *buffer;
    ptr += sizeof(libspectrum_dword);

    /* compression type */
#ifdef HAVE_ZLIB_H
    *ptr++ = 2;		/* Z-RLE */
#else
    *ptr++ = 1;		/* RLE */
#endif

    /* flags */
    *ptr++ = 0;		/* No flags */

    /* header extension length in bytes */
    *ptr++ = 0;		/* No header extension */

    /* encoding application description */
    memset( ptr, 0, 16 );
    ptr += 16; /* No creator for now */

    /* header extension data is zero so on to the data */

    error = csw_write_body( buffer, length, tape, sample_rate, length_offset, ptr );
    if( error != LIBSPECTRUM_ERROR_NONE ) return error;

    return LIBSPECTRUM_ERROR_NONE;
}
Ejemplo n.º 5
0
static libspectrum_error
rzx_write_signed_start( libspectrum_byte **buffer, libspectrum_byte **ptr,
			size_t *length, libspectrum_rzx_dsa_key *key,
			libspectrum_creator *creator )
{
#ifdef HAVE_GCRYPT_H
  
  libspectrum_make_room( buffer, 13, ptr, length );

  /* Block ID */
  *(*ptr)++ = LIBSPECTRUM_RZX_SIGN_START_BLOCK;

  /* Block length */
  libspectrum_write_dword( ptr, 13 );

  /* Key ID */
  if( !key || !key->y || strlen( key->y ) < 8 ) {
    libspectrum_print_error( LIBSPECTRUM_ERROR_INVALID,
			     "rzx_write_signed_start: invalid key" );
    return LIBSPECTRUM_ERROR_INVALID;
  }

  libspectrum_write_dword(
    ptr, strtoul( &key->y[ strlen( key->y ) - 8 ], NULL, 16 )
  );

  /* Week code */
  if( creator ) {
    libspectrum_write_dword( ptr,
			     libspectrum_creator_competition_code( creator ) );
  } else {
    libspectrum_write_dword( ptr, 0 );
  }

#endif				/* #ifdef HAVE_GCRYPT_H */

  return LIBSPECTRUM_ERROR_NONE;
}
Ejemplo n.º 6
0
static libspectrum_error
tzx_write_generalised_data( libspectrum_tape_block *block,
			    libspectrum_byte **buffer, libspectrum_byte **ptr,
			    size_t *length )
{
  size_t data_length, bits_per_symbol;
  libspectrum_error error;
  libspectrum_tape_generalised_data_symbol_table *pilot_table, *data_table;
  libspectrum_dword pilot_symbol_count, data_symbol_count, i;

  data_length = generalised_data_length( block );

  libspectrum_make_room( buffer, 5 + data_length, ptr, length );

  *(*ptr)++ = LIBSPECTRUM_TAPE_BLOCK_GENERALISED_DATA;
  libspectrum_write_dword( ptr, data_length );

  libspectrum_write_word( ptr, libspectrum_tape_block_pause( block ) );

  pilot_table = libspectrum_tape_block_pilot_table( block );
  data_table = libspectrum_tape_block_data_table( block );

  error = serialise_generalised_data_table( ptr, pilot_table );
  if( error != LIBSPECTRUM_ERROR_NONE ) return error;

  error = serialise_generalised_data_table( ptr, data_table );
  if( error != LIBSPECTRUM_ERROR_NONE ) return error;

  serialise_generalised_data_symbols( ptr, pilot_table );

  pilot_symbol_count = libspectrum_tape_generalised_data_symbol_table_symbols_in_block( pilot_table );

  for( i = 0; i < pilot_symbol_count; i++ ) {
    *(*ptr)++ = libspectrum_tape_block_pilot_symbols( block, i );
    libspectrum_write_word( ptr, libspectrum_tape_block_pilot_repeats( block, i ) );
  }

  serialise_generalised_data_symbols( ptr, data_table );

  bits_per_symbol = libspectrum_tape_block_bits_per_data_symbol( block );
  data_symbol_count = libspectrum_tape_generalised_data_symbol_table_symbols_in_block( data_table );

  data_length = ( ( bits_per_symbol * data_symbol_count ) + 7 ) / 8;

  memcpy( *ptr, libspectrum_tape_block_data( block ), data_length );
  (*ptr) += data_length;

  return LIBSPECTRUM_ERROR_NONE;
}
Ejemplo n.º 7
0
static void
rzx_write_creator( libspectrum_byte **buffer, libspectrum_byte **ptr,
		   size_t *length, libspectrum_creator *creator )
{
  size_t custom_length, block_length;

  custom_length = libspectrum_creator_custom_length( creator );
  block_length = 29 + custom_length;

  libspectrum_make_room( buffer, block_length, ptr, length );

  *(*ptr)++ = LIBSPECTRUM_RZX_CREATOR_BLOCK;
  libspectrum_write_dword( ptr, block_length );	/* Block length */

  memcpy( *ptr, libspectrum_creator_program( creator ), 20 ); (*ptr) += 20;

  libspectrum_write_word( ptr, libspectrum_creator_major( creator ) );
  libspectrum_write_word( ptr, libspectrum_creator_minor( creator ) );

  if( custom_length ) {
    memcpy( *ptr, libspectrum_creator_custom( creator ), custom_length );
    (*ptr) += custom_length;
  }
}
Ejemplo n.º 8
0
static libspectrum_error
rzx_write_input( input_block_t *block, libspectrum_byte **buffer,
		 libspectrum_byte **ptr, size_t *length, int compress )
{
  libspectrum_error error;
  size_t i, size;
  size_t length_offset, data_offset, flags_offset;
  libspectrum_byte *length_ptr; 

  libspectrum_make_room( buffer, 18, ptr, length );

  *(*ptr)++ = LIBSPECTRUM_RZX_INPUT_BLOCK;

  /* The length bytes: for uncompressed data, 18 for the block introduction
     and 4 per frame; the number of bytes in every frame is added in below.
     If compression is requested (and makes the data shorter), this will be
     overwritten with the compressed length */
  size = 18 + 4 * block->count;

  /* Store where the length will be written, and skip over those bytes */
  length_offset = *ptr - *buffer; (*ptr) += 4;

  /* How many frames? */
  libspectrum_write_dword( ptr, block->count );

  /* Each frame has an undefined length, so write a zero */
  *(*ptr)++ = 0;

  /* T-state counter */
  libspectrum_write_dword( ptr, block->tstates );

  /* Flags */
  flags_offset = *ptr - *buffer;
  libspectrum_write_dword( ptr, compress ? 0x02 : 0 );

  /* Write the frames */
  data_offset = *ptr - *buffer;
  for( i = 0; i < block->count; i++ ) {

    libspectrum_rzx_frame_t *frame = &block->frames[i];

    libspectrum_make_room( buffer, 4, ptr, length );
    libspectrum_write_word( ptr, frame->instructions );

    if( frame->repeat_last ) {
      libspectrum_write_word( ptr, libspectrum_rzx_repeat_frame );
    } else {

      size += frame->count;			/* Keep track of the size */

      libspectrum_write_word( ptr, frame->count );

      libspectrum_make_room( buffer, frame->count, ptr, length );
      memcpy( *ptr, frame->in_bytes, frame->count ); (*ptr) += frame->count;
    }
  }

  /* Write the length in */
  length_ptr = *buffer + length_offset;
  libspectrum_write_dword( &length_ptr, size ); length_ptr -= 4;

  if( compress ) {

#ifdef HAVE_ZLIB_H

    /* Compress the data the simple way. Really, we should stream the data */
    libspectrum_byte *gzsnap = NULL; size_t gzlength;
    libspectrum_byte *data_ptr = *buffer + data_offset;

    error = libspectrum_zlib_compress( data_ptr, *ptr - data_ptr,
				       &gzsnap, &gzlength );
    if( error != LIBSPECTRUM_ERROR_NONE ) return error;

    if( (ptrdiff_t)gzlength >= *ptr - data_ptr ) { /* Compression made it
						      bigger :-( */
      *(*buffer + flags_offset) &= ~0x02; /* Clear `compressed' bit */
    } else {
      /* Write the compressed data in */
      memcpy( data_ptr, gzsnap, gzlength );

      /* Correct the length word and the buffer length */
      libspectrum_write_dword( &length_ptr, 18 + gzlength );
      *ptr = *buffer + data_offset + gzlength;
    }

    libspectrum_free( gzsnap );

#else				/* #ifdef HAVE_ZLIB_H */

    libspectrum_print_error( LIBSPECTRUM_ERROR_UNKNOWN,
			     "rzx_write_input: compression needs zlib" );
    return LIBSPECTRUM_ERROR_UNKNOWN;

#endif				/* #ifdef HAVE_ZLIB_H */

  }

  return LIBSPECTRUM_ERROR_NONE;
}
Ejemplo n.º 9
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;
}
Ejemplo n.º 10
0
static libspectrum_error
csw_write_body( libspectrum_byte **buffer, size_t *length,
                libspectrum_tape *tape, libspectrum_dword sample_rate,
                size_t length_offset, libspectrum_byte *ptr )
{
    libspectrum_error error;
    int flags = 0;
    libspectrum_dword pulse_tstates = 0;
    libspectrum_dword balance_tstates = 0;
    libspectrum_byte *data = NULL;
    size_t data_size;
    size_t data_length = 0;
    libspectrum_byte *data_ptr = data;
    long scale = 3500000/sample_rate;
    libspectrum_tape_block_state it;
    libspectrum_byte *length_ptr;

    libspectrum_make_room( &data, 8192, &data_ptr, &data_size );

    if( libspectrum_tape_block_internal_init( &it, tape ) ) {
        while( !(flags & LIBSPECTRUM_TAPE_FLAGS_STOP) ) {
            libspectrum_dword pulse_length = 0;

            /* Use internal version of this that doesn't bugger up the
               external tape status */
            error = libspectrum_tape_get_next_edge_internal( &pulse_tstates, &flags,
                    tape, &it );
            if( error != LIBSPECTRUM_ERROR_NONE ) return error;

            balance_tstates += pulse_tstates;

            if( flags & LIBSPECTRUM_TAPE_FLAGS_NO_EDGE ) continue;

            /* next RLE value is: balance_tstates / scale; */
            pulse_length = balance_tstates / scale;
            balance_tstates = balance_tstates % scale;

            if( pulse_length ) {
                if( data_size < (data_length + 1 + sizeof(libspectrum_dword) ) )
                    libspectrum_make_room( &data, data_size*2, &data_ptr, &data_size );

                if( pulse_length <= 0xff ) {
                    *data_ptr++ = pulse_length;
                    data_length++;
                } else {
                    *data_ptr++ = 0;
                    data_length++;
                    libspectrum_write_dword( &data_ptr, pulse_length );
                    data_length+=sizeof(libspectrum_dword);
                }
            }
        }
    }

    /* Write the length in */
    length_ptr = *buffer + length_offset;
    libspectrum_write_dword( &length_ptr, data_length );

    /* compression type */
#ifdef HAVE_ZLIB_H
    if( data_length ) {
        libspectrum_byte *compressed_data = NULL;
        size_t compressed_length;

        error = libspectrum_zlib_compress( data, data_length,
                                           &compressed_data, &compressed_length );
        libspectrum_free( data );
        if( error ) return error;

        data = compressed_data;
        data_length = compressed_length;
    }
#endif

    if( data_length ) {
        libspectrum_make_room( buffer, data_length, &ptr, length );
        memcpy( ptr, data, data_length );
        ptr += data_length;
        libspectrum_free( data );
    }

    return LIBSPECTRUM_ERROR_NONE;
}