/*
**	$RCSfile: AlertDump.c,v $
**	$Filename: AlertDump.c $
**	$Revision: 1.3 $
**	$Date: 2001/04/28 19:51:58 $
**
**	sysmon.library support command AlertDump (version 1.5)
**	
**	(C) Copyright 1999-2002 by Etienne Vogt
*/

#include <exec/alerts.h>
#include <mmu/alerts.h>
#include <memory/memalerts.h>
#include <dos/dos.h>
#include <workbench/startup.h>
#define __USE_SYSBASE
#include <proto/exec.h>
#include <proto/dos.h>
#include <exec/execbase.h>
#include <string.h>
#include <stdlib.h>
#include "sysmon.h"

#ifndef AFF_68060
#define	AFB_68060	7
#define AFF_68060	(1L<<7)
#endif

ULONG __saveds main(void);
static void cleanexit(ULONG rc);
static STRPTR alerttype(ULONG alertnum);
static STRPTR alertsub(ULONG alertnum);
static STRPTR alertgen(ULONG alertnum);
static STRPTR alertobj(ULONG alertnum);
static STRPTR alertname(ULONG alertnum);
static char *cpustr(UWORD cpuflags);

static UBYTE version[] = "$VER: AlertDump 1.5 (6.1.2002)";
static UBYTE template[] = "CLEAR/S";

#define	OPT_CLEAR	0
#define	OPTMAX		1

struct ExecBase *SysBase;
struct DosLibrary *DOSBase;
static struct WBStartup *wbmsg;
static struct RDArgs *myrda;
struct SysmonBase *SysmonBase;

