#include <exec/types.h>
#include <exec/libraries.h>
#include <utility/tagitem.h>
#include <utility/hooks.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <stdlib.h>
#include <PowerUP/pragmas/ppc_pragmas.h>
#include <PowerUP/clib/ppc_protos.h>
#include <PowerUP/PPCLib/tasks.h>
#include "PPCShowTasks_VERSION.h"
#include <stdio.h>

UBYTE vers[] = VERSTAG;

extern struct ExecBase	*SysBase;

void __builtin_emit(int);


char	*ArgumentString = "Verbose/S,Register=Regs/S";
LONG	*MyArgs[3];

#define	INDEX_VERBOSE	0
#define	INDEX_REGS	1

char	*StateString[]=
{
	"Invalid",
	"Added",
	"Run",
	"Ready",
	"Wait",
	"-------",
	"Removed"
};

ULONG	TaskCount;

void __asm HookFunc(register __a0 struct Hook	*MyHook,
                    register __a2 void		*MyTask,
                    register __a1 void		*MyMessage)
{
struct Library	*PPCLibBase;
struct TagItem	MyTags[3];
char		*Name;
int		Pri;
ULONG		State;
ULONG		StackSize;
ULONG		CacheFlush;
ULONG		SigAlloc;
ULONG		SigWait;
ULONG		SigRecvd;
BPTR		InputHandle;
BPTR		OutputHandle;
BPTR		ErrorHandle;
int		i;

  PPCLibBase		=	(struct Library*) MyHook->h_Data;

  MyTags[1].ti_Tag	=	TAG_END;
  MyTags[0].ti_Tag	=	PPCTASKINFOTAG_NAME;
  Name			=	(char*) PPCGetTaskAttrs(MyTask,(struct TagItem*) &MyTags);

  MyTags[0].ti_Tag	=	PPCTASKINFOTAG_PRIORITY;
  Pri			=	PPCGetTaskAttrs(MyTask,(struct TagItem*) &MyTags);

  MyTags[0].ti_Tag	=	PPCTASKINFOTAG_STATE;
  State			=	PPCGetTaskAttrs(MyTask,(struct TagItem*) &MyTags);

  MyTags[0].ti_Tag	=	PPCTASKINFOTAG_STACKSIZE;
  StackSize		=	PPCGetTaskAttrs(MyTask,(struct TagItem*) &MyTags);

  MyTags[0].ti_Tag	=	PPCTASKINFOTAG_CACHEFLUSH;
  CacheFlush		=	PPCGetTaskAttrs(MyTask,(struct TagItem*) &MyTags);

  MyTags[0].ti_Tag	=	PPCTASKINFOTAG_SIGALLOC;
  SigAlloc		=	PPCGetTaskAttrs(MyTask,(struct TagItem*) &MyTags);

  MyTags[0].ti_Tag	=	PPCTASKINFOTAG_SIGWAIT;
  SigWait		=	PPCGetTaskAttrs(MyTask,(struct TagItem*) &MyTags);

  MyTags[0].ti_Tag	=	PPCTASKINFOTAG_SIGRECVD;
  SigRecvd		=	PPCGetTaskAttrs(MyTask,(struct TagItem*) &MyTags);

  MyTags[0].ti_Tag	=	PPCTASKINFOTAG_INPUTHANDLE;
  InputHandle		=	PPCGetTaskAttrs(MyTask,(struct TagItem*) &MyTags);

  MyTags[0].ti_Tag	=	PPCTASKINFOTAG_OUTPUTHANDLE;
  OutputHandle		=	PPCGetTaskAttrs(MyTask,(struct TagItem*) &MyTags);

  MyTags[0].ti_Tag	=	PPCTASKINFOTAG_ERRORHANDLE;
  ErrorHandle		=	PPCGetTaskAttrs(MyTask,(struct TagItem*) &MyTags);

  TaskCount++;

  puts("\n");
  Printf("Task %ld: ID 0x%08lx %s Pri %ld State %s\n",
         TaskCount,
         MyTask,
         Name,
         Pri,
         StateString[State]);

  if (MyArgs[INDEX_VERBOSE])
  {
    Printf("Task Internals:\n");
    Printf("StackSize\t\t0x%08lx\n",StackSize);
    Printf("SigAlloc\t\t0x%08lx\n",SigAlloc);
    Printf("SigWait\t\t\t0x%08lx\n",SigWait);
    Printf("SigRecvd\t\t0x%08lx\n",SigRecvd);
    Printf("InputHandle\t\t0x%08lx\n",InputHandle);
    Printf("OutputHandle\t\t0x%08lx\n",OutputHandle);
    Printf("ErrorHandle\t\t0x%08lx\n",ErrorHandle);
    Printf("CacheFlush\t\t%s\n",CacheFlush ? "AUTO" : "CUSTOM");
  }

  if (MyArgs[INDEX_REGS])
  {
    ULONG	GPR[8];
    double	FPR[8];
    ULONG	PC;
    ULONG	MSR;
    ULONG	CR;
    ULONG	XER;
    ULONG	CTR;
    ULONG	LR;
    ULONG	FPSCR[2];

    puts("\n");


    MyTags[0].ti_Tag	=	PPCTASKINFOTAG_PC;
    MyTags[0].ti_Data	=	(ULONG) &PC;
    MyTags[1].ti_Tag	=	TAG_END;
    PPCGetTaskAttrs(MyTask,(struct TagItem*) &MyTags);

    MyTags[0].ti_Tag	=	PPCTASKINFOTAG_MSR;
    MyTags[0].ti_Data	=	(ULONG) &MSR;
    MyTags[1].ti_Tag	=	TAG_END;
    PPCGetTaskAttrs(MyTask,(struct TagItem*) &MyTags);

    MyTags[0].ti_Tag	=	PPCTASKINFOTAG_CR;
    MyTags[0].ti_Data	=	0;
    MyTags[1].ti_Tag	=	TAG_END;
    CR			=	PPCGetTaskAttrs(MyTask,(struct TagItem*) &MyTags);

    MyTags[0].ti_Tag	=	PPCTASKINFOTAG_XER;
    MyTags[0].ti_Data	=	0;
    MyTags[1].ti_Tag	=	TAG_END;
    XER			=	PPCGetTaskAttrs(MyTask,(struct TagItem*) &MyTags);

    MyTags[0].ti_Tag	=	PPCTASKINFOTAG_CTR;
    MyTags[0].ti_Data	=	(ULONG) &CTR;
    MyTags[1].ti_Tag	=	TAG_END;
    PPCGetTaskAttrs(MyTask,(struct TagItem*) &MyTags);

    MyTags[0].ti_Tag	=	PPCTASKINFOTAG_LR;
    MyTags[0].ti_Data	=	(ULONG) &LR;
    MyTags[1].ti_Tag	=	TAG_END;
    PPCGetTaskAttrs(MyTask,(struct TagItem*) &MyTags);

    MyTags[0].ti_Tag	=	PPCTASKINFOTAG_FPSCR;
    MyTags[0].ti_Data	=	(ULONG) &FPSCR;
    MyTags[1].ti_Tag	=	TAG_END;
    PPCGetTaskAttrs(MyTask,(struct TagItem*) &MyTags);

    Printf("PC %08lx MSR %08lx\n",
            PC,
            MSR);

    Printf("LR %08lx CTR %08lx CR %08lx XER %08lx FPSCR %08lx%08lx\n",
            LR,
            CTR,
            CR,
            XER,
            FPSCR[0],
            FPSCR[1]);

    for (i=0;i<32;i++)
    {

      MyTags[0].ti_Tag	=	PPCTASKINFOTAG_GPR;
      MyTags[0].ti_Data	=	i;
      MyTags[1].ti_Tag	=	PPCTASKINFOTAG_VALUEPTR;
      MyTags[1].ti_Data	=	(ULONG) &GPR[i%8];
      MyTags[2].ti_Tag	=	TAG_END;

      PPCGetTaskAttrs(MyTask,(struct TagItem*) &MyTags);

      if (i > 0 && (i%8==7))
      {
        Printf("GPR %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
                GPR[0],
                GPR[1],
                GPR[2],
                GPR[3],
                GPR[4],
                GPR[5],
                GPR[6],
                GPR[7]);
      }
    }


    for (i=0;i<32;i++)
    {
      MyTags[0].ti_Tag	=	PPCTASKINFOTAG_FPR;
      MyTags[0].ti_Data	=	i;
      MyTags[1].ti_Tag	=	PPCTASKINFOTAG_VALUEPTR;
      MyTags[1].ti_Data	=	(ULONG) &FPR[i%8];
      MyTags[2].ti_Tag	=	TAG_END;

      PPCGetTaskAttrs(MyTask,(struct TagItem*) &MyTags);

      if (i > 0 && (i%8==7))
      {
        printf("FPR %g %g %g %g %g %g %g %g\n",
                FPR[0],
                FPR[1],
                FPR[2],
                FPR[3],
                FPR[4],
                FPR[5],
                FPR[6],
                FPR[7]);
      }
    }

  }
}



