
/*
    CPCD2DSK v1.2 - 11.03.2001 by Gerald Schnabel (Gerri@studserv.uni-stuttgart.de)

    Compiles on AMIGA, x86 (Linux, Win32)
*/

/*
    includes
*/

#include	<stdio.h>
#include	<string.h>
#include	<ctype.h>

#ifdef AMIGA
  #include	<exec/types.h>
  #include	<proto/dos.h>
  #include	<dos/rdargs.h>
  #include	"exec/execbase.h"
#else
  #include	<stdlib.h>
  #include	<sys/types.h>
  #include	"typedef.h"
#endif

#include	"endian.h"

#include	"cpcdisk.h"
#include	"emucpc.h"
#include	"dsk.h"

#define		PROGRAMDESC	"CPCD2DSK 1.2"		/* must be not larger than 12 chars! */
#define		PROGRAMDESCL	"cpcd2dsk 1.2"		/* must be not larger than 12 chars! */
#define		PROGRAMDATE	"11.3.2001"

/*
    AMIGA version string
*/

#ifdef AMIGA
  char versionstring[]="$VER: "PROGRAMDESC" ("PROGRAMDATE") by Gerald Schnabel (Gerri@studserv.uni-stuttgart.de)\r\n";
#endif

/* global variables */

FILE *HandleSource;
struct emucpcheader HeaderEmuCPC;
struct emucpctrack TrackEmuCPC;
struct dskheader HeaderDSK;
struct dsktrack TrackDSK;

#ifdef AMIGA
  struct
  {
    APTR cliarg[ 2 ];
  } array;
#endif

/* writeside ( side ) */

#ifdef AMIGA
  BOOL writeside( int side )
#else
  BOOL writeside( int side, int argc, char *argv[] )
#endif
{
	char *pos;
	FILE *HandleDest;
	int i, s;
	char destname [ 256 ];
	char extension[] = "_A.DSK";
	char *sourcestring, *searchstring;

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

	#ifdef AMIGA
	  if ( array.cliarg[ 1 ] )
	#else
	  if ( argc == 3 )
	#endif
	{
		#ifdef AMIGA
		  sourcestring = array.cliarg[ 1 ];
		#else
		  sourcestring = argv[ 2 ];
		#endif
		searchstring = ".dsk";
	}
	else
	{
		#ifdef AMIGA
		  sourcestring = array.cliarg[ 0 ];
		#else
		  sourcestring = argv[ 1 ];
		#endif
		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, (ULONG)pos-(ULONG)&destname );
	}
	else
	{
		memset( &destname, 0, 256 );
		strncpy( destname, sourcestring, 256 );
	}

	strncat( destname, extension, 256 );

	HandleDest = fopen( destname, "wb" );
	if ( HandleDest )
	{
		fwrite( &HeaderDSK, sizeof( HeaderDSK ), 1, HandleDest );

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

			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;
			}
			fwrite( &TrackDSK, sizeof( TrackDSK ), 1, HandleDest );

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

#ifdef AMIGA
  int main( void )
#else
  int main( int argc, char *argv[] )
