/***************************************************************************
                B         B           M
                 oot       block       maker
                   written 1988 by
                     G.Glendown
***************************************************************************/

/* Include Files */

#include	<exec/types.h>
#include	<graphics/gfxbase.h>
#include	<intuition/intuition.h>
#include	<devices/trackdisk.h>
#include	<exec/ports.h>
#include	<exec/nodes.h>
#include	<exec/io.h>
#include	<exec/devices.h>
#include	<libraries/dosextens.h>

#define	TD_READ	CMD_READ;
#define	TD_WRITE	CMD_WRITE

struct	MsgPort		*diskport,*CreatePort();
struct	IOExtTD		*diskreq;
struct	IORequest	*CreateExtIO();
struct	FileHandle	*fh,*Open();
char			FileName[256];
UBYTE			Buffer[TD_SECTOR*NUMSECS],Prg[1044];
ULONG			dcc;
ULONG			*SB,*SP;
int			lncnt,m;


main	(argc,argv)
int argc;
char *argv[];
{
	if (argc!=3) DError(argv);		/* genau 3 Parameter ? */
	if (argv[1][0]<'0'||argv[1][0]>'3') DError(argv); /* Device */

	m=argv[1][0]-'0';			/* in device umändern */
	puts(" ");

	SB=(ULONG *)Buffer;
	SP=(ULONG *)Prg;

	puts("**************************");
	puts("      B B M");
	puts("**************************");
	puts("  written by G. Glendown");
	puts(" ");
	puts("Schreibt Ass-Prg's");
	puts("in den Boot-Block\n");

	fh=Open(argv[2],MODE_OLDFILE);		/* File öffnen */
	if (!fh) DError(argv);			/* vorhanden ? */
	Read(fh,Prg,1044L);			/* einlesen */
	Close(fh);				/* schließen */

	ChangeBoot();				/* Bootsector ändern */
}

ChangeBoot()
/* Ändert den Bootsector */

{

int			error;
long			g,n,u;
long			drive;

	diskport = CreatePort (0L,0L);

	if (diskport) {

		diskreq = (struct IOExtTD *)
			CreateExtIO (diskport,(LONG)sizeof (struct IOExtTD));

		if (diskreq) {

			error = OpenDevice(TD_NAME,(long)m,diskreq,0L);

			if (!error) {

				diskreq->iotd_Req.io_Command = TD_CHANGENUM;
				DoIO(diskreq);
				dcc = diskreq->iotd_Req.io_Actual;
				ReadBlock();
				CopyProg();
				WriteBlock();
				CloseDevice (diskreq);

			}

			DeleteExtIO (diskreq,(long)sizeof(struct IOExtTD));

		}

		DeletePort (diskport);

	}

}

CopyProg()
/* Kopiert Programm in den Puffer */

{

ULONG t,g,h,s,q;

	SB[0]=0x444f5300;
	SB[1]=0L;
	SB[2]=0L;
	t=36;
	g=12;
	s=0;

	for (h=1044;h>36;h--)			/* Puffer kopieren */
		Buffer[g++]=Prg[t++];

	g=0;

	for (h=255;h<256;h--) {			/* Checksum berechnen */

		q=s+SB[g++];
		if (q<s) q++;
		s=q;

	}

	q=0xffffffff-s;
	SB[1]=q;				/* und einschreiben */

}

ReadBlock()
/* Block von Disk lesen */

{

	MotorOn();

	diskreq->iotd_Req.io_Length = 	TD_SECTOR*NUMSECS;
	diskreq->iotd_Req.io_Data = 	(APTR)Buffer;
	diskreq->iotd_Req.io_Command = 	ETD_READ;
	diskreq->iotd_Count = 		dcc;
	diskreq->iotd_Req.io_Offset = 	0L;

	DoIO (diskreq);

	MotorOff();

	return();
}

WriteBlock()
/* Block auf Disk schreiben */

{

	MotorOn();

	diskreq->iotd_Req.io_Length = 	TD_SECTOR*NUMSECS;
	diskreq->iotd_Req.io_Data = 	(APTR)Buffer;
	diskreq->iotd_Req.io_Command = 	ETD_WRITE;
	diskreq->iotd_Count = 		dcc;
	diskreq->iotd_Req.io_Offset = 	0L;

	DoIO (diskreq);

	diskreq->iotd_Req.io_Length =	0L;
	diskreq->iotd_Req.io_Command =	ETD_UPDATE;

	DoIO (diskreq);

	MotorOff();

	return();

}

MotorOn()
/* Schaltet Disk-Motor an */

{

	diskreq->iotd_Req.io_Length = 	1L;
	diskreq->iotd_Req.io_Command = 	TD_MOTOR;

	DoIO (diskreq);

}

MotorOff()
/* Schaltet Disk-Motor aus */

{

	diskreq->iotd_Req.io_Length = 	0L;
	diskreq->iotd_Req.io_Command =  TD_MOTOR;

	DoIO (diskreq);

}

DError(te)
char *te[];
/* Ausgabe der Syntax */

{

	puts("Syntax: %s <0/1/2/3> <Prg-Name>\n",te[0]);
	exit(-111);

}