void	main(ULONG	argc,
             char	*argv[])
{
struct Library	*PPCLibBase;
struct TagItem	MyTags[3];
struct Hook	MyHook;
struct RDArgs	*rdargs;

  if (PPCLibBase=OpenLibrary("ppc.library",0))
  {

    if ((rdargs=ReadArgs(ArgumentString,(LONG*) &MyArgs[0],NULL)))
    {
      MyHook.h_Entry	=	(ULONG (*)(void)) HookFunc;
      MyHook.h_SubEntry	=	(ULONG (*)(void)) NULL;
      MyHook.h_Data	=	(APTR) PPCLibBase;

      MyTags[0].ti_Tag	=	PPCTASKINFOTAG_ALLTASK;
      MyTags[0].ti_Data	=	TRUE;

      MyTags[1].ti_Tag	=	PPCTASKINFOTAG_HOOK;
      MyTags[1].ti_Data	=	(ULONG) &MyHook;

      MyTags[2].ti_Tag	=	TAG_END;

      PPCGetTaskAttrs(NULL,
                     (struct TagItem*) &MyTags);

      if (TaskCount==0)
      {
        puts("No PPC Task found\n");
      }

      FreeArgs(rdargs);
    }
    else
    {
      puts("Commandline Error\n");
      return;
    }
  }
  else
  {
    puts("Can`t open ppc.library\n");
    return;
  }
}
