
/*
 * TrackWizard.c by Jarkko Vatjus-Anttila & Ville Helin (c) 1997.
 *
 * USAGE:
 *
 * (read|write) UNIT (num) FILE (name) [startcyl (num) endcyl (num)]
 *
 * EXAMLE:
 *
 * TrackWizard read UNIT 0 FILE t:output startcyl 50 endcyl 79
 *
 * This is public domain!
 *
 * KNOWN BUGZ:
 *
 * 1) How to detect if the DoIO() returns a failure? With IoERR() perhaps?
 * 2) How to stop trackdisk motor after action??
 *
 */

#include "exec/types.h"
#include "exec/memory.h"
#include "exec/io.h"
#include "dos/dos.h"

#define cmd_write	1
#define	cmd_read	2
#define	cylsize		11264

struct IOStdReq *io = NULL;
struct MsgPort *msg = NULL;
ULONG trackflag;

char info[] = "[1mTrackWizard v1.0 by Jarkko Vatjus-Anttila & Ville Helin[0m";
char usagetxt[] = "USAGE: READ|WRITE FILE (name) UNIT (num) [STARTCYL (cyl) ENDCYL (cyl)]";

void cleanup(char *error);
BOOL stringcmp(char *t1, char *t2);

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

main(int argc, char *args[])
	{
	APTR *file;
	char *fname = NULL;
	ULONG action = 0, unit = 500, startcyl = 0, endcyl = 79, i;
	UBYTE *buffer;

	printf("%s\n", info);

	msg = (struct MsgPort *)CreateMsgPort();
	if (msg == NULL) cleanup("Not enough memory for Message port!");

	io = (struct IOStdReq *)CreateIORequest(msg, sizeof(struct IOStdReq));
	if (io == NULL) cleanup("Unable to create I/O request!");



/* Seuraavassa kerätään hieman parametrejä. Olisi ollut hienoa tehdä
 * parseri erikseen, mutta mitä hemmettiä. Täähän on vain tällanen
 * pikku ohjelma.
 *
 * Tarkistetaan mikä komento: read vai write??
 */

	if (stringcmp(args[1], "write") == TRUE) action = cmd_write;
	if (stringcmp(args[1], "read") == TRUE) action = cmd_read;
	if (action == 0) cleanup("*** No action (read|write) specified");

/*
 *	Sitten tarkistetaan onko tiedoston nimeä annettu!
 */

	for (i=1; i<argc; i++) if (stringcmp(args[i], "file") == TRUE) fname = args[i+1];
	if (fname == NULL) cleanup("*** No file name specified!");

/*
 * Ja sitten unitin numero.
 */

	for (i=1; i<argc; i++) if (stringcmp(args[i], "unit") == TRUE) unit = args[i+1][0] - '0';
	if (unit == 500) cleanup("*** No unit number specified!");

/*
 * Sitten startcyl ja endcyl
 */

	for (i=1; i<argc; i++) if (stringcmp(args[i], "startcyl") == TRUE)
		if (strlen(args[i+1]) == 2)
			{ startcyl = 10*(args[i+1][0]-'0')+args[i+1][1]-'0'; }
		else
			{ startcyl = args[i+1][0]-'0'; }

	for (i=1; i<argc; i++) if (stringcmp(args[i], "endcyl") == TRUE)
		if (strlen(args[i+1]) == 2)
			{ endcyl = 10*(args[i+1][0]-'0')+args[i+1][1]-'0'; }
		else
			{ endcyl = args[i+1][0]-'0'; }

	if (startcyl > 79) startcyl = 79;
	if (endcyl > 79) endcyl = 79;
	if (startcyl > endcyl) { i = startcyl; startcyl = endcyl; endcyl = i; }


/*
 * Sitten tulostetaan hieman infoa missä mennään: (debug)
 */

//	printf("Debug info:\n comm:\t%ld\n unit:\t%ld\n start\t%ld\n end:\t%ld\n len:\t%ld\n file:\t%s\n", action, unit, startcyl, endcyl, (endcyl-startcyl+1)*cylsize, fname);

/*
 * Ja sitten rokataan!!
 */

	trackflag = OpenDevice("trackdisk.device", unit, io, 0);
	if (trackflag != 0) cleanup("Unable to open trackdisk.device");

	buffer = (UBYTE *)AllocMem(cylsize, MEMF_ANY|MEMF_CLEAR);
	if (buffer == NULL) cleanup("Not enough memory!");

//	printf("Working...\n");

	if (action == cmd_write)
		{
		file = (APTR)Open(fname, MODE_OLDFILE);
		if (file == NULL)
			{
			FreeMem(buffer, cylsize);
			cleanup("*** Unable to open file");
			}
		for (i=startcyl; i<endcyl+1; i++)
			{
			Read(file, buffer, cylsize);
			io->io_Command = CMD_WRITE;
			io->io_Length = cylsize;
			io->io_Data = buffer;
			io->io_Offset = i*cylsize;
			DoIO(io);
			printf("Writing cylinder %ld. Bytes written: %ld\13\n", i, (i-startcyl+1)*cylsize);
			}
		Close(file);
		}
	else
		{
		file = (APTR)Open(fname, MODE_NEWFILE);
		if (file == NULL)
			{
			FreeMem(buffer, cylsize);
			cleanup("*** Unable to open file!");
			}
		for (i=startcyl; i<endcyl+1; i++)
			{
			io->io_Command = CMD_READ;
			io->io_Length = cylsize;
			io->io_Data = buffer;
			io->io_Offset = i*cylsize;
			DoIO(io);
			Write(file, buffer, cylsize);
			printf("Reading cylinder %ld. Bytes read: %ld\13\n", i, (i-startcyl+1)*cylsize);
			}
		Close(file);
		}

	printf("\n");
	FreeMem(buffer, cylsize);
	cleanup(NULL);
	}

/*****************************************************************************/
/* siivous rutkut */

void cleanup(char *error)
	{
	if (trackflag == NULL) CloseDevice(io);
	if (msg != NULL) DeleteMsgPort(msg);
	if (io != NULL) DeleteIORequest(io);

	if (error != NULL)
		{
		printf("%s\n", usagetxt);
		printf("%s\n", error);
		}

	exit(0);
	}

/*****************************************************************************/
/* Pikku aliohjelma stringien vertailuun */

BOOL stringcmp(char *t1, char *t2)
	{
	ULONG i;

	for (i=0; i<strlen(t1); i++)
		if ((t1[i] > 'A'-1) && (t1[i] < 'Z'+1)) t1[i] = t1[i]+32;

	if (strlen(t1) != strlen(t2)) return(FALSE);

	for (i=0; i<strlen(t1); i++)
		if (t1[i] != t2[i]) return(FALSE);

	return(TRUE);
	}
