/***************************************************************************
 *
 *                       PPCDebug
 *
 *  PPCDebug is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *
 *  This started as a small example to show how to
 *  use the ppc.library`s trap function and grew into
 *  a small, not very polished but useful, PPC debugger.
 *
 *  I`m sure you would like to see more features and because
 *  the source is public it should be easy to add the needed
 *  functions personally.
 *  But to coordinate this I suggest to contact me if these
 *  features should be available to everybody.
 *
 *  Ralph Schmidt
 *
 *
 *
 ***************************************************************************/

#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/libraries.h>
#include <exec/memory.h>
#include <exec/alerts.h>
#include <exec/interrupts.h>
#include <clib/alib_stdio_protos.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/dostags.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <PowerUP/PPCLib/Interface.h>
#include <PowerUP/PPCLib/tasks.h>
#include <PowerUP/PPCLib/ppc.h>
#include <PowerUP/PPCLib/object.h>
#include <PowerUP/PPCDisslib/PPCDiss.h>
#include <PowerUP/pragmas/ppc_pragmas.h>
#include <PowerUP/clib/ppc_protos.h>
#include <PowerUP/pragmas/ppcdiss_pragmas.h>
#include <PowerUP/clib/ppcdiss_protos.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include "PPCDebug_VERSION.h"
#include "/ArgParser/ArgParser.h"
#include "/ArgParser/ArgParser_protos.h"

void __builtin_emit(int);

struct	BreakPoint
{
	struct Node	Node;
	ULONG		*Address;
	ULONG		Opcode;
};

#define	EMPTYTRACEPOINT	((ULONG*)0xffffffff)

#define	LINEMAX		256


/* Quick Signal hack because i'm too lazy
 * to use AllocSignal()
 */

#define	SIGNAL_EXCEPTION	31


#define	MSRF_FP		0x2000


#define	OPCODE_LR	0x1
#define	OPCODE_TD31_0_0	0x7fe00008

#define	MASK_21_30(x)	(x &((1<<(31-21))|(1<<(31-22))|(1<<(31-23))|(1<<(31-24))|(1<<(31-25))|(1<<(31-26))|(1<<(31-27))|(1<<(31-28))|(1<<(31-29))|(1<<(31-30))))
#define	OP_ID(a,b,c,d,e,f,g,h,i,j)  ((1<<10)*a | \
                                      (1<<9)*b | \
                                      (1<<8)*c | \
                                      (1<<7)*d | \
                                      (1<<6)*e | \
                                      (1<<5)*f | \
                                      (1<<4)*g | \
                                      (1<<3)*h | \
                                      (1<<2)*i | \
                                      (1<<1)*j)


extern struct ExecBase	*SysBase;
extern struct Library	*DosBase;
struct Library		*PPCLibBase;
struct Library		*PPCDissBase;
BPTR			stdout;
struct Hook		MyHook;
struct Hook		MyAddressHook;
struct Hook		MySymbolHook;
struct Hook		MyRelocHook;
struct Hook		MyScanSymbolHook;
struct Hook		MyArgParserSymbolHook;
struct Hook		MyGetDataHook;
struct Process		*MsgProcess;
struct ExceptionMsg	ExceptionMsg;
void			*ExceptionTask;
BPTR			InputFile;
BPTR			OutputFile;
ULONG			CPU;
ULONG			PC;
ULONG			NewPC;
ULONG			MEM;
struct PPCObjectInfo	MyInfo;
void			*MyObject;
BOOL			MyInfoStatus;
extern ULONG		__base;
struct List		BreakPointList;
struct BreakPoint	MyTracePoint;
BOOL			GoSimulateFlag;


UBYTE	vers[] = VERSTAG;

char	*ExceptionStringTable[]=
{
	"Unknown",
	"Reset",
	"Machine Check",
	"Data Access",
	"Instruction Access",
	"External Interrupt",
	"Alignment",
	"Program",
	"FPU Unavailable",
	"Decrementer",
	"Interface Error",
	"Reserved B",
	"System Call",
	"Trace",
	"FPU Assist",
	"Reserved F",
	"Instruction Translation Miss",
	"Data Load Translation Miss",
	"Data Store Translation Miss",
	"Instruction Address Point",
	"System Management Interrupt"
};

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

BOOL	GetValue(char	*Ptr,
                 ULONG	*Result)
{
struct TagItem	MyTags[5];
ULONG		Error;
ULONG		Type;
void		*MyParseHandle;

  Type			=	PARSETYPE_INTEGER;

  MyTags[0].ti_Tag	=	PARSETAG_ERROR;
  MyTags[0].ti_Data	=	(ULONG) &Error;
  MyTags[1].ti_Tag	=	PARSETAG_VALUE;
  MyTags[1].ti_Data	=	(ULONG) Result;
  MyTags[2].ti_Tag	=	PARSETAG_TYPE;
  MyTags[2].ti_Data	=	(ULONG) &Type;
  MyTags[3].ti_Tag	=	PARSETAG_SYMBOLHOOK;
  MyTags[3].ti_Data	=	(ULONG) &MyArgParserSymbolHook;
  MyTags[4].ti_Tag	=	TAG_END;

  if (MyParseHandle=CreateParseHandle(MyTags))
  {
    MyTags[0].ti_Tag	=	TAG_END;
    if (ParseArgument(MyParseHandle,
                      Ptr,
                      MyTags))
    {
      return(TRUE);
    }
    else
    {
      printf("Error 0x%08lx\n",Error);
    }
  }
  else
  {
    printf("Not enough memory\n");
  }
  return(FALSE);
}


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

