Esempio n. 1
0
/* Load the next tape block into memory; returns 0 if a block was
   loaded (even if it had an tape loading error or equivalent) or
   non-zero if there was an error at the emulator level, or tape traps
   are not active */
int tape_load_trap( void )
{
  libspectrum_tape_block *block, *next_block;
  int error;

  /* Do nothing if tape traps aren't active, or the tape is already playing */
  if( !settings_current.tape_traps || tape_playing ) return 2;

  /* Do nothing if we're not in the correct ROM */
  if( !trap_check_rom( CHECK_TAPE_ROM ) ) return 3;

  /* Return with error if no tape file loaded */
  if( !libspectrum_tape_present( tape ) ) return 1;

  block = libspectrum_tape_current_block( tape );

  /* Skip over any meta-data blocks */
  while( libspectrum_tape_block_metadata( block ) ) {
    block = libspectrum_tape_select_next_block( tape );
    if( !block ) return 1;
  }
  
  /* If this block isn't a ROM loader, start the block playing. After
     that, return with `error' so that we actually do whichever
     instruction it was that caused the trap to hit */
  if( libspectrum_tape_block_type( block ) != LIBSPECTRUM_TAPE_BLOCK_ROM ||
      libspectrum_tape_state( tape ) != LIBSPECTRUM_TAPE_STATE_PILOT ) {
    tape_play( 1 );
    return -1;
  }

  /* We don't properly handle the case of partial loading, so don't run
     the traps in that situation */
  if( libspectrum_tape_block_data_length( block ) != DE + 2 ) {
    tape_play( 1 );
    return -1;
  }

  /* All returns made via the RET at #05E2, except on Timex 2068 at #0136 */
  if ( machine_current->machine == LIBSPECTRUM_MACHINE_TC2068 ||
       machine_current->machine == LIBSPECTRUM_MACHINE_TS2068 ) {
    PC = 0x0136;
  } else {
    PC = 0x05e2;
  }

  error = trap_load_block( block );
  if( error ) return error;

  /* Peek at the next block. If it's a ROM block, move along, initialise
     the block, and return */
  next_block = libspectrum_tape_peek_next_block( tape );

  if( libspectrum_tape_block_type(next_block) == LIBSPECTRUM_TAPE_BLOCK_ROM ) {

    next_block = libspectrum_tape_select_next_block( tape );
    if( !next_block ) return 1;

    ui_tape_browser_update( UI_TAPE_BROWSER_SELECT_BLOCK, NULL );

    return 0;
  }

  /* If the next block isn't a ROM block, set ourselves up such that the
     next thing to occur is the pause at the end of the current block */
  libspectrum_tape_set_state( tape, LIBSPECTRUM_TAPE_STATE_PAUSE );

  return 0;
}
Esempio n. 2
0
bool Tape::LoadTrap ()
{
    if (!IsInserted())
        return false;

    // If traps are disabled, try normal loading
    if (!GetOption(tapetraps))
    {
        Play();
        return false;
    }

    // Skip over any metadata blocks
    libspectrum_tape_block *block = libspectrum_tape_current_block(pTape);
    while (block && libspectrum_tape_block_metadata(block))
        block = libspectrum_tape_select_next_block(pTape);

    // Nothing else to process?
    if (!block)
        return false;

    libspectrum_tape_type type = libspectrum_tape_block_type(block);
    libspectrum_tape_state_type state = libspectrum_tape_state(pTape);

    // Consider both ROM blocks (normal speed) and turbo blocks, as used by custom SAM tape speeds (DEVICE tX)
    if ((type != LIBSPECTRUM_TAPE_BLOCK_ROM && type != LIBSPECTRUM_TAPE_BLOCK_TURBO) || state != LIBSPECTRUM_TAPE_STATE_PILOT)
    {
        // Fall back on non-trap loading for anything else
        Play();
        return false;
    }


    libspectrum_byte *pbData = libspectrum_tape_block_data(block);
    size_t nData = libspectrum_tape_block_data_length(block);

    // Base load address and load request size
    WORD wDest = HL;
    int nWanted = (read_byte(0x5ac8) << 16) | DE;

    // Fetch block type
    H = *pbData++;
    nData--;

    // Spectrum header?
    if (H == 0)
    {
        // Override request length 
        nWanted = (nWanted & ~0xff) | 17;
    }
    // Otherwise the type byte must match the request
    else if (H != A_)
    {
        // Advance to next block
        libspectrum_tape_select_next_block(pTape);

        // Failed, exit via: RET NZ
        F &= ~(FLAG_C|FLAG_Z);
        PC = 0xe6f6;

        return true;
    }

    // Parity byte initialised to type byte
    L = H;

    // More still to load?
    while (nWanted >= 0)
    {
        // Are we out of source data?  (ToDo: support continuation blocks?)
        if (!nData)
        {
            // Advance to next block
            libspectrum_tape_select_next_block(pTape);

            // Failed, exit via: RET NZ
            F &= ~(FLAG_C|FLAG_Z);
            PC = 0xe6f6;

            return true;
        }

        // Read next byte and update parity
        L ^= (H = *pbData++);
        nData--;

        // Request complete?
        if (!nWanted)
            break;

        // Write new byte
        write_byte(wDest, H);
        wDest++;
        nWanted--;

        // Destination now in the top 16K?
        if (wDest >= 0xc000)
        {
            // Slide paging up and move pointer back
            IO::OutHmpr(hmpr+1);
            wDest -= 0x4000;
        }
    }

    // Advance to next block
    libspectrum_tape_select_next_block(pTape);

    // Exit via: LD A,L ; CP 1 ; RET
    PC = 0xe739;

    return true;
}
Esempio n. 3
0
/* Load the next tape block into memory; returns 0 if a block was
   loaded (even if it had an tape loading error or equivalent) or
   non-zero if there was an error at the emulator level, or tape traps
   are not active */
