#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>

//----------------------------------------
//IECWriteD64 1.1.1
//
//Writes a D64 file to a disk inserted in
//the 1541 drive.
//
//----------------------------------------


struct iecbase *IECBase;

char Version[]="$VER:IECWriteD64 1.1.1 (15.10.96) by Fabrizio Farenga";
UWORD BlockSize;
char* DestName;	//Name of the D64 file to write (from AmigaDOS to the 1541)

FILE *fh;	//Input 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]); 
}



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

#define WRITESECTOR \
	Listen(device); \
	Second(CMD_DATA+2); \
 \ 
	c=0; \
		while (c<256) \
		{ \
		chkabort(); \
		CIOut(TrackBuffer[c]); \
		c++; \
		} \
\
	UnListen(); \
\
	Listen(device);  \
	Second(0x6f);  \
	sprintf(command,"U2: 2 0 %d %d",t,s); \
	SendString(command); \
\
	UnListen(); \
\
\
	printf ("Writing Track: %d, Sector %d   \n[1F",t,s);

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

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

//Open the D64 file to write to the 1541
fh=fopen (filename,"rb");

	if (fh==NULL)
	{
	printf ("\nFile Not Found\n\n");
	return;
	}

//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();

//Reset to zero the buffer pointer
Listen(device);	//PRINT #15,"B-P";2;0
Second(CMD_DATA+15);
SendString("B-P 2 0");
UnListen();


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


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

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

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


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)
{
IECBase = (struct iecbase*)OpenLibrary("iec.library",0L);

if ((rda = ReadArgs("FROM/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;
	}


if (IECBase!=0)
	{

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

	WriteDisk(DestName);

	CloseLibrary((struct Library*)IECBase);

	}
else
	{
	printf ("Can't open iec.library\n");
	return;
	}

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

}
