コード例 #1
0
ファイル: speccyboot.c プロジェクト: jacadym/fuse-emulator
static void
speccyboot_reset( int hard_reset GCC_UNUSED )
{
    static int tap_opened = 0;

    speccyboot_rom_active = 0;

    if( !periph_is_active( PERIPH_TYPE_SPECCYBOOT ) )
        return;

    if( machine_load_rom_bank( speccyboot_memory_map_romcs, 0,
                               settings_current.rom_speccyboot,
                               settings_default.rom_speccyboot, 0x2000 ) )
        return;

    out_register_state = 0xff;  /* force transitions to low */

    speccyboot_register_write( 0, 0 );

    /*
     * Open TAP. If this fails, SpeccyBoot emulation won't work.
     *
     * This is done here rather than in speccyboot_init() to ensure any
     * error messages are only displayed if SpeccyBoot emulation is
     * actually requested.
     */
    if( !tap_opened ) {
        nic_enc28j60_init( nic );
        tap_opened = 1;
    }
}
コード例 #2
0
ファイル: opus.c プロジェクト: jacadym/fuse-emulator
static void
opus_reset( int hard_reset )
{
    int i;

    opus_active = 0;
    opus_available = 0;

    if( !periph_is_active( PERIPH_TYPE_OPUS ) ) {
        return;
    }

    if( machine_load_rom_bank( opus_memory_map_romcs_rom, 0,
                               settings_current.rom_opus,
                               settings_default.rom_opus, 0x2000 ) ) {
        settings_current.opus = 0;
        periph_activate_type( PERIPH_TYPE_OPUS, 0 );
        return;
    }

    for( i = 0; i < MEMORY_PAGES_IN_2K; i++ ) {
        struct memory_page *page =
                &opus_memory_map_romcs_ram[ i ];
        page->page = opus_ram + i * MEMORY_PAGE_SIZE;
        page->offset = i * MEMORY_PAGE_SIZE;
    }

    machine_current->ram.romcs = 0;

    for( i = 0; i < MEMORY_PAGES_IN_2K; i++ )
        opus_memory_map_romcs_ram[ i ].writable = 1;

    data_reg_a = 0;
    data_dir_a = 0;
    control_a  = 0;
    data_reg_b = 0;
    data_dir_b = 0;
    control_b  = 0;

    opus_available = 1;

    if( hard_reset )
        memset( opus_ram, 0, sizeof( opus_ram ) );

    wd_fdc_master_reset( opus_fdc );

    for( i = 0; i < OPUS_NUM_DRIVES; i++ ) {
        ui_media_drive_update_menus( &opus_ui_drives[ i ],
                                     UI_MEDIA_DRIVE_UPDATE_ALL );
    }

    opus_fdc->current_drive = &opus_drives[ 0 ];
    fdd_select( &opus_drives[ 0 ], 1 );
    machine_current->memory_map();

    ui_statusbar_update( UI_STATUSBAR_ITEM_DISK, UI_STATUSBAR_STATE_INACTIVE );
}
コード例 #3
0
ファイル: sound.c プロジェクト: matthewbauer/fuse-libretro
/*
 * sound_specdrum_write - very simple routine
 * as the output is already a digitized waveform
 */
