#ifndef LIBRARIES_PATCHPRIVATE_H
#define LIBRARIES_PATCHPRIVATE_H
/*****************************************************************************/
/*
**	Filename:	libraries/patchPRIVATE.h
**	Release:	6.0
**	Date:		19.08.97
**
**	definition of patch.library PRIVATE structures and returncodes
**
**	(C) Copyright 1993-97 Stefan Fuchs
**	All Rights Reserved
*/
/*****************************************************************************/

#ifndef	EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef	EXEC_LISTS_H
#include	<exec/lists.h>
#endif	/* EXEC_LISTS_H */

#ifndef	EXEC_LIBRARIES_H
#include	<exec/libraries.h>
#endif	/* EXEC_LIBRARIES_H */

#ifndef	EXEC_SEMAPHORES_H
#include	<exec/semaphores.h>
#endif	/* EXEC_SEMAPHORES_H */

#ifndef	UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif


/*----------------------------------------------------------------------------*/

/* ErrorCodes */
#define PATERR_Ok		0	/* Everything Ok				*/
#define PATERR_PatchInUse	1	/* Patch Usecount <> 0				*/
#define PATERR_InvalidHandle	2	/* Pointer to patch is not (no longer) valid	*/
#define PATERR_OutOfMem		3	/* Out of memory				*/
#define PATERR_OpenLib		4	/* Failed to open requested library		*/
#define PATERR_FuncNotStd	5	/* Function to patch is not in the standard format */
#define PATERR_PatchInstalled	6	/* Can't remove patch because another program has  */
					/* installed a non-patch.library patch later       */
#define PATERR_InvalidTags	7	/* There was an error in the combination of the specified Tags */
#define PATERR_OpenDev		8	/* Failed to open requested device */
#define PATERR_NoTaskList	9	/* PATT_AddTask... or PATT_RemTask... was specified for a patch, */
					/* which had no PATT_CreateTaskList set */
#define PATERR_TaskListExists	10	/* PATT_CreateTaskList was specified, but there already exists a TaskList */
#define PATERR_InvalidTaskList	11	/* PATT_CreateTaskList was specified with a wrong parameter */
#define PATERR_PatchUnnamed	12	/* PATT_PatchName with GetPatch was specified, for a patch without an IDString */
#define PATERR_NoSemaphore	13	/* Could not allocate semaphore */

#define PATERR_KickTooOld	14	/* Kickstart version is too old for this function */
#define PATERR_InvalidPattern	15	/* Pattern passed via PATT_AddTaskPattern is not valid */
#define PATERR_Restricted	16	/* Certain tags/features may not be used when patching certain functions */


/*----------------------------------------------------------------------------*/
struct PatchNotifyMessage {
    struct Message pnm_ExecMessage;
    ULONG  pnm_Class;
    UWORD  pnm_Code;
    APTR   pnm_Object;
};

/*----------------------------------------------------------------------------*/
#define PATCHNOTIFY_CLASS	0x50000000
/*----------------------------------------------------------------------------*/
/*Notification codes (pnm_Code) (ignore messages with other codes): */
#define PATCOD_PatchInstalled	1	/* new patch has been added */
#define PATCOD_PatchRemoved	2	/* a patch has been removed */
#define PATCOD_PatchChanged	3	/* attributes of a patch have been changed */

/*----------------------------------------------------------------------------*/
#define	PatchName "patch.library"
#define STACKSLOTS 5	/* (V6) Maximum number of stacks, which can be preallocated for stackextension feature */

/*------------------------------------------------------------------------------*/
struct MasterPatch			/* This structure is PRIVATE */
{
struct	Node	MPS_Node;		/* ln_Name may contain a pointer to the name of the patched library */
	UWORD	MPS_Flags;		/* see below */
struct	MinList	MPS_PatchHeader;	/* Listheader Structure for Patch structures */
struct	Library	*MPS_PatchedLibraryBase; /* Pointer to patched Library */
	WORD	MPS_PatchedLVO;		/* Library Vektor Offset in patched library */
	UWORD	MPS_OldEntry01;		/* original entry point */
	ULONG	MPS_OldEntry02;
	APTR	MPS_PatchIORequest;	/* Pointer to IORequest for CloseDevice() (if available) */
	APTR	MPS_SetFunctionResult;	/* Pointer to result of SetFunction */
					/* (only used when the UseSetFunction Bit is set) */
					/* This need not equal the contents of MPS_OLDEntry, if a SetFunction Manager is installed */

struct	PatchStack *MPS_StackSlots[STACKSLOTS+1]; /* (V6) Array of pointers of preallocated stacks */


};

