/*

    CPCD2DSK v1.1 - 05.08.98 by Gerald Schnabel (Gerri@studbox.uni-stuttgart.de)

*/

#include	<exec/types.h>
#include	<proto/dos.h>
#include	<dos/rdargs.h>
#include	<string.h>
#include	<stdio.h>
#include	<ctype.h>

#define		SECTSIZE	512
#define		NBTRACK		40
#define		NBSECT		9
#define		EMUCPCNBSECT	26

char versionstring[]="$VER: CPCD2DSK 1.1 (05.08.98) by Gerald Schnabel (Gerri@studbox.uni-stuttgart.de)\0";


/* EmuCPC format */


typedef struct
	{
	ULONG	Signature;			/* "CPCD" */
	ULONG	MagicNumber;		/* 1 */
	UBYTE	NbSide;					/* 2 */
	UBYTE	NbTracks;				/* usually 40 */
	USHORT	TrackSize;		/* usually $1200 */
	ULONG	DiskSize;				/* usually 385280 */
	} EmuCPCHeader;


typedef struct
	{
	UBYTE	R;				/* sector ID */
	UBYTE	N;				/* sector size, usually 2 = 512bytes */
	SHORT	Un1;			/* CRC checksum */
	LONG	Offset;		/* sector data offset */
	} EmuCPCSect;


typedef struct
	{
	UBYTE	Data[ SECTSIZE ];
	} EmuCPCData;


typedef struct
	{
	EmuCPCSect	Sect[ EMUCPCNBSECT ];
	EmuCPCData	Sectdata[ NBSECT ];
	} EmuCPCTrack;


/* DSK format */


typedef struct
	{
	char	debut[ 0x22 ];			/* "MV - CPCEMU Disk-File\r\nDisk-Info\r\n" */
	char	creator [ 0x0e ];
	UBYTE	NbTracks;
	UBYTE	NbHeads;
	SHORT	DataSize;						/* 0x1300 */
	UBYTE	Unused[ 0xCC ];
	} DSKHeader;


typedef struct
	{
	UBYTE	C;		/* track */
	UBYTE	H;		/* head  */
	UBYTE	R;		/* sect  */
	UBYTE	N;		/* size  */
	SHORT	Unused1;
	SHORT	Unused2;
	} DSKSect;


typedef struct
	{
	char	ID[ 0x10 ];		/* "Track-Info\r\n\0\0" */
	UBYTE	Track;
	UBYTE	Head;
	SHORT	Unused1;
	UBYTE	X1;						/* 2    */
	UBYTE	X2;						/* 9    */
	UBYTE	X3;						/* 0x4E */
	UBYTE	X4;						/* 0xE5 */
	DSKSect	Sect[ NBSECT ];
	UBYTE	Unused2[160];
	} DSKTrack;


/* global variables */


	BPTR HandleSource;
	struct RDArgs *result;
	struct { APTR cliarg[ 2 ]; } array;
	static EmuCPCHeader HeaderEmuCPC;
	static EmuCPCTrack TrackEmuCPC;
	static DSKHeader HeaderDSK;
	static DSKTrack TrackDSK;


/* writeside ( side ) */


BOOL writeside( int side )

