Пример #1
0
int tape_toggle_play( int autoplay )
{
  if( tape_playing ) {
    return tape_stop();
  } else {
    return tape_play( autoplay );
  }
}
Пример #2
0
int tape_next_edge( void )
{
  int error; libspectrum_error libspec_error;

  libspectrum_dword edge_tstates;
  int flags;

  /* If the tape's not playing, just return */
  if( ! tape_playing ) return 0;

  /* Get the time until the next edge */
  libspec_error = libspectrum_tape_get_next_edge( &tape, &edge_tstates,
						  &flags );
  if( libspec_error != LIBSPECTRUM_ERROR_NONE ) return libspec_error;

  /* Invert the microphone state */
  if( edge_tstates || ( flags & LIBSPECTRUM_TAPE_FLAGS_STOP ) ) {
    tape_microphone = !tape_microphone;
    sound_beeper( 1, tape_microphone );
  }

  /* If we've been requested to stop the tape, do so and then
     return without stacking another edge */
  if( ( flags & LIBSPECTRUM_TAPE_FLAGS_STOP ) ||
      ( ( flags & LIBSPECTRUM_TAPE_FLAGS_STOP48 ) && 
	machine_current->machine == SPECTRUM_MACHINE_48 )
    ) {
    error = tape_stop(); if( error ) return error;
    return 0;
  }

  /* If that was the end of a block, tape traps are active _and_ the
     new block is a ROM loader, return without putting another event
     into the queue */
  if( ( flags & LIBSPECTRUM_TAPE_FLAGS_BLOCK ) &&
      settings_current.tape_traps &&
      ((libspectrum_tape_block*)(tape.current_block->data))->type ==
        LIBSPECTRUM_TAPE_BLOCK_ROM
    ) {
    tape_playing = 0;
    return 0;
  }

  /* Otherwise, put this into the event queue which will cause the
     next block to become active when it occurs */
  error = event_add( tstates + edge_tstates, EVENT_TYPE_EDGE );
  if( error ) return error;

  return 0;
}
Пример #3
0
int tape_close( void )
{
  int error;

  /* Stop the tape if it's currently playing */
  if( tape_playing ) {
    error = tape_stop();
    if( error ) return error;
  }

  /* And then remove it from memory */
  error = libspectrum_tape_clear( tape );
  if( error ) return error;

  //ui_tape_browser_update( UI_TAPE_BROWSER_NEW_TAPE, NULL );
  
  return 0;
}
Пример #4
0
void
loader_detect_loader( void )
{
  libspectrum_dword tstates_diff = tstates - last_tstates_read;
  libspectrum_byte b_diff = z80.bc.b.h - last_b_read;

  last_tstates_read = tstates;
  last_b_read = z80.bc.b.h;

  if( settings_current.detect_loader ) {

    if( tape_is_playing() ) {
      if( tstates_diff > 1000 || ( b_diff != 1 && b_diff != 0 &&
				   b_diff != 0xff ) ) {
	successive_reads++;
	if( successive_reads >= 2 ) {
	  tape_stop();
	}
      } else {
	successive_reads = 0;
      }
    } else {
      if( tstates_diff <= 500 && ( b_diff == 1 || b_diff == 0xff ) ) {
	successive_reads++;
	if( successive_reads >= 10 ) {
	  tape_do_play( 1 );
	}
      } else {
	successive_reads = 0;
      }
    }

  } else {

    successive_reads = 0;

  }

  if( settings_current.accelerate_loader && tape_is_playing() )
    check_for_acceleration();

}
Пример #5
0
int
machine_reset( int hard_reset )
{
  size_t i;
  int error;

  /* Clear poke list (undoes effects of active pokes on Spectrum memory) */
  pokemem_clear();

  sound_ay_reset();

  tape_stop();

  memory_pool_free();

  machine_current->ram.romcs = 0;

  machine_set_variable_timings( machine_current );

  memory_reset();

  /* Do the machine-specific bits, including loading the ROMs */
  error = machine_current->reset(); if( error ) return error;

  module_reset( hard_reset );

  error = machine_current->memory_map(); if( error ) return error;

  /* Set up the contention array */
  for( i = 0; i < machine_current->timings.tstates_per_frame; i++ ) {
    ula_contention[ i ] = machine_current->ram.contend_delay( i );
    ula_contention_no_mreq[ i ] = machine_current->ram.contend_delay_no_mreq( i );
  }

  /* Update the disk menu items */
  ui_menu_disk_update();

  /* clear out old display image ready for new one */
  display_refresh_all();

  return 0;
}
Пример #6
0
int
machine_reset( int hard_reset )
{
  size_t i;
  int error;

  sound_ay_reset();

  tape_stop();

  memory_pool_free();

  machine_current->ram.romcs = 0;

  machine_set_variable_timings( machine_current );

  /* Do the machine-specific bits, including loading the ROMs */
  error = machine_current->reset(); if( error ) return error;

  module_reset( hard_reset );

  error = machine_current->memory_map(); if( error ) return error;

  /* Set up the contention array */
  for( i = 0; i < machine_current->timings.tstates_per_frame; i++ ) {
    ula_contention[ i ] = machine_current->ram.contend_delay( i );
    ula_contention_no_mreq[ i ] = machine_current->ram.contend_delay_no_mreq( i );
  }

  /* Check for an Interface I ROM */
  ui_statusbar_update( UI_STATUSBAR_ITEM_MICRODRIVE,
		       UI_STATUSBAR_STATE_NOT_AVAILABLE );
  
  /* Update the disk menu items */
  ui_menu_disk_update();

  /* clear out old display image ready for new one */
  display_refresh_all();

  return 0;
}
Пример #7
0
/* Close the active tape file */
int tape_close( void )
{
  int error;
  ui_confirm_save_t confirm;

  /* If the tape has been modified, check if we want to do this */
  if( tape_modified ) {

    confirm =
      ui_confirm_save( "Tape has been modified.\nDo you want to save it?" );
    switch( confirm ) {

    case UI_CONFIRM_SAVE_SAVE:
      error = ui_tape_write(); if( error ) return error;
      break;

    case UI_CONFIRM_SAVE_DONTSAVE: break;
    case UI_CONFIRM_SAVE_CANCEL: return 1;

    }
  }

  /* Stop the tape if it's currently playing */
  if( tape_playing ) {
    error = tape_stop();
    if( error ) return error;
  }

  /* And then remove it from memory */
  error = libspectrum_tape_clear( tape );
  if( error ) return error;

  tape_modified = 0;
  ui_tape_browser_update( UI_TAPE_BROWSER_NEW_TAPE, NULL );

  return 0;
}
Пример #8
0
void
tape_next_edge( libspectrum_dword last_tstates, int type, void *user_data )
{
  libspectrum_error libspec_error;
  libspectrum_tape_block *block;

  libspectrum_dword edge_tstates;
  int flags;

  /* If the tape's not playing, just return */
  if( ! tape_playing ) return;

  /* Get the time until the next edge */
  libspec_error = libspectrum_tape_get_next_edge( &edge_tstates, &flags,
						  tape );
  if( libspec_error != LIBSPECTRUM_ERROR_NONE ) return;

  /* Invert the microphone state */
  if( edge_tstates ||
      !( flags & LIBSPECTRUM_TAPE_FLAGS_NO_EDGE ) ||
      ( flags & ( LIBSPECTRUM_TAPE_FLAGS_STOP |
                  LIBSPECTRUM_TAPE_FLAGS_LEVEL_LOW |
                  LIBSPECTRUM_TAPE_FLAGS_LEVEL_HIGH ) ) ) {

    if( flags & LIBSPECTRUM_TAPE_FLAGS_NO_EDGE ) {
      /* Do nothing */
    } else if( flags & LIBSPECTRUM_TAPE_FLAGS_LEVEL_LOW ) {
      tape_microphone = 0;
    } else if( flags & LIBSPECTRUM_TAPE_FLAGS_LEVEL_HIGH ) {
      tape_microphone = 1;
    } else {
      tape_microphone = !tape_microphone;
    }
  }

  sound_beeper( last_tstates, tape_microphone );

  /* If we've been requested to stop the tape, do so and then
     return without stacking another edge */
  if( ( flags & LIBSPECTRUM_TAPE_FLAGS_STOP ) ||
      ( ( flags & LIBSPECTRUM_TAPE_FLAGS_STOP48 ) && 
	( !( libspectrum_machine_capabilities( machine_current->machine ) &
	     LIBSPECTRUM_MACHINE_CAPABILITY_128_MEMORY
	   )
	)
      )
    )
  {
    tape_stop();
    return;
  }

  /* If that was the end of a block, update the browser */
  if( flags & LIBSPECTRUM_TAPE_FLAGS_BLOCK ) {

    ui_tape_browser_update( UI_TAPE_BROWSER_SELECT_BLOCK, NULL );

    /* If the tape was started automatically, tape traps are active
       and the new block is a ROM loader, stop the tape and return
       without putting another event into the queue */
    block = libspectrum_tape_current_block( tape );
    if( tape_autoplay && settings_current.tape_traps &&
	libspectrum_tape_block_type( block ) == LIBSPECTRUM_TAPE_BLOCK_ROM
      ) {
      tape_stop();
      return;
    }
  }

  /* Otherwise, put this into the event queue; remember that this edge
     should occur 'edge_tstates' after the last edge, not after the
     current time (these will be slightly different as we only process
     events between instructions). */
  event_add( last_tstates + edge_tstates, tape_edge_event );

  /* Store length flags for acceleration purposes */
  loader_set_acceleration_flags( flags );
}
Пример #9
0
int
tape_next_edge(Z80Regs *regs, int *edge_tstates, int *bit)
{
  int error; libspectrum_error libspec_error;
  libspectrum_tape_block *block;
  
  //libspectrum_dword edge_tstates;
  int flags;
  *edge_tstates = 0;
  *bit=-1;
  int one_value=0;
  /* If the tape's not playing, just return */
  if( ! tape_playing ) return 0;

  block = libspectrum_tape_current_block( tape );
  int type = libspectrum_tape_block_type( block );
  if(type==LIBSPECTRUM_TAPE_BLOCK_ROM || 
     type==LIBSPECTRUM_TAPE_BLOCK_TURBO || 
     type==LIBSPECTRUM_TAPE_BLOCK_PURE_DATA /*||
     type==LIBSPECTRUM_TAPE_BLOCK_RAW_DATA*/)
  { 
     int state = libspectrum_tape_state( tape );

     if(state==LIBSPECTRUM_TAPE_STATE_DATA1 || state==LIBSPECTRUM_TAPE_STATE_DATA2)
     {
        if(block->type==LIBSPECTRUM_TAPE_BLOCK_TURBO)
        {
           one_value = block->types.turbo.bit1_length;
        }
        else if(block->type==LIBSPECTRUM_TAPE_BLOCK_PURE_DATA)
        {
           one_value = block->types.pure_data.bit1_length;
        }
        else
        {
           one_value = 1710;
        }        
     }             
  }   

  /* Get the time until the next edge */
  libspectrum_dword tmp = 0;
  libspec_error = libspectrum_tape_get_next_edge(&tmp, &flags, tape);
  *edge_tstates = tmp;
  
  if(one_value!=0)
     *bit = *edge_tstates == one_value ? 1 : 0;
 
  //edge_tstates_target = edge_tstates_target+*edge_tstates; 
    
  if( libspec_error != LIBSPECTRUM_ERROR_NONE ) return libspec_error;

  /* Invert the microphone state */
  if( *edge_tstates || ( flags & LIBSPECTRUM_TAPE_FLAGS_STOP ) ) {

    if( flags & LIBSPECTRUM_TAPE_FLAGS_NO_EDGE ) {
      // Do nothing 
    } else if( flags & LIBSPECTRUM_TAPE_FLAGS_LEVEL_LOW ) {
      tape_microphone = 0;
    } else if( flags & LIBSPECTRUM_TAPE_FLAGS_LEVEL_HIGH ) {
      tape_microphone = 1;
    } else {
      tape_microphone = !tape_microphone;
    }

    if(regs!=NULL)
       sound_beeper_1(tape_microphone,regs->IPeriod-regs->ICount);//TODO: poner pref
  }

  /* If we've been requested to stop the tape, do so and then
     return without stacking another edge */
     
  int zx48=0;
  if(regs!=NULL)
    zx48=regs->IPeriod==69888;
         
  if((flags & LIBSPECTRUM_TAPE_FLAGS_STOP) || ( zx48 && (flags & LIBSPECTRUM_TAPE_FLAGS_STOP48) ) )
  {
    error = tape_stop(); if( error ) return error;
    return 0;
  }

  /* If that was the end of a block, update the browser */
  if( flags & LIBSPECTRUM_TAPE_FLAGS_BLOCK ) {

    //ui_tape_browser_update( UI_TAPE_BROWSER_SELECT_BLOCK, NULL );

    /* If the tape was started automatically, tape traps are active
       and the new block is a ROM loader, stop the tape and return
       without putting another event into the queue */
    block = libspectrum_tape_current_block( tape );    
    if( /*tape_autoplay &&*/ mconfig.flash_loading &&
	    libspectrum_tape_block_type( block ) == LIBSPECTRUM_TAPE_BLOCK_ROM
      ) {
      error = tape_stop(); if( error ) return error;
      return 0;//TODO: devolver valor que nos diga que nos diga que no hay que devolver otro edge?
    }
    
  }

  /* Otherwise, put this into the event queue; remember that this edge
     should occur 'edge_tstates' after the last edge, not after the
     current time (these will be slightly different as we only process
     events between instructions). */

  return 0;
}
Пример #10
0
int tape_open( const char *filename )
{
  struct stat file_info; int fd; unsigned char *buffer;

  int error; char error_message[ ERROR_MESSAGE_MAX_LENGTH ];

  /* If we already have a tape file open, close it */
  if( tape.blocks ) {
    error = tape_close();
    if( error ) return error;
  }

  fd = open( filename, O_RDONLY );
  if( fd == -1 ) {
    snprintf( error_message, ERROR_MESSAGE_MAX_LENGTH,
	      "%s: couldn't open `%s'", fuse_progname, filename );
    perror( error_message );
    return 1;
  }

  if( fstat( fd, &file_info) ) {
    snprintf( error_message, ERROR_MESSAGE_MAX_LENGTH,
	      "%s: Couldn't stat `%s'", fuse_progname, filename );
    perror( error_message );
    close(fd);
    return 1;
  }

  buffer = mmap( 0, file_info.st_size, PROT_READ, MAP_SHARED, fd, 0 );
  if( buffer == (void*)-1 ) {
    snprintf( error_message, ERROR_MESSAGE_MAX_LENGTH,
	      "%s: Couldn't mmap `%s'", fuse_progname, filename );
    perror( error_message );
    close(fd);
    return 1;
  }

  if( close(fd) ) {
    snprintf( error_message, ERROR_MESSAGE_MAX_LENGTH,
	      "%s: Couldn't close `%s'", fuse_progname, filename );
    perror( error_message );
    munmap( buffer, file_info.st_size );
    return 1;
  }

  /* First, try opening the file as a .tzx file; if we get back an
     error saying it didn't have the .tzx signature, then try opening
     it as a .tap file */
  error = libspectrum_tzx_create( &tape, buffer, file_info.st_size );
  if( error == LIBSPECTRUM_ERROR_SIGNATURE ) {
    error = libspectrum_tap_create( &tape, buffer, file_info.st_size );
  }

  if( error != LIBSPECTRUM_ERROR_NONE ) {
    fprintf( stderr,
	     "%s: error reading `%s': %s\n",
	     fuse_progname, filename, libspectrum_error_message(error) );
      munmap( buffer, file_info.st_size );
      return error;
  }

  if( munmap( buffer, file_info.st_size ) == -1 ) {
    snprintf( error_message, ERROR_MESSAGE_MAX_LENGTH,
	      "%s: Couldn't munmap `%s'", fuse_progname, filename );
    perror( error_message );
    return 1;
  }

  /* And the tape is stopped */
  if( tape_playing ) tape_stop();

  return 0;

}