BOOL	ShowDiss(ULONG	Address,
                 ULONG	Lines,
                 BOOL	ShowData)
{
void		*PPCDissHandle;
int		i;
char		LineBuffer[128];
struct TagItem	MyTags[1];

//  __builtin_emit(0x4afc);

  MyTags[0].ti_Tag	=	TAG_END;

//  Printf("PC: 0x%08lx::\n",Address);

  if (PPCDissHandle = CreateDisAssHandleTags(DISASS_DEFINEPC,Address,
                                             DISASS_SHOWDATA,ShowData,
                                             DISASS_USEDC68KDESC, TRUE,
                                             DISASS_ADDRESSHOOK,&MyAddressHook,
                                             DISASS_SYMBOLHOOK,&MySymbolHook,
                                             DISASS_RELOCHOOK,&MyRelocHook,
                                             DISASS_GETDATAHOOK,&MyGetDataHook,
                                             TAG_DONE))
  {
    for(i=0;i<Lines;i++)
    {
      if (MyInfoStatus==FALSE ||
          (MyInfo.Address==0 && MyInfo.Size==0) ||
          (MyInfo.Type==PPCELFINFOTYPE_SECTION) ||
          (Address < MyInfo.Address || Address >= (MyInfo.Address+MyInfo.Size)))
      {
//    __builtin_emit(0x4afc);
        MyInfo.Name		=	NULL;
        MyInfo.Address		=	Address;
        MyInfo.Size		=	0;
        MyInfoStatus=PPCGetObjectAttrs(MyObject,
                                       &MyInfo,
                                       MyTags);

//        Printf("Find New Symbol Status=%ld\n",MyInfoStatus);
      }


      DisAssTags(PPCDissHandle,
                 DISASS_BUFFER,LineBuffer,
                 TAG_DONE);
      if (MyInfoStatus)
      {
        Printf("%s+0x%lx: %s\n",
               MyInfo.Name,
               Address - MyInfo.Address,
               LineBuffer);
      }
      else
      {
        if (Address < 0xfff00000 || Address >= 0xfff10000)
        {
          Printf("0x%lx: %s\n",
                 Address,
                 LineBuffer);
        }
        else
        { 
          MyInfo.Name		=	"Kernel";
          MyInfo.Address	=	0xfff00000;
          MyInfo.Size		=	0x10000;
          /* Setting MyInfoStatus to false
           * has the effect that it searches again for symbols
           * otherwise it would find dynamic link symbols after
           * it showed a kernel symbol
           */
          MyInfoStatus		=	FALSE;
          Printf("%s+0x%lx: %s\n",
                 MyInfo.Name,
                 Address - MyInfo.Address,
                 LineBuffer);
        }
      }
      Address	+=	4;
    }
    DeleteDisAssHandle(PPCDissHandle);
    NewPC	=	Address;
    return(TRUE);
  }
  else
  {
    return(FALSE);
  }
}

BOOL	ShowMem(ULONG	Address,
                ULONG	Lines)
{
int	i;
  for (i=0;i<Lines;i++)
  {
    Printf("%08lx: %08lx %08lx %08lx %08lx\n",
           Address,
           PPCReadLong((ULONG*) (Address+0x00)),
           PPCReadLong((ULONG*) (Address+0x04)),
           PPCReadLong((ULONG*) (Address+0x08)),
           PPCReadLong((ULONG*) (Address+0x0c)));
    Address	+=	16;
  }
  return(TRUE);
}


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

void	ShowRegsGPR(void)
{
int	i;
  for (i=0;i<32;i+=8)
  {
    Printf("GPR %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
           ExceptionMsg.GPR[i+0],
           ExceptionMsg.GPR[i+1],
           ExceptionMsg.GPR[i+2],
           ExceptionMsg.GPR[i+3],
           ExceptionMsg.GPR[i+4],
           ExceptionMsg.GPR[i+5],
           ExceptionMsg.GPR[i+6],
           ExceptionMsg.GPR[i+7]);
  }
}

void	ShowRegsFPR(void)
{
int	i;
  if (ExceptionMsg.SRR1 & MSRF_FP)
  {
    Printf("FPSCR %08lx\n",
            ExceptionMsg.FPSCR);

    for (i=0;i<32;i+=8)
    {
      printf("FPR %g %g %g %g %g %g %g %g\n",
             ExceptionMsg.FPR[i+0],
             ExceptionMsg.FPR[i+1],
             ExceptionMsg.FPR[i+2],
             ExceptionMsg.FPR[i+3],
             ExceptionMsg.FPR[i+4],
             ExceptionMsg.FPR[i+5],
             ExceptionMsg.FPR[i+6],
             ExceptionMsg.FPR[i+7]);
    }
  }
}

void	ShowRegsFPRHex(void)
{
int	i;
  if (ExceptionMsg.SRR1 & MSRF_FP)
  {
    Printf("FPSCR %08lx\n",
            ExceptionMsg.FPSCR);

    for (i=0;i<32;i+=8)
    {
      printf("FPR 0x%08lx%08lx 0x%08lx%08lx 0x%08lx%08lx 0x%08lx%08lx\n",
             ((ULONG*) &ExceptionMsg.FPR[i+0])[0],((ULONG*) &ExceptionMsg.FPR[i+0])[1],
             ((ULONG*) &ExceptionMsg.FPR[i+1])[0],((ULONG*) &ExceptionMsg.FPR[i+1])[1],
             ((ULONG*) &ExceptionMsg.FPR[i+2])[0],((ULONG*) &ExceptionMsg.FPR[i+2])[1],
             ((ULONG*) &ExceptionMsg.FPR[i+3])[0],((ULONG*) &ExceptionMsg.FPR[i+3])[1]);
    }
  }
}

