
/***************************************************************************
**
**    $Header$
**
**    $Log$
** 
****************************************************************************/

/****************************************************************************
**
**  Name: SYMUSER.CPP
**
**  Description:
**      Entry points for Create/Delete User Defined Symbols.
**
**  Status:  CODED
**
**    Rev 1.0   1 Sept. 1995 8:30:00am  Gates Hua
** Initial revision.
**
**  Copyright (C) 1995 Microtek International.  All rights reserved.
**
*****************************************************************************/

                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/

#include "stdafx.h"

#include <string.h>
#include <io.h>
#include <fcntl.h>
#include <sys\stat.h>
#include "symcli.h"
#include "utilext.h"
#include "symimp.h"


#ifdef _LINK_WITH_ABI_
//#include "abibase.h"  
#include "abiextfn.h"
#else
typedef int STATUS;
typedef unsigned char FLAG;
typedef struct {
    FLAG addrType;
    unsigned long  addr;
} ADDR;


extern int TestKey(WORD wKey);   // jerry

/* All ABI routines Return codes */
typedef enum {
        ICE_OK              = 0x0,
        ICE_FAIL_STEP,                  //target cannot step
        ICE_FAIL_MEM_WRITE,             //memory write failure
        ICE_FAIL_MAP_INCLUDE,           //map status not included
        ICE_FAIL_MAP_BOUNDARY,          //map address boundary error
        ICE_NOT_FOUND       = 0x5,
        ICE_FOUND,
        ICE_TIME_OUT        = 0x7,
        ICE_PARA_ERROR      = 0x8,
        ICE_EP_RUNNING      = 0x10,
        ICE_TRACE_RUNNING   = 0x11,
        ICE_TRACE_READ_OVER = 0x12,
        ICE_COMMAND_INVALID = 0x13,

        ICE_FLASH_SW_ERROR  = 0x40,
        ICE_FLASH_EC_ERROR  = 0x41,
        ICE_FLASH_PRG_ERROR = 0x42,
        ICE_FLASH_REC_ERROR = 0x43,
        ICE_NO_RESPONSE        = 0xff
} RET_CODE;

#endif

#include "symblsvr.h"
#include "symuser.h"
#include "symuser1.h"
#include "symerrs.h"

                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/
extern class SymUserVarTable userVariables;
class SymUserTable userSymbols;
int nErrorNum = 0;      // global error number 

                       /****************************
                        *                          *
                        *    EXTERNAL VARIABLES    *
                        *                          *
                        ****************************/
//extern STATUS AbiGetMemN(ADDR addr1, ADDR addr2,char* pchBuff);     

extern void SrcUpdate();
  
extern void SymbolLineCmd(void);

                       /****************************
                        *                          *
                        *     LOCAL PROTOTYPES     *
                        *                          *
                       ****************************/

#ifdef __cplusplus
  extern "C"{
#endif

void WINAPI CreateCmd(int nArgc, char* pszArgv[]);
void WINAPI DeleteCmd(int nArgc, char* pszArgv[]);
void WINAPI SymbolCmd(int nArgc, char* pszArgv[]);
void WINAPI QueryCmd(int nArgc, char* pszArgv[]);
void WINAPI UploadCmd(int nArgc, char* pszArgv[]);
void WINAPI SsaveCmd(int nArgc, char* pszArgv[]);
void WINAPI SrecallCmd(int nArgc, char* pszArgv[]);  
#ifdef __cplusplus
 }
#endif





void prn_err( int num );
//void win_err( int num );
//int SymToAddr( char *lpStr , U8* lpType , U32* lpAddr );
//int AddrToSym( U8 type , U32 addr , char * str );

void U24ToStr(U32 ui , char *tt);
void U16ToStr(U16 ui , char *tt);
void U8ToStr(U8 ui , char *tt);
void StrToU32(U32& ul , char *tt);
void changeN(char *uc ,char *result, int n);
void showPC(U32 addr);

                       /****************************
                        *                          *
                        *      EXECUTABLE CODE     *
                        *                          *
                        ****************************/
extern RETCODE DisplaySymbols(LPSTR cmdString, int flag);
//extern RETCODE AddressOf(LPSTR cmdString);
//extern RETCODE NameOf(LPSTR cmdString);
extern RETCODE SymServerSymToAddr(char *lpStr , 
        U8* lpType , U32 * lpAddr);
extern RETCODE SymServerAddrToSym(U8 type , U32 addr , char *lpStr);
/*
class  CSymApp : CWinApp
{      
public:
    CSymApp( const char* pszAppName = NULL ) : CWinApp( pszAppName )
    {
    }

public:
    virtual BOOL InitInstance() { return TRUE; };
    virtual BOOL ExitInstance() { return TRUE; };
};

CSymApp symApp("symsvr.dll");
*/

/***************************************************************************
*                                                                          *
*  SymToAddr - convert symbol to addr                                      *
*                                                                          *
*  parameter :                                                             *
*       input :                                                            *
*           str - symbol name                                              *
*       output :                                                           *
*           type - symbol segment area                                     *
*           addr - symbol address                                          * 
*                                                                          *
*  return value :                                                          *
*       None                                                               *
*                                                                          *
***************************************************************************/
int WINAPI SymToAddr(char *lpStr , U8* lpType , U32 * lpAddr)
{                                                
    if ( GOOD != SymServerSymToAddr( lpStr , lpType , lpAddr) )
        return userSymbols.Sym2Addr( lpStr , lpType , lpAddr );
    else return GOOD;
}
                                                      
int SymUserTable::Sym2Addr( char *str , U8* type , U32 *addr )                             
{
    SymUserSearchNodeByName( str );
    if ( matchPtr == 0 ) return(-1);
    *type = matchPtr->type;
    *addr = matchPtr->addr;
    return(0);
}
    
/***************************************************************************
*                                                                          *
*  AddrToSym - convert address to symbol                                   *
*                                                                          *
*  parameter :                                                             *
*       output :                                                           *
*           str - symbol name                                              *
*       input :                                                            *
*           type - symbol segment area                                     *
*           addr - symbol address                                          * 
*                                                                          *
*  return value :                                                          *
*       None                                                               *
*                                                                          *
***************************************************************************/
int WINAPI AddrToSym(U8 type , U32 addr , char *str)
{                                                
    if ( GOOD != SymServerAddrToSym(type , addr , str) )
        return userSymbols.Addr2Sym( type , addr , str );
    else return GOOD;
}
                                                      
