Пример #1
0
libspectrum_byte
readbyte( libspectrum_word address )
{
  libspectrum_word bank;
  memory_page *mapping;

  bank = address >> MEMORY_PAGE_SIZE_LOGARITHM;
  mapping = &memory_map_read[ bank ];

  if( debugger_mode != DEBUGGER_MODE_INACTIVE )
    debugger_check( DEBUGGER_BREAKPOINT_TYPE_READ, address );

  if( mapping->contended ) tstates += ula_contention[ tstates ];
  tstates += 3;

  if( opus_active && address >= 0x2800 && address < 0x3800 )
    return opus_read( address );

  if( spectranet_paged ) {
    if( spectranet_w5100_paged_a && address >= 0x1000 && address < 0x2000 )
      return spectranet_w5100_read( mapping, address );
    if( spectranet_w5100_paged_b && address >= 0x2000 && address < 0x3000 )
      return spectranet_w5100_read( mapping, address );
  }

  return mapping->page[ address & MEMORY_PAGE_SIZE_MASK ];
}
Пример #2
0
void
writebyte( libspectrum_word address, libspectrum_byte b )
{
  libspectrum_word bank;
  memory_page *mapping;

  bank = address >> 13;
  mapping = &memory_map_write[ bank ];

  if( debugger_mode != DEBUGGER_MODE_INACTIVE )
    debugger_check( DEBUGGER_BREAKPOINT_TYPE_WRITE, address );

  if( mapping->contended ) tstates += ula_contention[ tstates ];

  tstates += 3;

  writebyte_internal( address, b );
}
Пример #3
0
libspectrum_byte
readbyte( libspectrum_word address )
{
  libspectrum_word bank;
  memory_page *mapping;

  bank = address >> 13;
  mapping = &memory_map_read[ bank ];

  if( debugger_mode != DEBUGGER_MODE_INACTIVE )
    debugger_check( DEBUGGER_BREAKPOINT_TYPE_READ, address );

  if( mapping->contended ) tstates += ula_contention[ tstates ];
  tstates += 3;

  if( opus_active && address >= 0x2800 && address < 0x3800 )
    return opus_read( address );

  return mapping->page[ address & 0x1fff ];
}
Пример #4
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"
    }

  }

}