void	ShowRegsMMU(void)
{
  Printf("SDR1 %08lx\n",
         ExceptionMsg.SDR1);


  if (FALSE)
  {
    /* 64bit CPU */
    Printf("ASR %08lx\n",
           ExceptionMsg.ASR);
  }

  if ((CPU==CPU_603) ||
      (CPU==CPU_603e) ||
      (CPU==CPU_603p))
  {
    Printf("DMISS %08lx DCMP %08lx IMISS %08lx ICMP %08lx\n",
           ExceptionMsg.DMISS,
           ExceptionMsg.DCMP,
           ExceptionMsg.IMISS,
           ExceptionMsg.ICMP);

    Printf("HASH1 %08lx HASH2 %08lx RPA %08lx\n",
           ExceptionMsg.HASH1,
           ExceptionMsg.HASH2,
           ExceptionMsg.RPA);
  }

  Printf("IBAT0U %08lx IBAT0L %08lx IBAT1U %08lx IBAT1L %08lx\n",
         ExceptionMsg.IBAT0U,
         ExceptionMsg.IBAT0L,
         ExceptionMsg.IBAT1U,
         ExceptionMsg.IBAT1L);

  Printf("IBAT2U %08lx IBAT2L %08lx IBAT3U %08lx IBAT3L %08lx\n",
         ExceptionMsg.IBAT2U,
         ExceptionMsg.IBAT2L,
         ExceptionMsg.IBAT3U,
         ExceptionMsg.IBAT3L);

  Printf("DBAT0U %08lx DBAT0L %08lx DBAT1U %08lx DBAT1L %08lx\n",
         ExceptionMsg.DBAT0U,
         ExceptionMsg.DBAT0L,
         ExceptionMsg.DBAT1U,
         ExceptionMsg.DBAT1L);

  Printf("DBAT2U %08lx DBAT2L %08lx DBAT3U %08lx DBAT3L %08lx\n",
         ExceptionMsg.DBAT2U,
         ExceptionMsg.DBAT2L,
         ExceptionMsg.DBAT3U,
         ExceptionMsg.DBAT3L);

  Printf("SR %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
         ExceptionMsg.SR[0],
         ExceptionMsg.SR[1],
         ExceptionMsg.SR[2],
         ExceptionMsg.SR[3],
         ExceptionMsg.SR[4],
         ExceptionMsg.SR[5],
         ExceptionMsg.SR[6],
         ExceptionMsg.SR[7]);

  Printf("SR %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
         ExceptionMsg.SR[8],
         ExceptionMsg.SR[9],
         ExceptionMsg.SR[10],
         ExceptionMsg.SR[11],
         ExceptionMsg.SR[12],
         ExceptionMsg.SR[13],
         ExceptionMsg.SR[14],
         ExceptionMsg.SR[15]);

}

void	ShowRegsMisc(void)
{
  Printf("PVR %08lx\n",
         ExceptionMsg.PVR);

  Printf("SPRG0 %08lx SPRG1 %08lx SPRG2 %08lx SPRG3 %08lx\n",
         ExceptionMsg.SPRG0,
         ExceptionMsg.SPRG1,
         ExceptionMsg.SPRG2,
         ExceptionMsg.SPRG3);

  Printf("TBL %08lx TBU %08lx DEC %08lx DABA %08lx\n",
         ExceptionMsg.TBL,
         ExceptionMsg.TBU,
         ExceptionMsg.DEC,
         ExceptionMsg.DABR);
}

void	ShowRegsFrame(void)
{
  Printf("PC %08lx MSR %08lx DAR %08lx DSISR %08lx\n",
         ExceptionMsg.SRR0,
         ExceptionMsg.SRR1,
         ExceptionMsg.DAR,
         ExceptionMsg.DSISR);

  Printf("CR %08lx XER %08lx LR %08lx CTR %08lx\n",
         ExceptionMsg.CR,
         ExceptionMsg.XER,
         ExceptionMsg.LR,
         ExceptionMsg.CTR);
}

void	ShowRegs(void)
{
  ShowRegsFrame();
  ShowRegsGPR();
  ShowRegsFPRHex();
  ShowRegsFPR();
  ShowDiss(ExceptionMsg.SRR0,
           1,
           FALSE);
}


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

BOOL	AddBreakPoint(ULONG	*Address)
{
struct BreakPoint	*MyBreakPoint;

  MyBreakPoint	=(struct BreakPoint*) BreakPointList.lh_Head;
  while (MyBreakPoint->Node.ln_Succ)
  {
    if (MyBreakPoint->Address == Address)
    {
      return(TRUE);
    }
    MyBreakPoint	=(struct BreakPoint*) MyBreakPoint->Node.ln_Succ;
  }

  if (MyBreakPoint=(struct BreakPoint*) AllocVec(sizeof(struct BreakPoint),MEMF_PUBLIC))
  {
//  __builtin_emit(0x4afc);
    AddTail(&BreakPointList,
            &MyBreakPoint->Node);

    MyBreakPoint->Address	=	Address;
    MyBreakPoint->Opcode	=	PPCReadLong(MyBreakPoint->Address);

    PPCWriteLongFlush((ULONG*) MyBreakPoint->Address,
                      OPCODE_TD31_0_0);
    return(TRUE);
  }
  else
  {
    return(FALSE);
  }
}

BOOL	RemoveBreakPoint(ULONG	*Address)
{
struct BreakPoint	*MyBreakPoint;

  MyBreakPoint	=(struct BreakPoint*) BreakPointList.lh_Head;
  while (MyBreakPoint->Node.ln_Succ)
  {
    if (MyBreakPoint->Address == Address)
    {
      Remove(&MyBreakPoint->Node);

      PPCWriteLongFlush(MyBreakPoint->Address,
                        MyBreakPoint->Opcode);

      FreeVec(MyBreakPoint);
      return(TRUE);
    }
    MyBreakPoint	=(struct BreakPoint*) MyBreakPoint->Node.ln_Succ;
  }
  return(FALSE);
}

void	RemoveBreakPointAll(void)
{
struct BreakPoint	*MyBreakPoint;
struct BreakPoint	*MyBreakPointSave;

  MyBreakPoint	=(struct BreakPoint*) BreakPointList.lh_Head;
  while (MyBreakPoint->Node.ln_Succ)
  {
    Remove(&MyBreakPoint->Node);
    MyBreakPointSave	=(struct BreakPoint*) MyBreakPoint->Node.ln_Succ;
    FreeVec(MyBreakPoint);
    MyBreakPoint	=	MyBreakPointSave;
  }
}

