Example #1
0
/* Check whether we're actually in the right ROM when a tape trap hit */
static int
trap_check_rom( void )
{
  if( plusd_available && plusd_active )
    return 0;		/* +D must not be active */

  if( opus_available && opus_active )
    return 0;		/* Opus must not be active */

  if( memory_custom_rom() )
    return 0;           /* and we can't be using a custom ROM */

  switch( machine_current->machine ) {
  case LIBSPECTRUM_MACHINE_16:
  case LIBSPECTRUM_MACHINE_48:
  case LIBSPECTRUM_MACHINE_48_NTSC:
  case LIBSPECTRUM_MACHINE_TC2048:
    return 1;		/* Always OK here */

  case LIBSPECTRUM_MACHINE_TC2068:
  case LIBSPECTRUM_MACHINE_TS2068:
    /* OK if we're in the EXROM (location of the tape routines) */
    return( memory_map_read[0].bank == MEMORY_BANK_EXROM );

  case LIBSPECTRUM_MACHINE_128:
  case LIBSPECTRUM_MACHINE_PLUS2:
  case LIBSPECTRUM_MACHINE_SE:
    /* OK if we're in ROM 1 */
    return( machine_current->ram.current_rom == 1 );

  case LIBSPECTRUM_MACHINE_PLUS2A:
  case LIBSPECTRUM_MACHINE_PLUS3:
  case LIBSPECTRUM_MACHINE_PLUS3E:
    /* OK if we're not in a 64Kb RAM configuration and we're in
       ROM 3 */
    return( ! machine_current->ram.special &&
	    machine_current->ram.current_rom == 3 );

  case LIBSPECTRUM_MACHINE_PENT:
  case LIBSPECTRUM_MACHINE_PENT512:
  case LIBSPECTRUM_MACHINE_PENT1024:
  case LIBSPECTRUM_MACHINE_SCORP:
    /* OK if we're in ROM 1 and the Beta disk interface is not active */
    return( machine_current->ram.current_rom == 1 && !beta_active );

  case LIBSPECTRUM_MACHINE_UNKNOWN:	/* should never happen */
    ui_error( UI_ERROR_ERROR,
	      "trap_check_rom: machine type is LIBSPECTRUM_MACHINE_UNKNOWN" );
    fuse_abort();

  }

  ui_error( UI_ERROR_ERROR, "trap_check_rom: unknown machine type %d",
	    machine_current->machine );
  fuse_abort();
}
Example #2
0
int
debugger_breakpoint_add_event( debugger_breakpoint_type type,
			       const char *type_string, const char *detail,
			       size_t ignore, debugger_breakpoint_life life,
			       debugger_expression *condition )
{
  debugger_breakpoint_value value;

  switch( type ) {
  case DEBUGGER_BREAKPOINT_TYPE_EVENT:
    break;

  default:
    ui_error( UI_ERROR_ERROR, "%s given type %d", __func__, type );
    fuse_abort();
  }

  if( !debugger_event_is_registered( type_string, detail ) ) {
    ui_error( UI_ERROR_WARNING, "Event type %s:%s not known", type_string,
              detail );
    return 1;
  }

  value.event.detail = NULL;
  value.event.type = strdup( type_string );
  value.event.detail = strdup( detail );
  if( !value.event.type || !value.event.detail ) {
    free( value.event.type );
    free( value.event.detail );
    return 1;
  }

  return breakpoint_add( type, value, ignore, life, condition );
}
Example #3
0
scaler_type
menu_get_scaler( scaler_available_fn selector )
{
  size_t count, i;
  const char *options[ SCALER_NUM ];
  widget_select_t info;
  int error;

  count = 0; info.current = 0;

  for( i = 0; i < SCALER_NUM; i++ )
    if( selector( i ) ) {
      if( current_scaler == i ) info.current = count;
      options[ count++ ] = scaler_name( i );
    }

  info.title = "Select scaler";
  info.options = options;
  info.count = count;

  error = widget_do( WIDGET_TYPE_SELECT, &info );
  if( error ) return SCALER_NUM;

  if( info.result == -1 ) return SCALER_NUM;

  for( i = 0; i < SCALER_NUM; i++ )
    if( selector( i ) && !info.result-- ) return i;

  ui_error( UI_ERROR_ERROR, "widget_select_scaler: ran out of scalers" );
  fuse_abort();
}
Example #4
0
static int
sdldisplay_load_gfx_mode( void )
{
  Uint16 *tmp_screen_pixels;

  sdldisplay_force_full_refresh = 1;

  tmp_screen = NULL;
  tmp_screen_width = (image_width + 3);

  sdldisplay_current_size = scaler_get_scaling_factor( current_scaler );

  sdldisplay_find_best_fullscreen_scaler();

  /* Create the surface that contains the scaled graphics in 16 bit mode */
  sdldisplay_gc = SDL_SetVideoMode(
    image_width * sdldisplay_current_size,
    image_height * sdldisplay_current_size,
    16,
    settings_current.full_screen ? (SDL_FULLSCREEN|SDL_SWSURFACE)
                                 : SDL_SWSURFACE
  );
  if( !sdldisplay_gc ) {
    fprintf( stderr, "%s: couldn't create SDL graphics context\n", fuse_progname );
    fuse_abort();
  }

  sdldisplay_is_full_screen =
      settings_current.full_screen = !!(sdldisplay_gc->flags & SDL_FULLSCREEN);

  /* Distinguish 555 and 565 mode */
  if( sdldisplay_gc->format->Gmask >> sdldisplay_gc->format->Gshift == 0x1f )
    scaler_select_bitformat( 555 );
  else
Example #5
0
/* Is a binary operator non-associative? */
static int
is_non_associative( int operation )
{
  switch( operation ) {

  /* Simple cases */
  case '+': case '*': return 0;
  case '-': case '/': return 1;

  /* None of the comparison operators are associative due to them
     returning truth values */
  case DEBUGGER_TOKEN_EQUAL_TO:
  case DEBUGGER_TOKEN_NOT_EQUAL_TO:
  case '<': case '>':
  case DEBUGGER_TOKEN_LESS_THAN_OR_EQUAL_TO:
  case DEBUGGER_TOKEN_GREATER_THAN_OR_EQUAL_TO:
    return 1;

  /* The logical operators are associative */
  case DEBUGGER_TOKEN_LOGICAL_AND: return 0;
  case DEBUGGER_TOKEN_LOGICAL_OR: return 0;

  /* The bitwise operators are also associative (consider them as
     vectorised logical operators) */
  case    '&': return 0;
  case    '^': return 0;
  case    '|': return 0;

  }

  /* Should never get here */
  ui_error( UI_ERROR_ERROR, "unknown binary operation %d", operation );
  fuse_abort();
}
Example #6
0
nic_w5100_t*
nic_w5100_alloc( void )
{
  int error;
  int i;
  nic_w5100_t *self;
  
  compat_socket_networking_init();

  self = libspectrum_new( nic_w5100_t, 1 );

  self->selfpipe = compat_socket_selfpipe_alloc();

  for( i = 0; i < 4; i++ )
    nic_w5100_socket_init( &self->socket[i], i );

  nic_w5100_reset( self );

  self->stop_io_thread = 0;

  error = pthread_create( &self->thread, NULL, w5100_io_thread, self );
  if( error ) {
    ui_error( UI_ERROR_ERROR, "w5100: error %d creating thread", error );
    fuse_abort();
  }

  return self;
}
Example #7
0
void
debugger_event( int event_code )
{
  debugger_event_t event;
  GSList *ptr;

  if( event_code >= registered_events->len ) {
    ui_error( UI_ERROR_ERROR, "internal error: invalid debugger event %d",
	      event_code );
    fuse_abort();
  }

  event = g_array_index( registered_events, debugger_event_t, event_code );

  for( ptr = debugger_breakpoints; ptr; ptr = ptr->next ) {
    debugger_breakpoint *bp = ptr->data;
    if( bp->type != DEBUGGER_BREAKPOINT_TYPE_EVENT ) continue;

    if( event_matches( &bp->value.event, event.type, event.detail ) &&
        debugger_breakpoint_trigger( bp ) ) {
      debugger_mode = DEBUGGER_MODE_HALTED;
      debugger_command_evaluate( bp->commands );
    }
  }
}
Example #8
0
/* Add a breakpoint */
int
debugger_breakpoint_add_address( debugger_breakpoint_type type, int page,
				 libspectrum_word offset, size_t ignore,
				 debugger_breakpoint_life life,
				 debugger_expression *condition )
{
  debugger_breakpoint_value value;

  switch( type ) {
  case DEBUGGER_BREAKPOINT_TYPE_EXECUTE:
  case DEBUGGER_BREAKPOINT_TYPE_READ:
  case DEBUGGER_BREAKPOINT_TYPE_WRITE:
    break;

  default:
    ui_error( UI_ERROR_ERROR, "debugger_breakpoint_add_address given type %d",
	      type );
    fuse_abort();
  }

  value.address.page = page;
  value.address.offset = offset;

  return breakpoint_add( type, value, ignore, life, condition );
}
Example #9
0
static enum precedence_t
binaryop_precedence( int operation )
{
  switch( operation ) {

  case DEBUGGER_TOKEN_LOGICAL_OR: return PRECEDENCE_LOGICAL_OR;
  case DEBUGGER_TOKEN_LOGICAL_AND: return PRECEDENCE_LOGICAL_AND;
  case    '|':		    return PRECEDENCE_BITWISE_OR;
  case    '^':		    return PRECEDENCE_BITWISE_XOR;
  case    '&':		    return PRECEDENCE_BITWISE_AND;
  case    '+': case    '-': return PRECEDENCE_ADDITION;
  case    '*': case    '/': return PRECEDENCE_MULTIPLICATION;

  case DEBUGGER_TOKEN_EQUAL_TO:
  case DEBUGGER_TOKEN_NOT_EQUAL_TO:
    return PRECEDENCE_EQUALITY;

  case    '<': case    '>':
  case DEBUGGER_TOKEN_LESS_THAN_OR_EQUAL_TO:
  case DEBUGGER_TOKEN_GREATER_THAN_OR_EQUAL_TO:
    return PRECEDENCE_COMPARISON;

  default:
    ui_error( UI_ERROR_ERROR, "unknown binary operator %d", operation );
    fuse_abort();
  }
}
Example #10
0
int
machine_select( libspectrum_machine type )
{
  int i;
  int error;

  for( i=0; i < machine_count; i++ ) {
    if( machine_types[i]->machine == type ) {
      machine_location = i;
      error = machine_select_machine( machine_types[i] );

      if( !error ) return 0;

      /* If we couldn't select the new machine type, try falling back
	 to plain old 48K */
      if( type != LIBSPECTRUM_MACHINE_48 ) 
	error = machine_select( LIBSPECTRUM_MACHINE_48 );
	
      /* If that still didn't work, give up */
      if( error ) {
	ui_error( UI_ERROR_ERROR, "can't select 48K machine. Giving up." );
	fuse_abort();
      } else {
	ui_error( UI_ERROR_INFO, "selecting 48K machine" );
	return 0;
      }
      
      return 0;
    }
  }

  ui_error( UI_ERROR_ERROR, "machine type %d unknown", type );
  return 1;
}
Example #11
0
libspectrum_dword
debugger_expression_evaluate( debugger_expression *exp )
{
  switch( exp->type ) {

  case DEBUGGER_EXPRESSION_TYPE_INTEGER:
    return exp->types.integer;

  case DEBUGGER_EXPRESSION_TYPE_REGISTER:
    return debugger_register_get( exp->types.reg );

  case DEBUGGER_EXPRESSION_TYPE_UNARYOP:
    return evaluate_unaryop( &( exp->types.unaryop ) );

  case DEBUGGER_EXPRESSION_TYPE_BINARYOP:
    return evaluate_binaryop( &( exp->types.binaryop ) );

  case DEBUGGER_EXPRESSION_TYPE_VARIABLE:
    return debugger_variable_get( exp->types.variable );

  }

  ui_error( UI_ERROR_ERROR, "unknown expression type %d", exp->type );
  fuse_abort();
}
Example #12
0
int
debugger_expression_deparse( char *buffer, size_t length,
			     const debugger_expression *exp )
{
  switch( exp->type ) {

  case DEBUGGER_EXPRESSION_TYPE_INTEGER:
    if( debugger_output_base == 10 ) {
      snprintf( buffer, length, "%d", exp->types.integer );
    } else {
      snprintf( buffer, length, "0x%x", exp->types.integer );
    }
    return 0;

  case DEBUGGER_EXPRESSION_TYPE_REGISTER:
    snprintf( buffer, length, "%s", debugger_register_text( exp->types.reg ) );
    return 0;

  case DEBUGGER_EXPRESSION_TYPE_UNARYOP:
    return deparse_unaryop( buffer, length, &( exp->types.unaryop ) );

  case DEBUGGER_EXPRESSION_TYPE_BINARYOP:
    return deparse_binaryop( buffer, length, &( exp->types.binaryop ) );

  case DEBUGGER_EXPRESSION_TYPE_VARIABLE:
    snprintf( buffer, length, "$%s", exp->types.variable );
    return 0;

  }

  ui_error( UI_ERROR_ERROR, "unknown expression type %d", exp->type );
  fuse_abort();
}
Example #13
0
int
compat_get_next_path( path_context *ctx )
{
  char buffer[ PATH_MAX ];
  const char *path_segment, *path2;

  switch( (ctx->state)++ ) {

    /* First look relative to the current directory */
  case 0:
    strncpy( ctx->path, ".", PATH_MAX );
    return 1;

    /* Then relative to the Fuse executable */
  case 1:

    switch( ctx->type ) {
    case UTILS_AUXILIARY_LIB: path_segment = "lib"; break;
    case UTILS_AUXILIARY_ROM: path_segment = "roms"; break;
    case UTILS_AUXILIARY_WIDGET: path_segment = "ui/widget"; break;
    case UTILS_AUXILIARY_GTK: path_segment = "ui/gtk"; break;
    default:
      ui_error( UI_ERROR_ERROR, "unknown auxiliary file type %d", ctx->type );
      return 0;
    }

    if( compat_is_absolute_path( fuse_progname ) ) {
      strncpy( buffer, fuse_progname, PATH_MAX );
      buffer[ PATH_MAX - 1 ] = '\0';
    } else {
      size_t len;
      len = PATH_MAX - strlen( fuse_progname ) - strlen( FUSE_DIR_SEP_STR );
      if( !getcwd( buffer, len ) ) {
        ui_error( UI_ERROR_ERROR, "error getting current working directory: %s",
	          strerror( errno ) );
        return 0;
      }
      strcat( buffer, FUSE_DIR_SEP_STR );
      strcat( buffer, fuse_progname );
    }

    path2 = dirname( buffer );
    snprintf( ctx->path, PATH_MAX, "%s" FUSE_DIR_SEP_STR "%s", path2,
              path_segment );
    return 1;

    /* Then where we may have installed the data files */
  case 2:

    path2 = "sd:/apps/fuse";
    strncpy( ctx->path, path2, PATH_MAX ); buffer[ PATH_MAX - 1 ] = '\0';
    return 1;

  case 3: return 0;
  }
  ui_error( UI_ERROR_ERROR, "unknown path_context state %d", ctx->state );
  fuse_abort();
}
Example #14
0
void
profile_map( libspectrum_word pc )
{
    if( tstates - profile_last_tstates > 256 ) fuse_abort();

    total_tstates[ profile_last_pc ] += tstates - profile_last_tstates;

    profile_last_pc = z80.pc.w;
    profile_last_tstates = tstates;
}
Example #15
0
int
compat_get_next_path( path_context *ctx )
{
  char buffer[ PATH_MAX ];
  const char *path_segment, *path2;

  switch( ctx->type ) {
  case UTILS_AUXILIARY_LIB: path_segment = "lib"; break;
  case UTILS_AUXILIARY_ROM: path_segment = "roms"; break;
  case UTILS_AUXILIARY_WIDGET: path_segment = "ui/widget"; break;
  case UTILS_AUXILIARY_GTK: path_segment = "ui/gtk"; break;
  default:
    ui_error( UI_ERROR_ERROR, "unknown auxiliary file type %d", ctx->type );
    return 0;
  }

  switch( (ctx->state)++ ) {

    /* First look relative to the Fuse executable */
  case 0:
    if( compat_is_absolute_path( fuse_progname ) ) {
      strncpy( buffer, fuse_progname, PATH_MAX );
      buffer[ PATH_MAX - 1 ] = '\0';
    } else {
      DWORD retval; 
      retval = GetModuleFileName( NULL, buffer, PATH_MAX );
      if( !retval ) return 0;
    }

    path2 = dirname( buffer );
    snprintf( ctx->path, PATH_MAX, "%s" FUSE_DIR_SEP_STR "%s", path2,
              path_segment );
    return 1;

    /* Then relative to %APPDATA%/Fuse directory */
  case 1:
    path2 = getenv( "APPDATA" );
    if( !path2 ) return 0;
    snprintf( ctx->path, PATH_MAX, "%s" FUSE_DIR_SEP_STR "Fuse" 
              FUSE_DIR_SEP_STR "%s", path2, path_segment );

    return 1;

    /* Then relative to the current directory */
  case 2:
    snprintf( ctx->path, PATH_MAX, "." FUSE_DIR_SEP_STR "%s",
              path_segment );
    return 1;

  case 3: return 0;
  }

  ui_error( UI_ERROR_ERROR, "unknown path_context state %d", ctx->state );
  fuse_abort();
}
Example #16
0
static enum precedence_t
unaryop_precedence( int operation )
{
  switch( operation ) {

  case '!': case '~': case '-': return PRECEDENCE_NEGATE;

  default:
    ui_error( UI_ERROR_ERROR, "unknown unary operator %d", operation );
    fuse_abort();
  }
}
Example #17
0
static keyboard_key_name
get_fire_button_key( int which, input_key button )
{
  switch( which ) {

  case 0:
    switch( button ) {
    case INPUT_JOYSTICK_FIRE_1 : return settings_current.joystick_1_fire_1;
    case INPUT_JOYSTICK_FIRE_2 : return settings_current.joystick_1_fire_2;
    case INPUT_JOYSTICK_FIRE_3 : return settings_current.joystick_1_fire_3;
    case INPUT_JOYSTICK_FIRE_4 : return settings_current.joystick_1_fire_4;
    case INPUT_JOYSTICK_FIRE_5 : return settings_current.joystick_1_fire_5;
    case INPUT_JOYSTICK_FIRE_6 : return settings_current.joystick_1_fire_6;
    case INPUT_JOYSTICK_FIRE_7 : return settings_current.joystick_1_fire_7;
    case INPUT_JOYSTICK_FIRE_8 : return settings_current.joystick_1_fire_8;
    case INPUT_JOYSTICK_FIRE_9 : return settings_current.joystick_1_fire_9;
    case INPUT_JOYSTICK_FIRE_10: return settings_current.joystick_1_fire_10;
    case INPUT_JOYSTICK_FIRE_11: return settings_current.joystick_1_fire_11;
    case INPUT_JOYSTICK_FIRE_12: return settings_current.joystick_1_fire_12;
    case INPUT_JOYSTICK_FIRE_13: return settings_current.joystick_1_fire_13;
    case INPUT_JOYSTICK_FIRE_14: return settings_current.joystick_1_fire_14;
    case INPUT_JOYSTICK_FIRE_15: return settings_current.joystick_1_fire_15;
    default: break;
    }
    break;

  case 1:
    switch( button ) {
    case INPUT_JOYSTICK_FIRE_1 : return settings_current.joystick_2_fire_1;
    case INPUT_JOYSTICK_FIRE_2 : return settings_current.joystick_2_fire_2;
    case INPUT_JOYSTICK_FIRE_3 : return settings_current.joystick_2_fire_3;
    case INPUT_JOYSTICK_FIRE_4 : return settings_current.joystick_2_fire_4;
    case INPUT_JOYSTICK_FIRE_5 : return settings_current.joystick_2_fire_5;
    case INPUT_JOYSTICK_FIRE_6 : return settings_current.joystick_2_fire_6;
    case INPUT_JOYSTICK_FIRE_7 : return settings_current.joystick_2_fire_7;
    case INPUT_JOYSTICK_FIRE_8 : return settings_current.joystick_2_fire_8;
    case INPUT_JOYSTICK_FIRE_9 : return settings_current.joystick_2_fire_9;
    case INPUT_JOYSTICK_FIRE_10: return settings_current.joystick_2_fire_10;
    case INPUT_JOYSTICK_FIRE_11: return settings_current.joystick_2_fire_11;
    case INPUT_JOYSTICK_FIRE_12: return settings_current.joystick_2_fire_12;
    case INPUT_JOYSTICK_FIRE_13: return settings_current.joystick_2_fire_13;
    case INPUT_JOYSTICK_FIRE_14: return settings_current.joystick_2_fire_14;
    case INPUT_JOYSTICK_FIRE_15: return settings_current.joystick_2_fire_15;
    default: break;
    }
    break;

  }

  ui_error( UI_ERROR_ERROR, "get_fire_button_key: which = %d, button = %d",
	    which, button );
  fuse_abort();
}
int
didaktik80_disk_insert( didaktik80_drive_number which, const char *filename,
		   int autoload )
{
  if( which >= DIDAKTIK80_NUM_DRIVES ) {
    ui_error( UI_ERROR_ERROR, "didaktik80_insert: unknown drive %d",
	      which );
    fuse_abort();
  }

  return ui_media_drive_insert( &didaktik_ui_drives[ which ], filename, autoload );
}
Example #19
0
/* Move all rectangles not updated on this line to the inactive list */
void
rectangle_end_line( int y )
{
  size_t i;
  struct rectangle *ptr;

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

    /* Skip if this rectangle was updated this line */
    if( rectangle_active[i].y + rectangle_active[i].h == y + 1 ) continue;

    if ( settings_current.frame_rate > 1 &&
	 compare_and_merge_rectangles( &rectangle_active[i] ) ) {

      /* Mark the active rectangle as done */
      rectangle_active[i].h = 0;
      continue;
    }

    /* We couldn't find a rectangle to extend, so create a new one */
    if( ++rectangle_inactive_count > rectangle_inactive_allocated ) {

      size_t new_alloc;

      new_alloc = rectangle_inactive_allocated     ?
	          2 * rectangle_inactive_allocated :
	          8;

      ptr = realloc( rectangle_inactive,
		     new_alloc * sizeof( struct rectangle ) );
      if( !ptr ) {
	ui_error( UI_ERROR_ERROR, "Out of memory at %s:%d",
		  __FILE__, __LINE__ );
        fuse_abort();
      }

      rectangle_inactive_allocated = new_alloc; rectangle_inactive = ptr;
    }

    rectangle_inactive[ rectangle_inactive_count - 1 ] = rectangle_active[i];

    /* Mark the active rectangle as done */
    rectangle_active[i].h = 0;
  }

  /* Compress the list of active rectangles */
  for( i = 0, ptr = rectangle_active; i < rectangle_active_count; i++ ) {
    if( rectangle_active[i].h == 0 ) continue;
    *ptr = rectangle_active[i]; ptr++;
  }

  rectangle_active_count = ptr - rectangle_active;
}
Example #20
0
void
compat_socket_networking_init( void )
{
  WORD wVersionRequested;
  WSADATA wsaData;
  int error;

  wVersionRequested = MAKEWORD( 2, 2 );
  error = WSAStartup( wVersionRequested, &wsaData );
  if( error ) {
    ui_error( UI_ERROR_ERROR, "%s:%d: error %d from WSAStartup()", __FILE__,
              __LINE__, error );
    fuse_abort();
  }

  if( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) {
    ui_error( UI_ERROR_ERROR,
              "%s:%d: unexpected version 0x%02x from WSAStartup()",
              __FILE__, __LINE__, wsaData.wVersion );
    fuse_abort();
  }
}
Example #21
0
static libspectrum_dword
evaluate_unaryop( struct unaryop_type *unary )
{
  switch( unary->operation ) {

  case '!': return !debugger_expression_evaluate( unary->op );
  case '~': return ~debugger_expression_evaluate( unary->op );
  case '-': return -debugger_expression_evaluate( unary->op );

  }

  ui_error( UI_ERROR_ERROR, "unknown unary operator %d", unary->operation );
  fuse_abort();
}
Example #22
0
/* Process a z80 maskable interrupt */
int
z80_interrupt( void )
{
  /* An interrupt will occur if IFF1 is set and the /INT line hasn't
     gone high again. On a Timex machine, we also need the SCLD's
     INTDISABLE to be clear */
  if( IFF1 &&
      tstates < machine_current->timings.interrupt_length &&
      !scld_last_dec.name.intdisable ) {

    /* If interrupts have just been enabled, don't accept the interrupt now,
       but check after the next instruction has been executed */
    if( tstates == z80.interrupts_enabled_at ) {
      event_add( tstates + 1, z80_interrupt_event );
      return 0;
    }

    if( z80.halted ) { PC++; z80.halted = 0; }
    
    IFF1=IFF2=0;

    writebyte( --SP, PCH ); writebyte( --SP, PCL );

    R++; rzx_instructions_offset--;

    switch(IM) {
      case 0: PC = 0x0038; tstates += 7; break;
      case 1: PC = 0x0038; tstates += 7; break;
      case 2: 
	{
	  libspectrum_word inttemp=(0x100*I)+0xff;
	  PCL = readbyte(inttemp++); PCH = readbyte(inttemp);
	  tstates += 7;
	  break;
	}
      default:
	ui_error( UI_ERROR_ERROR, "Unknown interrupt mode %d", IM );
	fuse_abort();
    }

    return 1;			/* Accepted an interrupt */

  } else {

    return 0;			/* Did not accept an interrupt */

  }
}
Example #23
0
/* Called by the menu when Machine/Reset selected */
void
menu_machine_reset( int action )
{
  int hard_reset = action;
  const char *message = "Reset?";

  if( hard_reset )
    message = "Hard reset?";
  
  if( win32ui_confirm( message ) && machine_reset( hard_reset ) ) {
    ui_error( UI_ERROR_ERROR, "couldn't reset machine: giving up!" );

    /* FIXME: abort() seems a bit extreme here, but it'll do for now */
    fuse_abort();
  }
}
Example #24
0
/* Check whether 'bp' should trigger if we're looking for a breakpoint
   of 'type' with parameter 'value'. Returns non-zero if we should trigger */