int SymUserTable::Addr2Sym( U8 type , U32 addr , char *str )                             
{
    SymUserSearchNodeByAddr( addr , type );
    if ( matchPtr == 0 ) return(-1);
    int i = strlen( matchPtr->name );
    if ( i > MAX_USE_DEFINE_SYMBOL_LENGTH ) 
        i = MAX_USE_DEFINE_SYMBOL_LENGTH;
    memcpy( str , matchPtr->name , i );
    str[i] = '\0';
    return(0);
}
    
/***************************************************************************
*                                                                          *
*  SsaveCmd - Shell window SSave Command    entry pointer                  *
*                                                                          *
*  parameter :                                                             *
*       input :                                                            *
*           argc - argument count                                          *
*           argv - argument string array                                   *
*                                                                          *
*  return value :                                                          *
*       None                                                               *
*                                                                          *
***************************************************************************/
void WINAPI SsaveCmd(int nArgc, char* pszArgv[])
{
    if ( nArgc != 2 ) return;
    if ( userSymbols.SymUserSSave( pszArgv[1] ) != 0 ) 
        prn_err( nErrorNum );
}

/***************************************************************************
*                                                                          *
*  SrecallCmd - Shell window SSave Command  entry pointer                  *
*                                                                          *
*  parameter :                                                             *
*       input :                                                            *
*           argc - argument count                                          *
*           argv - argument string array                                   *
*                                                                          *
*  return value :                                                          *
*       None                                                               *
*                                                                          *
***************************************************************************/
void WINAPI SrecallCmd(int nArgc, char* pszArgv[])
{
    if ( nArgc != 2 ) return;
    if ( userSymbols.SymUserSRecall( pszArgv[1] ) !=  0 ) 
        prn_err( nErrorNum );
}

/***************************************************************************
*                                                                          *
*  UploadCmd - Shell window upload Command  entry pointer                  *
*                                                                          *
*  parameter :                                                             *
*       input :                                                            *
*           argc - argument count                                          *
*           argv - argument string array                                   *
*                                                                          *
*  return value :                                                          *
*       None                                                               *
*                                                                          *
***************************************************************************/
void WINAPI UploadCmd(int nArgc, char* pszArgv[])
{          
    char filename[256];
    char olddata[256] , newdata[512];
    U32 staddr , endaddr , len;
    ADDR addr1 , addr2;
    int i , uploadFile;
    U16 count ;
    U8 uCheckSum;                                                   
    RET_ADDR retAddr;

    addr1.addrType = addr2.addrType = 0;
    switch ( pszArgv[1][0] ) {
    case 'X' :
    case 'x' :
        switch( pszArgv[1][1]-'0' )
        {                                                 
            case 0: 
                 addr1.addrType = addr2.addrType = MEM_X0;
                 break;
            case 1: 
                 addr1.addrType = addr2.addrType = MEM_X1;
                 break;
            case 2: 
                 addr1.addrType = addr2.addrType = MEM_X2;
                 break;
            case 3: 
                 addr1.addrType = addr2.addrType = MEM_X3;
                 break; 
            default:   
                addr1.addrType = addr2.addrType = MEM_X0;
                break;                                    
        }         
           //        addr1.addrType = addr2.addrType = 3;
        break;
    case 'I' :
    case 'i' :
        addr1.addrType = addr2.addrType = MEM_I;//4;
        break;
//    case 'R' :
//    case 'r' :
//        addr1.addrType = addr2.addrType = 5;
//        break;
//    case 'B' :
//    case 'b' :
//        addr1.addrType = addr2.addrType = 6;
//        break;
//    case 'S' :
//    case 's' :
//        addr1.addrType = addr2.addrType = 7;
//        break;
    case 'P':
    case 'p':
        switch( pszArgv[1][1]-'0' )
        {                                                 
            case 0: 
                 addr1.addrType = addr2.addrType = MEM_P0;
                 break;
            case 1: 
                 addr1.addrType = addr2.addrType = MEM_P1;
                 break;
            case 2: 
                 addr1.addrType = addr2.addrType = MEM_P2;
                 break;
            case 3: 
                 addr1.addrType = addr2.addrType = MEM_P3;
                 break;
            default:
                  addr1.addrType = addr2.addrType = MEM_P0;
                 break;                                        
        }         
           //        addr1.addrType = addr2.addrType = 3;
        break;
    default :
        addr1.addrType = addr2.addrType = MEM_P0;
        break;
    }
    
    if ( nArgc == 4 ) {
        strcpy( filename , pszArgv[3] );
        StrToU32( staddr , pszArgv[1] );
        StrToU32( endaddr , pszArgv[2] );
        endaddr = (staddr&0x0FFFF0000L)|(endaddr&0x0FFFFL);
        len = endaddr - staddr + 1;
    }
    else {
        strcpy( filename , pszArgv[4] );
        StrToU32( staddr , pszArgv[1] );
        StrToU32( endaddr , pszArgv[3] );
        len = endaddr;
        endaddr += staddr-1;
    }

    if ( addr1.addrType >= MEM_P0 && addr1.addrType <= MEM_P3 )
    {
        int nBank;
        
        SymConvertToBank( endaddr , nBank );
        SymConvertToBank( staddr , nBank );
        //addr1.addrType = addr2.addrType = Bank;
    }
    
    uploadFile = _open(filename,_O_CREAT|_O_RDWR|_O_BINARY,
                                _S_IREAD|_S_IWRITE);
    if ( uploadFile == -1 ) {
        nErrorNum = 0x4003;
        prn_err( nErrorNum );
        return;
    }               

    SymShowLine("Upload file : ");
    addr1.addr = staddr ;
    count = (U16)(len>>7) ;
    newdata[0] = ':';
    newdata[7] = '0';
    newdata[8] = '0';
    newdata[265] = 'F';
    newdata[266] = 'F';
    newdata[267] = 0x0d;
    newdata[268] = 0x0a;
    U8ToStr( 0x80 , &newdata[1] );
    for( i = 0 ; (U16)i < count ; i++) {            
        showPC( addr1.addr );
        addr2.addr = addr1.addr + 127;

#ifdef _LINK_WITH_ABI_
        
        if ( emuGetMemN( addr1 ,(U16)(1+addr2.addr-addr1.addr) ,(U8*)olddata,&retAddr ) != ICE_OK ) {
            nErrorNum = 0x4001;
            prn_err( nErrorNum );
            return;
        }
        
#endif 
       
        U16ToStr( (U16)addr1.addr , &newdata[3]);
        changeN( olddata , &newdata[9] , 128 );
        uCheckSum = 0;             
        int j;
        for( j = 0;j < 128;j++ ) {
            uCheckSum = (unsigned char)(uCheckSum + olddata[j]);
//            uCheckSum += (U8) olddata[j];
        }                    
        uCheckSum = (unsigned char)(uCheckSum+0x80);
        uCheckSum = (unsigned char)(uCheckSum+(addr1.addr&0xFF));
        uCheckSum = (unsigned char)(uCheckSum+
            ((addr1.addr>>8)&0xFF));
        
        j = 0x100 - uCheckSum;
        uCheckSum = (unsigned char)(j&0xFF);
        changeN( (char *)&uCheckSum, &newdata[265], 1 );
//        uCheckSum = ~uCheckSum + 1;    
        _write( uploadFile , newdata , 269 );
        addr1.addr += 128;        

        if ( TestKey(VK_ESCAPE) == 1 ) { 
            nErrorNum = 0x4010;
            prn_err( nErrorNum );
            U8ToStr( 0x0 , &newdata[1] );
            U16ToStr( 0x0 , &newdata[3] );
            U8ToStr( 0x1 , &newdata[7] );
            i = 9 ;     
            newdata[i++] = 'F';
            newdata[i++] = 'F';
            newdata[i++] = 0x0d;
            newdata[i++] = 0x0a;
            _write( uploadFile , newdata , i );
            _close( uploadFile );
            return;
        }                  

    }
    count = (U16)( len & 0x7F );
    if ( count ) {
        i = 9 + count*2 ;     
        newdata[i++] = 'F';
        newdata[i++] = 'F';
        newdata[i++] = 0x0d;
        newdata[i++] = 0x0a;
//        U8ToStr( 0x80 , &newdata[1] );
        U8ToStr( (U8)count , &newdata[1] );
        showPC( addr1.addr );
        addr2.addr = addr1.addr + count - 1;
        
#ifdef _LINK_WITH_ABI_
        
        if ( emuGetMemN( addr1 ,(U16)(1+addr2.addr-addr1.addr) , (U8*)olddata,&retAddr ) != ICE_OK ) {
            nErrorNum = 0x4001;
            prn_err( nErrorNum );
            return;
        }
        
#endif
        
        U16ToStr( (U16)addr1.addr , &newdata[3]);
        changeN( olddata , &newdata[9] , count );

        uCheckSum = 0;             
        int j;
        for( j = 0;j < (int)count;j++ ) {
            uCheckSum = (unsigned char)(uCheckSum + olddata[j]);
//            uCheckSum += (unsigned char)olddata[j];
        }    
        uCheckSum = (unsigned char)(uCheckSum+count);
        uCheckSum = (unsigned char)(uCheckSum+(addr1.addr&0xFF));
        uCheckSum = (unsigned char)(uCheckSum+
            ((addr1.addr>>8)&0xFF));

        j = 0x100 - uCheckSum;
        uCheckSum = (unsigned char)(j&0xFF);
//        i = 9 + count*2 ;     
        changeN( (char *)&uCheckSum, &newdata[9 + count*2], 1 );

        _write( uploadFile , newdata , i );
    }         
    U8ToStr( 0x0 , &newdata[1] );
    U16ToStr( 0x0 , &newdata[3] );
    U8ToStr( 0x1 , &newdata[7] );
    i = 9 ;     
    newdata[i++] = 'F';
    newdata[i++] = 'F';
    newdata[i++] = 0x0d;
    newdata[i++] = 0x0a;
    _write( uploadFile , newdata , i );
    _close( uploadFile );
}   

