/*
 * BPPCFix
 *
 * Disables the ppc.library resident module in Amigas with BPPC.
 * Written in 1998 by Frank Wille <frank@phoenix.owl.de>.
 *
 * V1.1  19-Jan-99
 *       Option 'reboot' reboots the system if the KickTag was not
 *       already installed.
 * V1.0  26-Dec-98
 *       created
 */

#include <exec/types.h>
#include <exec/execbase.h>
#include <proto/exec.h>
#include <proto/dos.h>

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "kicktags.h"

#define KICKTAG_VERSION 1
#define KICKTAG_REVISION 1
#define KICKTAG_PRI 0

static const char ResidentID[] = "$VER: BPPCFix 1.1 (19.01.99) "
                                 "Written by Frank Wille "
                                 "<frank@phoenix.owl.de>\r\n";
static const char ResidentName[] = "BPPCFix";

struct MyKickTag {
  struct KickTagHeader KTH;
  char ResidentID[sizeof(ResidentID)-6];
  char ResidentName[sizeof(ResidentName)];
  UWORD KickCode[1];  /* vbcc doesn't allow [0] */
};


extern struct ExecBase *SysBase;
extern void BPPCFixCode();
extern void BPPCFixCode_end();




static int strncasecmp(char *str1,char *str2,int n)
{
  if (!n) return 0;
  while(--n && tolower((unsigned char)*str1)==tolower((unsigned char)*str2)){
    if(!*str1) return 0;
    str1++;str2++;
  }
  return(tolower(*(unsigned char *)str1)-tolower(*(unsigned char *)str2));
}


static void ReBoot()
{
  Delay(100L);
  ColdReboot();
}


main(int argc,char *argv[])
{
  struct MyKickTag *kt;
  ULONG KickCodeSize = BPPCFixCode_end-BPPCFixCode;
  ULONG ktSize = KickCodeSize + sizeof(struct MyKickTag) - sizeof(UWORD);
  BOOL reboot = FALSE;

  if (SysBase->LibNode.lib_Version < 36)
    exit(20);
  if (argc<2 || argc>3) {
    Printf("BPPCFix V%ld.%ld - written by Frank Wille\nUsage:\n"
           "  %s <install | remove> [<reboot>]\n",
           KICKTAG_VERSION,KICKTAG_REVISION,argv[0]);
    exit(1);
  }
  if (argc==3)
    if (!strncasecmp(argv[2],"reb",3))
      reboot = TRUE;

  if (!strncasecmp(argv[1],"inst",4)) {
    /* install BPPCFix KickTag */
    Forbid();

    if (FindKickTag(SysBase,ResidentName,ktSize) == NULL) {
      if (kt = AllocKickMem(SysBase,ktSize,1,0)) {
        kt->KTH.Resident.rt_Flags = RTF_COLDSTART;
        kt->KTH.Resident.rt_Version = KICKTAG_VERSION;
        kt->KTH.Resident.rt_Type = NT_UNKNOWN;
        kt->KTH.Resident.rt_Pri = KICKTAG_PRI;
        kt->KTH.Resident.rt_Name = kt->ResidentName;
        kt->KTH.Resident.rt_IdString = kt->ResidentID;
        kt->KTH.Resident.rt_Init = kt->KickCode;

        CopyMem((void *)BPPCFixCode,kt->KickCode,KickCodeSize);
        CopyMem(&ResidentID[6],kt->ResidentID,sizeof(ResidentID)-6);
        CopyMem(ResidentName,kt->ResidentName,sizeof(ResidentName));
        clearCache(SysBase);
        AddKickTag(SysBase,(struct KickTagHeader *)kt,ktSize,0);
        if (reboot)
          ReBoot();
        Printf("%s KickTag installed at 0x%08lx.\n",
               ResidentName,(ULONG)kt);
      }
      else
        Printf("Insufficient free store for KickTag.\n");
    }
    else
      Printf("KickTag \"%s\" already installed in system.\n",ResidentName);

    Permit();
  }

  else {
    /* remove KickTag */
    if (kt = (struct MyKickTag *)RemKickTag(SysBase,ResidentName,ktSize)) {
      if (reboot)
        ReBoot();
      Printf("%s KickTag removed.\n",ResidentName);
      FreeMem(kt,ktSize);
    }
    else
      Printf("No %s KickTag installed in system.\n",ResidentName);
  }

  exit(0);
}