static int
breakpoint_check( debugger_breakpoint *bp, debugger_breakpoint_type type,
		  libspectrum_dword value )
{
  int page;

  if( bp->type != type ) return 0;

  switch( type ) {

  case DEBUGGER_BREAKPOINT_TYPE_EXECUTE:
  case DEBUGGER_BREAKPOINT_TYPE_READ:
  case DEBUGGER_BREAKPOINT_TYPE_WRITE:

    page = bp->value.address.page;

    /* If page == -1, value must match exactly; otherwise, the page and
       the offset must match */
    if( page == -1 ) {
      if( bp->value.address.offset != value ) return 0;
    } else {
      if( page != encode_bank_and_page( type, value ) ) return 0;
      if( bp->value.address.offset != ( value & 0x3fff ) ) return 0;
    }
    break;

    /* Port values must match after masking */
  case DEBUGGER_BREAKPOINT_TYPE_PORT_READ:
  case DEBUGGER_BREAKPOINT_TYPE_PORT_WRITE:
    if( ( value & bp->value.port.mask ) != bp->value.port.port ) return 0;
    break;

    /* Timed breakpoints trigger if we're past the relevant time */
  case DEBUGGER_BREAKPOINT_TYPE_TIME:
    if( bp->value.time.triggered || bp->value.time.tstates > tstates ) return 0;
    break;

  default:
    ui_error( UI_ERROR_ERROR, "Unknown breakpoint type %d", bp->type );
    fuse_abort();

  }

  return debugger_breakpoint_trigger( bp );
}
Example #25
0
compat_socket_selfpipe_t* compat_socket_selfpipe_alloc( void )
{
  int error;
  int pipefd[2];

  compat_socket_selfpipe_t *self =
    libspectrum_new( compat_socket_selfpipe_t, 1 );

  error = pipe( pipefd );
  if( error ) {
    ui_error( UI_ERROR_ERROR, "%s: %d: error %d creating pipe", __FILE__, __LINE__, error );
    fuse_abort();
  }

  self->read_fd = pipefd[0];
  self->write_fd = pipefd[1];

  return self;
}
Example #26
0
/* When deparsing, do we need to put brackets around `operand' when
   being used as an operand of the binary operation `top_operation'? */