/***************************************************************************
*                                                                          *
*  CreateCmd - Shell window create Command  entry pointer                  *
*                                                                          *
*  parameter :                                                             *
*       input :                                                            *
*           argc - argument count                                          *
*           argv - argument string array                                   *
*                                                                          *
*  return value :                                                          *
*       None                                                               *
*                                                                          *
***************************************************************************/
void WINAPI CreateCmd(int nArgc, char* pszArgv[])
{          
    char temp[MAX_USE_DEFINE_SYMBOL_LENGTH+1];
    U32 addr;
    U8 addrType;
    int i;
             
    if ( nArgc != 3 ) return;                     
    i = strlen( pszArgv[1] );
    if (i>MAX_USE_DEFINE_SYMBOL_LENGTH+1) 
        i=MAX_USE_DEFINE_SYMBOL_LENGTH+1;
    memcpy( temp , pszArgv[1] , i );
    temp[i] = '\0'; 
    addrType = 2;
    switch ( pszArgv[2][0] ) {
    case 'X' :
    case 'x' :
        switch(pszArgv[2][1]-'0')
        {
            case 0: addrType = MEM_X0;
                break;
            case 1: addrType = MEM_X1;
                break;
            case 2: addrType = MEM_X2 ;
                break;
            case 3: addrType = MEM_X3 ;
                break;
        }
        //addrType = 3;
        break;
    case 'I' :
    case 'i' :
        addrType =MEM_I;
        //drType = 4;
        break;
//    case 'R' :
//    case 'r' :
//        addrType = 5;
//        break;
//    case 'B' :
//    case 'b' :
//        addrType = 6;
//        break;
//    case 'S' :
//    case 's' :
//        addrType = 7;
//        break;
    case 'P' :
    case 'p' :
        switch(pszArgv[2][1]-'0')
        {
            case 0: addrType = MEM_P0;
                break;
            case 1: addrType = MEM_P1  ;
                break;
            case 2: addrType = MEM_P2  ;
                break;
            case 3: addrType = MEM_P3   ;
                break;
        }
        //addrType = 3;
        break;

    default :          
        addrType = MEM_P0;
        break;
    }
    StrToU32(addr , pszArgv[2]);  
    if ( addrType >= MEM_P0 && addrType <=MEM_P3) {
        int nBank;
/*
        if ( g_nBankNum ) {
            if ( g_nBankNum <=2 ) {
                if ( addr > 0x1FFFFL ) {
                    SymShowLine("bank switch address over range!");
                    return;
                }
            }            
        }
        else {
            if ( addr > 0x0FFFFL ) {
                ShowLine("Not support bank switch!");
                return;
            }
        }
*/ //perhaps these will be freed later.
    //    SymConvertToBank( addr , nBank );
        //addrType = nBank;
    }    
    
      
    i = userSymbols.SymUserCreate(temp , addrType , addr);
    if ( i == 0 ) {
        SymShowLine("Create symbol OK!");
        
        if ( addrType >= MEM_P0 && addrType <=MEM_P3 )
            SrcUpdate();
    }        
    else 
        prn_err( nErrorNum );
            
}   