ULONG __saveds main(void)	/* No startup code */
{
  struct Process *myproc;
  struct LastGuru *lastguru;
  LONG opts[OPTMAX];

  SysBase = *(struct ExecBase **)4;
  DOSBase = NULL;
  SysmonBase = NULL;
  wbmsg = NULL;
  myrda = NULL;

  myproc = (struct Process *)FindTask(NULL);
  if ((DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",36)) == NULL)
  { Alert(AT_Recovery|AG_OpenLib|AO_DOSLib);
    return 100;
  }

  if (!(myproc->pr_CLI))		/* If started from WB, exit cleanly */
  { WaitPort(&(myproc->pr_MsgPort));
    wbmsg = (struct WBStartup *)GetMsg(&(myproc->pr_MsgPort));
    cleanexit(20);
  }

  if ((SysmonBase = (struct SysmonBase *)OpenLibrary("sysmon.library",1)) == NULL)
  { PutStr("AlertDump: couldn't open sysmon.library V1+\n");
    cleanexit(20);
  }

  memset((char *)opts, 0, sizeof(opts));
  if ((myrda = ReadArgs(template, opts, NULL)) == NULL)
  { PrintFault(IoErr(),NULL);
    cleanexit(20);
  }

  if ((lastguru = SysmonBase->sb_LastGuru) && lastguru->lg_Sig == (ULONG)'HELP')
  { UWORD cpu = SysBase->AttnFlags;

    Printf("\n%s Alert %s\n", alerttype(lastguru->lg_AlertNum), cpustr(cpu));
    Printf(" Guru Meditation: %08lx  %s\n", lastguru->lg_AlertNum, alertname(lastguru->lg_AlertNum));
    Printf(" Current Task   : %08lx  %.32s\n", lastguru->lg_AlertAddr, lastguru->lg_TaskName);
    Printf(" SubSystem      : %s\n", alertsub(lastguru->lg_AlertNum));
    Printf(" General Error  : %s\n", alertgen(lastguru->lg_AlertNum));
    Printf(" Alert Object   : %s\n", alertobj(lastguru->lg_AlertNum));

    PutStr("\nInteger registers\n");
    Printf(" D0-D7 = %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",lastguru->lg_DataRegs[0],lastguru->lg_DataRegs[1],lastguru->lg_DataRegs[2],lastguru->lg_DataRegs[3],lastguru->lg_DataRegs[4],lastguru->lg_DataRegs[5],lastguru->lg_DataRegs[6],lastguru->lg_DataRegs[7]);
    Printf(" A0-A7 = %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",lastguru->lg_AddrRegs[0],lastguru->lg_AddrRegs[1],lastguru->lg_AddrRegs[2],lastguru->lg_AddrRegs[3],lastguru->lg_AddrRegs[4],lastguru->lg_AddrRegs[5],lastguru->lg_AddrRegs[6],lastguru->lg_AddrRegs[7]);
    Printf(" PC = %08lx, SR = %04lx\n",lastguru->lg_PC,(LONG)lastguru->lg_SR);

    if (SysmonBase->sb_Flags & SBFF_FPU)
    { PutStr("\nFloating Point registers\n");
      Printf(" FP0-FP1 = %08lx%08lx%08lx %08lx%08lx%08lx\n",lastguru->lg_FloatRegs[0],lastguru->lg_FloatRegs[1],lastguru->lg_FloatRegs[2],lastguru->lg_FloatRegs[3],lastguru->lg_FloatRegs[4],lastguru->lg_FloatRegs[5]);
      Printf(" FP2-FP3 = %08lx%08lx%08lx %08lx%08lx%08lx\n",lastguru->lg_FloatRegs[6],lastguru->lg_FloatRegs[7],lastguru->lg_FloatRegs[8],lastguru->lg_FloatRegs[9],lastguru->lg_FloatRegs[10],lastguru->lg_FloatRegs[11]);
      Printf(" FP4-FP5 = %08lx%08lx%08lx %08lx%08lx%08lx\n",lastguru->lg_FloatRegs[12],lastguru->lg_FloatRegs[13],lastguru->lg_FloatRegs[14],lastguru->lg_FloatRegs[15],lastguru->lg_FloatRegs[16],lastguru->lg_FloatRegs[17]);
      Printf(" FP6-FP7 = %08lx%08lx%08lx %08lx%08lx%08lx\n",lastguru->lg_FloatRegs[18],lastguru->lg_FloatRegs[19],lastguru->lg_FloatRegs[20],lastguru->lg_FloatRegs[21],lastguru->lg_FloatRegs[22],lastguru->lg_FloatRegs[23]);
      Printf(" FPCR = %08lx, FPSR = %08lx, FPIAR = %08lx\n",lastguru->lg_FPCR,lastguru->lg_FPSR,lastguru->lg_FPIAR);
    }

    PutStr("\nSystem registers\n");
    Printf(" USP = %08lx, ",lastguru->lg_USP);
    if ((cpu & AFF_68020) && (cpu & AFF_68060) == 0)
    { Printf("ISP = %08lx, MSP = %08lx\n",lastguru->lg_SSP,lastguru->lg_MSP);
    }
    else
    { Printf("SSP = %08lx\n",lastguru->lg_SSP);
    }
    if (cpu & AFF_68010)
    { Printf(" VBR = %08lx, SFC = %08lx, DFC = %08lx\n",lastguru->lg_VBR,lastguru->lg_SFC,lastguru->lg_DFC);
      if (cpu & AFF_68020)
      { Printf(" CACR = %08lx",lastguru->lg_CACR);
	if ((cpu & AFF_68040) == 0) Printf(", CAAR = %08lx",lastguru->lg_CAAR);
	PutStr("\n");
	if (cpu & AFF_68030)
	{ if (cpu & AFF_68040)
	  { Printf(" ITT0 = %08lx, ITT1 = %08lx, DTT0 = %08lx, DTT1 = %08lx\n",lastguru->lg_ITT0,lastguru->lg_ITT1,lastguru->lg_DTT0,lastguru->lg_DTT1);
	    Printf(" TC = %08lx, URP = %08lx, SRP = %08lx\n",lastguru->lg_TC,lastguru->lg_URP,lastguru->lg_SRP);
	  }
	  else
	  { Printf(" TT0 = %08lx, TT1 = %08lx\n",lastguru->lg_ITT0,lastguru->lg_ITT1);
	    Printf(" TC = %08lx, CRP = %08lx%08lx, SRP = %08lx%08lx\n",lastguru->lg_TC,lastguru->lg_DTT0,lastguru->lg_DTT1,lastguru->lg_URP,lastguru->lg_SRP);
	  }
	  if (cpu & AFF_68060) Printf(" PCR = %08lx, BUSCR = %08lx\n",lastguru->lg_MSP,lastguru->lg_MMUSR);
	  else if (cpu & AFF_68040) Printf(" MMUSR = %08lx\n",lastguru->lg_MMUSR);
	  else Printf(" MMUSR = %04lx\n",lastguru->lg_MMUSR >> 16);
	}
      }
    }

    if (opts[OPT_CLEAR]) lastguru->lg_Sig = 0;
  }
  else PutStr("No LastGuru data available\n");

  cleanexit(0);
}

static void cleanexit(ULONG rc)
{
  if (myrda) FreeArgs(myrda);
  if (DOSBase) CloseLibrary((struct Library *)DOSBase);
  if (SysmonBase) CloseLibrary((struct Library *)SysmonBase);
  if (wbmsg)
  { Forbid();
    ReplyMsg((struct Message *)wbmsg);
  }
  Exit(rc);
}

static STRPTR alerttype(ULONG alertnum)
{ if (alertnum & AT_DeadEnd) return "DeadEnd";
  else return "Recoverable";
}

static STRPTR alertsub(ULONG alertnum)
{ switch (alertnum & 0x7f000000)
  { case AN_ExecLib:
      return "exec.library";
    case AN_GraphicsLib:
      return "graphics.library";
    case AN_LayersLib:
      return "layers.library";
    case AN_Intuition:
      return "intuition.library";
    case AN_MathLib:
      return "math*.library";
    case 0x06000000:
      return "clist.library (obsolete)";
    case AN_DOSLib:
      return "dos.library";
    case AN_RAMLib:
      return "ramlib";
    case AN_IconLib:
      return "icon.library";
    case AN_ExpansionLib:
      return "expansion.library";
    case AN_DiskfontLib:
      return "diskfont.library";
    case AN_AudioDev:
      return "audio.device";
    case AN_ConsoleDev:
      return "console.device";
    case AN_GamePortDev:
      return "gameport.device";
    case AN_KeyboardDev:
      return "keyboard.device";
    case AN_TrackDiskDev:
      return "trackdisk.device";
    case AN_TimerDev:
      return "timer.device";
    case AN_CIARsrc:
      return "cia.resource";
    case AN_DiskRsrc:
      return "disk.resource";
    case AN_MiscRsrc:
      return "misc.resource";
    case AN_BootStrap:
      return "strap";
    case AN_Workbench:
      return "Workbench";
    case AN_DiskCopy:
      return "DiskCopy";
    case AN_GadTools:
      return "gadtools.library";
    case AN_UtilityLib:
      return "utility.library";
    case AN_Unknown:
      return "Unknown";
    case AN_MEMLib:			/* THOR subsystem codes */
      return "memory.library";
    case AN_MMULib:
      return "mmu.library";
    case 0x3f000000:
      return "680x0.library";
    case 0x40000000:
      return "sysmon.library";		/* my subsystem codes */
    case 0x50000000:
      return "vdisk.device";
    case 0x70000000:
      return "ErrorLogD";
    default:
      return "N/A";
  }
}

static STRPTR alertobj(ULONG alertnum)
{ switch (alertnum & 0x0000ffff)
  { case AO_ExecLib:
      return "exec.library";
    case AO_GraphicsLib:
      return "graphics.library";
    case AO_LayersLib:
      return "layers.library";
    case AO_Intuition:
      return "intuition.library";
    case AO_MathLib:
      return "math*.library";
    case 0x00008006:
      return "clist.library (obsolete)";
    case AO_DOSLib:
      return "dos.library";
    case AO_RAMLib:
      return "ramlib";
    case AO_IconLib:
      return "icon.library";
    case AO_ExpansionLib:
      return "expansion.library";
    case AO_DiskfontLib:
      return "diskfont.library";
    case AO_AudioDev:
      return "audio.device";
    case AO_ConsoleDev:
      return "console.device";
    case AO_GamePortDev:
      return "gameport.device";
    case AO_KeyboardDev:
      return "keyboard.device";
    case AO_TrackDiskDev:
      return "trackdisk.device";
    case AO_TimerDev:
      return "timer.device";
    case AO_CIARsrc:
      return "cia.resource";
    case AO_DiskRsrc:
      return "disk.resource";
    case AO_MiscRsrc:
      return "misc.resource";
    case AO_BootStrap:
      return "strap";
    case AO_Workbench:
      return "Workbench";
    case AO_DiskCopy:
      return "DiskCopy";
    case AO_GadTools:
      return "gadtools.library";
    case AO_UtilityLib:
      return "utility.library";
    case AO_Unknown:
      return "Unknown";
    case 0x0000803d:
      return "memory.library";
    case 0x0000803e:
      return "mmu.library";
    case 0x0000803f:
      return "680x0.library";
    case 0x00008040:
      return "sysmon.library";
    case 0x00008050:
      return "vdisk.device";
    case 0x00008070:
      return "ErrorLogD";
    default:
      return "N/A";
  }
}

static STRPTR alertgen(ULONG alertnum)
{ switch (alertnum & 0x00ff0000)
  { case AG_NoMemory:
      return "Not enough memory";
    case AG_MakeLib:
      return "Library initialization failure";
    case AG_OpenLib:
      return "OpenLibrary() failure";
    case AG_OpenDev:
      return "OpenDevice() failure";
    case AG_OpenRes:
      return "OpenResource() failure";
    case AG_IOError:
      return "I/O error";
    case AG_NoSignal:
      return "No signal available";
    case AG_BadParm:
      return "Bad parameter(s) to function";
    case AG_CloseLib:
      return "Mismatched or too many CloseLibrary()";
    case AG_CloseDev:
      return "Mismatched or too many CloseDevice()";
    case AG_ProcCreate:
      return "Process creation failed";
    default:
      return "N/A";
  }
}

static STRPTR alertname(ULONG alertnum)
{ ULONG num = alertnum & 0x7fffffff;

  if ((num >= 0x00000010 && num < 0x00000018) || num == 0x0000003B || num == 0x0000003E || num == 0x0000003F)
    return "ACPU_Reserved (Reserved CPU vector)";
  if (num >= 0x00000040 && num < 0x000000FF) return "ACPU_User (Quick interrupt vector)";

  switch (num)
  { case 0x00000001:		/* CPU Exception alerts */
      return "ACPU_Reset (System reset or shutdown)";
    case 0x00000002:
      return "ACPU_BusErr (Bus or access error)";
    case 0x00000003:
      return "ACPU_AddressErr (Odd address error)";
    case 0x00000004:
      return "ACPU_InstErr (Illegal instruction)";
    case 0x00000005:
      return "ACPU_DivZero (Division by zero)";
    case 0x00000006:
      return "ACPU_CHK (CHK instruction exception)";
    case 0x00000007:
      return "ACPU_TRAPV (TRAPcc instruction exception)";
    case 0x00000008:
      return "ACPU_PrivErr (Privilege violation)";
    case 0x00000009:
      return "ACPU_Trace (Trace exception)";
    case 0x0000000A:
      return "ACPU_LineA (Unimplemented line 1010 instruction)";
    case 0x0000000B:
      return "ACPU_LineF (Unimplemented line 1111 instruction)";
    case 0x0000000C:
      return "ACPU_EmulInt (Emulation mode interrupt)";
    case 0x0000000D:
      return "ACPU_CoproErr (Coprocessor protocol violation)";
    case 0x0000000E:
      return "ACPU_Format (Stack frame format error)";
    case 0x0000000F:
      return "ACPU_UnInitInt (Uninitialized interrupt)";
    case 0x00000018:
      return "ACPU_Spurious (Spurious interrupt error)";
    case 0x00000019:
      return "ACPU_AutoVec1 (AutoVector Level 1 interrupt)";
    case 0x0000001A:
      return "ACPU_AutoVec2 (AutoVector Level 2 interrupt)";
    case 0x0000001B:
      return "ACPU_AutoVec3 (AutoVector Level 3 interrupt)";
    case 0x0000001C:
      return "ACPU_AutoVec4 (AutoVector Level 4 interrupt)";
    case 0x0000001D:
      return "ACPU_AutoVec5 (AutoVector Level 5 interrupt)";
    case 0x0000001E:
      return "ACPU_AutoVec6 (AutoVector Level 6 interrupt)";
    case 0x0000001F:
      return "ACPU_AutoVec7 (AutoVector Level 7 interrupt)";
    case 0x00000020:
      return "ACPU_Trap0 (TRAP #0 exception)";
    case 0x00000021:
      return "ACPU_Trap1 (TRAP #1 exception)";
    case 0x00000022:
      return "ACPU_Trap2 (TRAP #2 exception)";
    case 0x00000023:
      return "ACPU_Trap3 (TRAP #3 exception)";
    case 0x00000024:
      return "ACPU_Trap4 (TRAP #4 exception)";
    case 0x00000025:
      return "ACPU_Trap5 (TRAP #5 exception)";
    case 0x00000026:
      return "ACPU_Trap6 (TRAP #6 exception)";
    case 0x00000027:
      return "ACPU_Trap7 (TRAP #7 exception)";
    case 0x00000028:
      return "ACPU_Trap8 (TRAP #8 exception)";
    case 0x00000029:
      return "ACPU_Trap9 (TRAP #9 exception)";
    case 0x0000002A:
      return "ACPU_TrapA (TRAP #A exception)";
    case 0x0000002B:
      return "ACPU_TrapB (TRAP #B exception)";
    case 0x0000002C:
      return "ACPU_TrapC (TRAP #C exception)";
    case 0x0000002D:
      return "ACPU_TrapD (TRAP #D exception)";
    case 0x0000002E:
      return "ACPU_TrapE (TRAP #E exception)";
    case 0x0000002F:
      return "ACPU_TrapF (TRAP #F exception)";
    case 0x00000030:		/* FPU exceptions */
      return "AFPU_BSUnord (Branch or Set on unordered condition)";
    case 0x00000031:
      return "AFPU_Inexact (Inexact result)";
    case 0x00000032:
      return "AFPU_FDivZero (Floating-point division by zero)";
    case 0x00000033:
      return "AFPU_Underflow (Floating-point underflow)";
    case 0x00000034:
      return "AFPU_Operand (Operand error)";
    case 0x00000035:
      return "AFPU_Overflow (Floating-point overflow)";
    case 0x00000036:
      return "AFPU_SNaN (Signaling Not a Number)";
    case 0x00000037:
      return "AFPU_UnDType (Unimplemented FP data type)";
    case 0x00000038:		/* MMU exceptions */
      return "AMMU_Config (Configuration error)";
    case 0x00000039:
      return "AMMU_IllOp (Illegal operation)";
    case 0x0000003A:
      return "AMMU_AccessErr (Access level violation)";
    case 0x0000003C:
      return "ACPU_UnEffAddr (Unimplemented effective address)";
    case 0x0000003D:
      return "ACPU_UnIntInst (Unimplemented integer instruction)";
    
    case 0x01000001:		/* exec.library alerts */
      return "AN_ExcptVect (Bad CPU exception vectors checksum)";
    case 0x01000002:
      return "AN_BaseChkSum (Bad ExecBase checksum)";
    case 0x01000003:
      return "AN_LibChkSum (Bad library jumptable checksum)";
    case 0x01000004:
      return "AN_LibMem (No memory for ExecBase structure)";
    case 0x01000005:
      return "AN_MemCorrupt (Corrupted memory list)";
    case 0x01000006:
      return "AN_IntrMem (No memory for interrupt servers)";
    case 0x01000007:
      return "AN_InitAPtr (InitStruct() with a 24bit address)";
    case 0x01000008:
      return "AN_SemCorrupt (Illegal semaphore state)";
    case 0x01000009:
      return "AN_FreeTwice (Freeing memory already freed)";
    case 0x0100000A:
      if (alertnum & AT_DeadEnd) return "AN_BogusExcpt (Illegal CPU exception taken)";
      else return "AN_UnInitExcpt (Uninitialized task exception)";
    case 0x0100000B:
      return "AN_IOUsedTwice (Pending IORequest reused)";
    case 0x0100000C:
      return "AN_MemoryInsane (Sanity check on memory list failed)";
    case 0x0100000D:
      return "AN_IOAfterClose (Closed IORequest reused)";
    case 0x0100000E:
      return "AN_StackProbe (Stack out of range)";
    case 0x0100000F:
      return "AN_BadFreeAddr (Memory header not located)";
    case 0x01000010:
      return "AN_BadSemaphore (Obsolete semaphore structure used)";
    case 0x010000FF:
      return "AN_UnQuickIntr (Uninitialized quick interrupt)";
    case 0x01000011:		/* PoolMem alerts */
      return "AN_MemHeadInsane (MemHeader Insane)";
    case 0x01000012:
      return "AN_InvDelHeader (Invalid DeleteHeader, internal)";
    case 0x01000013:
      return "AN_IllScratch (Scratch Entry Illegal)";
    case 0x01000014:
      return "AN_UnordPools (Memory Pools Unordered)";
    case 0x01000015:
      return "AN_AllocUnder (AllocMem Underflow)";
    case 0x01000016:
      return "AN_FreeOver (FreeMem Overflow)";

    case 0x02010000:		/* graphics.library alerts */
      return "AN_GfxNoMem (No memory for graphics.library)";
    case 0x02010001:
      return "AN_GfxNoMemMspc (No memory for MonitorSpec)";
    case 0x02010002:
      return "AN_CopInstr (No memory for Copperlist)";
    case 0x02000003:
      return "AN_CopListOver (Copperlist overload)";
    case 0x02000004:
      return "AN_CopIListOver (Intermediate Copperlist overload)";
    case 0x02010005:
      return "AN_CopListHead (No memory for Copperlist head)";
    case 0x02010006:
      return "AN_LongFrame (No memory for long-frame Copperlist)";
    case 0x02010007:
      return "AN_ShortFrame (No memory for short-frame Copperlist)";
    case 0x02010008:
      return "AN_FloodFill (No memory for Flood Fill)";
    case 0x02010009:
      return "AN_TextTmpRas (No memory for Text TmpRas)";
    case 0x0201000A:
      return "AN_BltBitMap (No memory for BltBitMap)";
    case 0x0201000B:
      return "AN_RegionMemory (No memory for Region)";
    case 0x0200000C:
      return "AN_GfxNewError (Illegal node type for GfxNew)";
    case 0x0200000D:
      return "AN_GfxFreeError (Bad ExtendedNode for GfxFree)";
    case 0x02000030:
      return "AN_MakeVPort (No memory for MakeVPort)";
    case 0x02000401:
      return "AN_ObsoleteFont (Obsolete font description)";
    case 0x02011234:
      return "AN_GfxNoLCM (Emergency memory not available)";

    case 0x03010000:		/* layers.library alerts */
      return "AN_LayersNoMem (No memory for layers.library)";

    case 0x04000001:		/* intuition.library alerts */
      return "AN_GadgetType (Unknown gadget type)";
    case 0x04010002:
      return "AN_CreatePort (No memory for CreatePort)";
    case 0x04010003:
      return "AN_ItemAlloc (No memory for MenuItem plane)";
    case 0x04010004:
      return "AN_SubAlloc (No memory for SubItem plane)";
    case 0x04010005:
      return "AN_PlaneAlloc (No memory for plane)";
    case 0x04000006:
      return "AN_ItemBoxTop (Item box in negative region)";
    case 0x04010007:
      return "AN_OpenScreen (No memory for OpenScreen)";
    case 0x04010008:
      return "AN_OpenScrnRast (No memory for raster in OpenScreen)";
    case 0x04000009:
      return "AN_SysScrnType (Unknown sys screen type)";
    case 0x0401000A:
      return "AN_AddSWGadget (No memory to add gadget)";
    case 0x0401000B:
      return "AN_OpenWindow (No memory for OpenWindow)";
    case 0x0400000C:
      return "AN_BadState (Bad State entering Intuition)";
    case 0x0400000D:
      return "AN_BadMessage (Bad Message received by IDCMP)";
    case 0x0400000E:
      return "AN_WeirdEcho (Weird echo on deferred action)";
    case 0x0400000F:
      return "AN_NoConsole (Couldn't open console.device)";
    case 0x04000010:
      return "AN_NoISem (Intuition skipped obtaining a sem)";
    case 0x04000011:
      return "AN_ISemOrder (Intuition obtained a sem in bad order)";

    case 0x07000000:		/* dos.library alerts */
      return "AN_Startup (Error initializing DOS)";
    case 0x07010001:
      return "AN_StartMem (No memory at DOS startup)";
    case 0x07000002:
      return "AN_EndTask (Task could not be terminated)";
    case 0x07000003:
      return "AN_QPktFail (Invalid link from DosPacket to Message)";
    case 0x07000004:
      return "AN_AsyncPkt (Unexpected packet received)";
    case 0x07000005:
      return "AN_FreeVec (Incorrect length in FreeVec)";
    case 0x07000006:
      return "AN_DiskBlkSeq (Disk block sequence error)";
    case 0x07000007:
      return "AN_BitMap (Defective bitmap)";
    case 0x07000008:
      return "AN_KeyFree (Block already free)";
    case 0x07000009:
      return "AN_BadChkSum (Invalid block checksum)";
    case 0x0700000A:
      return "AN_DiskError (Disk error)";
    case 0x0700000B:
      return "AN_KeyRange (Block number outside valid range)";
    case 0x0700000C:
      return "AN_BadOverlay (Error in overlay supervisor)";
    case 0x0700000D:
      return "AN_BadInitFunc (Invalid shell initialization packet)";
    case 0x0700000E:
      return "AN_FileReclosed (FileHandle closed more than once)";

    case 0x08000001:		/* ramlib alerts */
      return "AN_BadSegList (Overlay in shared library)";

    case 0x0A000001:		/* expansion.library alerts */
      return "AN_BadExpansionFree (Expansion slot already free)";

    case 0x11000001:		/* console.device alerts */
      return "AN_NoWindow (Can't open initial window)";

    case 0x14000001:		/* trackdisk.device alerts */
      return "AN_TDCalibSeek (Seek error during calibration)";
    case 0x14000002:
      return "AN_TDDelay (Timer error while waiting)";

    case 0x15000001:		/* timer.device alerts */
      return "AN_TMBadReq (Invalid timerequest)";
    case 0x15000002:
      return "AN_TMBadSupply (No ticks from power supply)";

    case 0x21000001:		/* disk.resource alerts */
      return "AN_DRHasDisk (Unit already active)";
    case 0x21000002:
      return "AN_DRIntNoAct (Interrupt without an active unit)";

    case 0x30000001:		/* strap alerts */
      return "AN_BootError (Boot code returned an error)";

    case 0x31000001:		/* Workbench alerts */
      if (alertnum & AT_DeadEnd) return "AN_NoFonts (Unable to open default font)";
      else return "AN_WBBadStartupMsg1 (Bad StartupMsg returned)";
    case 0x31000002:
      return "AN_WBBadStartupMsg2 (Bad StartupMsg returned)";
    case 0x31000003:
      return "AN_WBBadIOMsg (Unrecognized internal message)";
    case 0x31010004:
      return "AN_WBInitPotionAllocDrawer";
    case 0x31010005:
      return "AN_WBCreateWBMenusCreateMenus1";
    case 0x31010006:
      return "AN_WBCreateWBMenusCreateMenus2";
    case 0x31010007:
      return "AN_WBLayoutWBMenusLayoutMenus";
    case 0x31010008:
      return "AN_WBAddToolMenuItem";
    case 0x31010009:
      return "AN_WBReLayoutToolMenu";
    case 0x3101000A:
      return "AN_WBInitTimer";
    case 0x3101000B:
      return "AN_WBInitLayerDemon";
    case 0x3101000C:
      return "AN_WBInitWBGels";
    case 0x3101000D:
      return "AN_WBInitScreenAndWindows1";
    case 0x3101000E:
      return "AN_WBInitScreenAndWindows2";
    case 0x3101000F:
      return "AN_WBInitScreenAndWindows3";
    case 0x31010010:
      return "AN_WBMAlloc";

    case 0x3d000001:	/* memory.library alerts (THOR) */
      return "AN_MEMPageSetup (Page modification failed)";
    case 0x3d000002:
      return "AN_MEMQpkt (Swap daemon packet failure)";
    case 0x3d000003:
      return "AN_MEMCtxtInv (Invalid context found)";
    case 0x3d000004:
      return "AN_MEMCmdInv (Invalid swap daemon command)";
    case 0x3d000005:
      return "AN_MEMInvFree (Invalid freemem)";
    case 0x3d000006:
      return "AN_MEMFreeFail (Releasing memory pool failed)";
    case 0x3d000007:
      return "AN_MEMDupKey (Duplicate key found)";

    case 0x3e090001:	/* mmu.library alerts */
      return "AN_ContextOpen (Context still in use at Expunge())";
    case 0x3e018005:
      return "AN_BadFreePool (Internal memory pool is damaged)";
    case 0x3e018001:
      return "AN_NoPoolMem (No memory to build internal pool)";
    case 0x3e018002:
      return "AN_NoContext (No memory to build the context)";
    case 0x3e000002:
      return "AN_MMUInit (MMU Init vector failed)";
    case 0x3e000003:
      return "AN_IllegalTT (Illegal Transparent Translation mode)";
    case 0x3e000004:
      return "AN_IllegalMMU (Illegal MMU table layout)";
    case 0x3e000005:
      return "AN_BadContext (Context contains unaligned mappings)";
    case 0x3e000006:
      return "AN_BadTable (MMU table has been damaged)";
    case 0x3e000007:
      return "AN_FreeActive (Attempt to release an active context)";
    case 0x3e000008:
      return "AN_MapHole (Mapping contains undefined areas)";
    case 0x3e000009:
      return "AN_Phase (Unexpected context change required)";
    case 0x3e00000a:
      return "AN_BuildError (Lower tree level built failed)";
    case 0x3e00000b:
      return "AN_ConfigBroken (MMU config parameters invalid)";
    case 0x3e00000c:
      return "AN_NoRoot (No valid root pointer for context)";
    case 0x3e00000d:
      return "AN_NoCatcher (No catcher port for exceptions)";
    case 0x3e00000e:
      return "AN_ExcptBusy (Attempt to release a busy exception)";
    case 0x3e00000f:
      return "AN_NotCaller (Bad message hook release attempt)";
    case 0x3e000073:
      return "AN_QueueDaemon (Invalid reply from exception daemon)";
    case 0x3e000010:
      return "AN_LineWB (Unhandled line writeback fault)";
    case 0x3e000011:
      return "AN_LineRB (Unhandled line fetch fault)";
    case 0x3e000012:
      return "AN_GhostMovem (Invalid movem fault detected)";
    case 0x3e000013:
      return "AN_CheckMMU (CheckMMU couldn't repair test page)";
    case 0x3e000014:
      return "AN_BadDMA (Bad DMA transfer initiated)";
    case 0x3e000015:
      return "AN_PostSetup (Memory layout changed after setup)";
    case 0x3e000016:
      return "AN_NoMapMem (Free non-RemapSize() aligned memory)";
    case 0x3e000017:
      return "AN_NoMemMemList (AddMemList() MMU rebuild failed)";
    case 0x3e000018:
      return "AN_NoMemAddConf (AddConfigDev() MMU rebuild failed)";
    case 0x3e090009:
      return "AN_FreeCtxTwice (Child context detached twice)";
    case 0x3e001005:
      return "AN_BadShare (Can't share with non-shared context)";
    case 0x3e12800a:
      return "AN_NoResExp (No expansion library module)";

    case 0x3f000001:		/* THOR 680x0.libraries alerts */
      return "AN_ResVector (Reserved library vector called)";
    case 0x3f000002:
      if (alertnum & AT_DeadEnd) return "AN_FPSPFmtErr (Invalid FPU stack format)";
      else return "AN_Zombie (ColdReboot() didn't reboot)";
    case 0x3f000015:
      return "AN_PostSetup (Configuration changed after setup)";

    case 0x40000001:		/* sysmon.library alerts */
      return "AN_smNoTaskInfo (No TaskInfo structure found)";
    case 0x40010002:
      return "AN_smNoTIMem (No memory for TaskInfo at startup)";
    case 0x40010003:
      return "AN_smSysLogBuf (No memory for syslog buffers)";
    case 0x40000004:
      return "AN_BadSysLogMsg (Bad SysLogMsg received by server)";
    case 0x40010005:
      return "AN_smNoLastGuru (No memory for LastGuru buffer)";
    case 0x40010006:
      return "AN_smNoAlertMem (No memory for alert.hook module)";
    case 0x40000007:
      return "AN_smSuperTaskSwitch (TaskSwitch in Supervisor mode)";
    case 0x40000008:
      return "AN_smInconSchedState (Inconsistant Scheduling State)";

    case 0x50010001:		/* vdisk.device alerts */
      return "AN_VDRootMem (No memory for root structure)";
    case 0x50010002:
      return "AN_VDUnitMem (No memory for unit structure)";
    case 0x50010003:
      return "AN_VDReAlloc (Memory reallocation failed)";
    case 0x50010004:
      return "AN_VDAllocAbs (AllocAbs failed in AllocReverse)";
    case 0x50000005:
      return "AN_VDBadStartup (Error in Unit Startup)";
    case 0x50010006:
      return "AN_VDBadRootLoc (Root Structure in bad memory)";

    case 0x70000001:		/* ErrorLogD alerts */
      return "AN_elBadMessage (Unexpected message at HellGate)";
    case 0x700B0002:
      return "AN_elLoggerFail (Couldn't start logger process)";
    case 0x70000003:
      return "AN_elNoHellGate (Couldn't find HellGate semaphore)";
    case 0x70000004:
      return "AN_elBadEvilLst (Evil List is corrupted)";
    case 0x70000005:
      return "AN_elNoDoomNode (Couldn't find DoomNode)";

    default:
      if (num & 0x00008000) return "(Generic alert)";
      else return "(Unknown alert code)";
  }
}

static char *cpustr(UWORD cpuflags)
{
  if (cpuflags & AFF_68060) return "68060";
  else if (cpuflags & AFF_68040) return "68040";
  else if (cpuflags & AFF_68030) return "68030";
  else if (cpuflags & AFF_68020) return "68020";
  else if (cpuflags & AFF_68010) return "68010";
  else return "68000";
}
