Reading the Kansas City tape format

ZX80, ZX 81, ZX Spectrum, TS2068 and other clones
Post Reply
stefano
Well known member
Posts: 2137
Joined: Mon Jul 16, 2007 7:39 pm

Reading the Kansas City tape format

Post by stefano »

I set up the barebones function which help in dealing with the KCS tape format.
This current concept is tested on the ZX Spectrum only and should permit to deal with a good number of to tape formats at once.

bit_tapion() gets the leading tone and uses it to calibrate the loading speed (which should also permit to support different CPU speeds at once).
It exits as soon as the first start bit is found, so a loader written in C should quickly issue a bit_tapin() sequence to get the next bytes being transmitted.

On exit, bit_tapiof() will restore the interrupts and eventually stop the motor (where supported).

To slightly modify the synchronization and support different formats I provided also bit_tapin_bit(), it will simply skip the next bit (e.g. in case the loading scheme requires 2 start bits).

Here's an example program, it will analyze the MSX tape format.
I think it works also on the Spectravideo SVI, the Philips VG-5000, P-6001 and others.
Similar programs could be written for many other formats.

Code: Select all


#include <stdio.h>
#include <stdlib.h>
#include <sound.h>


int x;
unsigned int start,end,exec;

char name[6];
int type;

void main()
{
	if (bit_tapion()==-1) exit (-1);
	type=bit_tapin();
	
	// This approach is valid ONLY on MSX, SVI, VG-5000 and those systems
	// with the block type repeated 10 times
	for (x=0; x<9; x++) {
		if (bit_tapin() != type) exit (-2);		// Exit if not a valid header
	}

	for (x=0; x<6; x++) 
		name[x]=bit_tapin();
	
	bit_tapiof();
	
	switch (type) {
		
	case 0xD0:
		printf ("\nFound BLOAD type block: %s",name);
		if (bit_tapion()==-1) exit (1);
		start=bit_tapin()+256*bit_tapin();
		end=bit_tapin()+256*bit_tapin();
		exec=bit_tapin()+256*bit_tapin();
		bit_tapiof();		// Put a bit_tapin() loop here to load the data
		printf ("\nStart: %u, Length: %u,  Exec: %u", start, end-start, exec );
		exit(type);
		break;

	case 0xD3:
		printf ("\nFound CLOAD type block: %s",name);
		if (bit_tapion()==-1) exit (1);
		end=bit_tapin()+256*bit_tapin();
		start=bit_tapin()+256*bit_tapin();
		bit_tapiof();		// Put a bit_tapin() loop here to load the program data
		printf ("\nLength: %u", end-start);
		exit(type);
		break;

	default:
		printf ("\nUnknown block type: %x", type );
		break;

	}
}	


stefano
Well known member
Posts: 2137
Joined: Mon Jul 16, 2007 7:39 pm

Re: Reading the Kansas City tape format

Post by stefano »

I just found a note on the web telling that CSAVE on the vg5000 marks the header with $7A repeated 7 times only.
I think there's a little bit of margin to make a similar program more flexible, which proves the concept :cool:
stefano
Well known member
Posts: 2137
Joined: Mon Jul 16, 2007 7:39 pm

Re: Reading the Kansas City tape format

Post by stefano »

I couldn't find examples including the mentioned specs for the VG-5000.
Here's an incomplete header analyzer based on the bit of samples and information available online.

Code: Select all



#include <stdio.h>
#include <stdlib.h>
#include <sound.h>


int x;
unsigned int start,end,exec;

char name[7];
char line[6];
int b,type,bsize,version,protection;

unsigned char test[30];

void main()
{
	name[7]=line[6]=0;
	while (1) {
		if (bit_tapion()==-1) exit (-1);
		type=bit_tapin();
		
		// This approach is valid ONLY on MSX, SVI, VG-5000 and those systems
		// with the block type repeated 10 times
		for (x=0; x<9; x++) {
			if (b=bit_tapin() != type) {
				test[0]=b;
				for (x=1; x<30; x++) 
					test[x]=bit_tapin();
				bit_tapiof();
				printf ("\nUnknown header type.  First byte is: $%x", type);
				printf ("\nText: %s", test);
				for (x=0; x<30; x++) printf ("$%x, ",test[x]);
				printf ("\n");
				exit (-2);		// Exit if not a valid header
			}
		}

		bsize=bit_tapin();
		
		for (x=0; x<6; x++) 
			name[x]=bit_tapin();
		
		version=bit_tapin();

		// Start line number (text, leading zero padding)
		for (x=0; x<5; x++) 
			line[x]=bit_tapin();

		protection=bit_tapin();  // Protection byte (00=protected)
		bit_tapin(); bit_tapin();  // Checksum pos (0,0)
		start=bit_tapin()+256*bit_tapin();	// Start addr

		bit_tapiof();

//-----------------------------------		
		switch (type) {
			
		case 0xD6:
			printf ("\nFound $D6 type block");
			printf ("\nHeader size: %u", bsize );
			printf ("\n");
			break;

		case 0xD3:
			printf ("\nHeader size: %u", bsize );
			
			if (bsize == 0x20) {
				printf ("\nFound CLOAD type block: %s",name);
				printf ("\nProgram start line:");
				for (x=0; x<5; x++)  {
					if (line[x]==0) fputc_cons(' ');
					else fputc_cons(line[x]);
				}
				if (!protection) printf ("\n(protected)");
					else  printf ("\n(not protected, flag=$%x)",protection);
			}
			else
				printf ("\nFound block: %s",name);

			printf ("\nStart: %u", start);
			printf ("\n");
			break;

		default:
			printf ("\nUnknown block type: $%x", type );
			printf ("\n");
			break;

		}
	}
}	