/***************************************************************************
*                                                                          *
*  DeleteCmd - Shell window create Command  entry pointer                  *
*                                                                          *
*  parameter :                                                             *
*       input :                                                            *
*           argc - argument count                                          *
*           argv - argument string array                                   *
*                                                                          *
*  return value :                                                          *
*       None                                                               *
*                                                                          *
***************************************************************************/
void WINAPI DeleteCmd(int nArgc, char* pszArgv[])
{          
    char temp[MAX_USE_DEFINE_SYMBOL_LENGTH+1];
    int i;
                                  
    if ( nArgc != 2 ) return;                                  
    if ( pszArgv[1][0] == '#' ) {
        i = strlen( pszArgv[1] );
        if (i>MAX_USE_DEFINE_SYMBOL_LENGTH+1) 
            i=MAX_USE_DEFINE_SYMBOL_LENGTH+1;
        memcpy( temp , pszArgv[1] , i );
        temp[i] = '\0'; 
        i = userSymbols.SymUserDelete(temp);
    }
    else if ( pszArgv[1][0] == '$' ) {
        i = strlen( pszArgv[1] );
        if (i>MAX_USE_DEFINE_SYMBOL_LENGTH+1) 
            i=MAX_USE_DEFINE_SYMBOL_LENGTH+1;
        memcpy( temp , pszArgv[1] , i );
        temp[i] = '\0'; 
        i = userVariables.SymUserVarDelete(temp);
    }
    else {
        userSymbols.SymUserDeleteAll();
        userVariables.SymUserVarDeleteAll();
        i = 0;
    }
    if ( i == 0 ) {
        SymShowLine("Delete symbol OK!");      
#ifdef _LINK_WITH_SOURCE_        
        SrcUpdate();   
#endif
    }
    else 
        prn_err( nErrorNum );
        
}   

/***************************************************************************
*                                                                          *
*  SymbolCmd - Shell window symbol Command  entry pointer                  *
*                                                                          *
*  parameter :                                                             *
*       input :                                                            *
*           argc - argument count                                          *
*           argv - argument string array                                   *
*                                                                          *
*  return value :                                                          *
*       None                                                               *
*                                                                          *
***************************************************************************/
void WINAPI SymbolCmd(int nArgc, char* pszArgv[])
{                            
//  if ( nArgc != 1 ) return;
//  if ( pszArgv[0] == 0 ) return;
    if ( nArgc == 1 ) {  
        DisplaySymbols( 0 , 8 );
    }
    else if ( nArgc == 2 ) {
        if ( *pszArgv[1] == '#' ) {
            DisplaySymbols( &pszArgv[1][1] , 0 );
        }
        else if ( stricmp( pszArgv[1] , "global")==0 ) {
            DisplaySymbols( 0 , 4 );
        }
        else if ( stricmp( pszArgv[1] , "module")==0 ) {
            DisplaySymbols( 0 , 2 );
        }   
        else if ( stricmp( pszArgv[1] , "lines")==0 ) {
            SymbolLineCmd();
        }   
    }   
        
    if ( nArgc == 1 ) {
        userSymbols.SymUserList();
        userVariables.SymUserVarList();
    }
}   

/***************************************************************************
*                                                                          *
*  QueryCmd - Shell window query Command    entry pointer                  *
*                                                                          *
*  parameter :                                                             *
*       input :                                                            *
*           argc - argument count                                          *
*           argv - argument string array                                   *
*                                                                          *
*  return value :                                                          *
*       None                                                               *
*                                                                          *
***************************************************************************/
void WINAPI QueryCmd(int nArgc, char* pszArgv[])
{       
    int i;      
    char *ss ;
    
    i = 0;
    if ( nArgc != 2 ) return;                     
    ss = new char [ strlen( pszArgv[1] ) + 1 ];
    if ( ss == 0 ) return;                     
    strcpy( ss , pszArgv[1] );
    if ( *ss == '#' )
//          AddressOf( ss );
    {
        if ( AddressOf( ss ) != GOOD ) {
//          ShowLine("Address of Return Error!");
            i = 1;
        }
    }    
    else
//          NameOf( ss );
    {
        if ( NameOf( ss ) != GOOD ) {
            i = 1;
//          ShowLine("Name of Return Error!");
        }
    }    
    if ( userSymbols.SymUserQuery( pszArgv[1] ) != 0 ) {
        if ( i ) {
            if ( *pszArgv[1] == '#' ) SymShowLine("This symbol does not exist!");
             
            else SymShowLine("This address can not query symbol!");
/*
            CString strErr;
            if ( *pszArgv[1] == '#' ) {
                
                if ( GOOD == ErrGetErrorText(ER_ID_SYM_NOT_EXIST, strErr) ) {
                    ShowLine(strErr.GetBuffer( strErr.GetLength() ) );
                }
            }
            else {
                if ( GOOD == ErrGetErrorText(ER_ID_SYM_ADDR_TO_SYM, strErr) ) {
                    ShowLine(strErr.GetBuffer( strErr.GetLength() ) );
                }
            }
*/            
        }
        i = 1;
    }
//    i = userSymbols.SymUserQuery( pszArgv[1] );
    delete ss;
    if ( i != 0 ) 
        nErrorNum = 0;             
//      prn_err( nErrorNum );
        
}