void	ShowBreakPointAll(void)
{
struct BreakPoint	*MyBreakPoint;

  MyBreakPoint	=(struct BreakPoint*) BreakPointList.lh_Head;
  while (MyBreakPoint->Node.ln_Succ)
  {
    printf("Breakpoint at 0x%08lx with saved Opcode 0x%08lx\n",
           MyBreakPoint->Address,
           MyBreakPoint->Opcode);

    MyBreakPoint	=(struct BreakPoint*) MyBreakPoint->Node.ln_Succ;
  }
}


struct BreakPoint	*CheckBreakPoint(ULONG	*Address)
{
struct BreakPoint	*MyBreakPoint;

  MyBreakPoint	=(struct BreakPoint*) BreakPointList.lh_Head;
  while (MyBreakPoint->Node.ln_Succ)
  {
    if (MyBreakPoint->Address == Address)
    {
      return(MyBreakPoint);
    }
    MyBreakPoint	=(struct BreakPoint*) MyBreakPoint->Node.ln_Succ;
  }
  return(NULL);
}



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


BOOL __asm ExceptionHookFunc(register __a0 struct Hook		*MyHook,
                             register __a2 void			*MyTask,
                             register __a1 struct ExceptionMsg	*MyMsg)
{
  ExceptionTask	=	MyTask;

  CopyMem(MyMsg,
          &ExceptionMsg,
          sizeof(struct ExceptionMsg));

  if (MsgProcess)
  {
    Signal(&MsgProcess->pr_Task,
           1<<SIGNAL_EXCEPTION);
    return(TRUE);
  }
  else
  {
    return(FALSE);
  }
}

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


ULONG	__asm AddressHookFunc(register __a0 struct Hook		*MyHook,
                              register __a2 char		*MyBuffer,
                              register __a1 ULONG		PC)
{
  return(0);
}


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

ULONG	__asm SymbolHookFunc(register __a0 struct Hook		*MyHook,
                             register __a2 char			*MyBuffer,
                             register __a1 ULONG		PC)
{
struct PPCObjectInfo	MyInfo;
struct TagItem		MyTags[1];

  MyInfo.Address	=	PC;
  MyInfo.Name		=	NULL;
  MyTags[0].ti_Tag	=	TAG_END;

  if (PPCGetObjectAttrs(MyObject,
                        &MyInfo,
                        MyTags))
  {
//  __builtin_emit(0x4afc);
    if (PC == MyInfo.Address)
    {
      return((ULONG) sprintf(MyBuffer,"%s",
                             MyInfo.Name));
    }
    else
    {
      return((ULONG) sprintf(MyBuffer,"%s+0x%lx",
                             MyInfo.Name,
                             PC - MyInfo.Address));
    }
  }
  else
  {
    return(0);
  }
}

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

ULONG	__asm RelocHookFunc(register __a0 struct Hook		*MyHook,
                            register __a2 char			*MyBuffer,
                            register __a1 ULONG			PC)
{
struct PPCObjectInfo	MyInfo;
struct TagItem		MyTags[2];
char			*AddressMode;

  MyInfo.Address	=	PC;
  MyInfo.Name		=	NULL;
  MyTags[0].ti_Tag	=	PPCELFINFOTAG_RELOC;
  MyTags[0].ti_Data	=	TRUE;
  MyTags[1].ti_Tag	=	TAG_END;

//  __builtin_emit(0x4afc);
  if (PPCGetObjectAttrs(MyObject,
                        &MyInfo,
                        MyTags))
  {
    switch (MyInfo.SubType)
    {
      case	R_PPC_ADDR16_L:
                AddressMode	=	"@l";
                break;

      case	R_PPC_ADDR16_HI:
                AddressMode	=	"@hi";
                break;

      case	R_PPC_ADDR16_HA:
                AddressMode	=	"@ha";
                break;

      default:
                AddressMode	=	"";
                break;

    } 
    return((ULONG) sprintf(MyBuffer,"%s%s",
                           MyInfo.Name,
                           AddressMode));
  }
  return(0);
}

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

void	__asm ScanHookFunc(register __a0 struct Hook		*MyHook,
                           register __a2 void			*MyElfStruct,
                           register __a1 struct PPCObjectInfo	*MyInfo)
                            
{
  Printf("0x%08lx\t0x%08lx\t%s\n",
         MyInfo->Address,
         MyInfo->Size,
         MyInfo->Name);

}

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

BOOL	__asm ArgParserSymbolHookFunc(register __a0 struct Hook			*MyHook,
                                      register __a2 char			*MyBuffer,
                                      register __a1 struct SymbolHookMsg	*MyMsg)
{
char			LineBuffer[128];
char			a;
int			Length;
struct TagItem		MyTags[1];
struct PPCObjectInfo	MyInfo;

  Length=0;
  while (((a=MyBuffer[Length]) >= 'a' && MyBuffer[Length] <= 'z') ||
         (MyBuffer[Length] >= 'A' && MyBuffer[Length] <= 'Z') ||
         (MyBuffer[Length] >= '0' && MyBuffer[Length] <= '9') ||
         (MyBuffer[Length] >= '_'))
  {
    LineBuffer[Length]	=	a;
    Length++;
    if (Length > 126)
    {
      MyMsg->Error	=	ERROR_SYMBOLTOOLONG;
      return(FALSE);
    }
  }
  LineBuffer[Length]	=	'\0';
  MyMsg->Length		=	Length;

  MyInfo.Name		=	LineBuffer;
  MyInfo.Address	=	NULL;

  if (PPCGetObjectAttrs(MyObject,
                        &MyInfo,
                        MyTags))
  {
//    __builtin_emit(0x4afc);
    MyMsg->Type		=	PARSETYPE_INTEGER;
    *MyMsg->Integer	=	MyInfo.Address;
    return(TRUE);
  }
  else
  {
    MyMsg->Error	=	ERROR_UNKNOWNSYMBOL;
    return(FALSE);
  }

}

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