static int
brackets_necessary( int top_operation, debugger_expression *operand )
{
  enum precedence_t top_precedence, bottom_precedence;
  
  top_precedence = binaryop_precedence( top_operation );
  bottom_precedence = operand->precedence;

  /* If the top level operation has a higher precedence than the
     bottom level operation, we always need brackets */
  if( top_precedence > bottom_precedence ) return 1;

  /* If the two operations are of equal precedence, we need brackets
     i) if the top level operation is non-associative, or
     ii) if the operand is a non-associative operation

     Note the assumption here that all things with a precedence equal to
     a binary operator are also binary operators

     Strictly, we don't need brackets in either of these cases, but
     otherwise the user is going to have to remember operator
     left-right associativity; I think things are clearer with
     brackets in.
  */
  if( top_precedence == bottom_precedence ) {

    if( is_non_associative( top_operation ) ) return 1;

    /* Sanity check */
    if( operand->type != DEBUGGER_EXPRESSION_TYPE_BINARYOP ) {
      ui_error( UI_ERROR_ERROR,
		"binary operator has same precedence as non-binary operator" );
      fuse_abort();
    }

    return is_non_associative( operand->types.binaryop.operation );
  }

  /* Otherwise (ie if the top level operation is of lower precedence
     than the bottom, or both operators have equal precedence and
     everything is associative) we don't need brackets */
  return 0;
}
Example #27
0
/* Add the rectangle { x, line, w, 1 } to the list of rectangles to be
   redrawn, either by extending an existing rectangle or creating a
   new one */
