static void
spectranet_control_write( libspectrum_word port, libspectrum_byte data )
{
  if( data & 0x01 )
    spectranet_page( 1 );
  else if( spectranet_paged_via_io )
    spectranet_unpage();

  spectranet_programmable_trap_active = data & 0x08;
}
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 );
  }
}
Esempio n. 3
0
/* Execute Z80 opcodes until the next event */
void
z80_do_opcodes( void )
{
#ifdef HAVE_ENOUGH_MEMORY
  libspectrum_byte opcode = 0x00;
#endif

  int even_m1 =
    machine_current->capabilities & LIBSPECTRUM_MACHINE_CAPABILITY_EVEN_M1; 

#ifdef __GNUC__

#undef SETUP_CHECK
#define SETUP_CHECK( label, condition ) \
  if( condition ) { cgoto[ next ] = &&label; next = pos_##label + 1; } \
  check++;

#undef SETUP_NEXT
#define SETUP_NEXT( label ) \
  if( next != check ) { cgoto[ next ] = &&label; } \
  next = check;

  void *cgoto[ numchecks ]; size_t next = 0; size_t check = 0;

#include "z80_checks.h"

#endif				/* #ifdef __GNUC__ */

  while( tstates < event_next_event ) {

    /* Profiler */
    CHECK( profile, profile_active )

    profile_map( PC );

    END_CHECK

    /* If we're due an end of frame from RZX playback, generate one */
    CHECK( rzx, rzx_playback )

    if( R + rzx_instructions_offset >= rzx_instruction_count ) {
      event_add( tstates, spectrum_frame_event );
      break;		/* And break out of the execution loop to let
			   the interrupt happen */
    }

    END_CHECK

    /* Check if the debugger should become active at this point */
    CHECK( debugger, debugger_mode != DEBUGGER_MODE_INACTIVE )

    if( !z80.halted && debugger_check( DEBUGGER_BREAKPOINT_TYPE_EXECUTE, PC ) )
      debugger_trap();

    END_CHECK

    CHECK( beta, beta_available )

#define NOT_128_TYPE_OR_IS_48_TYPE ( !( machine_current->capabilities & \
            LIBSPECTRUM_MACHINE_CAPABILITY_128_MEMORY ) || \
            machine_current->ram.current_rom )

    if( beta_active ) {
      if( NOT_128_TYPE_OR_IS_48_TYPE && PC >= 16384 ) {
	beta_unpage();
      }
    } else if( ( PC & beta_pc_mask ) == beta_pc_value &&
               NOT_128_TYPE_OR_IS_48_TYPE ) {
      beta_page();
    }

    END_CHECK

    CHECK( plusd, plusd_available )

    if( PC == 0x0008 || PC == 0x003a || PC == 0x0066 || PC == 0x028e ) {
      plusd_page();
    }

    END_CHECK

    CHECK( didaktik80, didaktik80_available )

    if( PC == 0x0000 || PC == 0x0008 ) {
      didaktik80_page();
    } else if( PC == 0x1700 ) {
      didaktik80_unpage();
    }

    END_CHECK

    CHECK( disciple, disciple_available )

    if( PC == 0x0001 || PC == 0x0008 || PC == 0x0066 || PC == 0x028e ) {
      disciple_page();
    }

    END_CHECK

    CHECK( usource, usource_available )

    if( PC == 0x2bae ) {
      usource_toggle();
    }

    END_CHECK

    CHECK( if1p, if1_available )

    if( PC == 0x0008 || PC == 0x1708 ) {
      if1_page();
    }

    END_CHECK

    CHECK( divide_early, settings_current.divide_enabled )
    
    if( ( PC & 0xff00 ) == 0x3d00 ) {
      divide_set_automap( 1 );
    }
    
    END_CHECK

    CHECK( spectranet_page, spectranet_available && !settings_current.spectranet_disable )

    if( PC == 0x0008 || ((PC & 0xfff8) == 0x3ff8) )
      spectranet_page( 0 );

    if( PC == spectranet_programmable_trap &&
      spectranet_programmable_trap_active )
      event_add( 0, z80_nmi_event );

    END_CHECK

  opcode_delay:

    contend_read( PC, 4 );

    /* Check to see if M1 cycles happen on even tstates */
    CHECK( evenm1, even_m1 )

    if( tstates & 1 ) {
      if( ++tstates == event_next_event ) {
	break;
      }
    }

    END_CHECK

  run_opcode:
    /* Do the instruction fetch; readbyte_internal used here to avoid
       triggering read breakpoints */
    opcode = readbyte_internal( PC );

    CHECK( if1u, if1_available )

    if( PC == 0x0700 ) {
      if1_unpage();
    }

    END_CHECK

    CHECK( divide_late, settings_current.divide_enabled )

    if( ( PC & 0xfff8 ) == 0x1ff8 ) {
      divide_set_automap( 0 );
    } else if( (PC == 0x0000) || (PC == 0x0008) || (PC == 0x0038)
      || (PC == 0x0066) || (PC == 0x04c6) || (PC == 0x0562) ) {
      divide_set_automap( 1 );
    }
    
    END_CHECK

    CHECK( opus, opus_available )

    if( opus_active ) {
      if( PC == 0x1748 ) {
        opus_unpage();
      }
    } else if( PC == 0x0008 || PC == 0x0048 || PC == 0x1708 ) {
      opus_page();
    }

    END_CHECK

    CHECK( spectranet_unpage, spectranet_available )

    if( PC == 0x007c )
      spectranet_unpage();

    END_CHECK

    CHECK( z80_halted, z80.halted )

    /* Opcode read from memory is ignored and PC is left unchanged */
    R++;
    continue;

    END_CHECK

    CHECK( z80_iff2_read, z80.iff2_read )

    z80.iff2_read = 0;
    /* Execute *one* instruction before reevaluating the checks */
    event_add( tstates, z80_nmos_iff2_event );

    END_CHECK

    CHECK( didaktik80snap, didaktik80_snap )

    if( PC == 0x0066 && !didaktik80_active ) {
      opcode = 0xc7;	/* RST 00 */
      didaktik80_snap = 0; /* FIXME: this should be a time-based reset */
    }

    END_CHECK

    CHECK( svg_capture, svg_capture_active )

    svg_capture();

    END_CHECK

  end_opcode:
    PC++; R++;
    switch(opcode) {
#include "z80/opcodes_base.c"
    }

  }

}