/***************************************************************************
*                                                                          *
*  SymUserSSave - save user defined symbol to file                         *
*  parameter :                                                             *
*       str      symbol file name                                          *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
int SymUserTable::SymUserSSave(char *str)
{
    struct SymUserNode *temp;
    int symbolFile ,  i;     
    U32 num;
    char buf[200];
    
    if ( symno == 0 ) {
        nErrorNum = 0x4009;
        return(-1);                         
    }
    symbolFile = _open( str,_O_CREAT|_O_RDWR|_O_BINARY,
                                _S_IREAD|_S_IWRITE);
    if ( symbolFile == -1 ) {
        nErrorNum = 0x4003;
        return -1;
    }               
    buf[0] = 0x0;
    buf[1] = 0x1A;
    memcpy( &buf[2] , &symno , 4 );
    _write( symbolFile , buf , 6 );
    temp = namePtr; 
    num = 0;
    while( temp ) {
        memset( buf , 0 , MAX_USE_DEFINE_SYMBOL_LENGTH+10 );
        i = strlen( temp->name );
        if ( i > MAX_USE_DEFINE_SYMBOL_LENGTH ) {
            memcpy( buf , temp->name , MAX_USE_DEFINE_SYMBOL_LENGTH );
        }
        else {
            strcpy( buf , temp->name );
        }
        memcpy(&buf[MAX_USE_DEFINE_SYMBOL_LENGTH+2] , &temp->type , 1);
        memcpy(&buf[MAX_USE_DEFINE_SYMBOL_LENGTH+3] , &temp->addr , 4);
        _write( symbolFile , buf , MAX_USE_DEFINE_SYMBOL_LENGTH+7 );
        temp = temp->ptr;               
        num++;
    }       
    _close( symbolFile );
    if ( num != symno ) {
        nErrorNum = 0x400A;
        return(-1);
    }
    return 0;       
}

/***************************************************************************
*                                                                          *
*  SymUserSRecall - recall user defined symbol to file                     *
*  parameter :                                                             *
*       str      symbol file name                                          *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
int SymUserTable::SymUserSRecall(char *str)
{
    int symbolFile ;     
    U32 num ;
    U8 t ;
    U32 a ;
    char buf[200];
    
    symbolFile = _open( str,_O_RDONLY|_O_BINARY);
    if ( symbolFile == -1 ) {
        nErrorNum = 0x4003;
        return -1;
    }                          
    if ( _read( symbolFile , buf , 6 ) == -1 ) {
        nErrorNum = 0x4008;
        _close( symbolFile );
        return(-1);
    }
    if ( (buf[0]!=0x0) || (buf[1] != 0x1A) ) {
        nErrorNum = 0x400B;
        _close( symbolFile );
        return(-1);
    }
    memcpy( &num , &buf[2] , 4 );
    while( num > 0 ) {
        if ( _read( symbolFile , buf , MAX_USE_DEFINE_SYMBOL_LENGTH+7 ) == -1 ) {
            nErrorNum = 0x400C;
            _close( symbolFile );
            return(-1);
        }
        memcpy(&t , &buf[MAX_USE_DEFINE_SYMBOL_LENGTH+2] , 1 );
        memcpy(&a , &buf[MAX_USE_DEFINE_SYMBOL_LENGTH+3] , 4 );
        SymUserCreate( buf , t , a );
        num--;
    }       
    _close( symbolFile );
    return 0;       
}

/***************************************************************************
*                                                                          *
*  SymUserQuery - query a symbol to address or from address to name        *
*  parameter :                                                             *
*       str      query information                                         *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
int SymUserTable::SymUserQuery( char *str )
{ 
    char temp[41] , temp1[256];
    U32 addr;        
    U8 addrType;
    int i , j;
               
    j = 0;                
    if (*str == '#') {                     
        i = strlen( str );
        if (i>40) i=40;
        memcpy( temp , str , i );
        temp[i] = '\0'; 
        userSymbols.SymUserSearchNodeByName( temp );
        if ( matchPtr == 0 ) {
            nErrorNum = 0x4005;
            return( -1 );
        }
        else {
            switch( matchPtr->type ) {     
            case MEM_X0:
            sprintf(temp,"     X0:");
            break;
            
            case MEM_X1:
            sprintf(temp,"     X1:");
            break;

            case MEM_X2:
            sprintf(temp,"     X2:");
            break;

            case MEM_X3:
                sprintf(temp1,"     X3:");
                break;
            case MEM_I:
                sprintf(temp1,"     I:");
                break;
//            case 5:
//                sprintf(temp1,"      R:");
//                break;
//            case 6:
//                sprintf(temp1,"      B:");
//                break;
//            case 7:
//                sprintf(temp1,"      S:");
//                break;
            case MEM_P0:
            case MEM_P1:
            case MEM_P2:
            case MEM_P3:
                sprintf(temp1,"     P%d:", (int)(matchPtr->type-1) );  
                break;
            default:
                sprintf(temp1,"     P0:");
                break;
            }
            U16ToStr( matchPtr->addr , &temp1[8] );
            temp1[12] = temp1[13] = ' ';
            strcpy(&temp1[14] , matchPtr->name);
            SymShowLine( temp1 );
            j = 1;
        }
    }
    else {
        StrToU32(addr , str);   
        addrType = 2;
        switch ( str[0] ) {
        case 'X' :
        case 'x' : 
           switch( str[1]-'0')
           {
                case 0: addrType =MEM_X0;break;
                case 1: addrType =MEM_X1;break;
                case 2: addrType =MEM_X2;break;
                case 3: addrType =MEM_X3;break;
           }     
             
            //addrType = 3;
            break;
        case 'I' : 
        case 'i' :
            addrType = MEM_I;//4;
            break;
//        case 'R' :
//        case 'r' :
//            addrType = 5;
//            break;
//        case 'B' :
//        case 'b' :
//            addrType = 6;
//            break;
//        case 'S' :
//        case 's' :
//            addrType = 7;
//            break;
        case 'P' :
        case 'p' :
           switch( str[1]-'0')
           {
                case 0: addrType =MEM_P0;break;
                case 1: addrType =MEM_P1;break;
                case 2: addrType =MEM_P2;break;
                case 3: addrType =MEM_P3;break;
           }     
             
            //addrType = 3;
            break;
        
        default :                   
            addrType = MEM_P0;
            break;
        }
        userSymbols.SymUserSearchNodeByAddr( addr , addrType );
        if ( matchPtr == 0 ) {
            return( -1 );
        }
        else {
            while( matchPtr->addr == addr ) {
                if ( matchPtr->type == addrType ) {
                    sprintf( temp1,"     " );
                    switch( addrType ) {     
                    case MEM_X0://3:             
                        sprintf(temp1,"     X0:");
                        break;
                    case MEM_X1:
                        sprintf(temp1,"     X1:");
                        break;
                    case MEM_X2:
                        sprintf(temp1,"     X2:");
                        break;
                    case MEM_X3:
                        sprintf(temp1,"     X3:");
                        break;
                    case MEM_I://4:
                        sprintf(temp1,"     I:");
                        break;
//                    case 5:
//                        sprintf(temp1,"      R:");
//                        break;
//                    case 6:
//                        sprintf(temp1,"      B:");
//                        break;
//                    case 7:
//                        sprintf(temp1,"      S:");
//                        break;
                    case MEM_P0:
                        sprintf(temp1,"     P0:");                    
                        break;
                    case MEM_P1:
                        sprintf(temp1,"     P1:");                        
                        break ;
                    case MEM_P2:
                        sprintf(temp1,"     P2:");                    
                        break;
                    case MEM_P3:
                        sprintf(temp1,"     P3:");                    
                        break;
                    default:
                        sprintf(temp1,"     P0:");
                        break;
                    }
                    U16ToStr( matchPtr->addr , &temp1[8] );
                    temp1[14] = temp1[15] = ' ';
                    strcpy(&temp1[16] , matchPtr->name);
                    SymShowLine( temp1 );
                    j = 1;
                }
                matchPtr = matchPtr->next;
                if ( matchPtr == 0 ) break;
            }
        }
    }
    if ( j == 0 ) return FAILURE;
    return GOOD;
}   

/***************************************************************************
*                                                                          *
*  SymUserCreate - create a new user defined symbol to table               *
*  parameter :                                                             *
*       str      symbol name                                               *
*       type     symbol type                                               *
*       addr     symbol address                                            *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
int SymUserTable::SymUserCreate(char *str , U8 type , U32 addr)
{
    struct SymUserNode *node;
    int * nn;
    nn= new int;
    node = new SymUserNode;
    ASSERT( node );
    node->name = new char[ strlen( str ) + 1 ];
    ASSERT( node->name );
    strcpy( node->name , str );
    node->type = type;
    node->addr = addr;
    return ( SymUserAddNode( node ) );
}

/***************************************************************************
*                                                                          *
*  SymUserDelete - Delete a user defined symbol in symbol table            *
*  parameter :                                                             *
*       str      symbol name                                               *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
int SymUserTable::SymUserDelete(char *str)
{
    struct SymUserNode *temp , *temp1 , *node;
    struct SymUserNodeIndex *t1 , *t2;
    
    if ( symno == 0 ) {
        nErrorNum = 0x4005;
        return( -1 );      
    }
    if ( symno == 1 ) {
        if ( strcmp(str , namePtr->name) == 0 ) {
            if ( namePtr->name ) delete namePtr->name;
            delete namePtr;
            namePtr = addrPtr = 0;
            delete nameIndexPtr;
            delete addrIndexPtr;
            nameIndexPtr = addrIndexPtr = 0;
            symno = 0;
            return 0;
        }            
        else {
            nErrorNum = 0x4005;
            return (-1);  
        }
    }
        
    temp = temp1 = namePtr;
    t1 = t2 = nameIndexPtr;
    while ( t1 ) {
        if ( strcmp(str,t1->node->name)<=0 ) break;
        t2 = t1;
        t1 = t2->next;
    }
    if ( t1 == nameIndexPtr ) {
        if ( strcmp(str,t1->node->name)!=0 ) {
            nErrorNum = 0x4005;
            return(-1);
        }
        symno--;
        node = namePtr;
        namePtr = namePtr->ptr;
        t1->node = namePtr;
        t1->num--;  
        if ( symno > 10 && t1->num <= 10 ) {
            SymUserRejustNameIndex();
        }
    }     
    else {
        temp1 = temp = t2->node;
        while( temp ) {
            if ( strcmp(str,temp->name)<=0 ) break;
            temp1 = temp;
            temp = temp1->ptr;
        }
        if ( temp == 0 ) {
            nErrorNum = 0x4005;
            return ( -1 );
        }
        else if ( temp == t2->node ) {
            if ( strcmp(str,temp->name)!=0 ) return(-1);
            symno--;
            node = temp;
            temp1 = namePtr;
            while( temp1->ptr != temp ) {
                temp1 = temp1->ptr;
            }
            temp1->ptr = node->ptr;
            t2->num--;             
            t2->node = node->ptr;
            if ( symno > 10 && t2->num <= 10 ) {
                SymUserRejustNameIndex();
            }
        }   
        else {
            if ( strcmp(str,temp->name)!=0 ) return(-1);
            symno--;             
            node = temp;
            temp1->ptr = node->ptr;
            t2->num--;
            if ( symno > 10 && t2->num <= 10 ) {
                SymUserRejustNameIndex();
            }
        }
    }
                    
    temp = temp1 = addrPtr;
    t1 = t2 = addrIndexPtr;
    if ( addrPtr == node ) {
        addrPtr = node->next;
    }
    else {
        while ( temp->next != node ) {
            temp = temp->next;
        }
        temp->next = node->next;
    }
    SymUserRejustAddrIndex();

    if ( node->name ) delete node->name;
    delete node;
    
    return( 0 );
}

/***************************************************************************
*                                                                          *
*  SymUserSearchNodeByName - Search a symbol node by name in symbol table  *
*  parameter :                                                             *
*       str      symbol name                                               *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
void SymUserTable::SymUserSearchNodeByName( char *str )
{
    struct SymUserNode *temp , *temp1;
    struct SymUserNodeIndex *t1 , *t2;
        
    matchPtr = preMatchPtr = 0;
            
    if ( namePtr == 0 ) return;
    temp = temp1 = namePtr;
    t1 = t2 = nameIndexPtr;
    while ( t1 ) {
        if ( strcmp(str,t1->node->name)<=0 ) break;
        t2 = t1;
        t1 = t2->next;
    }
    temp1 = temp = t2->node;
    while( temp ) {
        if ( strcmp(str,temp->name)<=0 ) break;
        temp1 = temp;
        temp = temp1->ptr;
    }
    if ( temp == 0 ) return;
    if ( strcmp(str,temp->name)!=0 ) return;
    preMatchPtr = temp1;
    matchPtr = temp;
}

/***************************************************************************
*                                                                          *
*  SymUserSearchNodeByAddr - Search a symbol node by address               *
*  parameter :                                                             *
*       addr       symbol address                                          *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
void SymUserTable::SymUserSearchNodeByAddr( U32 addr , U8 type )
{
    struct SymUserNode *temp , *temp1;
    struct SymUserNodeIndex *t1 , *t2;
        
    matchPtr = preMatchPtr = 0;
            
    if ( addrPtr == 0 ) return ;
    temp = temp1 = addrPtr;
    t1 = t2 = addrIndexPtr;
    while ( t1 ) {
        if ( addr<=t1->node->addr ) break;
        t2 = t1;
        t1 = t2->next;
    }
    temp1 = temp = t2->node;
    while( temp ) {
        if ( addr<=temp->addr ) break;
        temp1 = temp;
        temp = temp1->next;
    }
    if ( temp == 0 ) return;
    if ( addr != temp->addr ) return;
    preMatchPtr = temp1;
    matchPtr = temp; 
    while ( matchPtr ) {
        if ( addr != matchPtr->addr ) break;
        if ( type == matchPtr->type ) return;
        preMatchPtr = matchPtr;
        matchPtr = preMatchPtr->next;
    }
    matchPtr = preMatchPtr = 0;
}
            
void SymUserTable::SymUserRejustNameIndex(void)
{
    int i;
    struct SymUserNode *temp1;
    struct SymUserNodeIndex *t1 , *t2;

    t1 = nameIndexPtr; 
    nameIndexPtr->node = namePtr;
    temp1 = namePtr;
    while( 1 ) {
        i = 0; 
        while ( temp1 && ( i < 20 ) ) {
            i++;
            temp1 = temp1->ptr;
        }
        t1->num = i;
        if ( temp1 == 0 ) break;
        if ( t1->next ) {
            t1 = t1->next;
            t1->node = temp1;
        }
        else {
            t1->next = new SymUserNodeIndex;
            ASSERT ( t1->next );
            t1 = t1->next;
            t1->node = temp1;
        }
    }
    if ( t1->next ) {
        t2 = t1->next;
        t1->next = 0;
        while( t2 ) {
            t1 = t2->next;
            delete t2;
            t2 = t1;
        }
    }
}   

void SymUserTable::SymUserRejustAddrIndex(void)
{
    int i;
    struct SymUserNode *temp1;
    struct SymUserNodeIndex *t1 , *t2;

    t1 = addrIndexPtr;           
    addrIndexPtr->node = addrPtr;
    temp1 = addrPtr;
    while( 1 ) {
        i = 0; 
        while ( temp1 && ( i < 20 ) ) {
            i++;
            temp1 = temp1->next;
        }
        t1->num = i;
        if ( temp1 == 0 ) break;
        if ( t1->next ) {
            t1 = t1->next;
            t1->node = temp1;
        }
        else {
            t1->next = new SymUserNodeIndex;
            ASSERT ( t1->next );
            t1 = t1->next;
            t1->node = temp1;
        }
    }
    if ( t1->next ) {
        t2 = t1->next;
        t1->next = 0;
        while( t2 ) {
            t1 = t2->next;
            delete t2;
            t2 = t1;
        }
    }
}   

/***************************************************************************
*                                                                          *
*  SymUserAddNode - Add a new user defined symbol to table                 *
*  parameter :                                                             *
*       node     the node which will be added                              *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
int SymUserTable::SymUserAddNode( struct SymUserNode *node )
{           
//  int i;
    struct SymUserNode *temp , *temp1;
    struct SymUserNodeIndex *t1 , *t2;
    
    
    if ( namePtr == 0 ) {
        addrPtr = namePtr = node;
        addrIndexPtr = new SymUserNodeIndex;
        nameIndexPtr = new SymUserNodeIndex;
        ASSERT( addrIndexPtr );
        ASSERT( nameIndexPtr );
        addrIndexPtr->node = addrPtr;
        addrIndexPtr->num = 1;
        nameIndexPtr->node = namePtr;
        nameIndexPtr->num = 1;
        symno++;
        return( 0 );        
    }
    temp = temp1 = namePtr;
    t1 = t2 = nameIndexPtr;
    while ( t1 ) {
        if ( strcmp(node->name,t1->node->name)<=0 ) break;
        t2 = t1;
        t1 = t2->next;
    }
    if ( t1 == nameIndexPtr ) {
        if ( strcmp(node->name,t1->node->name)==0 ) {
            nErrorNum = 0x4004;
            return(-1);
        }
        symno++;
        node->ptr = namePtr;
        namePtr = node;
        t1->node = node;
        t1->num++;  
        if ( symno > 20 && t1->num > 30 ) {
            SymUserRejustNameIndex();
        }
    }     
    else {
        temp1 = temp = t2->node;
        while( temp ) {
            if ( strcmp(node->name,temp->name)<=0 ) break;
            temp1 = temp;
            temp = temp1->ptr;
        }
        if ( temp == 0 ) {
            symno++;
            temp1->ptr = node;
            t2->num++; 
            if ( symno > 20 && t2->num > 30 ) {
                SymUserRejustNameIndex();
            }
        }
        else {
            if ( strcmp(node->name,temp->name)==0 ) {
                nErrorNum = 0x4004;
                return(-1);   
            }
            symno++;
            node->ptr = temp1->ptr;
            temp1->ptr = node;
            t2->num++;
            if ( symno > 20 && t2->num > 30 ) {
                SymUserRejustNameIndex();
            }
        }
    }               
    
    temp = temp1 = addrPtr;
    t1 = t2 = addrIndexPtr;
    while ( t1 ) {
        if ( node->addr <= t1->node->addr ) break;
        t2 = t1;
        t1 = t2->next;
    }
    if ( t1 == addrIndexPtr ) {
        node->next = addrPtr;
        addrPtr = node;
        t1->node = node;
        t1->num++;  
        if ( symno > 20 && t1->num > 30 ) {
            SymUserRejustAddrIndex();
        }
    }     
    else {
        temp1 = temp = t2->node;
        while( temp ) {
            if ( node->addr <= temp->addr ) break;
            temp1 = temp;
            temp = temp1->next;
        }
        if ( temp == 0 ) {
            temp1->next = node;
            t2->num++; 
            if ( symno > 20 && t2->num > 30 ) {
                SymUserRejustAddrIndex();
            }
        }
        else {
            node->next = temp1->next;
            temp1->next = node;
            t2->num++;
            if ( symno > 20 && t2->num > 30 ) {
                SymUserRejustAddrIndex();
            }
        }
    }               
    return(0);
}                             
              
int SymUserTable::SymUserList( void )
{
    char temp[255];
    struct SymUserNode *tt;
    int i;
    
    sprintf(temp , "User defined symbols : %d" , symno);
    SymShowLine( temp );
    if ( symno == 0 ) return 0;
    tt = namePtr ;
    while ( tt ) {
        i = strlen( tt->name );
        switch( tt->type ) {     
        case MEM_X0: 
            sprintf(temp,"     X0:");
            break;
        case MEM_X1:
            sprintf(temp,"     X1:");
            break;
        case MEM_X2:
            sprintf(temp,"     X2:");
            break;
        case MEM_X3:
            sprintf(temp,"     X3:");
            break;
        case MEM_I:
            sprintf(temp,"     I:");
            break;
//        case 5:
//            sprintf(temp,"      R:");
//            break;
//        case 6:
//            sprintf(temp,"      B:");
//            break;
//        case 7:
//            sprintf(temp,"      S:");
//            break;
        case MEM_P0    :
        case MEM_P1    :
        case MEM_P2    :
        case MEM_P3    :
            sprintf(temp,"     P%d:",(int)(tt->type-1));
            break;
        default:
            sprintf(temp,"     P0:");
            break;
        }
//      sprintf(temp,"     ");
        U16ToStr( tt->addr , &temp[8] );
        temp[12] = temp[13] = ' ';
        strcpy(&temp[14] , tt->name);
        SymShowLine( temp );
        tt = tt->ptr;
    }
    return(0);
}
              
void SymUserTable::SymUserClearUpNode()
{                         
    struct SymUserNode *temp , *temp1;
    
    temp = addrPtr;
    while ( temp ) {
        if ( temp->name ) delete temp->name;
        temp1 = temp->next;
        delete temp;
        temp = temp1;
    }                   
    addrPtr = 0;
    namePtr = 0;
    symno = 0;
    matchPtr = 0;
    preMatchPtr = 0;
}

void SymUserTable::SymUserClearUpIndex()
{    
    struct SymUserNodeIndex *temp , *temp1;
    
    temp = addrIndexPtr;
    while ( temp ) {
        temp1 = temp->next;
        delete temp;
        temp = temp1;
    }
    temp = nameIndexPtr;
    while ( temp ) {
        temp1 = temp->next;
        delete temp;
        temp = temp1;
    }           
    addrIndexPtr = nameIndexPtr = 0;
}

SymUserTable::~SymUserTable()
{
    SymUserClearUpNode();
    SymUserClearUpIndex();
}

void SymUserTable::SymUserDeleteAll(void)
{
    SymUserClearUpNode();
    SymUserClearUpIndex();
}
 
void U24ToStr(U32 ui , char *tt)
{
    sprintf(tt,"%06lX" ,ui);
}   

void U16ToStr(U16 ui , char *tt)
{
    sprintf(tt, "%04X",ui);
/*
    U16 u;
    int i;
    
    u = ui;
    for( i = 0; i < 4; i++ ) {
        if ( (u&0x000F) < 10 ) {
            tt[3-i] = (char)( '0' + (char)(u&0x000F) );
        }
        else {
            tt[3-i] = (char)( 'A' + (char)((u&0x000F) - 10) );
        }  
        u = (U16) u>>4;
    }
*/

}   

