#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>

#include <exec/exec.h>
#include <exec/execbase.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <proto/exec.h>
#include <proto/dos.h>

#include <iec/iec.h>

//----------------------------------------
//IECReadD64 1.1
//
//Get a D64 image from the disk inserted in
//the 1541 drive.
//
//----------------------------------------


struct iecbase *IECBase;

char Version[]="$VER:64ReadD64 1.1 (06.10.96) by Fabrizio Farenga";
UWORD BlockSize;
unsigned char c;
char* DestName;		//Name of the D64 file to create (using AmigaDos)

FILE *fh;	//Ouput File Handle

struct RDArgs *rda;
LONG argv[3]={0,0,0};
char device=8;	//Default device #

//******************************************
// Send a null-terminated string to the 1541
//******************************************
void SendString(char* string)
{
int t;
for (t=0;string[t]!=0;t++) CIOut(string[t]); 
}


//*****************************************************
//Read sector MACRO
//This read the sector "s" of track "t" to 
//TrackBuffer[] (256 bytes)
//*****************************************************

#define READSECTOR \
	Listen(device);  \
	Second(CMD_DATA+15);  \
	sprintf(command,"U1: 2 0 %d %d",t,s); \
	SendString(command); \
\
	UnListen(); \
\
\
	Talk(device); \
	TkSA(CMD_DATA+2); \
\
	c=0; \
		while (IECBase->iec_ST==ST_OK) \
		{ \
		chkabort(); \
		TrackBuffer[c]=ACPtr(); \
		c++; \
		} \
\
	UnTalk();\
\
	printf ("Reading Track: %d, Sector %d   \n[1F",t,s);

//*****************************************************

void ReadDisk(char* outname)
{
int t,s,c;
int buffernum;
char command[40];
char TrackBuffer[256];


//Open the command channel
Listen(device);	//OPEN 15,8,15
Second(CMD_OPEN+15);

	if (IECBase->iec_ST!=ST_OK)
	{
	printf ("\n?DEVICE NOT PRESENT\n\n");
	return;
	}

//Reset the disk controller
CIOut('I');		// PRINT#15,"I"
UnListen();

//Open the data channel and allocate a buffer in the 1541 memory
Listen(device);	//OPEN 2,8,2,"#"
Second(CMD_OPEN+2);
CIOut('#');
UnListen();

//Get the buffer number (unused)
Talk(device);	//GET #2,buffernum
TkSA(CMD_DATA+2);
buffernum=ACPtr();
UnTalk();

//Open the D64 file to create
fh=fopen (outname,"wb");

	//Read tracks 01 - 17 (21 sectors per track)
	for (t=1;t<18;t++)
	{
		for (s=0;s<21;s++)
		{
		READSECTOR
		//Write to AmigaDos
		fwrite (TrackBuffer,256,1,fh);
		}
	}

	//Write tracks 18 - 24 (19 sectors per track)
	for (t=18;t<25;t++)
	{
		for (s=0;s<19;s++)
		{
		READSECTOR
		//Write to AmigaDos
		fwrite (TrackBuffer,256,1,fh);
		}
	}

	//Write tracks 25 - 31 (18 sectors per track)
	for (t=25;t<31;t++)
	{
		for (s=0;s<18;s++)
		{
		READSECTOR
		//Write to AmigaDos
		fwrite (TrackBuffer,256,1,fh);
		}
	}

	//Write tracks 31 - 35 (17 sectors per track)
	for (t=31;t<36;t++)
	{
		for (s=0;s<17;s++)
		{
		READSECTOR
		//Write to AmigaDos
		fwrite (TrackBuffer,256,1,fh);
		}
	}

fclose (fh);


Listen(device);	//Close 2
Second(CMD_CLOSE+2);
UnListen();

Listen(device);	//Close 15
Second(CMD_CLOSE+15);
UnListen();

printf ("\n\n");

}

/* Break Handler */
int brk(void)
{
/* On break, close all */

fclose (fh);

Listen(device);	//Close 2
Second(CMD_CLOSE+2);
UnListen();

Listen(device);	//Close 15
Second(CMD_CLOSE+15);
UnListen();

CloseLibrary((struct Library*)IECBase);
if (rda!=0) FreeArgs(rda);

printf ("\n\nBreak received.\n\n");
return (1);
}

void main(void)
{
if ((rda = ReadArgs("TO/A,DEVICE/N",argv,NULL)) != NULL)
	{
	if (argv[0]!=0) DestName=(char*)argv[0];	//Destination filename

	if (argv[1]!=0) device=*(LONG *)argv[1];	//Device (if none, device = 8)
	}
else
	{
	printf ("Required argument missing\n\n");
	return;
	}


if (device<4)
	{
	printf ("\n?DEVICE NOT PRESENT\n\n");
	return;
	}

IECBase = (struct iecbase*)OpenLibrary("iec.library",0L);

if (IECBase!=0)
	{

	/*Set the break handler*/
	onbreak(&brk);

	ReadDisk(DestName);

	CloseLibrary((struct Library*)IECBase);
	}
else
	{
	printf ("Can't open iec.library\n");
	return;
	}

	if (rda!=0) FreeArgs(rda);

}