ULONG	__asm GetDataHookFunc(register __a0 struct Hook			*MyHook,
                              register __a2 ULONG			*Address,
                              register __a1 void			*Nobodycares)
{
struct BreakPoint	*MyBreakPoint;

  if (MyBreakPoint=CheckBreakPoint(Address))
  {
    return(MyBreakPoint->Opcode);
  }
  else
  {
    return(*Address);
  }
}


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

void	HandleInput(void)
{
char		MyBuffer[LINEMAX];
struct TagItem	MyTags[10];
ULONG		Length;
ULONG		Lines;
ULONG		Register;
char		*Ptr;
ULONG		Command;
ULONG		CommandWord;
ULONG		*TracePointAddress;

/*
 * Each Exception set the default PC
 */
  PC		=	ExceptionMsg.SRR0;
  MEM		=	ExceptionMsg.DAR;

  for (;;)
  {
    Printf(">");
    Flush(OutputFile);
    if (Length=Read(InputFile,&MyBuffer[0],LINEMAX))
    {
      MyBuffer[Length-1]	=	0;

      switch (tolower(MyBuffer[0]))
      {
        case	'g':
                if (tolower(MyBuffer[1]) == 's')
                {
                  MyTracePoint.Address	=	EMPTYTRACEPOINT;
                  MyTags[0].ti_Tag	=	PPCTASKSTARTTAG_TRACE;
                  MyTags[0].ti_Data	=	TRUE;
                  MyTags[1].ti_Tag	=	TAG_END;
                  PPCStartTask(ExceptionTask,&MyTags[0]);
                  GoSimulateFlag	=	TRUE;
                  return;
                }
                else
                {
                  MyTracePoint.Address	=	EMPTYTRACEPOINT;
                  MyTags[0].ti_Tag	=	PPCTASKSTARTTAG_RUN;
                  MyTags[0].ti_Data	=	TRUE;
                  MyTags[1].ti_Tag	=	TAG_END;
                  PPCStartTask(ExceptionTask,&MyTags[0]);
                  return;
                }
                break;

        case	's':
                MyTracePoint.Address	=	EMPTYTRACEPOINT;
                MyTags[0].ti_Tag	=	PPCTASKSTARTTAG_TRACE;
                MyTags[0].ti_Data	=	TRUE;
                MyTags[1].ti_Tag	=	TAG_END;
                PPCStartTask(ExceptionTask,&MyTags[0]);
                return;
                break;

        case	't':
//  __builtin_emit(0x4afc);
                CommandWord		=	*((ULONG*) ExceptionMsg.SRR0);
                Command			=	CommandWord >> (31-5);
                if ((Command == 0x10 && !(CommandWord & OPCODE_LR))								|| // bcx BO,BI,addr
                    (Command == 0x12 && !(CommandWord & OPCODE_LR))								|| // bx addr
                    (Command == 0x13 && MASK_21_30(CommandWord)== OP_ID(1,0,0,0,0,1,0,0,0,0) && !(CommandWord & OPCODE_LR))	|| // bcctr
                    (Command == 0x13 && MASK_21_30(CommandWord)== OP_ID(0,0,0,0,0,1,0,0,0,0) && !(CommandWord & OPCODE_LR))	|| // bclrx
                    (Command == 0x13 && MASK_21_30(CommandWord)== OP_ID(0,0,0,0,1,1,0,0,1,0)))	   				   // rfi
                {
                  /* Use Single Step for commands which change the PC */
                  MyTracePoint.Address	=	EMPTYTRACEPOINT;
                  MyTags[0].ti_Tag	=	PPCTASKSTARTTAG_TRACE;
                  MyTags[0].ti_Data	=	TRUE;
                  MyTags[1].ti_Tag	=	TAG_END;
                  PPCStartTask(ExceptionTask,&MyTags[0]);
                }
                else
                {

                  TracePointAddress		=	(ULONG*) (ExceptionMsg.SRR0+4);

                  /*
                   * Check if the TracePointAddress is already
                   * marked in the usual breakpoint list.
                   * to avoid ugly Breakpoint overloading.
                   */
                  if (CheckBreakPoint(TracePointAddress) == NULL)
                  {
                    MyTracePoint.Address	=	TracePointAddress;
                    MyTracePoint.Opcode		=	PPCReadLong(MyTracePoint.Address);

                    PPCWriteLongFlush((ULONG*) MyTracePoint.Address,
                                      OPCODE_TD31_0_0);

                    MyTags[0].ti_Tag		=	PPCTASKSTARTTAG_RUN;
                    MyTags[0].ti_Data		=	TRUE;
                    MyTags[1].ti_Tag		=	TAG_END;
                    PPCStartTask(ExceptionTask,&MyTags[0]);
                  }
                }
                return;
                break;

/*
 * I would have to change the Task/console to handle async events.
 * No time for this release
        case	'z':
                MyTags[0].ti_Tag	=	TAG_END;
                PPCStopTask(ExceptionTask,&MyTags[0]);
                return;
                break;
 */

        case	'd':
//  __builtin_emit(0x4afc);
                if (MyBuffer[1] != 'r')
                {
                  Ptr		=	&MyBuffer[1];
                  Lines		=	8;

                  if (Ptr=strtok(Ptr," "))
                  {
                    if (GetValue(Ptr,&PC))
                    {
                      if (Ptr=strtok(NULL," "))
                      {
                        GetValue(Ptr,&Lines);
                      }
                    }
                  }
                }
                else
                {
                  PC	=	ExceptionMsg.LR;
                  Lines	=	8;

                  if (Ptr=strtok(&MyBuffer[2]," "))
                  {
                    GetValue(Ptr,&Lines);
                  }
                }

                if (ShowDiss(PC,
                             Lines,
                             TRUE))
                {
                  PC		=	NewPC;
                }
                break;


        case	'm':
                Ptr		=	&MyBuffer[1];
                Lines		=	8;

                if (Ptr=strtok(Ptr," "))
                {
                  if (GetValue(Ptr,&MEM))
                  {
                    if (Ptr=strtok(NULL," "))
                    {
                      GetValue(Ptr,&Lines);
                    }
                  }
                }
                ShowMem(MEM,Lines);
                break;

        case	'f':
                {
                  struct PPCObjectInfo	MyInfo;

                  MyTags[0].ti_Tag	=	PPCELFINFOTAG_SCANSYMBOLHOOK;
                  MyTags[0].ti_Data	=	(ULONG) &MyScanSymbolHook;
                  MyTags[1].ti_Tag	=	TAG_END;
                  MyInfoStatus=PPCGetObjectAttrs(MyObject,
                                                 &MyInfo,
                                                 MyTags);
                }
                break;

        case	'r':
                Ptr		=	&MyBuffer[1];
//  __builtin_emit(0x4afc);

                if (Ptr=strtok(Ptr," ="))
                {
                  if (((tolower(MyBuffer[1]) == 'g') || (tolower(MyBuffer[1]) == 'f')) &&
                       MyBuffer[2] == '[')
                  {
                    if (Length=stcd_l(&MyBuffer[3],(long*) &Register))
                    {
                      if ((Register <= 31) &&
                          MyBuffer[3+Length] == ']')
                      {
                        Ptr		=	&MyBuffer[3+Length+1];
                        if (Ptr=strtok(NULL," "))
                        {
                          ULONG		Error;
                          ULONG		Value;
                          double	DValue;
                          ULONG		Type;
                          void		*MyParseHandle;

                          MyTags[0].ti_Tag	=	PARSETAG_ERROR;
                          MyTags[0].ti_Data	=	(ULONG) &Error;
                          MyTags[1].ti_Tag	=	PARSETAG_VALUE;

                          if (tolower(MyBuffer[1]) == 'g')
                          {
                            Type		=	PARSETYPE_INTEGER;
                            MyTags[1].ti_Data	=	(ULONG) &Value;
                          }
                          else
                          {
                            Type		=	PARSETYPE_DOUBLE;
                            MyTags[1].ti_Data	=	(ULONG) &DValue;
                          }

                          MyTags[2].ti_Tag	=	PARSETAG_TYPE;
                          MyTags[2].ti_Data	=	(ULONG) &Type;
                          MyTags[3].ti_Tag	=	PARSETAG_SYMBOLHOOK;
                          MyTags[3].ti_Data	=	(ULONG) &MyArgParserSymbolHook;
                          MyTags[4].ti_Tag	=	TAG_END;

                          if (MyParseHandle=CreateParseHandle(MyTags))
                          {
                            MyTags[0].ti_Tag	=	TAG_END;
                            if (ParseArgument(MyParseHandle,
                                              Ptr,
                                              MyTags))
                            {
                              if (tolower(MyBuffer[1] == 'g'))
                              {
                                printf("GPR[%ld] = 0x%08lx\n",
                                       Register,
                                       Value);

                                ExceptionMsg.GPR[Register]	=	Value;
                                MyTags[0].ti_Tag		=	PPCTASKINFOTAG_GPR;
                                MyTags[0].ti_Data		=	Register;
                                MyTags[1].ti_Tag		=	PPCTASKINFOTAG_VALUEPTR;
                                MyTags[1].ti_Data		=	(ULONG) &Value;
                                MyTags[2].ti_Tag		=	TAG_END;
                                PPCSetTaskAttrs(ExceptionTask,
                                                MyTags);
                              }
                              else
                              {
                                printf("FPR[%ld] = %g\n",
                                       Register,
                                       DValue);

                                ExceptionMsg.FPR[Register]	=	DValue;
                                MyTags[0].ti_Tag		=	PPCTASKINFOTAG_FPR;
                                MyTags[0].ti_Data		=	Register;
                                MyTags[1].ti_Tag		=	PPCTASKINFOTAG_VALUEPTR;
                                MyTags[1].ti_Data		=	(ULONG) &DValue;
                                MyTags[2].ti_Tag		=	TAG_END;
                                PPCSetTaskAttrs(ExceptionTask,
                                               MyTags);
                              }
                            }
                            else
                            {
                              printf("Error 0x%08lx\n",Error);
                            }
                            DeleteParseHandle(MyParseHandle);
                          }
                        }
                      }
                    }
                  }
                  else if (MyBuffer[1] == 'g')

                  {
                    ShowRegsGPR();
                  }
                  else if (MyBuffer[1] == 'f')

                  {
                    ShowRegsFPR();
                  }
                }
                else
                {
                  ShowRegs();
                }
                break;


        case	'+':
                ExceptionMsg.SRR0		+=	4;
                MyTags[0].ti_Tag		=	PPCTASKINFOTAG_PC;
                MyTags[0].ti_Data		=	(ULONG) &ExceptionMsg.SRR0;
                MyTags[1].ti_Tag		=	TAG_END;
                PPCSetTaskAttrs(ExceptionTask,
                               MyTags);
                break;

        case	'-':
                ExceptionMsg.SRR0		-=	4;
                MyTags[0].ti_Tag		=	PPCTASKINFOTAG_PC;
                MyTags[0].ti_Data		=	(ULONG) &ExceptionMsg.SRR0;
                MyTags[1].ti_Tag		=	TAG_END;
                PPCSetTaskAttrs(ExceptionTask,
                               MyTags);
                break;

        case	'?':
                Ptr		=	&MyBuffer[1];
                if (Ptr=strtok(Ptr," "))
                {
                  ULONG	Error;
                  ULONG	Value;
                  ULONG	Type;
                  void	*MyParseHandle;

                  Type			=	PARSETYPE_INTEGER;
                  MyTags[0].ti_Tag	=	PARSETAG_ERROR;
                  MyTags[0].ti_Data	=	(ULONG) &Error;
                  MyTags[1].ti_Tag	=	PARSETAG_VALUE;
                  MyTags[1].ti_Data	=	(ULONG) &Value;
                  MyTags[2].ti_Tag	=	PARSETAG_TYPE;
                  MyTags[2].ti_Data	=	(ULONG) &Type;
                  MyTags[3].ti_Tag	=	PARSETAG_SYMBOLHOOK;
                  MyTags[3].ti_Data	=	(ULONG) &MyArgParserSymbolHook;
                  MyTags[4].ti_Tag	=	TAG_END;

                  if (MyParseHandle=CreateParseHandle(MyTags))
                  {
                    MyTags[0].ti_Tag	=	TAG_END;
                    if (ParseArgument(MyParseHandle,
                                      Ptr,
                                      MyTags))
                    {
                      printf("= 0x%08lx\n",Value);
                    }
                    else
                    {
                      printf("Error 0x%08lx\n",Error);
                    }
                    DeleteParseHandle(MyParseHandle);
                  }
                }
                break;


        case	'b':
                if (MyBuffer[1]=='s')
                {
                  ShowBreakPointAll();
                  break;
                }

                if (MyBuffer[1]=='r')
                {
                  Ptr		=	&MyBuffer[2];
                }
                else
                {
                  Ptr		=	&MyBuffer[1];
                }
                if (Ptr=strtok(Ptr," "))
                {
                  ULONG	Error;
                  ULONG	Value;
                  ULONG	Type;
                  void	*MyParseHandle;

                  Type			=	PARSETYPE_INTEGER;
                  MyTags[0].ti_Tag	=	PARSETAG_ERROR;
                  MyTags[0].ti_Data	=	(ULONG) &Error;
                  MyTags[1].ti_Tag	=	PARSETAG_VALUE;
                  MyTags[1].ti_Data	=	(ULONG) &Value;
                  MyTags[2].ti_Tag	=	PARSETAG_TYPE;
                  MyTags[2].ti_Data	=	(ULONG) &Type;
                  MyTags[3].ti_Tag	=	PARSETAG_SYMBOLHOOK;
                  MyTags[3].ti_Data	=	(ULONG) &MyArgParserSymbolHook;
                  MyTags[4].ti_Tag	=	TAG_END;

                  if (MyParseHandle=CreateParseHandle(MyTags))
                  {
                    MyTags[0].ti_Tag	=	TAG_END;
                    if (ParseArgument(MyParseHandle,
                                      Ptr,
                                      MyTags))
                    {
                      if (MyBuffer[1]=='r')
                      {
                        if (RemoveBreakPoint((ULONG*) Value))
                        {
                          printf("No Breakpoint at 0x%08lx found\n",Value);
                        }
                        else
                        {
                          printf("Breakpoint at 0x%08lx removed\n",Value);
                        }
                      }
                      else
                      {
                        if (AddBreakPoint((ULONG*) Value))
                        {
                          printf("Breakpoint at 0x%08lx added\n",Value);
                        }
                      }
                    }
                    else
                    {
                      printf("Error 0x%08lx\n",Error);
                    }
                    DeleteParseHandle(MyParseHandle);
                  }
                }
                break;


        case	'h':
                Printf("(h)elp\n");
                Printf("(g)o\n");
                Printf("(gs) go with single step\n");
                Printf("(t)race\n");
                Printf("(s)ingle step\n");
                Printf("(z)top..sorry..can`t work because of the sync design\n");
                Printf("(d)isassemble [Address] [Lines]\n");
                Printf("(dr)isassemble-LR-Register [Lines]\n");
                Printf("(m)emory [Address] [Lines]\n");
                Printf("(r)egister dump\n");
                Printf("(rg) show GPR registers\n");
                Printf("(rf) show FPR registers\n");
                Printf("(rg[GPR Reg] Value) set GPR register\n");
                Printf("(rf[FPR Reg] Value) set FPR register\n");
                Printf("(b Value) add Breakpoint\n");
                Printf("(br Value) remove Breakpoint\n");
                Printf("(bs) show Breakpoint\n");
                Printf("(f) Symbol dump\n");
                Printf("(? Value)\n");
                Printf("(+) Next Instruction\n");
                Printf("(-) Previous Instruction\n");
                break;
      }
    }
  }
}

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

