Exemple #1
0
static void
tzx_write_archive_info( libspectrum_tape_block *block,
			libspectrum_byte **buffer, libspectrum_byte **ptr,
			size_t *length )
{
  size_t i, count, total_length;

  count = libspectrum_tape_block_count( block );

  /* 1 count byte, 2 bytes (ID and length) for every string */
  total_length = 1 + 2 * count;
  /* And then the length of all the strings */
  for( i = 0; i < count; i++ )
    total_length += strlen( (char*)libspectrum_tape_block_texts( block, i ) );

  /* Make room for all that, along with ID byte and two bytes storing the
     total length */
  libspectrum_make_room( buffer, total_length + 3, ptr, length );

  /* Write out the metadata */
  *(*ptr)++ = LIBSPECTRUM_TAPE_BLOCK_ARCHIVE_INFO;
  libspectrum_write_word( ptr, total_length );
  *(*ptr)++ = count;

  /* And the strings */
  for( i = 0; i < count; i++ ) {
    *(*ptr)++ = libspectrum_tape_block_ids( block, i );
    tzx_write_string( ptr, libspectrum_tape_block_texts( block, i ) );
  }
}
Exemple #2
0
static void
tzx_write_select( libspectrum_tape_block *block, libspectrum_byte **buffer,
		  libspectrum_byte **ptr, size_t *length )
{
  size_t count, total_length, i;

  /* The id byte, the total length (2 bytes), the count byte,
     and ( 2 offset bytes and 1 length byte ) per selection */
  count = libspectrum_tape_block_count( block );
  total_length = 4 + 3 * count;

  for( i = 0; i < count; i++ )
    total_length += strlen( (char*)libspectrum_tape_block_texts( block, i ) );

  libspectrum_make_room( buffer, total_length, ptr, length );

  *(*ptr)++ = LIBSPECTRUM_TAPE_BLOCK_SELECT;
  libspectrum_write_word( ptr, total_length );
  *(*ptr)++ = count;

  for( i = 0; i < count; i++ ) {
    libspectrum_write_word( ptr, libspectrum_tape_block_offsets( block, i ) );
    tzx_write_string( ptr, libspectrum_tape_block_texts( block, i ) );
  }
}
Exemple #3
0
static void
tzx_write_loop_start( libspectrum_tape_block *block, libspectrum_byte **buffer,
		      libspectrum_byte **ptr, size_t *length )
{
  libspectrum_make_room( buffer, 3, ptr, length );
  *(*ptr)++ = LIBSPECTRUM_TAPE_BLOCK_LOOP_START;
  libspectrum_write_word( ptr, libspectrum_tape_block_count( block ) );
}
Exemple #4
0
static void
tzx_write_pure_tone( libspectrum_tape_block *block, libspectrum_byte **buffer,
		     libspectrum_byte **ptr, size_t *length )
{
  /* Make room for the ID byte and the data */
  libspectrum_make_room( buffer, 5, ptr, length );

  *(*ptr)++ = LIBSPECTRUM_TAPE_BLOCK_PURE_TONE;
  libspectrum_write_word( ptr, libspectrum_tape_block_pulse_length( block ) );
  libspectrum_write_word( ptr, libspectrum_tape_block_count( block ) );
}
Exemple #5
0
static void
tzx_write_pulses( libspectrum_tape_block *block, libspectrum_byte **buffer,
		  libspectrum_byte **ptr, size_t *length )
{
  size_t i, count, block_length;

  /* ID byte, count and 2 bytes for length of each pulse */
  count = libspectrum_tape_block_count( block );
  block_length = 2 + 2 * count;

  /* Make room for the ID byte, the count and the data */
  libspectrum_make_room( buffer, block_length, ptr, length );

  *(*ptr)++ = LIBSPECTRUM_TAPE_BLOCK_PULSES;
  *(*ptr)++ = count;
  for( i = 0; i < count; i++ )
    libspectrum_write_word( ptr,
			    libspectrum_tape_block_pulse_lengths( block, i ) );
}
Exemple #6
0
static void
tzx_write_hardware( libspectrum_tape_block *block, libspectrum_byte **buffer,
		    libspectrum_byte **ptr, size_t *length )
{
  size_t i, count;

  /* We need one ID byte, one count byte and then three bytes for every
     entry */
  count = libspectrum_tape_block_count( block );
  libspectrum_make_room( buffer, 2 + 3 * count, ptr, length );

  /* Write out the metadata */
  *(*ptr)++ = LIBSPECTRUM_TAPE_BLOCK_HARDWARE;
  *(*ptr)++ = count;

  /* And the info */
  for( i = 0; i < count; i++ ) {
    *(*ptr)++ = libspectrum_tape_block_types( block, i );
    *(*ptr)++ = libspectrum_tape_block_ids  ( block, i );
    *(*ptr)++ = libspectrum_tape_block_values( block, i );
  }
}
Exemple #7
0
// Return a string describing a give tape block
const char *Tape::GetBlockDetails (libspectrum_tape_block *block)
{
    static char sz[128];
    sz[0] = '\0';

    char szExtra[64] = "";
    char szName[11] = "";
    const char *psz = NULL;

    libspectrum_byte *data = libspectrum_tape_block_data(block);
    long length = static_cast<long>(libspectrum_tape_block_data_length(block));


    // Is there enough data to include a possible filename?
    if (length >= 12)
    {
        for (int i = 0 ; i < 10 ; i++)
        {
            char ch = data[i+2];
            szName[i] = (ch >= ' ' && ch <= 0x7f) ? ch : '?';
        }
        szName[10] = '\0';
    }

    // Spectrum header length and type byte?
    if (length == 17+2 && data[0] == 0x00)
    {
        // Examine Spectrum file type
        switch (data[1])
        {
            case 0:
            {
                psz = "ZX BASIC";

                UINT uLine = (data[15] << 8) | data[14];
                if (uLine != 0xffff)
                    sprintf(szExtra, " LINE %u", uLine);

                break;
            }

            case 1: psz = "ZX DATA()"; break;
            case 2: psz = "ZX DATA$()"; break;

            case 3:
            {
                psz = "ZX CODE";

                UINT uAddr = (data[15] << 8) | data[14];
                UINT uLen = (data[13] << 8) | data[12];
                sprintf(szExtra, " %u,%u", uAddr, uLen);

                break;
            }
        }
    }
    // SAM header length and type byte?
    // Real length is 82, but TZX spec suggests there could be up to 7-8 trailing bits, so accept 83
    else if ((length == 80+2 || length == 80+1+2) && data[0] == 0x01)
    {
        // Examine SAM file type
        switch (data[1])
        {
            case 16:
            {
                psz = "BASIC";

                UINT uLine = (data[40] << 8) | data[39];
                if (data[38] == 0)
                    sprintf(szExtra, " LINE %u", uLine);

                break;
            }

            case 17: psz = "DATA()"; break;
            case 18: psz = "DATA$"; break;
            case 19:
            {
                psz = "CODE";

                UINT uAddr = TPeek(data+32) + 16384;
                UINT uLen = TPeek(data+35);

                sprintf(szExtra, " %u,%u", uAddr, uLen);
                if (data[38] == 0)
                    sprintf(szExtra+strlen(szExtra), ",%u", TPeek(data+38));

                break;
            }

            case 20:
            {
                psz = "SCREEN$";
                UINT uMode = data[17]+1;
                sprintf(szExtra, " MODE %u", uMode);
                break;
            }
        }
    }

    // Do we have a type string?
    if (psz)
    {
        // Start with type and append filename
        strcpy(sz, psz);
        strcat(sz, ": '");
        strcat(sz, szName);
        strcat(sz, "'");

        // Append any additional type-specific details
        if (szExtra[0])
        {
            strcat(sz, " ");
            strcat(sz, szExtra);
        }
    }

    // No details yet?
    if (!sz[0])
    {
        libspectrum_tape_type type = libspectrum_tape_block_type(block);

        switch (type)
        {
            case LIBSPECTRUM_TAPE_BLOCK_ROM:
            case LIBSPECTRUM_TAPE_BLOCK_TURBO:
            {
                // Raw tape block data length
                size_t length = libspectrum_tape_block_data_length(block);

                // If possible, exclude the type, sync, and checksum bytes from the length
                if (length >= 3)
                    length -= 3;

                snprintf(sz, sizeof(sz), "%u bytes", length);
                break;
            }

            case LIBSPECTRUM_TAPE_BLOCK_PURE_DATA:
            case LIBSPECTRUM_TAPE_BLOCK_RAW_DATA:
                snprintf(sz, sizeof(sz), "%u bytes", libspectrum_tape_block_data_length(block));
                break;

            case LIBSPECTRUM_TAPE_BLOCK_PURE_TONE:
                snprintf(sz, sizeof(sz), "%u tstates", libspectrum_tape_block_pulse_length(block));
                break;

            case LIBSPECTRUM_TAPE_BLOCK_PULSES:
                snprintf(sz, sizeof(sz), "%u pulses", libspectrum_tape_block_count(block));
                break;

            case LIBSPECTRUM_TAPE_BLOCK_PAUSE:
                snprintf(sz, sizeof(sz), "%ums", libspectrum_tape_block_pause(block));
                break;

            case LIBSPECTRUM_TAPE_BLOCK_GROUP_START:
            case LIBSPECTRUM_TAPE_BLOCK_COMMENT:
            case LIBSPECTRUM_TAPE_BLOCK_MESSAGE:
            case LIBSPECTRUM_TAPE_BLOCK_CUSTOM:
                snprintf(sz, sizeof(sz), "%s", libspectrum_tape_block_text(block));
                break;

            case LIBSPECTRUM_TAPE_BLOCK_JUMP:
            {
                int offset = libspectrum_tape_block_offset(block);
                if (offset >= 0)
                    snprintf(sz, sizeof(sz), "Forward %d blocks", offset);
                else
                    snprintf(sz, sizeof(sz), "Backward %d blocks", -offset);
                break;
            }

            case LIBSPECTRUM_TAPE_BLOCK_LOOP_START:
                snprintf(sz, sizeof(sz), "%u iterations", libspectrum_tape_block_count(block));
                break;

            case LIBSPECTRUM_TAPE_BLOCK_SELECT:
                snprintf(sz, sizeof(sz), "%u options", libspectrum_tape_block_count(block));
                break;

            case LIBSPECTRUM_TAPE_BLOCK_GENERALISED_DATA:
                snprintf(sz, sizeof(sz), "%u data symbols",
                    libspectrum_tape_generalised_data_symbol_table_symbols_in_block(libspectrum_tape_block_data_table(block)));
                break;

            case LIBSPECTRUM_TAPE_BLOCK_ARCHIVE_INFO:
            {
                size_t count = libspectrum_tape_block_count(block);

                for (size_t i = 0 ; i < count ; i++)
                {
                    int id = libspectrum_tape_block_ids(block, i);
                    const char *value = libspectrum_tape_block_texts(block, i);

                    // Full title TZX id?
                    if (id == 0x00)
                        strncpy(sz, value, sizeof(sz)-1);
                }
                break;
            }

            case LIBSPECTRUM_TAPE_BLOCK_HARDWARE:
            {
                size_t count = libspectrum_tape_block_count(block);

                for (size_t i = 0 ; i < count ; i++)
                {
                    int type = libspectrum_tape_block_types(block, i);
                    int id = libspectrum_tape_block_ids(block, i);

                    // Skip anything but the TZX "Computers" type
                    if (type != 0)
                        continue;

                    // Check for relevant computer ids
                    if (id == 9)
                        strcpy(sz, "SAM Coupe");
                    else if ((id >= 0x00 && id <= 0x05) || id == 0x0e)
                        strcpy(sz, "ZX Spectrum");
                    else if (id == 0x08)
                        strcpy(sz, "Pentagon");
                    else if (id == 0x06 || id == 0x07)
                        strcpy(sz, "Timex Sinclair");
                    else
                        snprintf(sz, sizeof(sz), "Unknown (%02X)", id);
                }

                break;
            }

            default:
                break;
        }
    }

    return sz;
}
int
tape_block_details( char *buffer, size_t length,
		    libspectrum_tape_block *block )
{
  libspectrum_byte *data;
  const char *type; unsigned char name[11];
  int offset;
  size_t i;
  unsigned long total_pulses;

  buffer[0] = '\0';

  switch( libspectrum_tape_block_type( block ) ) {

  case LIBSPECTRUM_TAPE_BLOCK_ROM:
  case LIBSPECTRUM_TAPE_BLOCK_DATA_BLOCK:
    /* See if this looks like a standard Spectrum header and if so
       display some extra data */
    if( libspectrum_tape_block_data_length( block ) != 19 ) goto normal;

    data = libspectrum_tape_block_data( block );

    /* Flag byte is 0x00 for headers */
    if( data[0] != 0x00 ) goto normal;

    switch( data[1] ) {
    case 0x00: type = "Program"; break;
    case 0x01: type = "Number array"; break;
    case 0x02: type = "Character array"; break;
    case 0x03: type = "Bytes"; break;
    default: goto normal;
    }
    
    make_name( name, &data[2] );

    snprintf( buffer, length, "%s: \"%s\"", type, name );

    break;

  normal:
    snprintf( buffer, length, "%lu bytes",
	      (unsigned long)libspectrum_tape_block_data_length( block ) );
    break;

  case LIBSPECTRUM_TAPE_BLOCK_TURBO:
  case LIBSPECTRUM_TAPE_BLOCK_PURE_DATA:
  case LIBSPECTRUM_TAPE_BLOCK_RAW_DATA:
    snprintf( buffer, length, "%lu bytes",
	      (unsigned long)libspectrum_tape_block_data_length( block ) );
    break;

  case LIBSPECTRUM_TAPE_BLOCK_PURE_TONE:
    snprintf( buffer, length, "%lu tstates",
	      (unsigned long)libspectrum_tape_block_pulse_length( block ) );
    break;

  case LIBSPECTRUM_TAPE_BLOCK_PULSES:
    snprintf( buffer, length, "%lu pulses",
	      (unsigned long)libspectrum_tape_block_count( block ) );
    break;

  case LIBSPECTRUM_TAPE_BLOCK_PULSE_SEQUENCE:
    total_pulses = 0;
    for( i=0; i < libspectrum_tape_block_count( block ); i++ )
      total_pulses += libspectrum_tape_block_pulse_repeats( block, i );
    snprintf( buffer, length, "%lu pulses", total_pulses );
    break;

  case LIBSPECTRUM_TAPE_BLOCK_PAUSE:
    snprintf( buffer, length, "%lu ms",
	      (unsigned long)libspectrum_tape_block_pause( block ) );
    break;

  case LIBSPECTRUM_TAPE_BLOCK_GROUP_START:
  case LIBSPECTRUM_TAPE_BLOCK_COMMENT:
  case LIBSPECTRUM_TAPE_BLOCK_MESSAGE:
  case LIBSPECTRUM_TAPE_BLOCK_CUSTOM:
    snprintf( buffer, length, "%s", libspectrum_tape_block_text( block ) );
    break;

  case LIBSPECTRUM_TAPE_BLOCK_JUMP:
    offset = libspectrum_tape_block_offset( block );
    if( offset > 0 ) {
      snprintf( buffer, length, "Forward %d blocks", offset );
    } else {
      snprintf( buffer, length, "Backward %d blocks", -offset );
    }
    break;

  case LIBSPECTRUM_TAPE_BLOCK_LOOP_START:
    snprintf( buffer, length, "%lu iterations",
	      (unsigned long)libspectrum_tape_block_count( block ) );
    break;

  case LIBSPECTRUM_TAPE_BLOCK_SELECT:
    snprintf( buffer, length, "%lu options",
	      (unsigned long)libspectrum_tape_block_count( block ) );
    break;

  case LIBSPECTRUM_TAPE_BLOCK_GENERALISED_DATA:
    snprintf( buffer, length, "%lu data symbols",
	      (unsigned long)libspectrum_tape_generalised_data_symbol_table_symbols_in_block( libspectrum_tape_block_data_table( block ) ) );
    break;

  case LIBSPECTRUM_TAPE_BLOCK_RLE_PULSE:
    /* Could do something better with this one */
    break;

  case LIBSPECTRUM_TAPE_BLOCK_GROUP_END:
  case LIBSPECTRUM_TAPE_BLOCK_LOOP_END:
  case LIBSPECTRUM_TAPE_BLOCK_STOP48:
  case LIBSPECTRUM_TAPE_BLOCK_SET_SIGNAL_LEVEL:
  case LIBSPECTRUM_TAPE_BLOCK_ARCHIVE_INFO:
  case LIBSPECTRUM_TAPE_BLOCK_HARDWARE:
  case LIBSPECTRUM_TAPE_BLOCK_CONCAT:
    break;

  }

  return 0;
}
Exemple #9
0
int
tape_block_details( char *buffer, size_t length,
		    libspectrum_tape_block *block )
{
  libspectrum_byte *data;
  const char *type; unsigned char name[11];
  int offset;

  buffer[0] = '\0';

  switch( libspectrum_tape_block_type( block ) ) {

  case LIBSPECTRUM_TAPE_BLOCK_ROM:
    /* See if this looks like a standard Spectrum header and if so
       display some extra data */
    if( libspectrum_tape_block_data_length( block ) != 19 ) goto normal;

    data = libspectrum_tape_block_data( block );

    /* Flag byte is 0x00 for headers */
    if( data[0] != 0x00 ) goto normal;

    switch( data[1] ) {
    case 0x00: type = "Program"; break;
    case 0x01: type = "Number array"; break;
    case 0x02: type = "Character array"; break;
    case 0x03: type = "Bytes"; break;
    default: goto normal;
    }

    make_name( name, &data[2] );

    snprintf( buffer, length, "%s: \"%s\"", type, name );

    break;

  normal:
    snprintf( buffer, length, "Data (%lu Bytes)",
	      (unsigned long)libspectrum_tape_block_data_length( block ) );
    break;

  case LIBSPECTRUM_TAPE_BLOCK_TURBO:
    snprintf( buffer, length, "Turbo Data (%lu Bytes)",
	      (unsigned long)libspectrum_tape_block_data_length( block ) );
    break;  
  case LIBSPECTRUM_TAPE_BLOCK_PURE_DATA:
    snprintf( buffer, length, "Pure Data (%lu Bytes)",
	      (unsigned long)libspectrum_tape_block_data_length( block ) );
    break;  
  case LIBSPECTRUM_TAPE_BLOCK_RAW_DATA:
    snprintf( buffer, length, "Raw Data (%lu Bytes)",
	      (unsigned long)libspectrum_tape_block_data_length( block ) );
    break;

  case LIBSPECTRUM_TAPE_BLOCK_PURE_TONE:
    snprintf( buffer, length, "Pure Tone (%lu tstates)",
	      (unsigned long)libspectrum_tape_block_pulse_length( block ) );
    break;

  case LIBSPECTRUM_TAPE_BLOCK_PULSES:
    snprintf( buffer, length, "Sequence Of %lu Pulses",
	      (unsigned long)libspectrum_tape_block_count( block ) );
    break;

  case LIBSPECTRUM_TAPE_BLOCK_PAUSE:
    if((unsigned long)libspectrum_tape_block_pause( block )==0)
      snprintf( buffer, length, "[Stop The Tape]");
    else 
      snprintf( buffer, length, "[Pause - %lu ms]",(unsigned long)libspectrum_tape_block_pause( block ));
    break;

  case LIBSPECTRUM_TAPE_BLOCK_GROUP_START:
  case LIBSPECTRUM_TAPE_BLOCK_COMMENT:
  case LIBSPECTRUM_TAPE_BLOCK_MESSAGE:
  case LIBSPECTRUM_TAPE_BLOCK_CUSTOM:
    snprintf( buffer, length, "[%s]", libspectrum_tape_block_text( block ) );
    break;

  case LIBSPECTRUM_TAPE_BLOCK_JUMP:
    offset = libspectrum_tape_block_offset( block );
    if( offset > 0 ) {
      snprintf( buffer, length, "[Forward %d Blocks]", offset );
    } else {
      snprintf( buffer, length, "[Backward %d Blocks]", -offset );
    }
    break;

  case LIBSPECTRUM_TAPE_BLOCK_LOOP_START:
    snprintf( buffer, length, "[Loop %lu Times]",
	      (unsigned long)libspectrum_tape_block_count( block ) );
    break;

  case LIBSPECTRUM_TAPE_BLOCK_SELECT:
    snprintf( buffer, length, "[Select %lu Options]",
	      (unsigned long)libspectrum_tape_block_count( block ) );
    break;

  case LIBSPECTRUM_TAPE_BLOCK_GENERALISED_DATA:
    snprintf( buffer, length, "[Generalised Data - %lu Data Symbols]",
	      (unsigned long)libspectrum_tape_generalised_data_symbol_table_symbols_in_block( (void*)libspectrum_tape_block_data_table( block ) ) );
    break;

  case LIBSPECTRUM_TAPE_BLOCK_RLE_PULSE:
    /* Could do something better with this one */
    break;

  case LIBSPECTRUM_TAPE_BLOCK_GROUP_END:
    snprintf( buffer, length, "[Group End]");
    break;
  case LIBSPECTRUM_TAPE_BLOCK_LOOP_END:
    snprintf( buffer, length, "[Loop End]");
    break;  
  case LIBSPECTRUM_TAPE_BLOCK_STOP48:
    snprintf( buffer, length, "[Stop The Tape If 48]");
    break;    
  case LIBSPECTRUM_TAPE_BLOCK_ARCHIVE_INFO:
    snprintf( buffer, length, "[Archive Info]");
    break;  
  case LIBSPECTRUM_TAPE_BLOCK_HARDWARE:
    snprintf( buffer, length, "[Hardware]");
    break;    
  case LIBSPECTRUM_TAPE_BLOCK_CONCAT:
    snprintf( buffer, length, "[Concat]");  
    break;

  }

  return 0;
}