#endif
{
	BOOL error = FALSE;
	long errcode;
	ULONG disksize;

        #ifdef AMIGA
	  struct RDArgs *result;
	  struct ExecBase *SysBase;

	  SysBase=( *(struct ExecBase **) 4L );

	  if ( SysBase->LibNode.lib_Version < 37 )
	  {
	    printf( "This program requires OS2.04+\n" );
	    return( RETURN_FAIL );
	  }
	#endif

	#ifdef AMIGA
	  if ( result = ReadArgs( "CPCDFILE/A,DSKFILE", (APTR)&array, 0L ) )
	#else
	  if ( ( argc == 2 ) || ( argc == 3 ) )
	#endif
	{

	/* clear header & track block */

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

	/* initialise header block */

		strncpy( HeaderDSK.debut , "MV - CPCEMU Disk-File\r\nDisk-Info\r\n", sizeof( HeaderDSK.debut ) );
		strncpy( HeaderDSK.creator , PROGRAMDESC"\r\n", sizeof( HeaderDSK.creator ) );
		HeaderDSK.NbTracks = NBTRACK;
		HeaderDSK.NbHeads = 1;
		#ifdef BIGENDIAN
		  HeaderDSK.DataSize = 0x0013;
		#else
		  HeaderDSK.DataSize = 0x1300;
		#endif

	/* 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 */

		#ifdef AMIGA
		  HandleSource = fopen( array.cliarg[0], "rb" );
		#else
		  HandleSource = fopen( argv[ 1 ], "rb" );
		#endif

		if ( HandleSource )
		{
			fread ( &HeaderEmuCPC, sizeof( HeaderEmuCPC ), 1, HandleSource );

			#ifdef BIGENDIAN
			  if ( HeaderEmuCPC.Signature == 0x43504344 )
			#else
			  if ( HeaderEmuCPC.Signature == 0x44435043 )
			#endif
			{

				disksize = HeaderEmuCPC.DiskSize;

				#ifdef LITTLEENDIAN
				  disksize = ( ( disksize & 0x000000FF ) << 24 ) + ( ( disksize & 0x0000FF00 ) << 8 ) + ( ( disksize & 0x00FF0000 ) >> 8 ) + ( ( disksize & 0xFF000000 ) >> 24 );
				#endif

				if ( disksize >= 0x0002F080 )
				{
				  #ifdef AMIGA
				    if ( !writeside( 0 ) )		/* write side 0 */
				  #else
				    if ( !writeside( 0, argc, argv ) )	/* write side 0 */
				  #endif
				  {
				      printf( "Error while opening output file #A\n" );
				      #ifdef AMIGA
				        SetIoErr( ERROR_BREAK );		/* ERROR_BREAK */
				      #else
				        errcode = 1;
				      #endif
				      error = TRUE;
				  }
				}

				if ( disksize == 0x0005E100 )
				{
				  #ifdef AMIGA
				    if ( !writeside( 1 ) )		/* write side 1 */
				  #else
				    if ( !writeside( 1, argc, argv ) )	/* write side 1 */
				  #endif
				  {
				      printf( "Error while opening output file #B\n" );
				      #ifdef AMIGA
				        SetIoErr( ERROR_BREAK );		/* ERROR_BREAK */
				      #else
				        errcode = 1;
				      #endif
				      error = TRUE;
				  }
				}
			}
			else
			{
				printf( "Inputfile is not an EmuCPC (.CPCD) file\n" );
				#ifdef AMIGA
				  SetIoErr( ERROR_OBJECT_WRONG_TYPE );		/* ERROR_OBJECT_WRONG_TYPE */
				#else
				  errcode = 1;
				#endif
				error = TRUE;
			}

			fclose( HandleSource );
		}
		else
		{
			#ifdef AMIGA
			  SetIoErr( ERROR_OBJECT_NOT_FOUND );		/* ERROR_OBJECT_NOT_FOUND */
			#else
			  errcode = 2;
			#endif
			error = TRUE;
		}

		#ifdef AMIGA
		  FreeArgs( result );
		#endif

	}
	else
	{
		#ifndef AMIGA
		  errcode = 3;
		#endif
		error = TRUE;
	}

	if ( error )
	{
		#ifdef AMIGA
		  PrintFault( errcode = IoErr() , "CPCD2DSK" );
		  return ( errcode );
		#else
		  switch ( errcode )
		  {
		    case 1:
		      break;

		    case 2:
		      printf( "File not found\n" );
		      break;

		    case 3:
		      printf( PROGRAMDESCL" ("PROGRAMDATE") by Gerald Schnabel\n" );
		      printf( "(Gerri@studserv.uni-stuttgart.de)\n\n" );
		      printf( "Usage: cpcd2dsk <cpcdfile> [dskfile]\n" );
		      break;

		    default:
		      printf( "Unknown error\n" );
		      break;
		  }

		  return EXIT_FAILURE;
		#endif
	}
	else
		#ifdef AMIGA
		  return ( RETURN_OK );
		#else
		  return EXIT_SUCCESS;
		#endif
}