int tape_load_trap(Z80Regs * regs)
{
  libspectrum_tape_block *block, *next_block;
  int error;

  /* Do nothing if tape traps aren't active, or the tape is already playing */
  if( !mconfig.flash_loading || tape_playing ) return 1;

  /* Do nothing if we're not in the correct ROM */
  //if( ! trap_check_rom() ) return 3;

  /* Return with error if no tape file loaded */
  if( !libspectrum_tape_present( tape ) ) return 1;

  block = libspectrum_tape_current_block( tape );

  /* Skip over any meta-data blocks */
  while( libspectrum_tape_block_metadata( block ) ) {
    block = libspectrum_tape_select_next_block( tape );
    if( !block ) return 1;
  }

  /* If this block isn't a ROM loader, start the block playing. After
     that, return with `error' so that we actually do whichever
     instruction it was that caused the trap to hit */
  if( libspectrum_tape_block_type( block ) != LIBSPECTRUM_TAPE_BLOCK_ROM 
   || libspectrum_tape_state( tape ) != LIBSPECTRUM_TAPE_STATE_PILOT  
  ) {
    tape_play( 1 );
    return /*-1*/1;
  }

  /* We don't properly handle the case of partial loading, so don't run
     the traps in that situation *///Esto hace cascar algunos games
   
  /* 
  if( libspectrum_tape_block_data_length( block ) != regs->DE.W + 2 ) {
    tape_play( 1 );
    return 1;
  }
  */
  
  error = trap_load_block( block , regs);//carga el bloque
  if( error ) return -1;

  /* Peek at the next block. If it's a ROM block, move along, initialise
     the block, and return */
  next_block = libspectrum_tape_peek_next_block( tape );

  if( libspectrum_tape_block_type(next_block) == LIBSPECTRUM_TAPE_BLOCK_ROM ) {

    next_block = libspectrum_tape_select_next_block( tape );
    if( !next_block ) return 1;

    //ui_tape_browser_update( UI_TAPE_BROWSER_SELECT_BLOCK, NULL );    

    return 0;//FLASHLOADED!
  }

  /* If the next block isn't a ROM block, set ourselves up such that the
     next thing to occur is the pause at the end of the current block */
     
  libspectrum_tape_set_state( tape, LIBSPECTRUM_TAPE_STATE_PAUSE );//TODO ? autodetect, sino no tira?
  //libspectrum_tape_block_set_state( block, LIBSPECTRUM_TAPE_STATE_PAUSE );
  
  /*
  error = tape_play(1);
  if( error ) return -1;
  */
  return 0;
  
}