/*****************************************************************************/
/*                                                                           */
/*   VECTREX HP3000 Software Emulator              Copyright K.Wilkins 1996  */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/*   Title      : This file contains all of the Debug Monitor command funcs  */
/*                                                                           */
/*   File Name  : MON_CMDS.C                                                 */
/*                                                                           */
/*   Author     : Keith Wilkins                                              */
/*                                                                           */
/*   Version    : 1.00                                                       */
/*                                                                           */
/*   Desciption : The Vectrex debug monitor commands are all function driven */
/*                and this file conatins all of the command functions that   */
/*                are called by fDebugMonitor() in monitor.c                 */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/*   Revision History:                                                       */
/*                                                                           */
/*   Version    Date    Who  Description of changes                          */
/*   -------    ----    ---  ----------------------                          */
/*                                                                           */
/*    0.01    20/03/93  K.W  Creation                                        */
/*    0.02    15/04/95  K.W  File name change and addition of new commands   */
/*    1.00    05/08/96  K.W  Public release of DVE V1.0                      */
/*                                                                           */
/*****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include <standard.h>

#include "io.h"
#include "keyboard.h"
#include "sequence.h"
#include "monitor.h"
#include "emu6809.h"
#include "dis6809.h"
#include "vdebug.h"
#include "verror.h"
#include "vectrex.h"
#include "mon_cmds.h"

static T_CHAR string_buffer[EDIT_LINE_LEN+1];
T_ULONG steps;

#ifdef fDebug
#undef fDebug
#endif
#define fDebug(level,body) ((bGblDebugEnable==T_TRUE && level>=tGblDebugLevel)?(tGblDebugMsgLevel=level),(fDebugXX body):0)
T_INT get_label_address(T_PUCHAR apcArgV1,T_PCHAR *label_name,T_PUWORD address);

/*****************************************************************************/
/*                                                                           */
/*   Function    : fMonCmdQuit()                                              */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Exit from the Vectrex emulator back to DOS                */
/*                                                                           */
/*   Accepts     : argc argv                                                 */
/*                                                                           */
/*   Returns     : T_TRUE/T_FALSE if command exec OK                             */
/*                                                                           */
/*****************************************************************************/

