Example #1
0
/* What happens when we write to the ULA? */
static void
ula_write( libspectrum_word port GCC_UNUSED, libspectrum_byte b )
{
  last_byte = b;

  display_set_lores_border( b & 0x07 );
  sound_beeper( (!!(b & 0x10) << 1) + ( (!(b & 0x8)) | tape_microphone ) );

  /* FIXME: shouldn't really be using the memory capabilities here */

  if( machine_current->timex ) {

    ula_default_value = 0x5f;

  } else if( machine_current->capabilities & LIBSPECTRUM_MACHINE_CAPABILITY_PLUS3_MEMORY ) {

    ula_default_value = 0xbf;

  } else if( machine_current->capabilities & LIBSPECTRUM_MACHINE_CAPABILITY_128_MEMORY || !settings_current.issue2 ) {

    /* 128K always acts like an Issue 3 */
    ula_default_value = b & 0x10 ? 0xff : 0xbf;

  } else {

    /* Issue 2 */
    ula_default_value = b & 0x18 ? 0xff : 0xbf;

  }

}
Example #2
0
int tape_play( void )
{
  libspectrum_tape_block* block;

  int error;

  if( tape.blocks == NULL ) return 1;
  
  block = (libspectrum_tape_block*)(tape.current_block->data);

  /* If tape traps are active and the current block is a ROM block, do
     nothing, _unless_ the ROM block has already reached the pause at
     its end which (hopefully) means we're in the magic state involving
     starting slow loading whilst tape traps are active */
  if( settings_current.tape_traps &&
      block->type == LIBSPECTRUM_TAPE_BLOCK_ROM &&
      block->types.rom.state != LIBSPECTRUM_TAPE_STATE_PAUSE )
    return 0;

  /* Otherwise, start the tape going */
  tape_playing = 1;
  tape_microphone = 0;
  sound_beeper( 1, tape_microphone );

  error = tape_next_edge(); if( error ) return error;

  return 0;
}
Example #3
0
int tape_init( void )
{
  tape.blocks = NULL;
  tape_playing = 0;
  tape_microphone = 0;
  sound_beeper( 1, tape_microphone );
  return 0;
}
Example #4
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;
}
Example #5
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 );
}
Example #6
0
unsigned int out(int h,int l,int a)
{
static int cpc_f4=0;

/* unlike a real speccy, it seems we should only emulate exact port
 * number matches, rather than using bitmasks.
 */
if(do_cpc<1)
  switch(l)
    {
    case 0xfd:
      switch(h)
        {
        case 0xff:
          do_cpc=-1;
        write_reg:
          ay_current_reg=(a&15);
          break;
        case 0xbf:
          do_cpc=-1;
        write_dat:
          sound_ay_write(ay_current_reg,a,tstates);
          break;
        default:
          /* ok, since we do at least have low byte=FDh,
           * do bitmask for top byte to allow for
           * crappy .ay conversions. But don't disable
           * CPC autodetect, just in case.
           */
          if((h&0xc0)==0xc0) goto write_reg;
          if((h&0xc0)==0x80) goto write_dat;
        }
      break;

    case 0xfe:
      do_cpc=-1;
      sound_beeper(a&0x10);
      break;
    }

if(do_cpc>-1)
  switch(h)
    {
    case 0xf6:
      switch(a&0xc0)
        {
        case 0x80:	/* write */
          sound_ay_write(ay_current_reg,cpc_f4,tstates);
          break;
        
        case 0xc0:	/* select */
          ay_current_reg=(cpc_f4&15);
          break;
        }
      break;

    case 0xf4:
      cpc_f4=a;
      if(!do_cpc)
        {
        /* restart as a more CPC-ish emulation */
        do_cpc=1;
        sound_ay_reset_cpc();
        tsmax=FRAME_STATES_CPC;
        if(tstates>tsmax) tstates-=tsmax;
        }
      break;
    }

return(0);	/* additional t-states */
}