void MsgTask(void)
{
struct Process	*MyTask;
struct TagItem	MyTags[10];
ULONG		SignalMask;
BPTR		OldInputFile;
BPTR		OldOutputFile;


  MyTask				=(struct Process*) FindTask(NULL);
  OldInputFile				=	MyTask->pr_CIS;
  OldOutputFile				=	MyTask->pr_COS;
  MyTask->pr_CIS			=	InputFile;
  MyTask->pr_COS			=	OutputFile;
  MyInfo.Address			=	0;
  MyInfo.Size				=	0;
  MyInfoStatus				=	FALSE;
  GoSimulateFlag			=	FALSE;

  MyAddressHook.h_Entry			=	(ULONG (*)(void)) AddressHookFunc;
  MyAddressHook.h_SubEntry		=	(ULONG (*)(void)) NULL;
  MyAddressHook.h_Data			=	(APTR) PPCLibBase;

  MySymbolHook.h_Entry			=	(ULONG (*)(void)) SymbolHookFunc;
  MySymbolHook.h_SubEntry		=	(ULONG (*)(void)) NULL;
  MySymbolHook.h_Data			=	(APTR) PPCLibBase;

  MyRelocHook.h_Entry			=	(ULONG (*)(void)) RelocHookFunc;
  MyRelocHook.h_SubEntry		=	(ULONG (*)(void)) NULL;
  MyRelocHook.h_Data			=	(APTR) PPCLibBase;

  MyScanSymbolHook.h_Entry		=	(ULONG (*)(void)) ScanHookFunc;
  MyScanSymbolHook.h_SubEntry		=	(ULONG (*)(void)) NULL;
  MyScanSymbolHook.h_Data		=	(APTR) PPCLibBase;

  MyArgParserSymbolHook.h_Entry		=	(ULONG (*)(void)) ArgParserSymbolHookFunc;
  MyArgParserSymbolHook.h_SubEntry	=	(ULONG (*)(void)) NULL;
  MyArgParserSymbolHook.h_Data		=	(APTR) PPCLibBase;

  MyGetDataHook.h_Entry			=	(ULONG (*)(void)) GetDataHookFunc;
  MyGetDataHook.h_SubEntry		=	(ULONG (*)(void)) NULL;
  MyGetDataHook.h_Data			=	(APTR) PPCLibBase;


  NewList(&BreakPointList);

  MyTags[0].ti_Tag			=	PPCINFOTAG_CPU;
  MyTags[1].ti_Tag			=	TAG_END;
  CPU					=	PPCGetAttrs((struct TagItem*) &MyTags);

  /*
   * Disable Tracepoint
   */
  MyTracePoint.Address			=	EMPTYTRACEPOINT;

  while ((SignalMask=Wait(1<<SIGNAL_EXCEPTION | 1<<SIGBREAKB_CTRL_C)) == 1<<SIGNAL_EXCEPTION)
  {
    Printf("----------------------------------------------------------\n");
    if (!(ExceptionMsg.Type & EXCEPTION_MSG))
    {
      /* Hardware Exception */

      if (MyTracePoint.Address != EMPTYTRACEPOINT)
      {
        /*
         * Remove tracetrap..doesn`t matter if it hit
         */

        PPCWriteLongFlush(MyTracePoint.Address,
                          MyTracePoint.Opcode);

        MyTracePoint.Address	= EMPTYTRACEPOINT;
      }

      RemoveBreakPoint((ULONG*) ExceptionMsg.SRR0);

      Printf("Exception: Type 0x%lx %s\n",
             ExceptionMsg.Type,
             ExceptionMsg.Type > (sizeof(ExceptionStringTable)/4) ? "Illegal ID" : ExceptionStringTable[ExceptionMsg.Type]);
    }
    else
    {
      /* Kernel Notify Exception */
    }


    if (ExceptionMsg.Type != EXCEPTION_FINISHTASK)
    {
      if ((ExceptionMsg.Type == EXCEPTION_DATAACCESS) ||
          (ExceptionMsg.Type == EXCEPTION_INSTRUCTIONACCESS))
      {
        Printf("Illegal Memory Access at %08lx\n",
                ExceptionMsg.DAR);
      }

      if (ExceptionMsg.Type != EXCEPTION_TRACE)
      {
        /* Switch off Simulate Mode and stop for a non trace exception
         */
        GoSimulateFlag	=	FALSE;
      }


      ShowRegs();

      if (GoSimulateFlag)
      {
        MyTracePoint.Address	=	EMPTYTRACEPOINT;
        MyTags[0].ti_Tag	=	PPCTASKSTARTTAG_TRACE;
        MyTags[0].ti_Data	=	TRUE;
        MyTags[1].ti_Tag	=	TAG_END;
        PPCStartTask(ExceptionTask,&MyTags[0]);
      }
      else
      {
        HandleInput();
      }
    }
    else
    {
      RemoveBreakPointAll();
      Printf("Task has finished...\n");
    }
  }
  MyTask->pr_CIS	=	OldInputFile;
  MyTask->pr_COS	=	OldOutputFile;
  MsgProcess=NULL;
}


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


