/* This is an example, how to implement library patching in pure SAS/C */
/* with patch.library V5+ */


#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <exec/types.h>
#include <exec/libraries.h>
#include <utility/tagitem.h>
#include <clib/exec_protos.h>
#include <pragmas/exec_pragmas.h>
#include "ASMSources:PatchLibrary/PatchInclude/patch_protos.h"
#include "ASMSources:PatchLibrary/PatchInclude/patch_pragmas.h"
#include "ASMSources:PatchLibrary/PatchInclude/patchtags.h"
#include "ASMSources:PatchLibrary/PatchInclude/patch.h"

#define	ASMFLAGS __saveds __asm
#define REGD0 register __d0
#define REGD1 register __d1
#define REGD2 register __d2
/* ... */
#define REGA0 register __a0
#define REGA1 register __a1
#define REGA2 register __a2
/* ... */
#define REGA6 register __a6

#define LVO_Delay		-198

char *ver="$VER: LongDelay 1.00 (17.10.96)  by Stefan Fuchs";
extern struct ExecBase *SysBase;
struct PatchBase *PatchBase = 0;
struct Patch *PatchPtr;

void Open_All(void);
void Close_All(STRPTR);
ASMFLAGS struct PatchXResult *LongDelay(REGD1 ULONG, REGA6 struct Library *);

void main()
{
ULONG sigrcvd;
BOOL weiter = TRUE;

	printf("LongDelay V1.0  © 1996 by Stefan Fuchs\n");
	Open_All();
	printf("Library patches successfully installed!\n");
	printf("Press CTRL-c to quit\n");

	while(weiter)
	{
		sigrcvd = Wait(SIGBREAKF_CTRL_C);
		if (sigrcvd & SIGBREAKF_CTRL_C) weiter = FALSE;
	}

	Close_All("");
}

void Open_All()
{
	if((PatchBase = (struct PatchBase *) OpenLibrary("patch.library", 5L)) == NULL)
		Close_All("Can't open V5+ patch.library !\n");
	PatchPtr = InstallPatchTags( (ULONG (*)())LongDelay,
			LVO_Delay, 
			PATT_LibraryName,"dos.library",
			PATT_PatchName,"LongDelay",
			PATT_Priority,10,
			PATT_StackSize,1000L,
			PATT_UseXResult,TRUE,
			TAG_DONE);
}

void Close_All(s)
STRPTR s;
{
	printf("%s",s);
	if(PatchPtr) RemovePatchTags(PatchPtr, PATT_TimeOut, 800L, TAG_DONE);
	if(PatchBase) CloseLibrary((struct Library *)PatchBase);
	exit(TRUE);
}


/* The following patch does almost nothing, it simply increases the number of ticks */
/* until Delay() returns */

/* As C-Functions may destroy the registers d0/d1/a0/a1 you must return them in */
/* the extended result structure */

ASMFLAGS struct PatchXResult *LongDelay(REGD1 ULONG ticks, REGA6 struct Library *DosBase)
{
struct PatchXResult *xresult;

	ticks += 30;			/* Do your stuff here */

	/* Allocate an extended result structure */
	/* patch.library will free this, when the patch is completed */
	/* This function better succeeds, as setting registers wrong */
	/* will in most cases cause crashes */

	if (xresult = (struct PatchXResult *)PatchAlloc(PS_TYPE_XRESULT))
	{
		xresult->pxr_RegPattern = PATREG_D1;	/* 'Or' all registers, you change here */
		xresult->pxr_RegD1 = ticks;		/* fill these registers in the appropriate fields */
	}
return (xresult);					/* return the extended return structure */
}
