Beispiel #1
0
static int tap_cas_fill_wave( INT16 *buffer, int length, UINT8 *bytes ) {
	INT16 *p = buffer;
	int size = 0;

	while( size < length ) {
		int data_size = bytes[0] + ( bytes[1] << 8 );
		int pilot_length = ( bytes[2] == 0x00 ) ? 8064 : 3220;	/* TZX specification */
//		int pilot_length = ( bytes[2] == 0x00 ) ? 8063 : 3223;	/* worldofspectrum */
		logerror( "tap_cas_fill_wave: Handling TAP block containing 0x%X bytes\n", data_size );
		bytes += 2;
		size += tzx_cas_handle_block( &p, bytes, 1000, data_size, 2168, pilot_length, 667, 735, 855, 1710, 8 );
		bytes += data_size;
	}
	return size;
}
Beispiel #2
0
static int tap_cas_to_wav_size( const UINT8 *casdata, int caslen ) {
	int size = 0;
	const UINT8 *p = casdata;

	while( p < casdata + caslen ) {
		int data_size = p[0] + ( p[1] << 8 );
		int pilot_length = ( p[2] == 0x00 ) ? 8064 : 3220;	/* TZX specification */
//		int pilot_length = ( p[2] == 0x00 ) ? 8063 : 3223;	/* worldofspectrum */
		logerror( "tap_cas_to_wav_size: Handling TAP block containing 0x%X bytes", data_size );
		p += 2;
		size += tzx_cas_handle_block( NULL, p, 1000, data_size, 2168, pilot_length, 667, 735, 855, 1710, 8 );
		logerror( ", total size is now: %d\n", size );
		p += data_size;
	}
	return size;
}
Beispiel #3
0
/*  Will go through blocks and calculate number of samples needed.
If buffer is not nullptr the sample data will also be written. */
static int tzx_cas_do_work( int16_t **buffer )
{
	int current_block = 0;
	int size = 0;

	wave_data = WAVE_LOW;

	int loopcount = 0, loopoffset = 0;

	while (current_block < block_count)
	{
		int pause_time;
		uint32_t data_size;
		int text_size, total_size, i;
		int pilot, pilot_length, sync1, sync2;
		int bit0, bit1, bits_in_last_byte;
		uint8_t *cur_block = blocks[current_block];
		uint8_t block_type = cur_block[0];
		uint16_t tstates = 0;

	/* Uncomment this to include into error.log a list of the types each block */
	LOG_FORMATS("tzx_cas_fill_wave: block %d, block_type %02x\n", current_block, block_type);

		switch (block_type)
		{
		case 0x10:  /* Standard Speed Data Block (.TAP block) */
			pause_time = cur_block[1] + (cur_block[2] << 8);
			data_size = cur_block[3] + (cur_block[4] << 8);
			pilot_length = (cur_block[5] == 0x00) ?  8064 : 3220;
			size += tzx_cas_handle_block(buffer, &cur_block[5], pause_time, data_size, 2168, pilot_length, 667, 735, 855, 1710, 8);
			current_block++;
			break;
		case 0x11:  /* Turbo Loading Data Block */
			pilot = cur_block[1] + (cur_block[2] << 8);
			sync1 = cur_block[3] + (cur_block[4] << 8);
			sync2 = cur_block[5] + (cur_block[6] << 8);
			bit0 = cur_block[7] + (cur_block[8] << 8);
			bit1 = cur_block[9] + (cur_block[10] << 8);
			pilot_length = cur_block[11] + (cur_block[12] << 8);
			bits_in_last_byte = cur_block[13];
			pause_time = cur_block[14] + (cur_block[15] << 8);
			data_size = cur_block[16] + (cur_block[17] << 8) + (cur_block[18] << 16);
			size += tzx_cas_handle_block(buffer, &cur_block[19], pause_time, data_size, pilot, pilot_length, sync1, sync2, bit0, bit1, bits_in_last_byte);
			current_block++;
			break;
		case 0x12:  /* Pure Tone */
			pilot = cur_block[1] + (cur_block[2] << 8);
			pilot_length = cur_block[3] + (cur_block[4] << 8);
			size += tzx_cas_handle_block(buffer, cur_block, 0, 0, pilot, pilot_length, 0, 0, 0, 0, 0);
			current_block++;
			break;
		case 0x13:  /* Sequence of Pulses of Different Lengths */
			for (data_size = 0; data_size < cur_block[1]; data_size++)
			{
				pilot = cur_block[2 + 2 * data_size] + (cur_block[3 + 2 * data_size] << 8);
				size += tzx_cas_handle_block(buffer, cur_block, 0, 0, pilot, 1, 0, 0, 0, 0, 0);
			}
			current_block++;
			break;
		case 0x14:  /* Pure Data Block */
			bit0 = cur_block[1] + (cur_block[2] << 8);
			bit1 = cur_block[3] + (cur_block[4] << 8);
			bits_in_last_byte = cur_block[5];
			pause_time = cur_block[6] + (cur_block[7] << 8);
			data_size = cur_block[8] + (cur_block[9] << 8) + (cur_block[10] << 16);
			size += tzx_cas_handle_block(buffer, &cur_block[11], pause_time, data_size, 0, 0, 0, 0, bit0, bit1, bits_in_last_byte);
			current_block++;
			break;
		case 0x20:  /* Pause (Silence) or 'Stop the Tape' Command */
			pause_time = cur_block[1] + (cur_block[2] << 8);
			if (pause_time == 0)
			{
				/* pause = 0 is used to let an emulator automagically stop the tape
				   in MESS we do not do that, so we insert a 5 second pause. */
				pause_time = 5000;
			}
			size += tzx_cas_handle_block(buffer, cur_block, pause_time, 0, 0, 0, 0, 0, 0, 0, 0);
			current_block++;
			break;
		case 0x16:  /* C64 ROM Type Data Block */       // Deprecated in TZX 1.20
		case 0x17:  /* C64 Turbo Tape Data Block */     // Deprecated in TZX 1.20
		case 0x34:  /* Emulation Info */                // Deprecated in TZX 1.20
		case 0x40:  /* Snapshot Block */                // Deprecated in TZX 1.20
			LOG_FORMATS("Deprecated block type (%02x) encountered.\n", block_type);
			LOG_FORMATS("Please look for an updated .tzx file.\n");
			current_block++;
			break;
		case 0x30:  /* Text Description */
			ascii_block_common_log("Text Description Block", block_type);
			for (data_size = 0; data_size < cur_block[1]; data_size++)
				LOG_FORMATS("%c", cur_block[2 + data_size]);
			LOG_FORMATS("\n");
			current_block++;
			break;
		case 0x31:  /* Message Block */
			ascii_block_common_log("Message Block", block_type);
			LOG_FORMATS("Expected duration of the message display: %02x\n", cur_block[1]);
			LOG_FORMATS("Message: \n");
			for (data_size = 0; data_size < cur_block[2]; data_size++)
			{
				LOG_FORMATS("%c", cur_block[3 + data_size]);
				if (cur_block[3 + data_size] == 0x0d)
					LOG_FORMATS("\n");
			}
			LOG_FORMATS("\n");
			current_block++;
			break;
		case 0x32:  /* Archive Info */
			ascii_block_common_log("Archive Info Block", block_type);
			total_size = cur_block[1] + (cur_block[2] << 8);
			text_size = 0;
			for (data_size = 0; data_size < cur_block[3]; data_size++)  // data_size = number of text blocks, in this case
			{
				if (cur_block[4 + text_size] < 0x09) {
					LOG_FORMATS("%s: \n", archive_ident[cur_block[4 + text_size]]);
				}
				else {
					LOG_FORMATS("Comment(s): \n");
				}

				for (i = 0; i < cur_block[4 + text_size + 1]; i++)
				{
					LOG_FORMATS("%c", cur_block[4 + text_size + 2 + i]);
				}
				text_size += 2 + i;
			}
			LOG_FORMATS("\n");
			if (text_size != total_size)
				LOG_FORMATS("Malformed Archive Info Block (Text length different from the declared one).\n Please verify your tape image.\n");
			current_block++;
			break;
		case 0x33:  /* Hardware Type */
			ascii_block_common_log("Hardware Type Block", block_type);
			for (data_size = 0; data_size < cur_block[1]; data_size++)  // data_size = number of hardware blocks, in this case
			{
				LOG_FORMATS("Hardware Type %02x - Hardware ID %02x - ", cur_block[2 + data_size * 3], cur_block[2 + data_size * 3 + 1]);
				LOG_FORMATS("%s \n ", hw_info[cur_block[2 + data_size * 3 + 2]]);
			}
			current_block++;
			break;
		case 0x35:  /* Custom Info Block */
			ascii_block_common_log("Custom Info Block", block_type);
			for (data_size = 0; data_size < 10; data_size++)
			{
				LOG_FORMATS("%c", cur_block[1 + data_size]);
			}
			LOG_FORMATS(":\n");
			text_size = cur_block[11] + (cur_block[12] << 8) + (cur_block[13] << 16) + (cur_block[14] << 24);
			for (data_size = 0; data_size < text_size; data_size++)
				LOG_FORMATS("%c", cur_block[15 + data_size]);
			LOG_FORMATS("\n");
			current_block++;
			break;
		case 0x5A:  /* "Glue" Block */
			LOG_FORMATS("Glue Block (type %02x) encountered.\n", block_type);
			LOG_FORMATS("Please use a .tzx handling utility to split the merged tape files.\n");
			current_block++;
			break;
		case 0x24:  /* Loop Start */
			loopcount = cur_block[1] + (cur_block[2] << 8);
			current_block++;
			loopoffset = current_block;

			LOG_FORMATS("loop start %d %d\n",  loopcount, current_block);
			break;
		case 0x25:  /* Loop End */
			if (loopcount>0)
			{
				current_block = loopoffset;
				loopcount--;
				LOG_FORMATS("do loop\n");
			}
			else
			{
				current_block++;
			}
			break;

		case 0x21:  /* Group Start */
		case 0x22:  /* Group End */
		case 0x23:  /* Jump To Block */
		case 0x26:  /* Call Sequence */
		case 0x27:  /* Return From Sequence */
		case 0x28:  /* Select Block */
		case 0x2A:  /* Stop Tape if in 48K Mode */
		case 0x2B:  /* Set signal level */
		default:
			LOG_FORMATS("Unsupported block type (%02x) encountered.\n", block_type);
			current_block++;
			break;

		case 0x15:  /* Direct Recording */ // used on 'bombscar' in the cpc_cass list
			// having this missing is fatal
			tstates = cur_block[1] + (cur_block[2] << 8);
			pause_time= cur_block[3] + (cur_block[4] << 8);
			bits_in_last_byte = cur_block[5];
			data_size = cur_block[6] + (cur_block[7] << 8) + (cur_block[8] << 16);
			size += tzx_handle_direct(buffer, &cur_block[9], pause_time, data_size, tstates, bits_in_last_byte);
			current_block++;
			break;

		case 0x18:  /* CSW Recording */
			// having this missing is fatal
			printf("Unsupported block type (0x15 - CSW Recording) encountered.\n");
			current_block++;
			break;

		case 0x19:  /* Generalized Data Block */
			{
				// having this missing is fatal
				// used crudely by batmanc in spectrum_cass list (which is just a redundant encoding of batmane ?)
				data_size = cur_block[1] + (cur_block[2] << 8) + (cur_block[3] << 16) + (cur_block[4] << 24);
				pause_time= cur_block[5] + (cur_block[6] << 8);

				uint32_t totp = cur_block[7] + (cur_block[8] << 8) + (cur_block[9] << 16) + (cur_block[10] << 24);
				int npp = cur_block[11];
				int asp = cur_block[12];
				if (asp == 0 && totp > 0) asp = 256;

				uint32_t totd = cur_block[13] + (cur_block[14] << 8) + (cur_block[15] << 16) + (cur_block[16] << 24);
				int npd = cur_block[17];
				int asd = cur_block[18];
				if (asd == 0 && totd > 0) asd = 256;

				size += tzx_handle_generalized(buffer, &cur_block[19], pause_time, data_size, totp, npp, asp, totd, npd, asd);

				current_block++;
			}
			break;

		}
	}
	return size;
}
Beispiel #4
0
/*
  Will go through blocks and calculate number of samples needed.
  If buffer is not NULL the sample data will also be written.
 */