void	main(ULONG argc,char *argv[])
{
ULONG		Result;
struct TagItem	MyTags[10];

  stdout	=	Output();

  if(argc != 2L)
  {
    Printf("Usage: Name\n");
  }
  else
  if (PPCLibBase=OpenLibrary("ppc.library",0))
  {
    if (PPCDissBase=OpenLibrary("ppcdiss.library",0L))
    {
      if (MyObject=PPCLoadObject(argv[1]))
      {
        InputFile		=	Input();
        OutputFile		=	Output();

	#if	0
/************************************************************
 *
 *
 *                MEGA HACK extraordinaire
 *      Don`t copy or you`ll suffer in programmer hell.
 *      SAS uses a stackcheck in certain string lib functions
 *	which doesn`t work with hooks/several tasks.
 *             So i fool the stackcheck code.
 *     Will be removed when Steve compiles a new libm881nb.lib
 *     and release the final 6.58 patch
 *
 ************************************************************/
        __base			=	0;
        #endif



        MyTags[0].ti_Tag	=	NP_Entry;
        MyTags[0].ti_Data	=(ULONG) &MsgTask;
        MyTags[1].ti_Tag	=	NP_Name;
        MyTags[1].ti_Data	=(ULONG) "PPCDebug: MsgTask";
        MyTags[2].ti_Tag	=	TAG_END;

        if (MsgProcess=CreateNewProc(&MyTags[0]))
        {
          MyHook.h_Entry	=	(ULONG (*)(void)) ExceptionHookFunc;
          MyHook.h_SubEntry	=	(ULONG (*)(void)) NULL;
          MyHook.h_Data		=	(APTR) PPCLibBase;

          MyTags[0].ti_Tag	=	PPCTASKTAG_STOPTASK;
          MyTags[0].ti_Data	=	TRUE;
          MyTags[1].ti_Tag	=	PPCTASKTAG_WAITFINISH;
          MyTags[1].ti_Data	=	TRUE;
          MyTags[2].ti_Tag	=	PPCTASKTAG_EXCEPTIONHOOK;
          MyTags[2].ti_Data	=	(ULONG) &MyHook;
          MyTags[3].ti_Tag	=	TAG_END;

          Result=(ULONG) PPCCreateTask(MyObject,
                                       &MyTags[0]);



          printf("Result:0x%lx\n",Result);
          if (MsgProcess)
          {
            Signal(&MsgProcess->pr_Task,
                   1<<SIGBREAKB_CTRL_C);
            while (MsgProcess);
          }
        }
        else
        {
          Printf("Can't create debugger msg task\n");
        }
        PPCUnLoadObject(MyObject);
      }
      else
      {
        Printf("Can't load %s\n",argv[1]);
      }
      CloseLibrary(PPCDissBase);
    }
    else
    {
      Printf("Can't open ppcdiss.library\n");
    }
    CloseLibrary(PPCLibBase);
  }
}