/* Master Patch Struct Flags */
#define MPSB_CloseLib		0	/* Patch.library opened the library */
#define MPSB_CloseDev		1	/* Patch.library opened the device */
#define MPSB_IncLibUsage	2	/* Patch.library did increase library usage counter (was MPSB_PatchSV) */
#define MPSB_Attached		3	/* Masterpatch is attached to library */
#define MPSB_UseSetFunction	4	/* Use SetFunction for installing and removing patches */

#define MPSF_CloseLib		(1L<<0)	/* Patch.library opened the library */
#define MPSF_CloseDev		(1L<<1)	/* Patch.library opened the device */
#define MPSF_IncLibUsage	(1L<<2)	/* Patch.library did increase library usage counter (was MPSF_PatchSV) */
#define MPSF_Attached		(1L<<3)	/* Masterpatch is attached to library */
#define MPSF_UseSetFunction	(1L<<4)	/* Use SetFunction for installing and removing patches */


/*----------------------------------------------------------------------------*/
struct	Patch			/* This structure is PRIVATE */
{
	struct	Node	PS_Node;	/* ln_Name may contain a pointer to the name of the patch */
	UWORD	PS_Flags;		/* see below */
	struct	PatchCode *PS_PatchCode;/* Pointer to PatchCode (Code begins at Offset + 8) */
	LONG	PS_UserPatchCodeSize;	/* Length of NewCode in bytes (if this field is >0 the memory starting at the UserPatch must be freed) */
	struct	List PS_RemoveHookList;	/* Header of a double linked list containing */
					/* hooks to be called, when a patch is finally removed */
	struct  MinNode PS_ProjectNode;	/* ListNode identifing the Project(if any), to which the */
					/* patch belongs */
	ULONG	PS_UserData;		/* Application specific data */
	ULONG	PS_StackSize;		/* (V6) Minimum Stacksize for this patch */
	UBYTE	PS_PatchCodeType;	/* (V6) Type of PatchCode attached via PS_PatchCode (see below) */
	UBYTE	PS_Pad;			/* reserved */

	APTR	PS_JmpNext;		/* (V6) Pointer to instruction to change, when linkage changes or NULL */
	APTR	PS_JmpOrig;		/* (V6) Pointer to instruction to change, when linkage changes or NULL */
	APTR	PS_Jsr;			/* (V6) Pointer to instruction to change, when linkage changes or NULL */
	APTR	PS_SystemEntry;		/* (V6) Address to reenter patchcode or NULL */

	APTR	PS_TestUsage1;		/* (V6) Pointer to instruction, which is not covered by a usage counter or NULL */
	APTR	PS_TestUsage2;		/* (V6) Pointer to instruction, which is not covered by a usage counter or NULL */
	APTR	PS_TestUsage3;		/* (V6) Pointer to instruction, which is not covered by a usage counter or NULL */

};
/* Patch Struct Flags: */
#define PSB_PatchSV		0	/* Object was installed with PatchSupervisor active */
#define PSB_OriginalType	2	/* (V6) Patch was installed with PATT_Original */
#define PSB_InternalCall	3	/* (V6) Calling SetPatch() from internal function */
					/* (SetPatchA() will always clear this flag) */
#define PSF_PatchSV		(1L<<0)	/* Object was installed with PatchSupervisor active */
#define PSF_OriginalType	(1L<<2)	/* (V6) Patch was installed with PATT_Original */
					/* implemented for GetPatch and InstallPatchTags() */
#define PSF_InternalCall	(1L<<3)	/* (V6) Calling SetPatch() from internal function */
					/* (SetPatchA() will always clear this flag) */