stefano
Well known member
Posts: 2137
Joined: Mon Jul 16, 2007 7:39 pm

Re: Reading the Kansas City tape format

Post by stefano »

I checked bit_load_msx() and it seems to work well on the Realspec emulator, I will put it online soon.
I'm also developing an equivalent function for the vg5000.
The fixed, updated code for the Philips VG5000 header probe is the following:

Code: Select all


#include <stdio.h>
#include <stdlib.h>
#include <sound.h>


int x;
unsigned int start,len,cksum;

char name[7];
char line[6];
int b,type,btype,version,protection;

unsigned char test[30];

void main()
{
	name[7]=line[6]=0;
	while (1) {
		if (bit_tapion()==-1) exit (-1);
		type=bit_tapin();
		
		// This approach is valid ONLY on MSX, SVI, VG-5000 and those systems
		// with the block type repeated 10 times
		for (x=0; x<9; x++) {
			if (b=bit_tapin() != type) {
				test[0]=b;
				for (x=1; x<30; x++) 
					test[x]=bit_tapin();
				bit_tapiof();
				printf ("\nUnknown header type.  First byte is: $%x", type);
				printf ("\nText: %s", test);
				for (x=0; x<30; x++) printf ("$%x, ",test[x]);
				printf ("\n");
				exit (-2);		// Exit if not a valid header
			}
		}

		btype=bit_tapin();
		
		for (x=0; x<6; x++) 
			name[x]=bit_tapin();
		
		version=bit_tapin();

		// Start line number (text, leading zero padding)
		for (x=0; x<5; x++) 
			line[x]=bit_tapin();

		protection=bit_tapin();  // Protection byte (00=protected)

		bit_tapin(); bit_tapin();  // Checksum pos (0,0)
		start=bit_tapin()+256*bit_tapin();	// Start addr
		len=bit_tapin()+256*bit_tapin();	//
		cksum=bit_tapin()+256*bit_tapin();	//

		bit_tapiof();

//-----------------------------------		
		switch (type) {
			
		case 0xD6:
			printf ("\nData block.  First bytes: $%x,", (unsigned char)btype );
			for (x=0; x<6; x++) 
				printf ("$%x,",(unsigned char)name[x]);

			printf ("\n");
			break;

		case 0xD3:
			if (btype == ' ') {
				printf ("\nFound CLOAD type block: %s",name);
				printf ("\nProgram start line:");
				for (x=0; x<5; x++)  {
					if (line[x]==0) fputc_cons(' ');
					else fputc_cons(line[x]);
				}
				if (!protection) printf ("\n(protected)");
					else  printf ("\n(not protected, flag=$%x)",protection);
			}
			else if (btype == 'M') {
				printf ("\nFound CLOADM header: %s",name);
				printf ("\nStart: %u", start);
				printf ("\nLength: %u", len);
				printf ("\nChecksum: %u", cksum);
			} else
				printf ("\nUnknown block. Type: %x", btype );

			printf ("\n");
			break;

		default:
			printf ("\nUnknown header type: $%x", type );
			printf ("\n");
			break;

		}
	}
}	

vg5000_header.png
You do not have the required permissions to view the files attached to this post.
stefano
Well known member
Posts: 2137
Joined: Mon Jul 16, 2007 7:39 pm

Re: Reading the Kansas City tape format

Post by stefano »

The new prototype set should currently work on the ZX Spectrum family only.

The function headers are in <sound.h>

bit_save_msx() saves data in MSX BLOAD format using the 1bit sound driver model
bit_load_msx() loads data in MSX BLOAD format using the tape port
bit_load_vg5000() loads data in Philips VG-5000 CLOADM format using the tape port

For what I could observe, the Spectravideo SVI tape audio format is NOT compatible with MSX, nor based on the Kansas City Standard.. (I was wrong)

Out of curiosity, the SEGA SC-3000 has a probably similar tape format, but the CLOADM command is supported only when the SF-7000 tape expansion was attached.
The barebones model had CLOAD only !
stefano
Well known member
Posts: 2137
Joined: Mon Jul 16, 2007 7:39 pm

Re: Reading the Kansas City tape format

Post by stefano »

Good news, the substanding code is somehow portable, I tested it on the MSX, the Mattel Aquarius and the SAM Coupè (this latter one required a bit of slowdown).
The SVI has definitely a different tape hardware.
aquarius_msx.png
You do not have the required permissions to view the files attached to this post.
Stefan
Member
Posts: 19
Joined: Fri Nov 29, 2013 10:21 pm

Re: Reading the Kansas City tape format

Post by Stefan »

stefano wrote: Fri Feb 10, 2023 10:18 pm SAM Coupè (this latter one required a bit of slowdown)
Is this maybe because it’s SAM Coupé’s evil twin? =D
Post Reply