/********************************************************************************/
/*                              DmaSwitch                                       */
/*                                                                              */
/*                              Written by                                      */
/*                             Andreas Jung                                     */
/*                           Klosterstrasse 2                                   */
/*                           D-6602 Dudweiler                                   */
/*                      Federal Republic of Germany                             */
/*                                                                              */
/* DMASwitch enables or disables the DMA by pressing the left ALT-key.          */
/* DMASwitch must be started from CLI by entering 'dma'. The program will       */
/* its own task. You can leave DMASwitch by entering 'dma' again.               */
/* DMASwitch can be used to increase the speed of your amiga, because the amiga */
/* spares the time of DMA etc. It can also be used to prevent other people      */
/* looking on your amiga.                                                       */
/*                                                                              */
/* Warning: This program requieres the 'arp.library' !!!!!!!!!!!!!!!            */
/*                                                                              */
/* Bugs: The program uses a FOR-loop for delay. I tried Delay() from the        */
/* dos.library, but there were any problems I couldn't fix. Can anybody help ?  */
/********************************************************************************/

#include <functions.h>
#include <exec/types.h>
#include <exec/tasks.h>
#include <exec/memory.h>
#include <libraries/arpbase.h>
#include <arp.h>

#define SIZE_STACK 300
struct ArpBase *ArpBase;

void Finish(void);
void Prog(void);
void _cli_parse(void) {};
void _wb_parse(void) {};
void MyExit(int faultcode);

void _main(void)
{
	void Prog(),Finish();
	APTR fscode;
	static char TaskName[]="DMASwitch";
	APTR c1,c2;
	struct Task *st;

	struct alltask 
	{
		struct Task tc;
		char Name[sizeof(TaskName)];
		char Stack[SIZE_STACK];
	} *ftask;

	ArpBase=(struct ArpBase *) OpenLibrary("arp.library",0);
	if (ArpBase == NULL) MyExit(20);


	st=FindTask(TaskName);                 /* Existiert Task bereits ??? */
	if (st != NULL)
	{
		RemTask(st);
		Puts("DMA-Switch off !");
		FreeMem(st,2000);
		MyExit(0);
	}

	ftask=AllocMem(2000,MEMF_PUBLIC|MEMF_CLEAR);   /* Speicher reservieren */
	if(ftask==0)
	{
		Puts("No memory free !");
		MyExit(0);
	}

	fscode=AllocMem((ULONG)Finish-(ULONG)Prog+50,MEMF_PUBLIC);
	if(fscode==0)
	{
		FreeMem(ftask,(ULONG)sizeof(*ftask));
		Puts("No memory free !");
		MyExit(0);
	}


	strcpy(ftask->Name,TaskName);                     /* Task installieren */

	ftask->tc.tc_SPLower=(APTR)ftask->Stack;
	ftask->tc.tc_SPUpper=(APTR)ftask->Stack+SIZE_STACK;
	ftask->tc.tc_SPReg  =ftask->tc.tc_SPUpper;
	ftask->tc.tc_Node.ln_Type=NT_TASK;
	ftask->tc.tc_Node.ln_Name=ftask->Name;

	for(c1=(APTR)Prog,c2=(APTR)fscode;c1<=(APTR)Finish;*c2++=*c1++);
	Puts("DMA-Switch on !");

	AddTask((struct Task*)ftask,fscode,0);   /* Task freigeben */
	SetTaskPri((struct Task*)ftask,-125);     /* Priorität erniedrigen */
}





void Prog(void)
{
	long i;
	char *keypoint  =(char *)0xbfec01;
	label: i=1;
		#asm
			move.w #$8380,$dff096
		#endasm
		for (i=0;i<80000;i++);				/* Terrible, I don't know a better solution (Delay() doesn't work */
		while (*keypoint != 55);
		#asm
			move.w #$180,$dff096
		#endasm
		for (i=0;i<80000;i++);
		while (*keypoint != 55);
	goto label;
}

void Finish(void)
{}

void MyExit(int faultcode)
{
	if (ArpBase != NULL) CloseLibrary(ArpBase);
	exit(faultcode);
}