Exemplo n.º 1
0
static libspectrum_error
write_128k_sna( libspectrum_byte **buffer, libspectrum_byte **ptr,
		size_t *length, libspectrum_snap *snap )
{
  size_t i, page; libspectrum_error error;
  
  page = libspectrum_snap_out_128_memoryport( snap ) & 0x07;

  libspectrum_make_room( buffer, 0xc000 + LIBSPECTRUM_SNA_128_HEADER_LENGTH,
			 ptr, length );

  error = write_page( *ptr, snap, 5 ); (*ptr) += 0x4000;
  if( error ) return error;
  error = write_page( *ptr, snap, 2 ); (*ptr) += 0x4000;
  if( error ) return error;
  error = write_page( *ptr, snap, page ); (*ptr) += 0x4000;
  if( error ) return error;

  libspectrum_write_word( ptr, libspectrum_snap_pc( snap ) );
  *(*ptr)++ = libspectrum_snap_out_128_memoryport( snap );
  *(*ptr)++ = '\0';

  for( i = 0; i < 8; i++ ) {

    /* Already written pages 5, 2 and whatever's paged in */
    if( i == 5 || i == 2 || i == page ) continue;

    libspectrum_make_room( buffer, 0x4000, ptr, length );

    error = write_page( *ptr, snap, i ); (*ptr) += 0x4000;
    if( error ) return error;
  }

  return LIBSPECTRUM_ERROR_NONE;
}
Exemplo n.º 2
0
static void
tzx_write_archive_info( libspectrum_tape_block *block,
			libspectrum_byte **buffer, libspectrum_byte **ptr,
			size_t *length )
{
  size_t i, count, total_length;

  count = libspectrum_tape_block_count( block );

  /* 1 count byte, 2 bytes (ID and length) for every string */
  total_length = 1 + 2 * count;
  /* And then the length of all the strings */
  for( i = 0; i < count; i++ )
    total_length += strlen( (char*)libspectrum_tape_block_texts( block, i ) );

  /* Make room for all that, along with ID byte and two bytes storing the
     total length */
  libspectrum_make_room( buffer, total_length + 3, ptr, length );

  /* Write out the metadata */
  *(*ptr)++ = LIBSPECTRUM_TAPE_BLOCK_ARCHIVE_INFO;
  libspectrum_write_word( ptr, total_length );
  *(*ptr)++ = count;

  /* And the strings */
  for( i = 0; i < count; i++ ) {
    *(*ptr)++ = libspectrum_tape_block_ids( block, i );
    tzx_write_string( ptr, libspectrum_tape_block_texts( block, i ) );
  }
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
0
static void
tzx_write_select( libspectrum_tape_block *block, libspectrum_byte **buffer,
		  libspectrum_byte **ptr, size_t *length )
{
  size_t count, total_length, i;

  /* The id byte, the total length (2 bytes), the count byte,
     and ( 2 offset bytes and 1 length byte ) per selection */
  count = libspectrum_tape_block_count( block );
  total_length = 4 + 3 * count;

  for( i = 0; i < count; i++ )
    total_length += strlen( (char*)libspectrum_tape_block_texts( block, i ) );

  libspectrum_make_room( buffer, total_length, ptr, length );

  *(*ptr)++ = LIBSPECTRUM_TAPE_BLOCK_SELECT;
  libspectrum_write_word( ptr, total_length );
  *(*ptr)++ = count;

  for( i = 0; i < count; i++ ) {
    libspectrum_write_word( ptr, libspectrum_tape_block_offsets( block, i ) );
    tzx_write_string( ptr, libspectrum_tape_block_texts( block, i ) );
  }
}
Exemplo n.º 5
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 */
}
Exemplo n.º 6
0
static void
write_header( libspectrum_byte **buffer, libspectrum_byte **ptr,
	      size_t *length, libspectrum_snap *snap )
{
  libspectrum_make_room( buffer, LIBSPECTRUM_SNA_HEADER_LENGTH, ptr, length );

  *(*ptr)++ = libspectrum_snap_i ( snap );
  libspectrum_write_word( ptr, libspectrum_snap_hl_( snap ) );
  libspectrum_write_word( ptr, libspectrum_snap_de_( snap ) );
  libspectrum_write_word( ptr, libspectrum_snap_bc_( snap ) );
  *(*ptr)++ = libspectrum_snap_f_( snap );
  *(*ptr)++ = libspectrum_snap_a_( snap );
  libspectrum_write_word( ptr, libspectrum_snap_hl ( snap ) );
  libspectrum_write_word( ptr, libspectrum_snap_de ( snap ) );
  libspectrum_write_word( ptr, libspectrum_snap_bc ( snap ) );
  libspectrum_write_word( ptr, libspectrum_snap_iy ( snap ) );
  libspectrum_write_word( ptr, libspectrum_snap_ix ( snap ) );

  *(*ptr)++ = libspectrum_snap_iff2( snap ) ? 0x04 : 0x00;

  *(*ptr)++ = libspectrum_snap_r ( snap );
  *(*ptr)++ = libspectrum_snap_f ( snap );
  *(*ptr)++ = libspectrum_snap_a ( snap );

  libspectrum_write_word( ptr, libspectrum_snap_sp ( snap ) );

  *(*ptr)++ = libspectrum_snap_im( snap );
  *(*ptr)++ = libspectrum_snap_out_ula( snap ) & 0x07;
}
Exemplo n.º 7
0
static void
tzx_write_pause( libspectrum_tape_block *block, libspectrum_byte **buffer,
		 libspectrum_byte **ptr, size_t *length )
{
  libspectrum_make_room( buffer, 3, ptr, length );
  *(*ptr)++ = LIBSPECTRUM_TAPE_BLOCK_PAUSE;
  libspectrum_write_word( ptr, libspectrum_tape_block_pause( block ) );
}
Exemplo n.º 8
0
static void
tzx_write_loop_start( libspectrum_tape_block *block, libspectrum_byte **buffer,
		      libspectrum_byte **ptr, size_t *length )
{
  libspectrum_make_room( buffer, 3, ptr, length );
  *(*ptr)++ = LIBSPECTRUM_TAPE_BLOCK_LOOP_START;
  libspectrum_write_word( ptr, libspectrum_tape_block_count( block ) );
}
Exemplo n.º 9
0
static void
tzx_write_empty_block( libspectrum_byte **buffer, libspectrum_byte **ptr,
		       size_t *length, libspectrum_tape_type id )
{
  /* Make room for the ID byte */
  libspectrum_make_room( buffer, 1, ptr, length );

  *(*ptr)++ = id;
}
Exemplo n.º 10
0
static void
tzx_write_stop( libspectrum_byte **buffer, libspectrum_byte **ptr,
		size_t *length )
{
  /* Make room for the ID byte and four length bytes */
  libspectrum_make_room( buffer, 5, ptr, length );

  *(*ptr)++ = LIBSPECTRUM_TAPE_BLOCK_STOP48;
  *(*ptr)++ = '\0'; *(*ptr)++ = '\0'; *(*ptr)++ = '\0'; *(*ptr)++ = '\0';
}
Exemplo n.º 11
0
static void
tzx_write_pure_tone( libspectrum_tape_block *block, libspectrum_byte **buffer,
		     libspectrum_byte **ptr, size_t *length )
{
  /* Make room for the ID byte and the data */
  libspectrum_make_room( buffer, 5, ptr, length );

  *(*ptr)++ = LIBSPECTRUM_TAPE_BLOCK_PURE_TONE;
  libspectrum_write_word( ptr, libspectrum_tape_block_pulse_length( block ) );
  libspectrum_write_word( ptr, libspectrum_tape_block_count( block ) );
}
Exemplo n.º 12
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;
}
Exemplo n.º 13
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;
}
Exemplo n.º 14
0
static void
tzx_write_rom( libspectrum_tape_block *block, libspectrum_byte **buffer,
	       libspectrum_byte **ptr, size_t *length )
{
  /* Make room for the ID byte, the pause, the length and the actual data */
  libspectrum_make_room( buffer, 5 + libspectrum_tape_block_data_length( block ), ptr, length);

  /* Write the ID byte and the pause */
  *(*ptr)++ = LIBSPECTRUM_TAPE_BLOCK_ROM;
  libspectrum_write_word( ptr, libspectrum_tape_block_pause( block ) );

  /* Copy the data across */
  tzx_write_bytes( ptr, libspectrum_tape_block_data_length( block ), 2,
                   libspectrum_tape_block_data( block ) );
}
Exemplo n.º 15
0
static void
tzx_write_jump( libspectrum_tape_block *block, libspectrum_byte **buffer,
		libspectrum_byte **ptr, size_t *length )
{
  int u_offset;

  /* Make room for the ID byte and the offset */
  libspectrum_make_room( buffer, 3, ptr, length );

  *(*ptr)++ = LIBSPECTRUM_TAPE_BLOCK_JUMP;

  u_offset = libspectrum_tape_block_offset( block );
  if( u_offset < 0 ) u_offset += 65536;
  libspectrum_write_word( ptr, u_offset );
}
Exemplo n.º 16
0
static void
tzx_write_comment( libspectrum_tape_block *block, libspectrum_byte **buffer,
		   libspectrum_byte **ptr, size_t *length )
{
  char *comment; size_t comment_length;

  comment = libspectrum_tape_block_text( block );
  comment_length = strlen( (char*)comment );

  /* Make room for the ID byte, the length byte and the text */
  libspectrum_make_room( buffer, 2 + comment_length, ptr, length );

  *(*ptr)++ = LIBSPECTRUM_TAPE_BLOCK_COMMENT;

  tzx_write_string( ptr, comment );
}
Exemplo n.º 17
0
static void
tzx_write_message( libspectrum_tape_block *block, libspectrum_byte **buffer,
		   libspectrum_byte **ptr, size_t *length )
{
  char *message; size_t text_length;

  message = libspectrum_tape_block_text( block );
  text_length = strlen( (char*)message );

  /* Make room for the ID byte, the time byte, length byte and the text */
  libspectrum_make_room( buffer, 3 + text_length, ptr, length );

  *(*ptr)++ = LIBSPECTRUM_TAPE_BLOCK_MESSAGE;
  *(*ptr)++ = libspectrum_tape_block_pause( block );

  tzx_write_string( ptr, message );
}
Exemplo n.º 18
0
static void
tzx_write_group_start( libspectrum_tape_block *block,
		       libspectrum_byte **buffer, libspectrum_byte **ptr,
		       size_t *length )
{
  char *name; size_t name_length;

  name = libspectrum_tape_block_text( block );
  name_length = strlen( (char*)name );

  /* Make room for the ID byte, the length byte and the name */
  libspectrum_make_room( buffer, 2 + name_length, ptr, length );

  *(*ptr)++ = LIBSPECTRUM_TAPE_BLOCK_GROUP_START;
  
  tzx_write_string( ptr, name );
}
Exemplo n.º 19
0
static void
tzx_write_raw_data( libspectrum_tape_block *block, libspectrum_byte **buffer,
		libspectrum_byte **ptr, size_t *length )
{
  size_t data_length;

  /* Make room for the ID byte, the metadata and the actual data */
  data_length = libspectrum_tape_block_data_length( block );
  libspectrum_make_room( buffer, 8 + data_length, ptr, length );

  /* Write the ID byte and the metadata */
  *(*ptr)++ = LIBSPECTRUM_TAPE_BLOCK_RAW_DATA;
  libspectrum_write_word( ptr, libspectrum_tape_block_bit_length( block ) );
  libspectrum_write_word( ptr, libspectrum_tape_block_pause( block ) );
  *(*ptr)++ = libspectrum_tape_block_bits_in_last_byte( block );

  tzx_write_bytes( ptr, data_length, 3, libspectrum_tape_block_data( block ) );
}
Exemplo n.º 20
0
static void
tzx_write_custom( libspectrum_tape_block *block, libspectrum_byte **buffer,
		  libspectrum_byte **ptr, size_t *length )
{
  size_t data_length;

  data_length = libspectrum_tape_block_data_length( block );

  /* An ID byte, 16 description bytes, 4 length bytes and the data
     itself */
  libspectrum_make_room( buffer, 1 + 16 + 4 + data_length, ptr, length );

  *(*ptr)++ = LIBSPECTRUM_TAPE_BLOCK_CUSTOM;
  memcpy( *ptr, libspectrum_tape_block_text( block ), 16 ); *ptr += 16;

  tzx_write_bytes( ptr, data_length, 4,
		   libspectrum_tape_block_data( block ) );
}
Exemplo n.º 21
0
static void
tzx_write_pulses( libspectrum_tape_block *block, libspectrum_byte **buffer,
		  libspectrum_byte **ptr, size_t *length )
{
  size_t i, count, block_length;

  /* ID byte, count and 2 bytes for length of each pulse */
  count = libspectrum_tape_block_count( block );
  block_length = 2 + 2 * count;

  /* Make room for the ID byte, the count and the data */
  libspectrum_make_room( buffer, block_length, ptr, length );

  *(*ptr)++ = LIBSPECTRUM_TAPE_BLOCK_PULSES;
  *(*ptr)++ = count;
  for( i = 0; i < count; i++ )
    libspectrum_write_word( ptr,
			    libspectrum_tape_block_pulse_lengths( block, i ) );
}
Exemplo n.º 22
0
static void
tzx_write_turbo( libspectrum_tape_block *block, libspectrum_byte **buffer,
		 libspectrum_byte **ptr, size_t *length )
{
  /* Make room for the ID byte, the metadata and the actual data */
  libspectrum_make_room( buffer, 19 + libspectrum_tape_block_data_length( block ), ptr, length);

  /* Write the ID byte and the metadata */
  *(*ptr)++ = LIBSPECTRUM_TAPE_BLOCK_TURBO;
  libspectrum_write_word( ptr, libspectrum_tape_block_pilot_length( block ) );
  libspectrum_write_word( ptr, libspectrum_tape_block_sync1_length( block ) );
  libspectrum_write_word( ptr, libspectrum_tape_block_sync2_length( block ) );
  libspectrum_write_word( ptr, libspectrum_tape_block_bit0_length ( block ) );
  libspectrum_write_word( ptr, libspectrum_tape_block_bit1_length ( block ) );
  libspectrum_write_word( ptr, libspectrum_tape_block_pilot_pulses( block ) );
  *(*ptr)++ = libspectrum_tape_block_bits_in_last_byte( block );
  libspectrum_write_word( ptr, libspectrum_tape_block_pause       ( block ) );

  tzx_write_bytes( ptr, libspectrum_tape_block_data_length( block ), 3,
                   libspectrum_tape_block_data( block ) );
}
Exemplo n.º 23
0
static void
tzx_write_hardware( libspectrum_tape_block *block, libspectrum_byte **buffer,
		    libspectrum_byte **ptr, size_t *length )
{
  size_t i, count;

  /* We need one ID byte, one count byte and then three bytes for every
     entry */
  count = libspectrum_tape_block_count( block );
  libspectrum_make_room( buffer, 2 + 3 * count, ptr, length );

  /* Write out the metadata */
  *(*ptr)++ = LIBSPECTRUM_TAPE_BLOCK_HARDWARE;
  *(*ptr)++ = count;

  /* And the info */
  for( i = 0; i < count; i++ ) {
    *(*ptr)++ = libspectrum_tape_block_types( block, i );
    *(*ptr)++ = libspectrum_tape_block_ids  ( block, i );
    *(*ptr)++ = libspectrum_tape_block_values( block, i );
  }
}
Exemplo n.º 24
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;
}
Exemplo n.º 25
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;
  }
}
Exemplo n.º 26
0
static libspectrum_error
write_48k_sna( libspectrum_byte **buffer, libspectrum_byte **ptr,
	       size_t *length, libspectrum_snap *snap )
{
  libspectrum_error error;
  libspectrum_byte *stack, *sp;

  /* Must have somewhere in RAM to store PC */
  if( libspectrum_snap_sp( snap ) < 0x4002 ) {
    libspectrum_print_error( LIBSPECTRUM_ERROR_INVALID,
			     "SP is too low (0x%04x) to stack PC",
			     libspectrum_snap_sp( snap ) );
    return LIBSPECTRUM_ERROR_INVALID;
  }

  libspectrum_make_room( buffer, 0xc000, ptr, length );

  error = write_page( &( (*ptr)[ 0x0000 ] ), snap, 5 );
  if( error ) return error;
  error = write_page( &( (*ptr)[ 0x4000 ] ), snap, 2 );
  if( error ) return error;
  error = write_page( &( (*ptr)[ 0x8000 ] ), snap, 0 );
  if( error ) return error;

  /* Place PC on the stack */
  stack = &( (*ptr)[ libspectrum_snap_sp( snap ) - 0x4000 - 2 ] );
  libspectrum_write_word( &stack, libspectrum_snap_pc( snap ) );

  *ptr += 0xc000;

  /* Store the new value of SP */
  sp = *buffer + SNA_OFFSET_SP;
  libspectrum_write_word( &sp, libspectrum_snap_sp( snap ) - 2 );

  return LIBSPECTRUM_ERROR_NONE;
}
Exemplo n.º 27
0
libspectrum_error
internal_tzx_write( libspectrum_byte **buffer, size_t *length,
		    libspectrum_tape *tape )
{
  libspectrum_error error;
  libspectrum_tape_iterator iterator;
  libspectrum_tape_block *block;
  libspectrum_byte *ptr = *buffer;

  size_t signature_length = strlen( libspectrum_tzx_signature );

  /* First, write the .tzx signature and the version numbers */
  libspectrum_make_room( buffer, signature_length + 2, &ptr, length );

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

  *ptr++ = 1;		/* Major version number */
  *ptr++ = 20;		/* Minor version number */

  for( block = libspectrum_tape_iterator_init( &iterator, tape );
       block;
       block = libspectrum_tape_iterator_next( &iterator )       )
  {
    switch( libspectrum_tape_block_type( block ) ) {

    case LIBSPECTRUM_TAPE_BLOCK_ROM:
      tzx_write_rom( block, buffer, &ptr, length );
      break;

    case LIBSPECTRUM_TAPE_BLOCK_TURBO:
      tzx_write_turbo( block, buffer, &ptr, length );
      break;

    case LIBSPECTRUM_TAPE_BLOCK_PURE_TONE:
      tzx_write_pure_tone( block, buffer, &ptr, length );
      break;
    case LIBSPECTRUM_TAPE_BLOCK_PULSES:
      tzx_write_pulses( block, buffer, &ptr, length );
      break;
    case LIBSPECTRUM_TAPE_BLOCK_PURE_DATA:
      tzx_write_data( block, buffer, &ptr, length );
      break;

    case LIBSPECTRUM_TAPE_BLOCK_RAW_DATA:
      tzx_write_raw_data( block, buffer, &ptr, length );
      break;

    case LIBSPECTRUM_TAPE_BLOCK_GENERALISED_DATA:
      error = tzx_write_generalised_data( block, buffer, &ptr, length );
      if( error != LIBSPECTRUM_ERROR_NONE ) { libspectrum_free( *buffer ); return error; }
      break;

    case LIBSPECTRUM_TAPE_BLOCK_PAUSE:
      tzx_write_pause( block, buffer, &ptr, length );
      break;
    case LIBSPECTRUM_TAPE_BLOCK_GROUP_START:
      tzx_write_group_start( block, buffer, &ptr, length );
      break;

    case LIBSPECTRUM_TAPE_BLOCK_GROUP_END:
      tzx_write_empty_block( buffer, &ptr, length, libspectrum_tape_block_type( block ) );
      break;
    case LIBSPECTRUM_TAPE_BLOCK_JUMP:
      tzx_write_jump( block, buffer, &ptr, length );
      break;
    case LIBSPECTRUM_TAPE_BLOCK_LOOP_START:
      tzx_write_loop_start( block, buffer, &ptr, length );
      break;
    case LIBSPECTRUM_TAPE_BLOCK_LOOP_END:
      tzx_write_empty_block( buffer, &ptr, length, libspectrum_tape_block_type( block ) );
      break;

    case LIBSPECTRUM_TAPE_BLOCK_SELECT:
      tzx_write_select( block, buffer, &ptr, length );
      break;

    case LIBSPECTRUM_TAPE_BLOCK_STOP48:
      tzx_write_stop( buffer, &ptr, length );
      break;

    case LIBSPECTRUM_TAPE_BLOCK_COMMENT:
      tzx_write_comment( block, buffer, &ptr, length );
      break;

    case LIBSPECTRUM_TAPE_BLOCK_MESSAGE:
      tzx_write_message( block, buffer, &ptr, length );
      break;

    case LIBSPECTRUM_TAPE_BLOCK_ARCHIVE_INFO:
      tzx_write_archive_info( block, buffer, &ptr, length );
      break;

    case LIBSPECTRUM_TAPE_BLOCK_HARDWARE:
      tzx_write_hardware( block, buffer, &ptr, length );
      break;

    case LIBSPECTRUM_TAPE_BLOCK_CUSTOM:
      tzx_write_custom( block, buffer, &ptr, length );
      break;

    case LIBSPECTRUM_TAPE_BLOCK_RLE_PULSE:
      error = tzx_write_rle( block, buffer, &ptr, length, tape, iterator );
      if( error != LIBSPECTRUM_ERROR_NONE ) { libspectrum_free( *buffer ); return error; }
      break;

    default:
      libspectrum_free( *buffer );
      libspectrum_print_error(
        LIBSPECTRUM_ERROR_LOGIC,
	"libspectrum_tzx_write: unknown block type 0x%02x",
	libspectrum_tape_block_type( block )
      );
      return LIBSPECTRUM_ERROR_LOGIC;
    }
  }

  (*length) = ptr - *buffer;

  return LIBSPECTRUM_ERROR_NONE;
}
Exemplo n.º 28
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;
}
Exemplo n.º 29
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;
}
Exemplo n.º 30
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;
}