/* PS_PatchCodeType: */
#define PCODE_GENERIC	  0	
#define PCODE_START	  6	/* For PS_TYPE_START */
#define PCODE_ORIG	  7	/* For PS_TYPE_ORIG  */
#define PCODE_END	  8	/* For PS_TYPE_END   */

#define PCODE_USER0	 10	/* For PS_TYPE_USER   ->Replace + No UseXResult */
#define PCODE_USER1	 11	/* For PS_TYPE_USER   ->Replace + UseXResult    */
#define PCODE_USER2	 12	/* For PS_TYPE_USER   ->Pri <> 0 + NoOrig + No UseXResult */
#define PCODE_USER3	 13	/* For PS_TYPE_USER   ->Pri <> 0 + NoOrig + UseXResult    */
#define PCODE_USER4	 14	/* For PS_TYPE_USER   ->Pri >  0 + Orig   + No UseXResult */
#define PCODE_USER5	 15	/* For PS_TYPE_USER   ->Pri >  0 + Orig   + UseXResult */

#define PCODE_SYSTEM     14	/* same as PCODE_USER4 */

/*----------------------------------------------------------------------------*/

struct PatchProject		/* This structure is PRIVATE */
{
struct	Node	PPR_Node;
	UWORD	PPR_Flags;	/* see below */
	struct	List PPR_PatchListHeader; /* Header of a double linked list containing */
					  /* patches belonging to the Project */
	ULONG	PPR_UserData;		  /* (V6) Application specific data (not implemented) */
};
/* ln_Type: PS_TYPE_PROJECT */
/* ln_Name: Name of Project */

#define PPRB_InternalCall	0	/* (V6) Calling SetPatchProject() from internal function */
					/* (SetPatchProject() will always clear this flag) */
					/* (set PSF_InternalCall for all SetPatchA calls) */
#define PPRF_InternalCall	(1L<<0)	/* (V6) Calling SetPatchProject() from internal function */
					/* (SetPatchProject() will always clear this flag) */
					/* (set PSF_InternalCall for all SetPatchA calls) */


/*----------------------------------------------------------------------------*/
struct TLHeader			/* This structure is PRIVATE */
{
	struct	List	TL_List;
	ULONG	TL_Result1;	/* Result1: 0 if Type: TL_TYPE_INCLUDE otherwise 1 */
	ULONG	TL_Result2;	/* Result1: 1 if Type: TL_TYPE_INCLUDE otherwise 0 */
};
/*----------------------------------------------------------------------------*/
struct TLNode			/* This structure is PRIVATE */
{
	struct	Node	TN_Node;
	APTR	TN_Pattern;	/* TLI_TYPE_TASKPATTERN only:Pattern returned by ParsePattern() */
};
/*----------------------------------------------------------------------------*/
struct PatchXResult {		/* Use PatchAlloc(PS_TYPE_XRESULT) to allocate this */
    struct Node pxr_Node;	/* Reserved */
    ULONG  pxr_RegPattern;	/* Which of the following register fields are used */
    ULONG  pxr_RegD0;
    ULONG  pxr_RegD1;
    ULONG  pxr_RegD2;
    ULONG  pxr_RegD3;
    ULONG  pxr_RegD4;
    ULONG  pxr_RegD5;
    ULONG  pxr_RegD6;
    ULONG  pxr_RegD7;
    ULONG  pxr_RegA0;
    ULONG  pxr_RegA1;
    ULONG  pxr_RegA2;
    ULONG  pxr_RegA3;
    ULONG  pxr_RegA4;
    ULONG  pxr_RegA5;
    ULONG  pxr_RegA6;
    UWORD  pxr_FlowControl;	/* What patches follow this one (see below) */
};
/*----------------------------------------------------------------------------*/
/* types for patch, masterpatch and project structures: */
#define PS_TYPE_UNKNOWN 	0	/* do not use */
#define PS_TYPE_MASTER		1	/* node is MasterPatch structure */
#define PS_TYPE_USER		2	/* node was installed by an Application using the library interface */
#define PS_TYPE_SYSTEM		3	/* node was installed by the support program PatchSetFunc */
#define PS_TYPE_DELUSER		4	/* this struct is PS_TYPE_USER, but should be removed */
#define PS_TYPE_DELSYSTEM	5	/* this struct is PS_TYPE_SYSTEM, but should be removed */
#define PS_TYPE_START		6	/* this struct points to a JMP */
#define PS_TYPE_ORIG		7	/* this struct points to a routine that calls the old routine */
#define PS_TYPE_END		8	/* this struct points to a RTS */
#define PS_TYPE_PROJECT		20	/* this struct, is a Header structure to a list of PS_TYPE_USER structures belonging to one project */
#define PS_TYPE_XRESULT		30	/* this struct is an PatchXResult structure */