void U8ToStr(U8 ui , char *tt)
{
    U8 u;
    int i;
    
    u = ui;    
    for( i = 0; i < 2; i++ ) {
        if ( (u&0x0F) < 10 ) {
            tt[1-i] = (char)( '0' + (char)(u&0x0F) );
        }
        else {
            tt[1-i] = (char)( 'A' + (char)((u&0x0F)-10) );
        }  
        u = (U8) (u>>4);
    }
}   
    
void StrToU32(U32& ul , char *tt)
{   
    char *s , c ,c1;
    
    ul = 0;       
    s = tt;
    
    if ( *tt != '\0' ) {    
//        if ( *tt == 'b' || *tt == 'B' ) {
        if ( *tt == 'p' || *tt == 'P' ) {
            ASSERT(*(tt+1) !=0 );
            if ( *(tt+1) != '\0' ) {
                if ( *(tt+2) == ':' ) {
                    s += 3;
                    c1 = *(tt+1);
                    if ( c1 > '3' || c1 < '0' ) return;
//                    c1 -= '1';
                    c1 -= '0';
                    while( *s != '\0' ) {
                        ul = (U32) ul<<4;
                        c = *s;
                        if ( (c>='0')&&(c<='9') ) c -= '0';
                        else if ( (c>='A')&&(c<='F') ) c = (char)(c-'A'+10);
                        else if ( (c>='a')&&(c<='f') ) c = (char)(c-'a'+10);
                        else c = 0;
                        ul += (U32)c;      
                        s++;
                    }         
                    ul = ( ul & 0x0FFFFL ) | ( ((U32)c1) << 16 );

                    return;
                }                   
                else if ( *(tt+1) == ':' ) s += 2;
            }
        }
        else if ( *(tt+1) == ':' ) s += 2;
    }
    while( *s != '\0' ) {
        ul = (U32) ul<<4;
        c = *s;
        if ( (c>='0')&&(c<='9') ) c -= '0';
        else if ( (c>='A')&&(c<='F') ) c = (char)(c-'A'+10);
        else if ( (c>='a')&&(c<='f') ) c = (char)(c-'a'+10);
        else c = 0;
        ul += (U32)c;      
        s++;
    }
}