void
sound_specdrum_write( libspectrum_word port GCC_UNUSED, libspectrum_byte val )
{
  if( periph_is_active( PERIPH_TYPE_SPECDRUM ) ) {
    blip_synth_update( left_specdrum_synth, tstates, ( val - 128) * 128);
    if( right_specdrum_synth ) {
      blip_synth_update( right_specdrum_synth, tstates, ( val - 128) * 128);
    }
    machine_current->specdrum.specdrum_dac = val - 128;
  }
}
コード例 #4
0
static void
didaktik_reset( int hard_reset )
{
  int i;

  didaktik80_active = 0;
  didaktik80_available = 0;

  ui_menu_activate( UI_MENU_ITEM_MACHINE_DIDAKTIK80_SNAP, 0 );
  if( !periph_is_active( PERIPH_TYPE_DIDAKTIK80 ) ) {
    return;
  }

  if( machine_load_rom_bank( didaktik_memory_map_romcs_rom, 0,
                             settings_current.rom_didaktik80,
                             settings_default.rom_didaktik80, ROM_SIZE ) ) {
    settings_current.didaktik80 = 0;
    periph_activate_type( PERIPH_TYPE_DIDAKTIK80, 0 );
    return;
  }

  ui_menu_activate( UI_MENU_ITEM_MACHINE_DIDAKTIK80_SNAP, 1 );

  for( i = 0; i < MEMORY_PAGES_IN_2K; i++ ) {
    struct memory_page *page =
      &didaktik_memory_map_romcs_ram[ i ];
    page->page = ram + i * MEMORY_PAGE_SIZE;
    page->offset = i * MEMORY_PAGE_SIZE;
    page->writable = 1;
  }

  machine_current->ram.romcs = 0;

  aux_register = 0;

  didaktik80_available = 1;

  if( hard_reset )
    memset( ram, 0, sizeof( ram ) );

  wd_fdc_master_reset( didaktik_fdc );

  for( i = 0; i < DIDAKTIK80_NUM_DRIVES; i++ ) {
    ui_media_drive_update_menus( &didaktik_ui_drives[ i ],
                                 UI_MEDIA_DRIVE_UPDATE_ALL );
  }

  didaktik_fdc->current_drive = &didaktik_drives[ 0 ];
  fdd_select( &didaktik_drives[ 0 ], 1 );
  fdd_select( &didaktik_drives[ 1 ], 0 );
  machine_current->memory_map();

}
コード例 #5
0
ファイル: plusd.c プロジェクト: jacadym/fuse-emulator
static void
plusd_reset( int hard_reset )
{
  int i;

  plusd_active = 0;
  plusd_available = 0;

  if( !periph_is_active( PERIPH_TYPE_PLUSD ) ) {
    return;
  }

  if( machine_load_rom_bank( plusd_memory_map_romcs_rom, 0,
			     settings_current.rom_plusd,
			     settings_default.rom_plusd, 0x2000 ) ) {
    settings_current.plusd = 0;
    periph_activate_type( PERIPH_TYPE_PLUSD, 0 );
    return;
  }

  machine_current->ram.romcs = 0;

  for( i = 0; i < MEMORY_PAGES_IN_8K; i++ ) {
    plusd_memory_map_romcs_ram[ i ].page = &plusd_ram[ i * MEMORY_PAGE_SIZE ];
    plusd_memory_map_romcs_ram[ i ].writable = 1;
  }

  plusd_available = 1;
  plusd_active = 1;

  if( hard_reset )
    memset( plusd_ram, 0, 0x2000 );

  wd_fdc_master_reset( plusd_fdc );

  for( i = 0; i < PLUSD_NUM_DRIVES; i++ ) {
    ui_media_drive_update_menus( &plusd_ui_drives[ i ],
                                 UI_MEDIA_DRIVE_UPDATE_ALL );
  }

  plusd_fdc->current_drive = &plusd_drives[ 0 ];
  fdd_select( &plusd_drives[ 0 ], 1 );
  machine_current->memory_map();

  ui_statusbar_update( UI_STATUSBAR_ITEM_DISK, UI_STATUSBAR_STATE_INACTIVE );
}
コード例 #6
0
static void
didaktik_to_snapshot( libspectrum_snap *snap )
{
  libspectrum_byte *buffer;
  int drive_count = 0;
  int i;
  size_t memory_length;

  if( !periph_is_active( PERIPH_TYPE_DIDAKTIK80 ) ) return;

  libspectrum_snap_set_didaktik80_active( snap, 1 );

  memory_length = ROM_SIZE;

  libspectrum_snap_set_didaktik80_custom_rom( snap, 1 );
  libspectrum_snap_set_didaktik80_rom_length( snap, 0, memory_length );

  buffer = libspectrum_new( libspectrum_byte, memory_length );

  for( i = 0; i < MEMORY_PAGES_IN_14K; i++ )
    memcpy( buffer + i * MEMORY_PAGE_SIZE,
            didaktik_memory_map_romcs_rom[ i ].page, MEMORY_PAGE_SIZE );

  libspectrum_snap_set_didaktik80_rom( snap, 0, buffer );

  memory_length = RAM_SIZE;
  buffer = libspectrum_new( libspectrum_byte, memory_length );

  for( i = 0; i < MEMORY_PAGES_IN_2K; i++ )
    memcpy( buffer + i * MEMORY_PAGE_SIZE,
            didaktik_memory_map_romcs_ram[ i ].page, MEMORY_PAGE_SIZE );
  libspectrum_snap_set_didaktik80_ram( snap, 0, buffer );

  drive_count++; /* Drive 1 is not removable */
  if( option_enumerate_diskoptions_drive_didaktik80b_type() > 0 ) drive_count++;
  libspectrum_snap_set_didaktik80_drive_count( snap, drive_count );

  libspectrum_snap_set_didaktik80_paged ( snap, didaktik80_active );
  libspectrum_snap_set_didaktik80_direction( snap, didaktik_fdc->direction );
  libspectrum_snap_set_didaktik80_status( snap, didaktik_fdc->status_register );
  libspectrum_snap_set_didaktik80_track ( snap, didaktik_fdc->track_register );
  libspectrum_snap_set_didaktik80_sector( snap, didaktik_fdc->sector_register );
  libspectrum_snap_set_didaktik80_data  ( snap, didaktik_fdc->data_register );
  libspectrum_snap_set_didaktik80_aux   ( snap, aux_register );
}
コード例 #7
0
static void
spectranet_to_snapshot( libspectrum_snap *snap )
{
  libspectrum_byte *snap_buffer, *src;

  int active = periph_is_active( PERIPH_TYPE_SPECTRANET );
  libspectrum_snap_set_spectranet_active( snap, active );

  if( !active )
    return;

  libspectrum_snap_set_spectranet_paged( snap, spectranet_paged );
  libspectrum_snap_set_spectranet_paged_via_io( snap, spectranet_paged_via_io );
  libspectrum_snap_set_spectranet_programmable_trap( snap,
    spectranet_programmable_trap );
  libspectrum_snap_set_spectranet_programmable_trap_active( snap,
    spectranet_programmable_trap_active );
  libspectrum_snap_set_spectranet_programmable_trap_msb( snap, trap_write_msb );
  libspectrum_snap_set_spectranet_deny_downstream_a15( snap, 0 );
  libspectrum_snap_set_spectranet_nmi_flipflop( snap, nmi_flipflop );

  libspectrum_snap_set_spectranet_all_traps_disabled( snap,
    settings_current.spectranet_disable );
  libspectrum_snap_set_spectranet_rst8_trap_disabled( snap, 0 );
  libspectrum_snap_set_spectranet_page_a(
    snap, spectranet_current_map[1 * MEMORY_PAGES_IN_4K].page_num );
  libspectrum_snap_set_spectranet_page_b(
    snap, spectranet_current_map[2 * MEMORY_PAGES_IN_4K].page_num );

  libspectrum_snap_set_spectranet_w5100( snap, 0,
    nic_w5100_to_snapshot( w5100 ) );

  snap_buffer = libspectrum_new( libspectrum_byte, SPECTRANET_ROM_LENGTH );

  src = spectranet_full_map[SPECTRANET_ROM_BASE * MEMORY_PAGES_IN_4K].page;
  memcpy( snap_buffer, src, SPECTRANET_ROM_LENGTH );
  libspectrum_snap_set_spectranet_flash( snap, 0, snap_buffer );

  snap_buffer = libspectrum_new( libspectrum_byte, SPECTRANET_RAM_LENGTH );

  src = spectranet_full_map[SPECTRANET_RAM_BASE * MEMORY_PAGES_IN_4K].page;
  memcpy( snap_buffer, src, SPECTRANET_RAM_LENGTH );
  libspectrum_snap_set_spectranet_ram( snap, 0, snap_buffer );
}
コード例 #8
0
static void
spectranet_from_snapshot( libspectrum_snap *snap )
{
  if( !libspectrum_snap_spectranet_active( snap ) )
    return;

  if( periph_is_active( PERIPH_TYPE_SPECTRANET ) ) {

    spectranet_programmable_trap =
      libspectrum_snap_spectranet_programmable_trap( snap );
    spectranet_programmable_trap_active = 
      libspectrum_snap_spectranet_programmable_trap_active( snap );
    trap_write_msb =
      libspectrum_snap_spectranet_programmable_trap_msb( snap );

    settings_current.spectranet_disable =
      libspectrum_snap_spectranet_all_traps_disabled( snap );

    spectranet_map_page( 1, libspectrum_snap_spectranet_page_a( snap ) );
    spectranet_map_page( 2, libspectrum_snap_spectranet_page_b( snap ) );

    nmi_flipflop = libspectrum_snap_spectranet_nmi_flipflop( snap );

    if( libspectrum_snap_spectranet_paged( snap ) ) {
      spectranet_page( libspectrum_snap_spectranet_paged_via_io( snap ) );
      memory_map_romcs_full( spectranet_current_map );
    }
    else
      spectranet_unpage();

    nic_w5100_from_snapshot( w5100,
      libspectrum_snap_spectranet_w5100( snap, 0 ) );

    memcpy(
      spectranet_full_map[SPECTRANET_ROM_BASE * MEMORY_PAGES_IN_4K].page,
      libspectrum_snap_spectranet_flash( snap, 0 ), SPECTRANET_ROM_LENGTH );
    memcpy(
      spectranet_full_map[SPECTRANET_RAM_BASE * MEMORY_PAGES_IN_4K].page,
      libspectrum_snap_spectranet_ram( snap, 0 ), SPECTRANET_RAM_LENGTH );
  }
}
コード例 #9
0
static void
usource_reset( int hard_reset GCC_UNUSED )
{
  usource_active = 0;
  usource_available = 0;

  if( !periph_is_active( PERIPH_TYPE_USOURCE ) )
    return;

  if( machine_load_rom_bank( usource_memory_map_romcs, 0,
			     settings_current.rom_usource,
			     settings_default.rom_usource, 0x2000 ) ) {
    settings_current.usource = 0;
    periph_activate_type( PERIPH_TYPE_USOURCE, 0 );
    return;
  }

  machine_current->ram.romcs = 0;

  usource_available = 1;
}
コード例 #10
0
static void
spectranet_reset( int hard_reset )
{
  if( !periph_is_active( PERIPH_TYPE_SPECTRANET ) ) {
    spectranet_available = 0;
    spectranet_paged = 0;
    return;
  }

  spectranet_available = 1;
  spectranet_paged = !settings_current.spectranet_disable;

  if( hard_reset )
    spectranet_hard_reset();

  if( spectranet_paged ) {
    machine_current->ram.romcs = 1;
    machine_current->memory_map();
  }

  nic_w5100_reset( w5100 );
}
コード例 #11
0
ファイル: sound.c プロジェクト: matthewbauer/fuse-libretro
static void
sound_ay_overlay( void )
{
  static int rng = 1;
  static int noise_toggle = 0;
  static int env_first = 1, env_rev = 0, env_counter = 15;
  int tone_level[3];
  int mixer, envshape;
  int g, level;
  libspectrum_dword f;
  struct ay_change_tag *change_ptr = ay_change;
  int changes_left = ay_change_count;
  int reg, r;
  int chan1, chan2, chan3;
  int last_chan1 = 0, last_chan2 = 0, last_chan3 = 0;
  unsigned int tone_count, noise_count;

  /* If no AY chip, don't produce any AY sound (!) */
  if( !( periph_is_active( PERIPH_TYPE_FULLER) ||
         periph_is_active( PERIPH_TYPE_MELODIK ) ||
         machine_current->capabilities & LIBSPECTRUM_MACHINE_CAPABILITY_AY ) )
    return;

  for( f = 0; f < machine_current->timings.tstates_per_frame;
       f+= AY_CLOCK_DIVISOR * AY_CLOCK_RATIO ) {
    /* update ay registers. */
    while( changes_left && f >= change_ptr->tstates ) {
      sound_ay_registers[ reg = change_ptr->reg ] = change_ptr->val;
      change_ptr++;
      changes_left--;

      /* fix things as needed for some register changes */
      switch ( reg ) {
      case 0: case 1: case 2: case 3: case 4: case 5:
        r = reg >> 1;
        /* a zero-len period is the same as 1 */
        ay_tone_period[r] = ( sound_ay_registers[ reg & ~1 ] |
                              ( sound_ay_registers[ reg | 1 ] & 15 ) << 8 );
        if( !ay_tone_period[r] )
          ay_tone_period[r]++;

        /* important to get this right, otherwise e.g. Ghouls 'n' Ghosts
         * has really scratchy, horrible-sounding vibrato.
         */
        if( ay_tone_tick[r] >= ay_tone_period[r] * 2 )
          ay_tone_tick[r] %= ay_tone_period[r] * 2;
        break;
      case 6:
        ay_noise_tick = 0;
        ay_noise_period = ( sound_ay_registers[ reg ] & 31 );
        break;
      case 11: case 12:
        ay_env_period =
          sound_ay_registers[11] | ( sound_ay_registers[12] << 8 );
        break;
      case 13:
        ay_env_internal_tick = ay_env_tick = ay_env_cycles = 0;
        env_first = 1;
        env_rev = 0;
        env_counter = ( sound_ay_registers[13] & AY_ENV_ATTACK ) ? 0 : 15;
        break;
      }
    }

    /* the tone level if no enveloping is being used */
    for( g = 0; g < 3; g++ )
      tone_level[g] = ay_tone_levels[ sound_ay_registers[ 8 + g ] & 15 ];

    /* envelope */
    envshape = sound_ay_registers[13];
    level = ay_tone_levels[ env_counter ];

    for( g = 0; g < 3; g++ )
      if( sound_ay_registers[ 8 + g ] & 16 )
        tone_level[g] = level;

    /* envelope output counter gets incr'd every 16 AY cycles. */
    ay_env_cycles += AY_CLOCK_DIVISOR;
    noise_count = 0;
    while( ay_env_cycles >= 16 ) {
      ay_env_cycles -= 16;
      noise_count++;
      ay_env_tick++;
      while( ay_env_tick >= ay_env_period ) {
        ay_env_tick -= ay_env_period;

        /* do a 1/16th-of-period incr/decr if needed */
        if( env_first ||
            ( ( envshape & AY_ENV_CONT ) && !( envshape & AY_ENV_HOLD ) ) ) {
          if( env_rev )
            env_counter -= ( envshape & AY_ENV_ATTACK ) ? 1 : -1;
          else
            env_counter += ( envshape & AY_ENV_ATTACK ) ? 1 : -1;
          if( env_counter < 0 )
            env_counter = 0;
          if( env_counter > 15 )
            env_counter = 15;
        }

        ay_env_internal_tick++;
        while( ay_env_internal_tick >= 16 ) {
          ay_env_internal_tick -= 16;

          /* end of cycle */
          if( !( envshape & AY_ENV_CONT ) )
            env_counter = 0;
          else {
            if( envshape & AY_ENV_HOLD ) {
              if( env_first && ( envshape & AY_ENV_ALT ) )
                env_counter = ( env_counter ? 0 : 15 );
            } else {
              /* non-hold */
              if( envshape & AY_ENV_ALT )
                env_rev = !env_rev;
              else
                env_counter = ( envshape & AY_ENV_ATTACK ) ? 0 : 15;
            }
          }

          env_first = 0;
        }

        /* don't keep trying if period is zero */
        if( !ay_env_period )
          break;
      }
    }

    /* generate tone+noise... or neither.
     * (if no tone/noise is selected, the chip just shoves the
     * level out unmodified. This is used by some sample-playing
     * stuff.)
     */
    chan1 = tone_level[0];
    chan2 = tone_level[1];
    chan3 = tone_level[2];
    mixer = sound_ay_registers[7];

    ay_tone_cycles += AY_CLOCK_DIVISOR;
    tone_count = ay_tone_cycles >> 3;
    ay_tone_cycles &= 7;

    if( ( mixer & 1 ) == 0 ) {
      level = chan1;
      ay_do_tone( level, tone_count, &chan1, 0 );
    }
    if( ( mixer & 0x08 ) == 0 && noise_toggle )
      chan1 = 0;

    if( ( mixer & 2 ) == 0 ) {
      level = chan2;
      ay_do_tone( level, tone_count, &chan2, 1 );
    }
    if( ( mixer & 0x10 ) == 0 && noise_toggle )
      chan2 = 0;

    if( ( mixer & 4 ) == 0 ) {
      level = chan3;
      ay_do_tone( level, tone_count, &chan3, 2 );
    }
    if( ( mixer & 0x20 ) == 0 && noise_toggle )
      chan3 = 0;

    if( last_chan1 != chan1 ) {
      blip_synth_update( ay_a_synth, f, chan1 );
      if( ay_a_synth_r ) blip_synth_update( ay_a_synth_r, f, chan1 );
      last_chan1 = chan1;
    }
    if( last_chan2 != chan2 ) {
      blip_synth_update( ay_b_synth, f, chan2 );
      if( ay_b_synth_r ) blip_synth_update( ay_b_synth_r, f, chan2 );
      last_chan2 = chan2;
    }
    if( last_chan3 != chan3 ) {
      blip_synth_update( ay_c_synth, f, chan3 );
      if( ay_c_synth_r ) blip_synth_update( ay_c_synth_r, f, chan3 );
      last_chan3 = chan3;
    }

    /* update noise RNG/filter */
    ay_noise_tick += noise_count;
    while( ay_noise_tick >= ay_noise_period ) {
      ay_noise_tick -= ay_noise_period;

      if( ( rng & 1 ) ^ ( ( rng & 2 ) ? 1 : 0 ) )
        noise_toggle = !noise_toggle;

      /* rng is 17-bit shift reg, bit 0 is output.
       * input is bit 0 xor bit 3.
       */
      if( rng & 1 ) {
        rng ^= 0x24000;
      }
      rng >>= 1;

      /* don't keep trying if period is zero */
      if( !ay_noise_period )
        break;
    }
  }
}
コード例 #12
0
ファイル: utils.c プロジェクト: jacadym/fuse-emulator
/* Open `filename' and do something sensible with it; autoload tapes
   if `autoload' is true and return the type of file found in `type' */