T_UCHAR fMonCmdQuit(T_SWORD iArgC,T_PUCHAR apcArgV[],T_PUCHAR apcArgV1[])
{
 iArgC=0;
 apcArgV[0]=NULL;
 wGblQuitFlag=EMU_DONE;
 init_after_execution=T_TRUE;
 action_after_execution=V_QUIT;
 return (DBG_QUIT);
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fMonCmdHelp()                                              */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Printout the debug command list help to the monitor       */
/*                 window.                                                   */
/*                                                                           */
/*   Accepts     : argc,argv                                                 */
/*                                                                           */
/*   Returns     : T_FALSE as we dont want debug to exit                       */
/*                                                                           */
/*****************************************************************************/

T_UCHAR fMonCmdHelp(T_SWORD iArgC,T_PUCHAR apcArgV[],T_PUCHAR apcArgV1[])
{
 T_SWORD iIndex=0;
 iArgC=0;
 apcArgV[0]=NULL;

 while (asCommandList[iIndex].pfCommandFunc!=NULL)
 {
  if (strcmp(asCommandList[iIndex].pcCommandHelp,"")!=0)
  {
   edit_log_add(get_window(MonitorWinId),asCommandList[iIndex].pcCommandHelp);
  }
  iIndex++;
 }
 edit_log_add(get_window(MonitorWinId),"");
 return(DBG_OK);
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fMonCmdBreakSet()                                          */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Set CPU breakpoint                                        */
/*                                                                           */
/*   Accepts     : iArgC, apcArgV                                            */
/*                                                                           */
/*   Returns     : Not much,                                                 */
/*                                                                           */
/*****************************************************************************/

T_UCHAR fMonCmdBreakSet(T_SWORD iArgC,T_PUCHAR apcArgV[],T_PUCHAR apcArgV1[])
{
 T_UWORD iBPAddr;
 T_UWORD iBPSkip=0;

 T_LISTE *liste;
 T_UWORD value=0;
 T_UWORD address;
// T_INT mem=T_FALSE;
 T_INT label=T_FALSE;
 T_PCHAR label_name;

 if (dis_init_state==T_FALSE)
 {
  dis_init_state=T_TRUE;
  init_dis();
 }
 if (iArgC<2 || iArgC>3)
 {
  edit_log_add(get_window(MonitorWinId),"Invalid argument.\nUsage: BSET <xxxx> <skip>");
  edit_log_add(get_window(MonitorWinId),"");
  return(DBG_ERROR);
 }
 // now first look if it is a label of some kind...
 liste=info_liste_first;
 while (liste!=NULL)
 {
  D_ADDRESS_INFO *info;
  info=(D_ADDRESS_INFO *)(liste->objekt);
//  t_printf(0,"\n%s==%s",info->string);
  if (info->kind_of_info==D_INFO_LABEL)
  {
   T_INT cmp_len;
   if (strlen(info->string)>strlen(apcArgV1[1]))
    cmp_len=strlen(info->string);
   else
    cmp_len=strlen(apcArgV1[1]);
   if (strncmp(info->string,apcArgV1[1],cmp_len)==0)
   {
    label=T_TRUE;
    address=info->address;
    label_name=info->string;
    if (iArgC==3)
    {
     if (fStringToWord(apcArgV[2],&value)==T_FALSE)
     {
      edit_log_add(get_window(MonitorWinId),"Invalid breakpoint value (1).");
      edit_log_add(get_window(MonitorWinId),"");
      return(DBG_ERROR);
     }
     if (value>255)
     {
      edit_log_add(get_window(MonitorWinId),"Invalid breakpoint UBYTE required (1).");
      edit_log_add(get_window(MonitorWinId),"");
      return(DBG_ERROR);
     }
    }
    iBPAddr=address;
    iBPSkip=value;
    break;
   }
  }
  liste=liste->naechstes;
 }
 if (liste==NULL)
 {
  if (fStringToWord(apcArgV[1],&iBPAddr)==T_FALSE)
  {
   edit_log_add(get_window(MonitorWinId),"Invalid breakpoint address (2).");
   edit_log_add(get_window(MonitorWinId),"");
   return(DBG_ERROR);
  }
  if (iArgC==3 && fStringToWord(apcArgV[2],&iBPSkip)==T_FALSE)
  {
   edit_log_add(get_window(MonitorWinId),"Invalid breakpoint skip (2).");
   edit_log_add(get_window(MonitorWinId),"");
   return(DBG_ERROR);
  }
 }
 f6809SetBreakpoint(iBPAddr,iBPSkip);
 sprintf(string_buffer," Breakpoint set to $%X.",iBPAddr);
 edit_log_add(get_window(MonitorWinId),string_buffer);
 edit_log_add(get_window(MonitorWinId),"");
 return(DBG_OK);
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fMonCmdBreakClear()                                        */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Clear CPU breakpoint                                      */
/*                                                                           */
/*   Accepts     : iArgC, apcArgV                                            */
/*                                                                           */
/*   Returns     : Nowt much,                                                */
/*                                                                           */
/*****************************************************************************/

T_UCHAR fMonCmdBreakClear(T_SWORD iArgC,T_PUCHAR apcArgV[],T_PUCHAR apcArgV1[])
{
 T_INT i;
 T_UWORD bpnum;
 T_LISTE *bpl=bliste_first;
 apcArgV[0]=NULL;
 if (iArgC==1)
 {
  f6809ClearBreakpoint();
  while (bliste_first)
  {
   VARIABLE_BREAKPOINT *bp=(VARIABLE_BREAKPOINT *)bliste_first->objekt;
   d_entferne_aus_liste(bp,&bliste_first,&bliste_last,DL_CLEAN_UP);
   if (bp)
    free(bp);
  }
  return(DBG_OK);
 }
 if (iArgC==2)
 {
  if (fStringToWord(apcArgV[1],(T_UWORD *)&bpnum)==T_FALSE)
  {
   edit_log_add(get_window(MonitorWinId),"Invalid variable breakpoint clear value");
   edit_log_add(get_window(MonitorWinId),"");
   return(DBG_ERROR);
  }
  i=0;
  while (bpl)
  {
   if (i==bpnum)
   {
    VARIABLE_BREAKPOINT *bp=(VARIABLE_BREAKPOINT *)bpl->objekt;
    d_entferne_aus_liste(bp,&bliste_first,&bliste_last,DL_CLEAN_UP);
    if (bp)
     free(bp);
    break;
   }
   bpl=bpl->naechstes;
   i++;
  }
  return(DBG_OK);
 }
 edit_log_add(get_window(MonitorWinId),"Invalid variable breakpoint clear value");
 edit_log_add(get_window(MonitorWinId),"");
 return(DBG_ERROR);
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fMonCmdBreakShow()                                        */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Show CPU breakpoint                                       */
/*                                                                           */
/*   Accepts     : iArgC, apcArgV                                            */
/*                                                                           */
/*   Returns     : Nowt much,                                                */
/*                                                                           */
/*****************************************************************************/

T_UCHAR fMonCmdBreakShow(T_SWORD iArgC,T_PUCHAR apcArgV[],T_PUCHAR apcArgV1[])
{
 T_UWORD iBPAddr;
 T_UWORD iSkip;
 T_UWORD iEnable;
 T_INT i=0;
 T_LISTE *bpl=bliste_first;

 apcArgV[0]=NULL;
 if (iArgC!=1)
 {
  edit_log_add(get_window(MonitorWinId),"No arguments required (nothing done)");
  edit_log_add(get_window(MonitorWinId),"");
  return(DBG_ERROR);
 }
 f6809ReadBreakpoint(&iBPAddr,&iSkip,&iEnable);
 sprintf(string_buffer," Addr-0x%04x  Skip-0x%02x (%s)",iBPAddr,iSkip,iEnable?"enabled":"diasabled");
 edit_log_add(get_window(MonitorWinId),string_buffer);
 edit_log_add(get_window(MonitorWinId),"");

 while (bpl)
 {
  VARIABLE_BREAKPOINT *bp=(VARIABLE_BREAKPOINT *)bpl->objekt;
  if (bp)
  {
   if (bp->kind&T_KIND_REG)
   {
    if (bp->kind&T_KIND_BREAK_ON_VALUE)
    {
     sprintf(string_buffer,"(%i) REG:%s == %i ($%X)",i,bp->name,bp->compare,bp->compare);
    }
    else
     sprintf(string_buffer,"(%i) REG:%s",i,bp->name);
   }
   else // memory
   {
    if ((bp->kind&T_KIND_LABEL)==0)
    {
     if (bp->kind&T_KIND_BREAK_ON_VALUE)
     {
      sprintf(string_buffer,"(%i) Memory:%i($%04X) == %i ($%X)",i,
      (T_UWORD)(((T_PUCHAR)bp->pointer)-(&atSystemImage[0])),
      (T_UWORD)(((T_PUCHAR)bp->pointer)-(&atSystemImage[0])),
      bp->compare,bp->compare);
     }
     else
     {
      sprintf(string_buffer,"(%i) Memory:%i($%04X)",i,
      (T_UWORD)(((T_PUCHAR)bp->pointer)-(&atSystemImage[0])),
      (T_UWORD)(((T_PUCHAR)bp->pointer)-(&atSystemImage[0])));
     }
    } // if ((bp->kind&T_KIND_LABEL)==0)
    else // if ((bp->kind&T_KIND_LABEL)==0)
    {
     if (bp->kind&T_KIND_BREAK_ON_VALUE)
     {
      sprintf(string_buffer,"(%i) Memory:%s (%i($%04X)) == %i ($%X)",i,bp->name,
      (T_UWORD)(((T_PUCHAR)bp->pointer)-(&atSystemImage[0])),
      (T_UWORD)(((T_PUCHAR)bp->pointer)-(&atSystemImage[0])),
      bp->compare,bp->compare);
     }
     else
     {
      sprintf(string_buffer,"(%i) Memory:%s (%i($%04X))",i,bp->name,
      (T_UWORD)(((T_PUCHAR)bp->pointer)-(&atSystemImage[0])),
      (T_UWORD)(((T_PUCHAR)bp->pointer)-(&atSystemImage[0])));
     }
    } // else if ((bp->kind&T_KIND_LABEL)==0)
   }
   edit_log_add(get_window(MonitorWinId),string_buffer);
   edit_log_add(get_window(MonitorWinId),"");
  }
  bpl=bpl->naechstes;
  i++;
 }
 return(DBG_OK);
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fMonCmdDebug()                                            */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Enable/Disable debug window                               */
/*                                                                           */
/*   Accepts     : int argc char ** argv                                     */
/*                                                                           */
/*   Returns     : nothing                                                   */
/*                                                                           */
/*****************************************************************************/

T_UCHAR fMonCmdDebug(T_SWORD iArgC,T_PUCHAR apcArgV[],T_PUCHAR apcArgV1[])
{
 if (iArgC==1)
 {
  fDebugToggle(0);
 }
 else if (iArgC==2)
 {
  if (strcmp(apcArgV[1],"LOW")==0)
  {
   fDebugLevelLow(0);
  }
  else if (strcmp(apcArgV[1],"MED")==0)
  {
   fDebugLevelMid(0);
  }
  else if (strcmp(apcArgV[1],"HIGH")==0)
  {
   fDebugLevelHigh(0);
  }
  else if (strcmp(apcArgV[1],"FILE")==0)
  {
   fDebugFileToggle(0);
  }
  else
  {
   edit_log_add(get_window(MonitorWinId),"Invalid argument: LOW,MED,HIGH,FILE");
   edit_log_add(get_window(MonitorWinId),"");
   return(DBG_ERROR);
  }
 }
 else
 {
  edit_log_add(get_window(MonitorWinId),"No arguments required (nothing done)");
  edit_log_add(get_window(MonitorWinId),"");
  return(DBG_ERROR);
 }
 return(DBG_OK);
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fMonCmdDissasemble()                                       */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Dissasemble 6809 code to the screen.                      */
/*                                                                           */
/*   Accepts     : int argc char ** argv                                     */
/*                                                                           */
/*   Returns     : nothing                                                   */
/*                                                                           */
/*****************************************************************************/

T_UCHAR fMonCmdDissemble(T_SWORD iArgC,T_PUCHAR apcArgV[],T_PUCHAR apcArgV1[])
{
 // following comment taken out of emu6809, it is relevant for
 // the address read here too :-(
 //
 // this looks fairly exotic, but for debug compiling
 // the compiler ALLWAYS leaves garbage in DX, and
 // f6809AddressRead uses DL (NOT DX) for argument passing
 // this exotic thing ensures a clean (non speed optimized) 8 bit value
 // (stupid compiler !!!)
 volatile static T_UWORD wAddress=0;
 volatile static T_UWORD wLoop;
 volatile static T_UWORD wStart;
 volatile static T_UWORD wEnd;
 volatile static T_UWORD wByteCount;
 volatile static T_UCHAR acDisString[DISAS_MAX_STRING];
 T_UWORD address1;
 T_PCHAR label_name1;
 T_INT label1=T_FALSE;
 T_UWORD address2;
 T_PCHAR label_name2;
 T_INT label2=T_FALSE;

 /* Set defaults for now values */
 wStart=wAddress;
 wEnd=wStart+DISAS_DEFAULT_LENGTH;

 /* Proces the input params */
 switch (iArgC)
 {
  case 3:
   if (fStringToWord(apcArgV[1],(T_UWORD *)&wStart)==T_FALSE)
   {
    label1=get_label_address(apcArgV1[1],&label_name1,&address1);
    if (label1!=T_TRUE)
    {
     edit_log_add(get_window(MonitorWinId),"Invalid Start Address.");
     edit_log_add(get_window(MonitorWinId),"");
     return(DBG_ERROR);
    }
    wStart=address1;
   }
   if (fStringToWord(apcArgV[2],(T_UWORD *)&wEnd)==T_FALSE)
   {
    label2=get_label_address(apcArgV1[2],&label_name2,&address2);
    if (label2!=T_TRUE)
    {
     edit_log_add(get_window(MonitorWinId),"Invalid End Address.");
     edit_log_add(get_window(MonitorWinId),"");
     return(DBG_ERROR);
    }
    wEnd=address2;
   }
   else
    wEnd=wStart+wEnd;
   break;
  case 2:
   if (fStringToWord(apcArgV[1],(T_UWORD *)&wStart)==T_FALSE)
   {
    label1=get_label_address(apcArgV1[1],&label_name1,&address1);
    if (label1!=T_TRUE)
    {
     edit_log_add(get_window(MonitorWinId),"Invalid Start Address.");
     edit_log_add(get_window(MonitorWinId),"");
     return(DBG_ERROR);
    }
    wStart=address1;
    wEnd=address1+DISAS_DEFAULT_LENGTH;
   }
   else
    wEnd=wStart+DISAS_DEFAULT_LENGTH;
   break;
  case 1:
   break;
  default:
   edit_log_add(get_window(MonitorWinId),"Too many arguments.");
   edit_log_add(get_window(MonitorWinId),"Usage: U xxxx, yy");
   edit_log_add(get_window(MonitorWinId),"");
   return(DBG_ERROR);
 }
 /* Now do the Dump */
 do
 {
  /* Do the disassemble and print out addr + bytes + string */
  wAddress=f6809Disassemble((T_UWORD)wStart,(T_UCHAR *)acDisString);
  wByteCount=wAddress-wStart;
  sprintf(string_buffer,"%04x  ",(T_UWORD)wStart);
  for (wLoop=0;wLoop<wByteCount;wLoop++)
  {
   sprintf(string_buffer+strlen(string_buffer),"%02x ",f6809AddressRead(wStart+wLoop));
  }
  for (wLoop=wByteCount;wLoop<DISAS_BYTE_MAX;wLoop++)
  {
   sprintf(string_buffer+strlen(string_buffer),"   ");
  }
  sprintf(string_buffer+strlen(string_buffer),"  %s",(T_UCHAR *)acDisString);
  edit_log_add(get_window(MonitorWinId),string_buffer);
  wStart=wAddress;
 }
 while(wAddress<=wEnd);
 edit_log_add(get_window(MonitorWinId),"");
 return(DBG_OK);
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fMonCmdDump()                                             */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Dump memory in hex format to the screen.                  */
/*                                                                           */
/*   Accepts     : argc argv                                                 */
/*                                                                           */
/*   Returns     : T_FALSE as we dont want debug to exit                       */
/*                                                                           */
/*****************************************************************************/

T_UCHAR fMonCmdDump(T_SWORD iArgC,T_PUCHAR apcArgV[],T_PUCHAR apcArgV1[])
{
 volatile static T_UWORD wAddress=0;
 volatile static T_UWORD wStart;
 volatile static T_UWORD wEnd;
 volatile static T_UWORD tSave;
 volatile static T_SWORD iCount;
 volatile static T_SWORD iLoop;
 T_UWORD address1;
 T_PCHAR label_name1;
 T_INT label1=T_FALSE;
 T_UWORD address2;
 T_PCHAR label_name2;
 T_INT label2=T_FALSE;

 // following comment taken out of emu6809, it is relevant for
 // the address read here too :-(
 //
 // this looks fairly exotic, but for debug compiling
 // the compiler ALLWAYS leaves garbage in DX, and
 // f6809AddressRead uses DL (NOT DX) for argument passing
 // this exotic thing ensures a clean (non speed optimized) 8 bit value
 // (stupid compiler !!!)
 iCount=0;
 /* Set defaults for now values */
 wStart=wAddress;
 wEnd=wStart+DUMP_DEFAULT_LENGTH;
 /* Proces the input params */
 switch(iArgC)
 {
  case 3:
   if (fStringToWord(apcArgV[1],(T_UWORD *)&wStart)==T_FALSE)
   {
    label1=get_label_address(apcArgV1[1],&label_name1,&address1);
    if (label1!=T_TRUE)
    {
     edit_log_add(get_window(MonitorWinId),"Invalid Start Address.");
     edit_log_add(get_window(MonitorWinId),"");
     return(DBG_ERROR);
    }
    wStart=address1;
   }
   if (fStringToWord(apcArgV[2],(T_UWORD *)&wEnd)==T_FALSE)
   {
    label2=get_label_address(apcArgV1[2],&label_name2,&address2);
    if (label2!=T_TRUE)
    {
     edit_log_add(get_window(MonitorWinId),"Invalid End Address.");
     edit_log_add(get_window(MonitorWinId),"");
     return(DBG_ERROR);
    }
    wEnd=address2;
   }
   wEnd=((wEnd+DUMP_LINE_WIDTH-1)/DUMP_LINE_WIDTH)*DUMP_LINE_WIDTH;
   break;
  case 2:
   if (fStringToWord(apcArgV[1],(T_UWORD *)&wStart)==T_FALSE)
   {
    label1=get_label_address(apcArgV1[1],&label_name1,&address1);
    if (label1!=T_TRUE)
    {
     edit_log_add(get_window(MonitorWinId),"Invalid Start Address.");
     edit_log_add(get_window(MonitorWinId),"");
     return(DBG_ERROR);
    }
    wStart=address1;
   }
   wEnd=wStart+DUMP_DEFAULT_LENGTH;
   break;
  case 1:
   break;
  default:
   edit_log_add(get_window(MonitorWinId),"Too many arguments.");
   edit_log_add(get_window(MonitorWinId),"Usage: D <xxxx>,<yyyy>");
   edit_log_add(get_window(MonitorWinId),"");
   return(DBG_ERROR);
 }
 /* Now do the Dump */
 wAddress=wStart;
 iCount=0;
 do
 {
  /* Print Address header when required */
  if (iCount==0)
  {
   tSave=wAddress;
   sprintf(string_buffer,"%04x ",(T_UWORD)wAddress);
  }
  /* Print a byte */
  sprintf(string_buffer+strlen(string_buffer),"%02x ",f6809AddressRead((T_UWORD)wAddress));

  /* Increment the count of line width */
  if (++iCount>=DUMP_LINE_WIDTH)
  {
   /* We are at the end of the line so print out the characters representing the line */
   /* from the SAVE position                                                          */
   sprintf(string_buffer+strlen(string_buffer)," ");
   for (iLoop=0;iLoop<DUMP_LINE_WIDTH;iLoop++)
   {
    if (((T_UCHAR)f6809AddressRead((T_UWORD)(tSave))<' ')||((T_UCHAR)f6809AddressRead((T_UWORD)(tSave))>(T_UCHAR)127))
    {
     sprintf(string_buffer+strlen(string_buffer),".");
     tSave++;
    }
    else
     sprintf(string_buffer+strlen(string_buffer),"%c",(T_UCHAR)f6809AddressRead((T_UWORD)(tSave++)));
   }
   edit_log_add(get_window(MonitorWinId),string_buffer);
   iCount=0;
  }
 }
 while(++wAddress!=wEnd+1);
 edit_log_add(get_window(MonitorWinId),"");
 return(DBG_OK);
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fMonCmdDumpReg()                                           */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Dump CPU registers of 6809 processor to screen            */
/*                                                                           */
/*   Accepts     : argc argv                                                 */
/*                                                                           */
/*   Returns     : T_FALSE as we dont want debug to exit                       */
/*                                                                           */
/*****************************************************************************/

T_UCHAR fMonCmdRegDump(T_SWORD iArgC,T_PUCHAR apcArgV[],T_PUCHAR apcArgV1[])
{
 CPUREGISTERS tsRegs;
 if (RegWinId!=-1)
 {
  return (DBG_OK);
 }
 iArgC=0;
 apcArgV[0]=NULL;
 f6809RegistersRead(&tsRegs);
 sprintf(string_buffer,"x   0x%04x    y   0x%04x    d   0x%04x (a=0x%02x  b=0x%02x)",tsRegs.tX,tsRegs.tY,tsRegs.uABD.tD,tsRegs.uABD.sAB.tA,tsRegs.uABD.sAB.tB);
 edit_log_add(get_window(MonitorWinId),string_buffer);
 sprintf(string_buffer,"usp 0x%04x    hsp 0x%04x    dp  0x%02x",tsRegs.tUSP,tsRegs.tHSP,tsRegs.tDP);
 edit_log_add(get_window(MonitorWinId),string_buffer);
 sprintf(string_buffer,"pc  0x%04x    cc  0x%02x",tsRegs.tPC,tsRegs.uCC.tCC);
 edit_log_add(get_window(MonitorWinId),string_buffer);
 sprintf(string_buffer,"(c:%d v:%d z:%d n:%d i:%d h:%d f:%d e:%d)",tsRegs.uCC.sCC.bC,tsRegs.uCC.sCC.bV,tsRegs.uCC.sCC.bZ,tsRegs.uCC.sCC.bN,tsRegs.uCC.sCC.bI,tsRegs.uCC.sCC.bH,tsRegs.uCC.sCC.bF,tsRegs.uCC.sCC.bE);
 edit_log_add(get_window(MonitorWinId),string_buffer);
 edit_log_add(get_window(MonitorWinId),"");
 return (DBG_OK);
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fMonCmdExit()                                              */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Exit from the debug monitor back to the sequencer         */
/*                                                                           */
/*   Accepts     : argc argv                                                 */
/*                                                                           */
/*   Returns     : DBG_QUIT always                                           */
/*                                                                           */
/*****************************************************************************/

T_UCHAR fMonCmdExit(T_SWORD iArgC,T_PUCHAR apcArgV[],T_PUCHAR apcArgV1[])
{
 iArgC=0;
 apcArgV[0]=NULL;
 return(DBG_QUIT);
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fMonCmdFind()                                              */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Find a hex string within CPU memory space                 */
/*                                                                           */
/*   Accepts     : argc argv                                                 */
/*                                                                           */
/*                 find <start> <end> xx xx xx xx                            */
/*                 find <start> <end> xxxxxxxx OR xxxx xxxx OR xxxxxx xx xx  */
/*                 find <start> <end> "string"                               */
/*                                                                           */
/*   Returns     : DBG_OK if executed OK else DBG_ERROR                      */
/*                                                                           */
/*****************************************************************************/

T_UCHAR fMonCmdFind(T_SWORD iArgC,T_PUCHAR apcArgV[],T_PUCHAR apcArgV1[])
{
 // following comment taken out of emu6809, it is relevant for
 // the address read here too :-(
 //
 // this looks fairly exotic, but for debug compiling
 // the compiler ALLWAYS leaves garbage in DX, and
 // f6809AddressRead uses DL (NOT DX) for argument passing
 // this exotic thing ensures a clean (non speed optimized) 8 bit value
 // (stupid compiler !!!)
 volatile static T_UCHAR   abFind[FIND_MAX_LENGTH];
 volatile static T_UWORD   wStart;
 volatile static T_UWORD   wEnd;
 volatile static T_UWORD   wAddress;
// volatile static T_UWORD   wInchar;
 volatile static T_UWORD   wFindCount;
 volatile static T_UWORD   wHitCount;
 volatile static T_UCHAR   acTmpStr[3];
 volatile static T_UCHAR   acFakeArgs[3][6];
 volatile static T_PUCHAR  pcTextPtr;
 volatile static T_PUCHAR  apcFakeArgList[3];
 volatile static T_SWORD   iArgNo;
 volatile static T_SWORD   iNibbleNo;
 volatile static T_UCHAR   b;

 /* Check argument count against max */
 if (iArgC<4 || iArgC > (FIND_MAX_LENGTH+3))
 {
  //*** fWinPrintf(pwMonitorWin,asMonWin[wGblDisplayMode].iWinFontsize,"\nIncorrect number of arguments.");
  edit_log_add(get_window(MonitorWinId),"Incorrect number of arguments.");
  edit_log_add(get_window(MonitorWinId),"");
  return(DBG_ERROR);
 }

 /* Retrieve the start and end address */
 iArgNo=1;
 if (fStringToWord(apcArgV[iArgNo++],(T_PUWORD)(&wStart))==T_FALSE)
 {
  //*** fWinPrintf(pwMonitorWin,asMonWin[wGblDisplayMode].iWinFontsize,"\nInvalid Start Address.");
  edit_log_add(get_window(MonitorWinId),"Invalid Start Address.");
  edit_log_add(get_window(MonitorWinId),"");
  return(DBG_ERROR);
 }
 if (fStringToWord(apcArgV[iArgNo++],(T_PUWORD)(&wEnd))==T_FALSE)
 {
  //*** fWinPrintf(pwMonitorWin,asMonWin[wGblDisplayMode].iWinFontsize,"\nInvalid End Address.");
  edit_log_add(get_window(MonitorWinId),"Invalid End Address.");
  edit_log_add(get_window(MonitorWinId),"");
  return(DBG_ERROR);
 }

 /* Generate the find array from the arguments, test for string or hex */
 wFindCount=0;

 if (apcArgV[iArgNo][0]=='"')
 {
  /* Text string */
  if (strlen(apcArgV[iArgNo])>FIND_MAX_LENGTH+2)
  {
   //*** fWinPrintf(pwMonitorWin,asMonWin[wGblDisplayMode].iWinFontsize,"\nString too long.");
   edit_log_add(get_window(MonitorWinId),"String too long.");
   edit_log_add(get_window(MonitorWinId),"");
   return(DBG_ERROR);
  }

  /* Copy the string across minus the quotes */
  pcTextPtr=&apcArgV[iArgNo][1];
  while (*pcTextPtr!='"' && *pcTextPtr!='\0')
  {
   abFind[wFindCount++]=(T_UCHAR)*(pcTextPtr++);

   if (wFindCount>FIND_MAX_LENGTH)
   {
    //*** fWinPrintf(pwMonitorWin,asMonWin[wGblDisplayMode].iWinFontsize,"\nString too long.");
    edit_log_add(get_window(MonitorWinId),"String too long.");
    edit_log_add(get_window(MonitorWinId),"");
    return(DBG_ERROR);
   }
  }
 }
 else
 {
  /* Hex string, convert in byte pairs */
  do
  {
   pcTextPtr=apcArgV[iArgNo++];

   /* Process string */
   iNibbleNo=0;
   while (*pcTextPtr!='\0')
   {
    if (iNibbleNo==0)
    {
     acTmpStr[0]=*pcTextPtr++;
     iNibbleNo++;
    }
    else
    {
     acTmpStr[1]=*pcTextPtr++;
     acTmpStr[2]='\0';

     /* We've got the 2nd byte, now convert */
     if(fHexStringToByte((T_PUCHAR)acTmpStr,(T_PUCHAR)(&abFind[wFindCount]))==T_FALSE)
     {
      //*** fWinPrintf(pwMonitorWin,asMonWin[wGblDisplayMode].iWinFontsize,"\nArgument error, use HEX only.");
      edit_log_add(get_window(MonitorWinId),"Argument error, use HEX only.");
      edit_log_add(get_window(MonitorWinId),"");
      return(DBG_ERROR);
     }

     /* Converted O.K so increment the search count, and reset the nibble count */
     wFindCount++;
     iNibbleNo=0;
    }
   }
  }
  while(iArgNo!=iArgC);
 }
 /* Now lets search */
 wHitCount=0;
 for (wAddress=wStart;wAddress!=wEnd;wAddress++)
 {
  /* Check for byte match */
  b=f6809AddressRead(wAddress); /* doesn't work otherwise, see above */
  if (b==abFind[wHitCount])
  {
   wHitCount++;
  }
  else
  {
   wHitCount=0;
  }

  /* Check for complete match, and if so dump 3 lines and pause */
  if (wHitCount==wFindCount)
  {
   wHitCount=0;
   strcpy((T_PUCHAR)(acFakeArgs[0]),"DUMP");
   sprintf((T_PUCHAR)(acFakeArgs[1]),"$%04x",wAddress-wFindCount-15);
   sprintf((T_PUCHAR)(acFakeArgs[2]),"$%04x",wAddress-wFindCount+32);
   for (iNibbleNo=0;iNibbleNo<3;iNibbleNo++)
   {
    apcFakeArgList[iNibbleNo]=acFakeArgs[iNibbleNo];
   }
   fMonCmdDump(3,(T_UCHAR**)apcFakeArgList,(T_UCHAR**)apcFakeArgList);

   /* Ask if user wants to search further */
   //*** fWinPrintf(pwMonitorWin,asMonWin[wGblDisplayMode].iWinFontsize,"\nContinue (y/n)");
//   edit_log_add(get_window(MonitorWinId),"Continue (y/n)");
//   edit_log_add(get_window(MonitorWinId),"");
//   wInchar=toupper(fKBDgetch());
   //*** fWinPrintf(pwMonitorWin,asMonWin[wGblDisplayMode].iWinFontsize,"\b\b\b\b\b\b\b\b\b\b\b\b\b\b              \b\b\b\b\b\b\b\b\b\b\b\b\b\b");
//   if (wInchar==KEY_N || wInchar==KEY_Q)
    return(DBG_OK);
  }
 }
 /* Sucessful exit */
 return(DBG_OK);
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fMonCmdRun()                                               */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Run the emulator from a given position or from current    */
/*                 PC if no address is given.                                */
/*                                                                           */
/*   Accepts     : argc argv                                                 */
/*                                                                           */
/*   Returns     : T_FALSE as we exit debug by disabling debug mode            */
/*                                                                           */
/*****************************************************************************/

T_UCHAR fMonCmdRun(T_SWORD iArgC,T_PUCHAR apcArgV[],T_PUCHAR apcArgV1[])
{
 T_UWORD         tRunAddress;
 CPUREGISTERS    ts6809Regs;

 /* Check argc */
 if (iArgC>2)
 {
  //*** fWinPrintf(pwMonitorWin,asMonWin[wGblDisplayMode].iWinFontsize,"\nToo many arguments.\nUsage: R <xxxx>");
  edit_log_add(get_window(MonitorWinId),"Too many arguments.");
  edit_log_add(get_window(MonitorWinId),"Usage: R <xxxx>");
  edit_log_add(get_window(MonitorWinId),"");
  return(DBG_ERROR);
 }
 /* Decode the address agument is it exists */
 if (iArgC==2)
 {
  if (fStringToWord(apcArgV[1],&tRunAddress)==T_FALSE)
  {
   //*** fWinPrintf(pwMonitorWin,asMonWin[wGblDisplayMode].iWinFontsize,"\nInvalid Run Address.");
   edit_log_add(get_window(MonitorWinId),"Invalid Run Address.");
   edit_log_add(get_window(MonitorWinId),"");
   return(DBG_ERROR);
  }

  /* Set the new PC in the CPU registers */
  f6809RegistersRead(&ts6809Regs);
  ts6809Regs.tPC=tRunAddress;
  f6809RegistersWrite(&ts6809Regs);
  fDebug(HIGH,("fMonCmdRun() CPU program counter set to %04x",tRunAddress));
 }
 /* Exit command exec with no errors, and close debug */
 f6809StatusWrite(CPU_FETCH);
 return (DBG_RUN);
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fMonCmdReset()                                             */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Reset some/all of the vectrex functions                   */
/*                                                                           */
/*   Accepts     : argv,argc                                                 */
/*                                                                           */
/*   Returns     : T_TRUE if execution with no errors                          */
/*                                                                           */
/*****************************************************************************/

T_UCHAR fMonCmdReset(T_SWORD iArgC,T_PUCHAR apcArgV[],T_PUCHAR apcArgV1[])
{
 if (iArgC>2)
 {
  //*** fWinPrintf(pwMonitorWin,asMonWin[wGblDisplayMode].iWinFontsize,"\nToo many arguments.");
  edit_log_add(get_window(MonitorWinId),"Too many arguments.");
  edit_log_add(get_window(MonitorWinId),"");
  return(DBG_ERROR);
 }
 if (strcmp(apcArgV[1],"ALL")==0 || iArgC==1)
 {
  fSequencerReboot(0);
 }
 else if (strcmp(apcArgV[1],"CPU")==0)
 {
  fSequencerReset(0);
 }
 else
 {
  //*** fWinPrintf(pwMonitorWin,asMonWin[wGblDisplayMode].iWinFontsize,"\nBad reset argument.");
  edit_log_add(get_window(MonitorWinId),"Bad reset argument.");
  edit_log_add(get_window(MonitorWinId),"");
 }
 return(DBG_OK);
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fMonCmdTicks()                                             */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Display system tick status counters                       */
/*                                                                           */
/*   Accepts     : argv,argc                                                 */
/*                                                                           */
/*   Returns     : T_TRUE if execution with no errors                          */
/*                                                                           */
/*****************************************************************************/

T_UCHAR fMonCmdTicks(T_SWORD iArgC,T_PUCHAR apcArgV[],T_PUCHAR apcArgV1[])
{
 iArgC=0;
 apcArgV[0]=NULL;

//*** fWinPrintf(pwMonitorWin,asMonWin[wGblDisplayMode].iWinFontsize,"\nTicks:  system=%08ld   display=%08ld",
//                                              lwGblSystemTickTotal,
//                                              lwGblSystemTickTotal/lwGblDisplayTickReload);
 sprintf(string_buffer,"Ticks:  system=%08ld   display=%08ld",lwGblSystemTickTotal,lwGblSystemTickTotal/lwGblDisplayTickReload);
 edit_log_add(get_window(MonitorWinId),string_buffer);
 edit_log_add(get_window(MonitorWinId),"");
 return(DBG_OK);
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fMonCmdSequence()                                          */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Execute a certain number machine cycles of a particular   */
/*                 subsystem either T=System Cycles C=CPU A=Analog S=Sound   */
/*                 P=Persistance                                             */
/*                 If no subsysem is specified then default is T.            */
/*                                                                           */
/*                                                                           */
/*   Accepts     : argv,argc                                                 */
/*                                                                           */
/*   Returns     : T_TRUE if execution with no errors                          */
/*                                                                           */
/*****************************************************************************/

T_UCHAR fMonCmdSequence(T_SWORD iArgC,T_PUCHAR apcArgV[],T_PUCHAR apcArgV1[])
{
 T_ULONG   lwStepCount;
 T_SWORD   iArgNo;
 T_UCHAR   cStepType;

 if (iArgC>3)
 {
  //*** fWinPrintf(pwMonitorWin,asMonWin[wGblDisplayMode].iWinFontsize,"\nToo many arguments.");
  edit_log_add(get_window(MonitorWinId),"Too many arguments.");
  edit_log_add(get_window(MonitorWinId),"");
  return(DBG_ERROR);
 }
 else if (iArgC<2)
 {
  //*** fWinPrintf(pwMonitorWin,asMonWin[wGblDisplayMode].iWinFontsize,"\nNo arguments specified.");
  edit_log_add(get_window(MonitorWinId),"No arguments specified.");
  edit_log_add(get_window(MonitorWinId),"");
  return(DBG_ERROR);
 }

 /* Decode the address argument if it exists */
 if (iArgC==3)
 {
  if (strlen(apcArgV[1])!=1)
  {
   //*** fWinPrintf(pwMonitorWin,asMonWin[wGblDisplayMode].iWinFontsize,"\nBad Step type : T,D,S are valid");
   edit_log_add(get_window(MonitorWinId),"Bad Step type : T,D,S are valid");
   edit_log_add(get_window(MonitorWinId),"");
   return(DBG_ERROR);
  }
  cStepType=toupper(apcArgV[1][0]);
  iArgNo=2;
 }
 else
 {
  iArgNo=1;
  cStepType='T';
 }
 if (fStringToLongWord(apcArgV[iArgNo],&lwStepCount)==T_FALSE || lwStepCount==0)
 {
  //*** fWinPrintf(pwMonitorWin,asMonWin[wGblDisplayMode].iWinFontsize,"\nError: Step count missing or invalid");
   edit_log_add(get_window(MonitorWinId),"Error: Step count missing or invalid");
   edit_log_add(get_window(MonitorWinId),"");
  return(DBG_ERROR);
 }

 /* Now convert the StepCount into system Ticks by multiplying by reload values */
 switch (cStepType)
 {
  case 'D':
   lwStepCount=lwStepCount*lwGblDisplayTickReload;
   break;
  case 'T':
  default:
   break;
 }

 /* Set when the breakpoint will occur */
 lwGblSystemTickBreakpoint=lwGblSystemTickTotal+lwStepCount;
 fDebug(HIGH,("fMonCmdSequence(): Tick=%ld, Breakpoint=%ld",lwGblSystemTickTotal,lwGblSystemTickBreakpoint));

 /* Now return debug to the sequencer */
 // f6809StatusWrite(CPU_FETCH);
 return (DBG_SEQUENCE);
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fMonCmdStep()                                              */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Single step the CPU a certain number of instructions      */
/*                 is one cycle.                                             */
/*                                                                           */
/*   Accepts     : argv,argc                                                 */
/*                                                                           */
/*   Returns     : T_TRUE if execution with no errors                          */
/*                                                                           */
/*****************************************************************************/

T_UCHAR fMonCmdStep(T_SWORD iArgC,T_PUCHAR apcArgV[],T_PUCHAR apcArgV1[])
{
 steps=1;
 if (iArgC>2)
 {
  //*** fWinPrintf(pwMonitorWin,asMonWin[wGblDisplayMode].iWinFontsize,"\nToo many arguments.\nUsage: R <xxxx>");
  edit_log_add(get_window(MonitorWinId),"Too many arguments.\nUsage: S <xx>");
  edit_log_add(get_window(MonitorWinId),"");
  return(DBG_ERROR);
 }

 /* Decode the address agument is it exists */
 if (iArgC==2)
 {
  if (fStringToLongWord(apcArgV[1],&steps)==T_FALSE)
  {
   //*** fWinPrintf(pwMonitorWin,asMonWin[wGblDisplayMode].iWinFontsize,"\nInvalid Run Address.");
   edit_log_add(get_window(MonitorWinId),"Invalid stepcount");
   edit_log_add(get_window(MonitorWinId),"");
   return(DBG_ERROR);
  }
 }
 fDebug(HIGH,("fMonCmdStep() we will step %i CPU instructions",steps));
 return(DBG_STEP);
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fMonCmdStepRun()                                           */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Single step the CPU a continuously                        */
/*                                                                           */
/*   Accepts     : argv,argc                                                 */
/*                                                                           */
/*   Returns     : T_TRUE if execution with no errors                          */
/*                                                                           */
/*****************************************************************************/

T_UCHAR fMonCmdStepRun(T_SWORD iArgC,T_PUCHAR apcArgV[],T_PUCHAR apcArgV1[])
{
 T_UWORD       tRunAddress;
 CPUREGISTERS  ts6809Regs;
 if(iArgC>2)
 {
  //*** fWinPrintf(pwMonitorWin,asMonWin[wGblDisplayMode].iWinFontsize,"\nToo many arguments.\nUsage: R <xxxx>");
  edit_log_add(get_window(MonitorWinId),"Too many arguments.\nUsage: SRUN <xxxx>");
  edit_log_add(get_window(MonitorWinId),"");
  return(DBG_ERROR);
 }

 /* Decode the address agument is it exists */
 if (iArgC==2)
 {
  if (fStringToWord(apcArgV[1],&tRunAddress)==T_FALSE)
  {
   //*** fWinPrintf(pwMonitorWin,asMonWin[wGblDisplayMode].iWinFontsize,"\nInvalid Run Address.");
   edit_log_add(get_window(MonitorWinId),"Invalid Run Address.");
   edit_log_add(get_window(MonitorWinId),"");
   return(DBG_ERROR);
  }

  /* Set the new PC in the CPU registers */
  f6809RegistersRead(&ts6809Regs);
  ts6809Regs.tPC=tRunAddress;
  f6809RegistersWrite(&ts6809Regs);
  fDebug(HIGH,("fMonCmdStep() CPU program counter set to %04x",tRunAddress));
 }
 f6809StatusWrite(CPU_FETCH);
 return(DBG_STEPRUN);
}

T_UCHAR fBset(T_SWORD iArgC,T_PUCHAR apcArgV[],T_PUCHAR apcArgV1[])
{
 T_UWORD value=0;
 T_UWORD address;
 T_PCHAR label_name;
 T_INT label=T_FALSE;
 T_INT mem=T_FALSE;
 VARIABLE_BREAKPOINT *bp;
 T_INT i=0;
 if ((iArgC!=3)&&(iArgC!=2))
 {
  edit_log_add(get_window(MonitorWinId),"Invalid argument.\nUsage: B_SET string|address [value]");
  edit_log_add(get_window(MonitorWinId),"");
  return(DBG_ERROR);
 }
 strcpy(string_buffer,apcArgV1[1]); // to preserve case of label
 if (fStringToWord(string_buffer,&address)==T_FALSE)
 {
  T_INT done=T_FALSE;
  // now check if the breakpoint is on some internal stuff
  // like 6522 or psg...
  while (vlist[i].name!=NULL)
  {
   T_INT cmp_len;
   if (strlen(vlist[i].name)>strlen(apcArgV1[1]))
    cmp_len=strlen(vlist[i].name);
   else
    cmp_len=strlen(apcArgV1[1]);
   if (strncmp(vlist[i].name,apcArgV1[1],cmp_len)==0)
   {
    done=T_TRUE;
    if (iArgC==3)
    {
     T_ULONG len;
     if (fStringToWord(apcArgV1[2],&value)==T_FALSE)
     {
      edit_log_add(get_window(MonitorWinId),"Invalid breakpoint value.");
      edit_log_add(get_window(MonitorWinId),"");
      return(DBG_ERROR);
     }
     len=256;
     if (vlist[i].len==T_WORD_LEN) len*=256;
     if (vlist[i].len==T_INT_LEN) len*=256*256*256;
     len--;
     if ((T_ULONG)value>len)
     {
      edit_log_add(get_window(MonitorWinId),"Invalid value (to high).");
      edit_log_add(get_window(MonitorWinId),"");
      return(DBG_ERROR);
     }
    }
    bp=(VARIABLE_BREAKPOINT *)malloc(sizeof(VARIABLE_BREAKPOINT));
    if (bp==NULL)
    {
     fFatal("fBset() out of memory");
    }
    bp->compare=value;
    bp->kind=0;
    if (iArgC==3)
     bp->kind+=T_KIND_BREAK_ON_VALUE;
    else
     bp->kind+=T_KIND_BREAK_ON_CHANGE;
    bp->kind+=T_KIND_REG;
    bp->len=vlist[i].len;
    bp->name=vlist[i].name;
    bp->pointer=vlist[i].pointer;
    if (iArgC!=3)
    {
     if (bp->len==T_BYTE_LEN)
      bp->start=*((T_PUCHAR)bp->pointer);
     if (bp->len==T_WORD_LEN)
      bp->start=*((T_PUWORD)bp->pointer);
     if (bp->len==T_INT_LEN)
      bp->start=*((T_PUINT)bp->pointer);
    }
    else
     bp->start=0;
    d_fuege_in_liste_ein( bp, &bliste_first, &bliste_last, DL_HINTEN );
   } // if (strncmp(vlist[i].name,apcArgV1[1],cmp_len)==0)
   i++;
  } // while (vlist[i].name!=NULL)

  // check if breakpoint is on a variable loaded in dissassembly control file
  if (iArgC==3)
  {
   if (fStringToWord(apcArgV1[2],&value)==T_FALSE)
   {
    edit_log_add(get_window(MonitorWinId),"Invalid breakpoint value.");
    edit_log_add(get_window(MonitorWinId),"");
    return(DBG_ERROR);
   }
   if (value>255)
   {
    edit_log_add(get_window(MonitorWinId),"Invalid breakpoint UBYTE required");
    edit_log_add(get_window(MonitorWinId),"");
    return(DBG_ERROR);
   }
  }
  label=get_label_address(apcArgV1[1],&label_name,&address);
  if (label==T_TRUE)
  {
   bp=(VARIABLE_BREAKPOINT *)malloc(sizeof(VARIABLE_BREAKPOINT));
   if (bp==NULL)
   {
    fFatal("fBset() out of memory");
   }
   bp->compare=value;
   bp->kind=0;
   if (iArgC==3)
    bp->kind+=T_KIND_BREAK_ON_VALUE;
   else
    bp->kind+=T_KIND_BREAK_ON_CHANGE;
   if (mem==T_FALSE)
   {
    bp->kind+=T_KIND_MEM;
    bp->kind+=T_KIND_LABEL;
    bp->len=T_BYTE_LEN;
    bp->name=label_name;
    bp->pointer=&(atSystemImage[address]);
   } // if (mem==T_FALSE)
   if (iArgC!=3)
   {
    if (bp->len==T_BYTE_LEN)
     bp->start=*((T_PUCHAR)bp->pointer);
    if (bp->len==T_WORD_LEN)
     bp->start=*((T_PUWORD)bp->pointer);
    if (bp->len==T_INT_LEN)
     bp->start=*((T_PUINT)bp->pointer);
   }
   else
    bp->start=0;
   d_fuege_in_liste_ein( bp, &bliste_first, &bliste_last, DL_HINTEN );
   return(DBG_OK);
  } // if (label==T_TRUE)
  if (done==T_FALSE)
  {
   edit_log_add(get_window(MonitorWinId),"Invalid breakpoint register");
   edit_log_add(get_window(MonitorWinId),"");
   return(DBG_ERROR);
  }

 } // if (fStringToWord(apcArgV1[1],&address)==T_FALSE)
 else
 {
  if (iArgC==3)
  {
   if (fStringToWord(apcArgV1[2],&value)==T_FALSE)
   {
    edit_log_add(get_window(MonitorWinId),"Invalid breakpoint value.");
    edit_log_add(get_window(MonitorWinId),"");
    return(DBG_ERROR);
   }
   if (value>255)
   {
    edit_log_add(get_window(MonitorWinId),"Invalid breakpoint UBYTE required");
    edit_log_add(get_window(MonitorWinId),"");
    return(DBG_ERROR);
   }
  }
  mem=T_TRUE;
  bp=(VARIABLE_BREAKPOINT *)malloc(sizeof(VARIABLE_BREAKPOINT));
  if (bp==NULL)
  {
   fFatal("fBset() out of memory");
  }
  bp->compare=value;
  bp->kind=0;
  if (iArgC==3)
   bp->kind+=T_KIND_BREAK_ON_VALUE;
  else
   bp->kind+=T_KIND_BREAK_ON_CHANGE;
  bp->kind+=T_KIND_MEM;
  bp->len=T_BYTE_LEN;
  bp->name=NULL;
  bp->pointer=&(atSystemImage[address]);
  if (iArgC!=3)
  {
   if (bp->len==T_BYTE_LEN)
    bp->start=*((T_PUCHAR)bp->pointer);
   if (bp->len==T_WORD_LEN)
    bp->start=*((T_PUWORD)bp->pointer);
   if (bp->len==T_INT_LEN)
    bp->start=*((T_PUINT)bp->pointer);
  }
  else
   bp->start=0;
  d_fuege_in_liste_ein( bp, &bliste_first, &bliste_last, DL_HINTEN );
  return(DBG_OK);
 }
 return(DBG_OK);
}


T_INT get_label_address(T_PUCHAR apcArgV1,T_PCHAR *label_name,T_PUWORD address)
{
 T_LISTE *liste;
 T_INT label = T_FALSE;
 if (dis_init_state==T_FALSE)
 {
  dis_init_state=T_TRUE;
  init_dis();
 }
 // now first look if it is a label of some kind...
 liste=info_liste_first;
 while (liste!=NULL)
 {
  D_ADDRESS_INFO *info;
  info=(D_ADDRESS_INFO *)(liste->objekt);
  if (info->kind_of_info==D_INFO_LABEL)
  {
   T_INT cmp_len;
   if (strlen(info->string)>strlen(apcArgV1))
    cmp_len=strlen(info->string);
   else
    cmp_len=strlen(apcArgV1);
   if (strncmp(info->string,apcArgV1,cmp_len)==0)
   {
    label=T_TRUE;
    *address=info->address;
    *label_name=info->string;
    break;
   }
  }
  liste=liste->naechstes;
 }
 return label;
}