void
rectangle_add( int y, int x, int w )
{
  size_t i;
  struct rectangle *ptr;

  /* Check through all 'active' rectangles (those which were modified
     on the previous line) and see if we can use this new rectangle
     to extend them */
  for( i = 0; i < rectangle_active_count; i++ ) {

    if( rectangle_active[i].x == x &&
	rectangle_active[i].w == w    ) {
      rectangle_active[i].h++;
      return;
    }
  }

  /* We couldn't find a rectangle to extend, so create a new one */
  if( ++rectangle_active_count > rectangle_active_allocated ) {

    size_t new_alloc;

    new_alloc = rectangle_active_allocated     ?
                2 * rectangle_active_allocated :
                8;

    ptr = realloc( rectangle_active, new_alloc * sizeof( struct rectangle ) );
    if( !ptr ) {
      ui_error( UI_ERROR_ERROR, "Out of memory at %s:%d", __FILE__, __LINE__ );
      fuse_abort();
    }

    rectangle_active_allocated = new_alloc; rectangle_active = ptr;
  }

  ptr = &rectangle_active[ rectangle_active_count - 1 ];

  ptr->x = x; ptr->y = y;
  ptr->w = w; ptr->h = 1;
}
Example #28
0
static int
deparse_unaryop( char *buffer, size_t length,
		 const struct unaryop_type *unaryop )
{
  char *operand_buffer; const char *operation_string = NULL;
  int brackets;

  int error;

  operand_buffer = malloc( length );
  if( !operand_buffer ) {
    ui_error( UI_ERROR_ERROR, "out of memory at %s:%d", __FILE__, __LINE__ );
    return 1;
  }

  error = debugger_expression_deparse( operand_buffer, length, unaryop->op );
  if( error ) { free( operand_buffer ); return error; }

  switch( unaryop->operation ) {
  case '!': operation_string = "!"; break;
  case '~': operation_string = "~"; break;
  case '-': operation_string = "-"; break;

  default:
    ui_error( UI_ERROR_ERROR, "unknown unary operation %d",
	      unaryop->operation );
    fuse_abort();
  }

  brackets = ( unaryop->op->precedence                  < 
	       unaryop_precedence( unaryop->operation )   );
    
  snprintf( buffer, length, "%s%s%s%s", operation_string,
	    brackets ? "( " : "", operand_buffer,
	    brackets ? " )" : "" );

  free( operand_buffer );

  return 0;
}
Example #29
0
int
debugger_breakpoint_add_time( debugger_breakpoint_type type,
			      libspectrum_dword tstates, size_t ignore,
			      debugger_breakpoint_life life,
			      debugger_expression *condition )
{
  debugger_breakpoint_value value;

  switch( type ) {
  case DEBUGGER_BREAKPOINT_TYPE_TIME:
    break;

  default:
    ui_error( UI_ERROR_ERROR, "debugger_breakpoint_add_time given type %d",
	      type );
    fuse_abort();
  }

  value.time.tstates = tstates;

  return breakpoint_add( type, value, ignore, life, condition );
}
int
machine_select( libspectrum_machine type )
{
  int i;
  int error;

  /* We don't want to have to deal with screen size changes in the movie code
     and recording movies where we change machines seems pretty obscure */
  movie_stop();

  for( i=0; i < machine_count; i++ ) {
    if( machine_types[i]->machine == type ) {
      machine_location = i;
      error = machine_select_machine( machine_types[i] );

      if( !error ) return 0;

      /* If we couldn't select the new machine type, try falling back
	 to plain old 48K */
      if( type != LIBSPECTRUM_MACHINE_48 ) 
	error = machine_select( LIBSPECTRUM_MACHINE_48 );
	
      /* If that still didn't work, give up */
      if( error ) {
	ui_error( UI_ERROR_ERROR, "can't select 48K machine. Giving up." );
	fuse_abort();
      } else {
	ui_error( UI_ERROR_INFO, "selecting 48K machine" );
	return 0;
      }
      
      return 0;
    }
  }

  ui_error( UI_ERROR_ERROR, "machine type %d unknown", type );
  return 1;
}