#include <exec/memory.h>
#include <exec/resident.h>
#include <exec/execbase.h>

#include <proto/exec.h>

__builtin_memcpy(void *, void *, int);

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

struct InsertResident
   {
      struct Resident *MyResident;
      struct Resident *OldResident;
      ULONG Link;
   };

struct MyResident
   {
      struct InsertResident ResArray;
      struct Resident Resident;
   };

ULONG PasswordCode(void);
void PasswordCodeEnd(void);

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

void main(void)

{
   struct Resident **ResArray;
   struct ExecBase *SysBase;
   struct MyResident *MyResident;
   ULONG CodeLen;

/*   if (*((UBYTE *)0x00bfe001) & 0x80) */
      {
         Disable();
         SysBase=*((struct ExecBase **)4);
         if ((((ULONG)FindResident(SysBase->LibNode.lib_Node.ln_Name))&0x00f80000)==0x00f80000)
            {
               ResArray=(struct Resident **)(SysBase->ResModules);
               while (ResArray)
                  {
                     if (((ULONG)*ResArray)&0x80000000 || !*ResArray)
                        {
                           ResArray=(struct Resident **)(((ULONG)*ResArray)&0x7fffffff);
                        }
                     else
                        {
                           if ((*ResArray)->rt_Pri<=-50)
                              {
                                 CodeLen=(ULONG)PasswordCodeEnd-(ULONG)PasswordCode;
                                 MyResident=AllocMem(sizeof(struct MyResident)+CodeLen,MEMF_CLEAR);
                                 MyResident->Resident.rt_MatchWord=RTC_MATCHWORD;
                                 MyResident->Resident.rt_MatchTag=&MyResident->Resident;
                                 MyResident->Resident.rt_EndSkip=((char *)(MyResident+1))+CodeLen;
                                 MyResident->Resident.rt_Init=MyResident+1;
                                 MyResident->Resident.rt_Flags=RTF_COLDSTART;
                                 MyResident->Resident.rt_Pri=-59;
                                 MyResident->ResArray.MyResident=&MyResident->Resident;
                                 MyResident->ResArray.OldResident=*ResArray;
                                 MyResident->ResArray.Link=0x80000000|(ULONG)(ResArray+1);
                                 *ResArray=(struct Resident *)(((ULONG)MyResident)|0x80000000);
                                 ResArray=NULL;
                                 __builtin_memcpy(MyResident->Resident.rt_Init,PasswordCode,CodeLen);
                                 if (SysBase->LibNode.lib_Version>=37)
                                    {
                                       CacheClearE(MyResident->Resident.rt_Init,CodeLen,CACRF_ClearI);
                                    }
                              }
                           else
                              {
                                 ResArray++;
                              }
                        }
                  }
            }
         else
            {
               if (MyResident=(struct MyResident *)FindResident("alert.hook\xd\xa"))
                  {
                     ResArray=(struct Resident **)(SysBase->ResModules);
                     while (ResArray)
                        {
                           if (((ULONG)*ResArray)&0x80000000 || !*ResArray)
                              {
                                 ResArray=(struct Resident **)(((ULONG)*ResArray)&0x7fffffff);
                              }
                           else
                              {
                                 if (*ResArray==(struct Resident *)MyResident)
                                    {
                                       *ResArray=(struct Resident *)(((ULONG)(ResArray+1))|0x80000000);
                                       ResArray=NULL;
                                    }
                                 else
                                    {
                                       ResArray++;
                                    }
                              }
                        }
                  }
            }
         Enable();
      }
}