void changeN(char *uc ,char *result, int n)
{
    int i,j,k;

    for( i = 0; i < n;i++) {
        j = (uc[i]&0x00FF)>>4;
        k = uc[i]&0x000F;
        if( j < 10 ) result[2*i] = (char)('0'+j);
        else result[2*i] = (char)('A'+j-10);
        if( k < 10 ) result[2*i+1] = (char)('0'+k);
        else result[2*i+1] = (char)('A'+k-10);
    }
}

/***************************************************************************
*                                                                          *
*  displayPC - display pc value string                                     *
*  parameter :                                                             *
*       addr  ----     pc value                                            *
*  return value :                                                          *
*       NONE                                                               *
*                                                                          *
***************************************************************************/
void showPC(U32 addr)
{
    char tempStr[100];
    int l , i , j;

    sprintf(tempStr , "Upload file : ");
    l = strlen(tempStr);
    for( i=0; i < 6;i++) {
        j = addr & 0x000F;
        if ( j < 10 ) tempStr[5-i+l] = (char) ('0' + j);
        else tempStr[5-i+l] = (char) ('A' + j - 10);
        addr = addr >> 4;
    }
    tempStr[6+l] = '\0';                         

   SymShlReshowLine(tempStr , 6+l);
}        /* end of showPC() */

void prn_err( int num ) 
{
//    CString strErr;

    if ( num > 0x4000 ) {
        num -= 0x4000;
//        ShowLine(strErrMsg[num]);
//        ShowLine("Load Failure!");
       SymShowLine("print error!");
/*        
        if ( GOOD == ErrGetErrorText((U32)num, strErr) ) {
            ShowLine(strErr.GetBuffer( strErr.GetLength() ) );
        }
*/        
        nErrorNum = 0;                         
    }
}    

/*
void win_err( int num ) 
{
    if ( num > 0x4000 ) {
        num -= 0x4000;
//        AfxMessageBox(strErrMsg[num]);
        AfxMessageBox("Load Failure!");
        nErrorNum = 0;                         
    }
}
*/
/******************************** E O F ***********************************/