{
	APTR pos;
	BPTR HandleDest;
	int i, s;
	char destname [ 256 ];
	char extension[] = "_A.DSK";
	APTR sourcestring, searchstring;

	extension[ 1 ] = extension[ 1 ] + side;

	if ( array.cliarg[ 1 ] )
	{
		sourcestring = array.cliarg[ 1 ];
		searchstring = ".dsk";
	}
	else
	{
		sourcestring = array.cliarg[ 0 ];
		searchstring = ".cpcd";
	}

	strncpy ( destname , sourcestring , 256 );
	for ( i = 0 ; i < sizeof(destname) ; i++)
		destname[ i ]=tolower( destname[i] );

	if ( pos=strstr( destname , searchstring ) )
	{
		memset( &destname, 0, 256 );
		strncpy ( destname , sourcestring , (int)pos-(int)&destname );
	}
	else
	{
		memset( &destname, 0, 256 );
		strncpy ( destname , sourcestring , 256 );
	}

	strncat ( destname , extension , 256 );

	HandleDest = Open( destname , MODE_NEWFILE );
	if ( HandleDest )
	{
		Write( HandleDest, &HeaderDSK, sizeof( HeaderDSK ) );

		for ( i = 0; i < NBTRACK ; i++ )
		{
			Read( HandleSource, &TrackEmuCPC, sizeof( TrackEmuCPC ) );

			TrackDSK.Track = i;

			for ( s = 0 ; s < NBSECT ; s++ )
			{
				TrackDSK.Sect[ s ].C = i;
				TrackDSK.Sect[ s ].R = TrackEmuCPC.Sect[ s ].R;
				TrackDSK.Sect[ s ].N = TrackEmuCPC.Sect[ s ].N;
			}
			Write( HandleDest, &TrackDSK, sizeof( TrackDSK ) );

			for ( s = 0; s < NBSECT; s++ )
				Write( HandleDest, &TrackEmuCPC.Sectdata[ s ] , SECTSIZE );
		}
		Close( HandleDest );
		return( TRUE );
	}
	else
		return( FALSE );
}


int main( void )

{
	BOOL error = FALSE;
	LONG errcode;
	ULONG CPCSignature = 0x43504344;	/* "CPCD" */

	if (result = ReadArgs( "CPCDFILE/A,DSKFILE" , (APTR)&array , 0L ))
	{

	/* clear header & track block */

		memset( &HeaderDSK, 0, sizeof( HeaderDSK ) );
		memset( &TrackDSK, 0, sizeof( TrackDSK ) );

	/* initialise header block */

		strcpy( HeaderDSK.debut , "MV - CPCEMU Disk-File\r\nDisk-Info\r\n" );
		strcpy( HeaderDSK.creator , "CPCD2DSK 1.0\r\n" );
		HeaderDSK.NbTracks = NBTRACK;
		HeaderDSK.NbHeads = 1;
		HeaderDSK.DataSize = 0x0013;

	/* initialise track block */

		strcpy( TrackDSK.ID, "Track-Info\r\n" );
		TrackDSK.X1 = 2;			/* BPS=2 (512 bytes) */
		TrackDSK.X2 = NBSECT;	/* SPT=9 (9 sectors per track) */
		TrackDSK.X3 = 0x4E;		/* GAP #3 */
		TrackDSK.X4 = 0xE5;		/* filler byte */

		HandleSource = Open( array.cliarg[0], MODE_OLDFILE );
		if ( HandleSource )
		{
			Read ( HandleSource, &HeaderEmuCPC, sizeof( HeaderEmuCPC ) );

			if ( HeaderEmuCPC.Signature == CPCSignature )
			{
				if ( HeaderEmuCPC.MagicNumber == 1 )
				{
					if ( !writeside( 0 ) )		/* write side 0 */
						printf( "Error while opening output file #A\n" );
					if ( !writeside( 1 ) )		/* write side 1 */
						printf( "Error while opening output file #B\n" );
				}
				else
				{
					printf( "Revision of inputfile not supported\n" );
					SetIoErr(212L);		/* ERROR_OBJECT_WRONG_TYPE */
					error=TRUE;
				}
			}
			else
			{
				printf( "Inputfile is not an EmuCPC (.CPCD) file\n" );
				SetIoErr(212L);		/* ERROR_OBJECT_WRONG_TYPE */
				error=TRUE;
			}

			Close( HandleSource );
		}
		else
		{
			SetIoErr(205L);		/* ERROR_OBJECT_NOT_FOUND */
			error=TRUE;
		}

		FreeArgs( result );

	}
	else
		error=TRUE;

	if ( error )
	{
		PrintFault ( errcode=IoErr() , "CPCD2DSK" );
		return	( errcode );
	}
	else
		return ( 0L );
}