static int tzx_cas_do_work( INT16 **buffer ) {
	int	current_block = 0;
	int	size = 0;

	wave_data = WAVE_LOW;

	while( current_block < block_count ) {
		int	pause_time;
		int	data_size;
		int	pilot, pilot_length, sync1, sync2;
		int	bit0, bit1, bits_in_last_byte;
		UINT8	*cur_block = blocks[current_block];
		UINT8	block_type =cur_block[0];
		logerror( "tzx_cas_fill_wave: block %d, block_type %02x\n", current_block, block_type );
		switch( block_type ) {
		case 0x10:	/* Standard Speed Data Block (.TAP block) */
			pause_time = cur_block[1] + ( cur_block[2] << 8 );
			data_size = cur_block[3] + ( cur_block[4] << 8 );
			pilot_length = ( cur_block[5] == 0x00 ) ?  8064 : 3220;
			size += tzx_cas_handle_block( buffer, &cur_block[5], pause_time, data_size, 2168, pilot_length, 667, 735, 855, 1710, 8 );
			current_block++;
			break;
		case 0x11:	/* Turbo Loading Data Block */
			pilot = cur_block[1] + ( cur_block[2] << 8 );
			sync1 = cur_block[3] + ( cur_block[4] << 8 );
			sync2 = cur_block[5] + ( cur_block[6] << 8 );
			bit0 = cur_block[7] + ( cur_block[8] << 8 );
			bit1 = cur_block[9] + ( cur_block[10] << 8 );
			pilot_length = cur_block[11] + ( cur_block[12] << 8 );
			bits_in_last_byte = cur_block[13];
			pause_time = cur_block[14] + ( cur_block[15] << 8 );
			data_size = cur_block[16] + ( cur_block[17] << 8 ) + ( cur_block[18] << 16 );
			size += tzx_cas_handle_block( buffer, &cur_block[19], pause_time, data_size, pilot, pilot_length, sync1, sync2, bit0, bit1, bits_in_last_byte );
			current_block++;
			break;
		case 0x12:	/* Pure Tone */
			pilot = cur_block[1] + ( cur_block[2] << 8 );
			pilot_length = cur_block[3] + ( cur_block[4] << 8 );
			size += tzx_cas_handle_block( buffer, cur_block, 0, 0, pilot, pilot_length, 0, 0, 0, 0, 0 );
			current_block++;
			break;
		case 0x13:	/* Sequence of Pulses of Different Lengths */
			for( data_size = 0; data_size < cur_block[1]; data_size++ ) {
				pilot = cur_block[1 + 2*data_size] + ( cur_block[2 + 2*data_size] << 8 );
				size += tzx_cas_handle_block( buffer, cur_block, 0, 0, pilot, 1, 0, 0, 0, 0, 0 );
			}
			current_block++;
			break;
		case 0x14:	/* Pure Data Block */
			bit0 = cur_block[1] + ( cur_block[2] << 8 );
			bit1 = cur_block[3] + ( cur_block[4] << 8 );
			bits_in_last_byte = cur_block[5];
			pause_time = cur_block[6] + ( cur_block[7] << 8 );
			data_size = cur_block[8] + ( cur_block[9] << 8 ) + ( cur_block[10] << 16 );
			size += tzx_cas_handle_block( buffer, &cur_block[11], pause_time, data_size, 0, 0, 0, 0, bit0, bit1, bits_in_last_byte );
			current_block++;
			break;
		case 0x15:	/* Direct Recording */
		case 0x16:	/* C64 ROM Type Data Block */
		case 0x17:	/* C64 Turbo Tape Data Block */
			logerror( "Unsupported block type (%02x) encountered\n", block_type );
			current_block++;
			break;
		case 0x20:	/* Pause (Silence) or 'Stop the Tape' Command */
			pause_time = cur_block[1] + ( cur_block[2] << 8 );
			if ( pause_time == 0 ) {
				/* pause = 0 is used to let an emulator automagically stop the tape
				   in MESS we do not do that, so we insert a 5 second pause.
				 */
				pause_time = 5000;
			}
			size += tzx_cas_handle_block( buffer, cur_block, pause_time, 0, 0, 0, 0, 0, 0, 0, 0 );
			current_block++;
			break;
		case 0x21:	/* Group Start */
		case 0x22:	/* Group End */
		case 0x23:	/* Jump To Block */
		case 0x24:	/* Loop Start */
		case 0x25:	/* Loop End */
		case 0x26:	/* Call Sequence */
		case 0x27:	/* Return From Sequence */
		case 0x28:	/* Select Block */
		case 0x2A:	/* Stop Tape if in 48K Mode */
		case 0x30:	/* Text Description */
		case 0x31:	/* Message Block */
		case 0x32:	/* Archive Info */
		case 0x33:	/* Hardware Type */
		case 0x34:	/* Emulation Info */
		case 0x35:	/* Custom Info Block */
		case 0x40:	/* Snapshot Block */
		case 0x5A:	/* Merge Block */
		default:
			logerror( "Unsupported block type (%02x) encountered\n", block_type );
			current_block++;
			break;
		}
	}
	return size;
}