Esempio n. 1
0
/* Append to the current tape file in memory; returns 0 if a block was
   saved or non-zero if there was an error at the emulator level, or tape
   traps are not active */
int tape_save_trap( void )
{
  libspectrum_tape_block *block;
  libspectrum_byte parity, *data;
  size_t length;

  int i;

  /* Do nothing if tape traps aren't active */
  if( !settings_current.tape_traps || tape_recording ) return 2;

  /* Check we're in the right ROM */
  if( ! trap_check_rom() ) return 3;

  block = libspectrum_tape_block_alloc( LIBSPECTRUM_TAPE_BLOCK_ROM );
  
  /* The +2 here is for the flag and parity bytes */
  length = DE + 2;
  libspectrum_tape_block_set_data_length( block, length );

  data = malloc( length * sizeof(libspectrum_byte) );
  if( !data ) { free( block ); return 1; }
  libspectrum_tape_block_set_data( block, data );

  /* First, store the flag byte (and initialise the parity counter) */
  data[0] = parity = A;

  /* then the main body of the data, counting parity along the way */
  for( i=0; i<DE; i++) {
    libspectrum_byte b = readbyte_internal( IX+i );
    parity ^= b;
    data[i+1] = b;
  }

  /* And finally the parity byte */
  data[ DE+1 ] = parity;

  /* Give a 1 second pause after this block */
  libspectrum_tape_block_set_pause( block, 1000 );

  libspectrum_tape_append_block( tape, block );

  tape_modified = 1;
  ui_tape_browser_update( UI_TAPE_BROWSER_NEW_BLOCK, block );

  /* And then return via the RET at #053E, except on Timex 2068 at #00E4 */
  if ( machine_current->machine == LIBSPECTRUM_MACHINE_TC2068 ||
       machine_current->machine == LIBSPECTRUM_MACHINE_TS2068 ) {
    PC = 0x00e4;
  } else {
    PC = 0x053e;
  }

  return 0;

}
static int
append_inlay_file( char *inlay_file, libspectrum_tape *tape )
{
  libspectrum_tape_block* block;
  char *description;
  libspectrum_byte* jpg_data; size_t jpg_length;
  libspectrum_byte* custom_block_data; size_t custom_block_length;

  block = libspectrum_tape_block_alloc( LIBSPECTRUM_TAPE_BLOCK_CUSTOM );

  /* Get the description */
  description = malloc( DESCRIPTION_BUFFER_LEN );
  memcpy( description, "Picture        ", DESCRIPTION_BUFFER_LEN );
  libspectrum_tape_block_set_text( block, description );

  /* Read in the data */
  if( read_file( inlay_file, &jpg_data, &jpg_length ) ) {
    free( description );
    free( block );
    return 1;
  }

  custom_block_length = jpg_length + 2;
  custom_block_data = malloc( custom_block_length );

  /* Picture format */
  if( is_filetype( inlay_file, ".jpg" ) ) {
    custom_block_data[0] = 1;
  } else if( is_filetype( inlay_file, ".gif" ) ) {
    custom_block_data[0] = 0;
  } else {
    free( custom_block_data );
    return 1;
  }

  /* Picture description length 0 == "Inlay Card" */
  custom_block_data[1] = 0;
  /* and the JPG itself */
  memcpy( custom_block_data + 2, jpg_data, jpg_length );

  libspectrum_tape_block_set_data_length( block, custom_block_length );
  libspectrum_tape_block_set_data( block, custom_block_data );

  /* Finally, put the block into the block list */
  libspectrum_tape_append_block( tape, block );

  return 0;
}
static int
append_scr_file( char *scr_file, libspectrum_tape *tape )
{
  libspectrum_tape_block* block;
  char *description;
  libspectrum_byte* scr_data; size_t scr_length;
  libspectrum_byte* custom_block_data; size_t custom_block_length;

  block = libspectrum_tape_block_alloc( LIBSPECTRUM_TAPE_BLOCK_CUSTOM );

  /* Get the description */
  description = malloc( DESCRIPTION_BUFFER_LEN );
  memcpy( description, "Spectrum Screen ", DESCRIPTION_BUFFER_LEN );
  libspectrum_tape_block_set_text( block, description );

  /* Read in the data */
  if( read_file( scr_file, &scr_data, &scr_length ) ) {
    free( description );
    free( block );
    return 1;
  }

  custom_block_length = scr_length + 2;
  custom_block_data = malloc( custom_block_length );

  /* Picture description length 0 == "Loading Screen" */
  custom_block_data[0] = 0;
  /* Border colour 0 == black */
  custom_block_data[1] = 0;
  /* and the SCR itself */
  memcpy( custom_block_data + 2, scr_data, scr_length );

  libspectrum_tape_block_set_data_length( block, custom_block_length );
  libspectrum_tape_block_set_data( block, custom_block_data );

  /* Finally, put the block into the block list */
  libspectrum_tape_append_block( tape, block );

  return 0;
}
Esempio n. 4
0
int
tape_record_stop( void )
{
  libspectrum_tape_block* block;

  /* put last sample into the recording buffer */
  rec_state.tape_buffer_used = write_rec_buffer( rec_state.tape_buffer,
                                                 rec_state.tape_buffer_used,
                                                 rec_state.last_level_count );

  /* stop scheduling events and turn buffer into a block and
     pop into the current tape */
  event_remove_type( record_event );

  block = libspectrum_tape_block_alloc( LIBSPECTRUM_TAPE_BLOCK_RLE_PULSE );

  libspectrum_tape_block_set_scale( block, rec_state.tstates_per_sample );
  libspectrum_tape_block_set_data_length( block, rec_state.tape_buffer_used );
  libspectrum_tape_block_set_data( block, rec_state.tape_buffer );

  libspectrum_tape_append_block( tape, block );

  rec_state.tape_buffer = NULL;
  rec_state.tape_buffer_size = 0;
  rec_state.tape_buffer_used = 0;

  tape_modified = 1;
  ui_tape_browser_update( UI_TAPE_BROWSER_NEW_BLOCK, block );

  tape_recording = 0;

  /* Also want to reenable other tape actions */
  ui_menu_activate( UI_MENU_ITEM_TAPE_RECORDING, 0 );

  return 0;
}
Esempio n. 5
0
int
main(int argc, char *argv[])
{
	int opt, i, quiet = 0;
	char *output = "output.tzx", *p;
	int turbo_params[6] = { 2168, 3323, 667, 735, 855, 1710 };

	FILE *fd;
	size_t data_len;

	libspectrum_tape *tape;
	libspectrum_byte *data;
	libspectrum_tape_block *block;
	libspectrum_dword pause, pause_tstates;

	while ((opt = getopt(argc, argv, "vhqt:o:")) != -1)
	{
		switch(opt)
		{
			case 'q':
				quiet = 1;
				break;
			case 't':
				if (sscanf(optarg, "%i:%i:%i:%i:%i:%i", &turbo_params[0],
					&turbo_params[1], &turbo_params[2], &turbo_params[3], 
					&turbo_params[4], &turbo_params[5]) != 6)
					fatal(argv[0], "Failed to parse turbo params");
				break;
			case 'o':
				output = strdup(optarg);
				break;
			case 'h':
				help(argv[0]);
				exit(0);
			case 'v':
				fprintf(stderr,  VERSION "\n");
				exit(0);
			default:
				fprintf(stderr, "\n");
				help(argv[0]);
				exit(1);
		}
	}

	if (optind >= argc)
		fatal(argv[0], "Expected input filename to process");

	if (libspectrum_init())
		fatal(argv[0], "Failed to init libspectrum");

	fd = fopen(argv[optind], "rb");
	if (!fd)
		fatal(argv[0], "Failed to open input file");

	fseek(fd, 0, SEEK_END);
	data_len = ftell(fd);
	fseek(fd, 0, SEEK_SET);

	data = (libspectrum_byte *) malloc(data_len);
	if (!data)
	{
		fclose(fd);
		fatal(argv[0], "Failed to allocate memory");
	}

	if (fread(data, sizeof(libspectrum_byte), data_len, fd) != data_len)
	{
		fclose(fd);
		free(data);
		fatal(argv[0], "Failed to read input file");
	}
	fclose(fd);

	tape = libspectrum_tape_alloc();
	if (!tape)
	{
		fclose(fd);
		free(data);
		fatal(argv[0], "Failed to allocate tape memory");
	}

	if (libspectrum_tape_read(tape, data, data_len, LIBSPECTRUM_ID_UNKNOWN, argv[optind]))
	{
		fclose(fd);
		free(data);
		free(tape);
		fatal(argv[0], "Failed to read tape");
	}
	free(data);

	for (i = optind + 1; i < argc; i++)
	{
		for (p = argv[i]; *p && isdigit(*p); p++);

		if (*p)
		{
			fprintf(stderr, "WARNING: Parameter is not a valid block number, skipping\n");
			continue;
		}

		if (libspectrum_tape_nth_block(tape, atoi(argv[i])))
			continue;

		block = libspectrum_tape_current_block(tape);
		if (!block)
			continue;

		if (!quiet)
			printf("%s: Setting block #%i (type 0x%02x): ", argv[0], atoi(argv[i]),
					libspectrum_tape_block_type(block));

		data = libspectrum_tape_block_data(block);
		data_len = libspectrum_tape_block_data_length(block);
		pause = libspectrum_tape_block_pause(block);
		pause_tstates = libspectrum_tape_block_pause_tstates(block);

		if (libspectrum_tape_block_set_type(block, LIBSPECTRUM_TAPE_BLOCK_TURBO)
			|| libspectrum_tape_block_set_pilot_pulses(block, turbo_params[1])
			|| libspectrum_tape_block_set_pilot_length(block, turbo_params[0])
			|| libspectrum_tape_block_set_sync1_length(block, turbo_params[2])
			|| libspectrum_tape_block_set_sync2_length(block, turbo_params[3])
			|| libspectrum_tape_block_set_bit0_length(block, turbo_params[4])
			|| libspectrum_tape_block_set_bit1_length(block, turbo_params[5])
			|| libspectrum_tape_block_set_data(block, data)
		 	|| libspectrum_tape_block_set_data_length(block, data_len)
			|| libspectrum_tape_block_set_pause(block, pause)
			|| libspectrum_tape_block_set_pause_tstates(block, pause_tstates)
			|| libspectrum_tape_block_set_bits_in_last_byte(block, 8)
			)
		{
			if (!quiet)
				printf("failed!\n");
			fprintf(stderr, "WARNING: Failed to set block %i\n", atoi(argv[i]));
			continue;
		}

		if (!quiet)
			printf("OK\n");
	}

	data = NULL;
	data_len = 0;
	if (libspectrum_tape_write(&data, &data_len, tape, LIBSPECTRUM_ID_TAPE_TZX))
	{
		free(tape);
		fatal(argv[0], "Failed to write the output file");
	}

	fd = fopen(output, "wb");
	if (!fd)
	{
		free(data);
		free(tape);
		fatal(argv[0], "Failed to open output file");
	}

	if (fwrite(data, sizeof(libspectrum_byte), data_len, fd) != data_len)
	{
		fclose(fd);
		free(data);
		free(tape);
		fatal(argv[0], "Failed to write output file");
	}
	fclose(fd);
	free(data);
	free(tape);

	exit(0);
}
Esempio n. 6
0
libspectrum_error
libspectrum_wav_read( libspectrum_tape *tape, const char *filename )
{
  libspectrum_byte *buffer; size_t length;
  libspectrum_byte *tape_buffer; size_t tape_length;
  size_t data_length;
  libspectrum_tape_block *block = NULL;
  int frames;

  /* Our filehandle from libaudiofile */
  AFfilehandle handle;

  /* The track we're using in the file */
  int track = AF_DEFAULT_TRACK; 

  if( !filename ) {
    libspectrum_print_error(
      LIBSPECTRUM_ERROR_LOGIC,
      "libspectrum_wav_read: no filename provided - wav files can only be loaded from a file"
    );
    return LIBSPECTRUM_ERROR_LOGIC;
  }

  handle = afOpenFile( filename, "r", NULL );
  if( handle == AF_NULL_FILEHANDLE ) {
    libspectrum_print_error(
      LIBSPECTRUM_ERROR_LOGIC,
      "libspectrum_wav_read: audiofile failed to open file:%s", filename
    );
    return LIBSPECTRUM_ERROR_LOGIC;
  }

  if( afSetVirtualSampleFormat( handle, track, AF_SAMPFMT_UNSIGNED, 8 ) ) {
    afCloseFile( handle );
    libspectrum_print_error(
      LIBSPECTRUM_ERROR_LOGIC,
      "libspectrum_wav_read: audiofile failed to set virtual sample format"
    );
    return LIBSPECTRUM_ERROR_LOGIC;
  }

  if( afSetVirtualChannels( handle, track, 1 ) ) {
    afCloseFile( handle );
    libspectrum_print_error(
      LIBSPECTRUM_ERROR_LOGIC,
      "libspectrum_wav_read: audiofile failed to set virtual channel count"
    );
    return LIBSPECTRUM_ERROR_LOGIC;
  }

  length = afGetFrameCount( handle, track );

  tape_length = length;
  if( tape_length%8 ) tape_length += 8 - (tape_length%8);

  buffer = libspectrum_new0( libspectrum_byte,
			     tape_length * afGetChannels(handle, track) );

  frames = afReadFrames( handle, track, buffer, length );
  if( frames == -1 ) {
    libspectrum_free( buffer );
    afCloseFile( handle );
    libspectrum_print_error(
      LIBSPECTRUM_ERROR_CORRUPT,
      "libspectrum_wav_read: can't calculate number of frames in audio file"
    );
    return LIBSPECTRUM_ERROR_CORRUPT;
  }

  if( !length ) {
    libspectrum_free( buffer );
    afCloseFile( handle );
    libspectrum_print_error(
      LIBSPECTRUM_ERROR_CORRUPT,
      "libspectrum_wav_read: empty audio file, nothing to load"
    );
    return LIBSPECTRUM_ERROR_CORRUPT;
  }

  if( frames != length ) {
    libspectrum_free( buffer );
    afCloseFile( handle );
    libspectrum_print_error(
      LIBSPECTRUM_ERROR_CORRUPT,
      "libspectrum_wav_read: read %d frames, but expected %lu\n", frames,
      (unsigned long)length
    );
    return LIBSPECTRUM_ERROR_CORRUPT;
  }

  block = libspectrum_tape_block_alloc( LIBSPECTRUM_TAPE_BLOCK_RAW_DATA );

  /* 44100 Hz 79 t-states 22050 Hz 158 t-states */
  libspectrum_tape_block_set_bit_length( block,
                                         3500000/afGetRate( handle, track ) );
  libspectrum_set_pause_ms( block, 0 );
  libspectrum_tape_block_set_bits_in_last_byte( block,
              length % LIBSPECTRUM_BITS_IN_BYTE ?
                length % LIBSPECTRUM_BITS_IN_BYTE : LIBSPECTRUM_BITS_IN_BYTE );
  data_length = tape_length / LIBSPECTRUM_BITS_IN_BYTE;
  libspectrum_tape_block_set_data_length( block, data_length );

  tape_buffer = libspectrum_new0( libspectrum_byte, data_length );

  libspectrum_byte *from = buffer;
  libspectrum_byte *to = tape_buffer;
  length = tape_length;
  do {
    libspectrum_byte val = 0;
    int i;
    for( i = 7; i >= 0; i-- ) {
      if( *from++ > 127 ) val |= 1 << i;
    }
    *to++ = val;
  } while ((length -= 8) > 0);

  libspectrum_tape_block_set_data( block, tape_buffer );

  libspectrum_tape_append_block( tape, block );

  if( afCloseFile( handle ) ) {
    libspectrum_free( buffer );
    libspectrum_print_error(
      LIBSPECTRUM_ERROR_UNKNOWN,
      "libspectrum_wav_read: failed to close audio file"
    );
    return LIBSPECTRUM_ERROR_UNKNOWN;
  }

  libspectrum_free( buffer );

  /* Successful completion */
  return LIBSPECTRUM_ERROR_NONE;
}
Esempio n. 7
0
/* Convert RLE block to a TZX DRB as TZX CSW block support is limited :/ */
static libspectrum_error
tzx_write_rle( libspectrum_tape_block *block, libspectrum_byte **buffer,
               libspectrum_byte **ptr, size_t *length,
               libspectrum_tape *tape,
               libspectrum_tape_iterator iterator )
{
  libspectrum_error error;
  libspectrum_tape_block_state it;
  libspectrum_dword scale = libspectrum_tape_block_scale( block );
  libspectrum_dword pulse_tstates = 0;
  libspectrum_dword balance_tstates = 0;
  int flags = 0;

  libspectrum_tape_block *raw_block = 
    libspectrum_tape_block_alloc( LIBSPECTRUM_TAPE_BLOCK_RAW_DATA );

  libspectrum_tape_block_set_bit_length( raw_block, scale );
  libspectrum_tape_block_set_pause     ( raw_block, 0 );

  rle_state.bits_used = 0;
  rle_state.level = 0;
  rle_state.length = 0;
  rle_state.tape_length = 8192;
  rle_state.tape_buffer = libspectrum_malloc( rle_state.tape_length );

  *rle_state.tape_buffer = 0;

  it.current_block = iterator;
  error = libspectrum_tape_block_init( block, &it );
  if( error != LIBSPECTRUM_ERROR_NONE ) {
    libspectrum_free( rle_state.tape_buffer );
    libspectrum_tape_block_free( raw_block );
    return error;
  }

  while( !(flags & LIBSPECTRUM_TAPE_FLAGS_BLOCK) ) {
    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 ) {
      libspectrum_free( rle_state.tape_buffer );
      libspectrum_tape_block_free( raw_block );
      return error;
    }

    balance_tstates += pulse_tstates;

    /* next set of pulses is: balance_tstates / scale; */
    pulse_length = balance_tstates / scale;
    balance_tstates = balance_tstates % scale;

    /* write pulse_length bits of the current level into the buffer */
    write_pulse( pulse_length );
  }

  if( rle_state.length || rle_state.bits_used ) {
    if( rle_state.bits_used ) {
      rle_state.length++;
    } else {
      rle_state.bits_used = 8;
    }

    error = libspectrum_tape_block_set_bits_in_last_byte( raw_block,
                                                          rle_state.bits_used );
    if( error != LIBSPECTRUM_ERROR_NONE ) {
      libspectrum_free( rle_state.tape_buffer );
      libspectrum_tape_block_free( raw_block );
      return error;
    }

    error = libspectrum_tape_block_set_data_length( raw_block,
                                                    rle_state.length );
    if( error != LIBSPECTRUM_ERROR_NONE ) {
      libspectrum_free( rle_state.tape_buffer );
      libspectrum_tape_block_free( raw_block );
      return error;
    }

    error = libspectrum_tape_block_set_data( raw_block, rle_state.tape_buffer );
    if( error != LIBSPECTRUM_ERROR_NONE ) {
      libspectrum_free( rle_state.tape_buffer );
      libspectrum_tape_block_free( raw_block );
      return error;
    }

    /* now have tzx_write_raw_data finish the job */
    tzx_write_raw_data( raw_block, buffer, ptr, length );
  } else {
    libspectrum_free( rle_state.tape_buffer );
  }

  return libspectrum_tape_block_free( raw_block );
}