#define TLI_TYPE_TASKNAME	3	/* LN_NAME points to TaskName */
#define TLI_TYPE_TASKID		4	/* LN_NAME points to Task structure */
#define TLI_TYPE_TASKPATTERN    5       /* LN_NAME points to Token string for MatchPattern() (V5) */

/*----------------------------------------------------------------------------*/
/* pre patchcode structure: */
struct PatchCode {
	ULONG PC_PatchXResult;		/* TRUE, if PatchXResult system is used */
	struct Patch *PC_PatchStruct;	/* Pointer to PatchStruct */
	ULONG PC_StackSize;		/* Stacksize required to execute the patchcode */
	ULONG PC_Disable;		/* Disable nesting counter 0= Enabled */
	struct TLHeader *PC_TaskList;	/* Exclude/Include List */
	ULONG PC_Usage;			/* Usage Counter */
	UBYTE PC_PatchCodeStart;	/* Assembler PatchCode follows */
/* PatchCode: */
};
/*----------------------------------------------------------------------------*/
/* This structure is at the high adresses (the bottom) of an extended stack */
/* .... stack .... */
struct PatchStack
{
	ULONG PST_Reserved2;		/* $CCDDEEFF */
	ULONG PST_Reserved1;		/* $8899AABB */
struct StackSwapStruct PST_StackSwap;	/* structure for StackSwap */
	ULONG PST_Usage;		/* 1: this stack is in use  0: stack is free */
	APTR  PST_OldStack;		/* Pointer to oldstack */
	ULONG PST_Stacksize;		/* Size of this stack */
	APTR  PST_Magic2;		/* pointer to PST_Magic1 */
	ULONG PST_Magic1;		/* magic PatchStackID 'PATC' */
};
/*----------------------------------------------------------------------------*/


/* Beginning of GetPatch tags (currently PRIVATE) */
#define	PATT_NewCode	TAG_USER+0x5000+50	/* G: BOOL Return pointer to installed patch */
						/* 	default: FALSE */

/* Beginning of PRIVATE tags */
#define	PATT_SYSTEM	TAG_USER+0x5000+60	/* I: True: Install patch in system mode */
						/* 	FOR PatchSetFunc *ONLY* */
	 					/* F: APTR Return pointer to patch structure */
						/*	of the given code pointer */
						/* G: True: return Setfunction() result */
#define PATT_LVO	TAG_USER+0x5000+61	/* F: UWORD Return pointer to master patch structure */
						/* 	of the given LibraryBase and LVO */
						/* 	if you specify this tag you must also specify */
						/* 	the public tag PATT_LibraryBase or PATT_LibraryName */
#define PATT_Detach	TAG_USER+0x5000+62	/* S: BOOL the library for this patch has been closed */
						/* 	Parameter (MasterPatch structure instead of Patch struct) */
					   	/*	FOR PatchSupervisor *ONLY* */
#define PATT_Attach	TAG_USER+0x5000+63	/* S: struct Library * */
						/* 	Reattach a MasterStruct to a Library */
						/* 	Parameter (MasterPatch structure instead of Patch struct) */
						/*   	FOR PatchSupervisor *ONLY* */
/*	PATT_LibraryBase	*/		/* F: APTR Return pointer to master patch structure */
						/* 	of the given LibraryBase and LVO */
						/* 	if you specify this tag you must also specify */
						/* 	the private tag PATT_LVO */
/*	PATT_LibraryName	*/		/* F: APTR Return pointer to master patch structure */
						/* 	of the given Libraryname and LVO */
						/* 	if you specify this tag you must also specify */
						/* 	the private tag PATT_LVO */



#endif	/* LIBRARIES_PATCHPRIVATE_H */