int
utils_open_file( const char *filename, int autoload,
		 libspectrum_id_t *type_ptr)
{
  utils_file file;
  libspectrum_id_t type;
  libspectrum_class_t class;
  int error;

  error = 0;
  if( rzx_recording ) error = rzx_stop_recording();
  if( rzx_playback  ) error = rzx_stop_playback( 1 );
  if( error ) return error;

  /* Read the file into a buffer */
  if( utils_read_file( filename, &file ) ) return 1;

  /* See if we can work out what it is */
  if( libspectrum_identify_file_with_class( &type, &class, filename,
					    file.buffer, file.length ) ) {
    utils_close_file( &file );
    return 1;
  }

  switch( class ) {
    
  case LIBSPECTRUM_CLASS_UNKNOWN:
    ui_error( UI_ERROR_ERROR, "utils_open_file: couldn't identify `%s'",
	      filename );
    utils_close_file( &file );
    return 1;

  case LIBSPECTRUM_CLASS_RECORDING:
    error = rzx_start_playback_from_buffer( file.buffer, file.length );
    break;

  case LIBSPECTRUM_CLASS_SNAPSHOT:
    error = snapshot_read_buffer( file.buffer, file.length, type );
    pokemem_find_pokfile( filename );
    break;

  case LIBSPECTRUM_CLASS_TAPE:
    error = tape_read_buffer( file.buffer, file.length, type, filename,
			      autoload );
    pokemem_find_pokfile( filename );
    break;

  case LIBSPECTRUM_CLASS_DISK_PLUS3:
    if( !( machine_current->capabilities &
	   LIBSPECTRUM_MACHINE_CAPABILITY_PLUS3_DISK ) ) {
      error = machine_select( LIBSPECTRUM_MACHINE_PLUS3 ); if( error ) break;
    }

    error = specplus3_disk_insert( SPECPLUS3_DRIVE_A, filename, autoload );
    break;

  case LIBSPECTRUM_CLASS_DISK_DIDAKTIK:

    error = didaktik80_disk_insert( DIDAKTIK80_DRIVE_A, filename, autoload );
    break;

  case LIBSPECTRUM_CLASS_DISK_PLUSD:

    if( periph_is_active( PERIPH_TYPE_DISCIPLE ) )
      error = disciple_disk_insert( DISCIPLE_DRIVE_1, filename, autoload );
    else
      error = plusd_disk_insert( PLUSD_DRIVE_1, filename, autoload );
    break;

  case LIBSPECTRUM_CLASS_DISK_OPUS:

    error = opus_disk_insert( OPUS_DRIVE_1, filename, autoload );
    break;

  case LIBSPECTRUM_CLASS_DISK_TRDOS:

    if( !( machine_current->capabilities &
	   LIBSPECTRUM_MACHINE_CAPABILITY_TRDOS_DISK ) &&
        !periph_is_active( PERIPH_TYPE_BETA128 ) ) {
      error = machine_select( LIBSPECTRUM_MACHINE_PENT ); if( error ) break;
    }

    /* Check that we actually got a Beta capable machine to insert the disk */
    if( ( machine_current->capabilities & 
          LIBSPECTRUM_MACHINE_CAPABILITY_TRDOS_DISK ) ||
        periph_is_active( PERIPH_TYPE_BETA128 ) ) {
      error = beta_disk_insert( BETA_DRIVE_A, filename, autoload );
    }
    break;

  case LIBSPECTRUM_CLASS_DISK_GENERIC:
    if( machine_current->machine == LIBSPECTRUM_MACHINE_PLUS3 ||
        machine_current->machine == LIBSPECTRUM_MACHINE_PLUS2A )
      error = specplus3_disk_insert( SPECPLUS3_DRIVE_A, filename, autoload );
    else if( machine_current->machine == LIBSPECTRUM_MACHINE_PENT ||
          machine_current->machine == LIBSPECTRUM_MACHINE_PENT512 ||
          machine_current->machine == LIBSPECTRUM_MACHINE_PENT1024 ||
          machine_current->machine == LIBSPECTRUM_MACHINE_SCORP )
      error = beta_disk_insert( BETA_DRIVE_A, filename, autoload );
    else
      if( periph_is_active( PERIPH_TYPE_BETA128 ) )
        error = beta_disk_insert( BETA_DRIVE_A, filename, autoload );
      else if( periph_is_active( PERIPH_TYPE_DISCIPLE ) )
        error = disciple_disk_insert( DISCIPLE_DRIVE_1, filename, autoload );
      else if( periph_is_active( PERIPH_TYPE_PLUSD ) )
        error = plusd_disk_insert( PLUSD_DRIVE_1, filename, autoload );
    break;

  case LIBSPECTRUM_CLASS_CARTRIDGE_IF2:
    error = if2_insert( filename );
    break;

  case LIBSPECTRUM_CLASS_MICRODRIVE:
    error = if1_mdr_insert( -1, filename );
    break;

  case LIBSPECTRUM_CLASS_CARTRIDGE_TIMEX:
    if( !( machine_current->capabilities &
	   LIBSPECTRUM_MACHINE_CAPABILITY_TIMEX_DOCK ) ) {
      error = machine_select( LIBSPECTRUM_MACHINE_TC2068 ); if( error ) break;
    }
    /* Check that we actually got a Dock capable machine to insert the cart */
    if( machine_current->capabilities &
	   LIBSPECTRUM_MACHINE_CAPABILITY_TIMEX_DOCK ) {
      error = dck_insert( filename );
    }
    break;

  case LIBSPECTRUM_CLASS_HARDDISK:
    if( !settings_current.simpleide_active &&
	!settings_current.zxatasp_active   &&
	!settings_current.divide_enabled   &&
	!settings_current.zxcf_active         ) {
      settings_current.zxcf_active = 1;
      periph_update();
    }

    if( settings_current.zxcf_active ) {
      error = zxcf_insert( filename );
    } else if( settings_current.zxatasp_active ) {
      error = zxatasp_insert( filename, LIBSPECTRUM_IDE_MASTER );
    } else if( settings_current.simpleide_active ) {
      error = simpleide_insert( filename, LIBSPECTRUM_IDE_MASTER );
    } else {
      error = divide_insert( filename, LIBSPECTRUM_IDE_MASTER );
    }
    if( error ) return error;
    
    break;

  case LIBSPECTRUM_CLASS_AUXILIARY:
    if( type == LIBSPECTRUM_ID_AUX_POK ) {
      ui_pokemem_selector( filename );
    }
    break;

  default:
    ui_error( UI_ERROR_ERROR, "utils_open_file: unknown class %d", type );
    error = 1;
    break;
  }

  if( error ) { utils_close_file( &file ); return error; }

  utils_close_file( &file );

  if( type_ptr ) *type_ptr = type;

  return 0;
}