
/***************************************************************************
**
**    $Header:   D:/ECB2S/SRC/LOG/MEMCOMP.CPP   1.2.1.4   17 Apr 1997 15:56:14   ZJRD  $
**
**    $Log:   D:/ECB2S/SRC/LOG/MEMCOMP.CPP  $
** 
**    Rev 1.2.1.4   17 Apr 1997 15:56:14   ZJRD
** No change.
** 
**    Rev 1.2.1.3   16 Apr 1997 10:27:26   ZJRD
** No change.
** 
**    Rev 1.2.1.2   10 Apr 1997 15:38:02   ZJRD
** No change.
** 
**    Rev 1.2.1.1   03 Apr 1997 15:17:14   ZJRD
** No change.
** 
**    Rev 1.2.1.0   28 Mar 1997 10:22:16   ZJRD
** easy pack sld 2.09d
** 
**    Rev 1.1   19 Mar 1997 11:32:22   ZJRD
** No change.
** 
**    Rev 1.0   12 Mar 1997 14:47:56   ZJRD
** Initial revision.
** 
**    Rev 1.7.1.0.1.2   09 Dec 1996 10:14:12   ZJRD
** EasyPack/SLD Version 2.0P
** 
**    Rev 1.7.1.0.1.0   11 Nov 1996 12:57:28   ZJRD
** EasyPack/SLD Version 2.01
** 
**    Rev 1.7.1.4   09 Sep 1996 13:13:32   ZJRD
** No change.
** 
**    Rev 1.7.1.3   05 Sep 1996 11:25:04   ZJRD
** No change.
** 
**    Rev 1.7.1.2   02 Sep 1996 09:52:12   ZJRD
** No change.
** 
**    Rev 1.7.1.1   28 Aug 1996 15:44:38   ZJRD
** No change.
** 
**    Rev 1.7.1.0   12 Aug 1996 10:49:56   ZJRD
** EasyPack/SLD Version 1.98
** 
**    Rev 1.5   05 Jun 1996 14:52:04   ZJRD
** EasyPack/SLD Version 1.96
** 
**    Rev 1.4   29 May 1996 09:28:06   ZJRD
** No change.
** 
**    Rev 1.3   16 May 1996 09:08:28   ZJRD
** No change.
** 
**    Rev 1.2   10 May 1996 09:08:58   ZJRD
** EasyPack/SLD Version 1.93
** 
**    Rev 1.1   02 May 1996 10:24:54   ZJRD
** EasyPack/SLD Version 1.92
** 
**    Rev 1.31   18 Apr 1996 13:00:38   Shirley
** No change.
** 
**    Rev 1.30   12 Apr 1996 10:37:40   Shirley
** EasyPack/SLD Version 1.90
** 
**    Rev 1.28   15 Feb 1996 08:52:12   Shirley
** No change.
** 
**    Rev 1.27   12 Feb 1996 14:06:44   Shirley
** No change.
** 
**    Rev 1.26   06 Feb 1996 15:33:12   Shirley
** No change.
** 
**    Rev 1.25   06 Feb 1996 13:48:08   Shirley
** No change.
** 
**    Rev 1.24   01 Feb 1996 10:12:28   Shirley
** No change.
** 
**    Rev 1.23   26 Jan 1996 09:12:12   Shirley
** No change.
** 
**    Rev 1.22   25 Jan 1996 13:12:52   Shirley
** No change.
** 
**    Rev 1.21   24 Jan 1996 10:36:28   Shirley
** No change.
** 
**    Rev 1.20   23 Jan 1996 11:24:54   Shirley
** No change.
** 
**    Rev 1.19   18 Jan 1996 10:09:16   Shirley
** No change.
** 
**    Rev 1.18   15 Jan 1996 16:12:16   Shirley
** No change.
** 
**    Rev 1.17   04 Jan 1996 11:14:46   Shirley
** No change.
** 
**    Rev 1.16   30 Nov 1995 09:09:58   Shirley
** No change.
** 
**    Rev 1.15   28 Nov 1995 15:30:48   Shirley
** No change.
** 
**    Rev 1.14   21 Nov 1995 11:23:52   Shirley
** No change.
** 
**    Rev 1.13   13 Nov 1995 09:26:14   Shirley
** No change.
** 
**    Rev 1.12   12 Nov 1995 11:30:22   Shirley
** No change.
** 
**    Rev 1.11   08 Nov 1995 16:33:36   Shirley
** No change.
** 
**    Rev 1.10   08 Nov 1995 12:43:18   Shirley
** EasyPack/SLD Version 0.22
** 
**    Rev 1.9   02 Nov 1995 10:05:22   Shirley
** No change.
** 
**    Rev 1.8   27 Oct 1995 16:49:28   Shirley
** No change.
** 
**    Rev 1.7   27 Oct 1995 13:48:52   Shirley
** No change.
** 
**    Rev 1.6   25 Oct 1995 14:28:28   Shirley
** No change.
** 
**    Rev 1.5   18 Oct 1995 14:52:40   Shirley
** No change.
** 
**    Rev 1.4   13 Oct 1995 13:20:36   Shirley
** EasyPack/SLD Version 0.1d
** 
**    Rev 1.3   29 Sep 1995 09:52:24   Shirley
** No change.
** 
**    Rev 1.2   20 Sep 1995 10:55:42   Shirley
** EasyPack/SLD Version 0.1b
** 
**    Rev 1.1   15 Sep 1995 09:45:52   Shirley
** No change.
** 
**    Rev 1.0   07 Sep 1995 09:54:44   Shirley
** Initial revision.
**
****************************************************************************/

/////////////////////////////////////////////////////////////////////////////
//
//  File name: MEMCOMP.CPP
//
//  Description: The implementation file for the class: CMemoryCompare.
//
//  Author: Chen Jun
//
//  Date: 04/29/95
//
//  Modification:
//      1. 04/29/95, Initial version of the class: CMemoryCompare.
//
/////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////
// Include files.
#include "stdafx.h"
#include "resource.h"

#include "memcomp.h"
#include "uicom.h"
#include "hosterrs.h"
extern RETCODE EXPORT ErrGetErrorText(U32 errorCode, LPSTR lpszError ...);
extern RETCODE EXPORT ErrGetErrorText(U32 errorCode, CString& strError ...);


/////////////////////////////////////////////////////////////////////////////
// Debug flags.
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif


/////////////////////////////////////////////////////////////////////////////
// Type definitions.


/////////////////////////////////////////////////////////////////////////////
// Macro definitions.


/////////////////////////////////////////////////////////////////////////////
// Global variables.


/////////////////////////////////////////////////////////////////////////////
// Static variables.


/////////////////////////////////////////////////////////////////////////////
// External variables.


/////////////////////////////////////////////////////////////////////////////
// Global function prototypes.
void CompareCmd(int nArgc, char* pszArgv[]);
BOOL MemServerCompare(ADDRESS Start, ADDRESS End,ADDRESS Target,
    	ADDRESS& Source, char* pszResult);


/////////////////////////////////////////////////////////////////////////////
// Local function prototypes.


/////////////////////////////////////////////////////////////////////////////
// External function prototypes.
#ifndef _SERVER_NO_ABI
    extern STATUS AbiCompare(ADDR addr1, ADDR addr2, ADDR destAddr,
                             ADDR* retAddr);
    extern STATUS AbiGetMemN(ADDR addr1, ADDR addr2, char* pchBuff);
#endif  // _SERVER_NO_ABI
extern BOOL GetCpuStatus(unsigned char &);
extern void ShowLine(char *);


/////////////////////////////////////////////////////////////////////////////
// Executable codes.

/////////////////////////////////////////////////////////////////////////////
// Public functions.

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   CompareCmd().
//
//  Description: The main control routine of Compare command.
//
//  Input:  nArgc - Number of input parameters.
//          pszArgv - Input parameters.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
void CompareCmd(int nArgc, char* pszArgv[])
{
    // Assertion of the input parameters.
    ASSERT( 4 == nArgc || 5 == nArgc );
    for ( int i = 0; i < nArgc; i++ ) {
        ASSERT( pszArgv[i] );
    }
    
    char error[128];
    // Compare EMM contents.
    CMemoryCompare* pMemoryCompare = new CMemoryCompare;
    if ( !pMemoryCompare ) {
        AfxMessageBox("Insufficient Memory !");
        ASSERT( FALSE );
        return;
    }
    else {
       unsigned char result;         
       if ( ::GetCpuStatus(result) ) {
          if ( 1/*STATUS_GO*/ == result ) {
            //::ShowLine ("EP running. Stop EP first");
            ::ErrGetErrorText(ER_GOFLY_ERR_MSG, error);
            ::ShowLine (error);
          }    
          else {
            pMemoryCompare->CompareAction(nArgc, pszArgv);
            delete pMemoryCompare;
          }           
       }   
    }

//    CMemoryCompare objCompare;
//    objCompare.MemoryCompare(nArgc, pszArgv);

}   // End of CompareCmd().


// Memory Compare server.
BOOL MemServerCompare(ADDRESS Start, ADDRESS End,ADDRESS Target,
    	ADDRESS& Source, char* pszResult)
{
    // Assertion of the input parameters.
    ASSERT( pszResult );

    // Compare EMM contents.
    CMemoryCompare* pMemoryCompare = new CMemoryCompare;
    if ( !pMemoryCompare ) {
        AfxMessageBox("Insufficient Memory !");
        ASSERT( FALSE );
        return (FALSE);
    }
    else {
        BOOL isMismatch =
            pMemoryCompare->MemServerCompare(Start, End, Target, 
                Source, pszResult);
        delete pMemoryCompare;
        return (isMismatch);
    }

}   // End of MemServerCompare().



/////////////////////////////////////////////////////////////////////////////
// Implementation codes of class: CMemoryCompare.

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   CMemoryCompare::CMemoryCompare().
//
//  Description: The construction of the class: CMemoryCompare.
//
//  Input:  None.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
CMemoryCompare::CMemoryCompare()
{

}   // End of CMemoryCompare::CMemoryCompare().


/////////////////////////////////////////////////////////////////////////////
//
//  Name:   CMemoryCompare::~CMemoryCompare().
//
//  Description: The destruction of the class: CMemoryCompare.
//
//  Input:  None.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
CMemoryCompare::~CMemoryCompare()
{

}   // End of CMemoryCompare::~CMemoryCompare().



/////////////////////////////////////////////////////////////////////////////
//
//  Name:   CMemoryCompare::CompareAction().
//
//  Description: Compare EMM.
//
//  Input:  None.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
void CMemoryCompare::CompareAction(int nArgc, char* pszArgv[])
{
    // Assertion of the input parameters.
    BOOL endSpace;
    ASSERT( 4 == nArgc || 5 == nArgc );
    for ( int i = 0; i < nArgc; i++ ) {
        ASSERT( pszArgv[i] );
    }
    
    // Set Start address & End address.
    if ( 4 == nArgc ) {
        // Compare adr1 adr2 adr3.
        endSpace=!( ':' != pszArgv[2][1] && ':' != pszArgv[2][2] );
        SetAddrVar(pszArgv[1], m_StartAddr);
        SetAddrVar(pszArgv[2], m_EndAddr);
        SetAddrVar(pszArgv[3], m_TargetAddr);
        if ( ':' != pszArgv[3][1] && ':' != pszArgv[3][2] ) {
            if ( ':' != pszArgv[1][1] && ':' != pszArgv[1][2] ) {
                m_TargetAddr.m_uchType = MEM_EXTERNAL;
            }
            else {
                m_TargetAddr.m_uchType = m_StartAddr.m_uchType;
            }
        }
    }
    else if ( 5 == nArgc ) {
        // Compare adr1 Length length adr3.
        endSpace=TRUE;
        SetAddrVar(pszArgv[1], m_StartAddr);
        SetAddrVar(pszArgv[1], pszArgv[3], m_EndAddr);
        SetAddrVar(pszArgv[4], m_TargetAddr);
        if ( ':' != pszArgv[4][1] && ':' != pszArgv[4][2] ) {
            if ( ':' != pszArgv[1][1] && ':' != pszArgv[1][2] ) {
                m_TargetAddr.m_uchType = MEM_EXTERNAL;
            }
            else {
                m_TargetAddr.m_uchType = m_StartAddr.m_uchType;
            }
        }
    }
    else {
        ASSERT( FALSE );
        return;
    }
    
    // Set the default memory space.
    if ( ':' != pszArgv[1][1] && ':' != pszArgv[1][2] ) {
        m_StartAddr.m_uchType = MEM_EXTERNAL;
    }
    if(!endSpace)
    	m_EndAddr.m_uchType = m_StartAddr.m_uchType;
    
    // Memory Compare kernel routine.
    MemoryCompareKernel();
        
}   // End of CMemoryCompare::CompareAction().


void CMemoryCompare::MemoryCompareKernel(void)
{
    // Assertion of the input parameters.
    
    // Call Abi routine.
    m_nErrorID = MyAbiCompare((ADDR&) m_StartAddr, (ADDR&) m_EndAddr,
                            (ADDR&) m_TargetAddr, &(ADDR&) m_SrcAddr);
//	if(g_nBankNum)
//		m_SrcAddr.m_uchType+=5;
    if ( 5 == m_nErrorID ) {
        // No difference.
        ShowLine("No different data.");
        m_bServerRet = FALSE;
    }
    else if ( 6 == m_nErrorID ) {
        // Display difference.
        DisplayDifferent();
        m_bServerRet = TRUE;
    }
    else if ( 0 != m_nErrorID ) {
        // Display error message.
        DisplayErrorMessage();
        m_bServerRet = FALSE;
    }
    else {
        m_bServerRet = FALSE;
        ASSERT( FALSE );
    }
        
}   // End of CMemoryCompare::MemoryCompareKernel().


void CMemoryCompare::DisplayDifferent(void)
{
    // Assertion of the input parameters.
    
    // Format result string.
    m_DestAddr = m_TargetAddr + (m_SrcAddr - m_StartAddr);
    char pszData[20];
    strcpy(m_pszResult, "Different data at: ");
    if ( !GetDiffCell(m_SrcAddr, pszData) ) {
        DisplayErrorMessage();
        return;
    }
    else {
        char chType[3];
        switch ( m_SrcAddr.m_uchType ) {
            case MEM_PROGRAM:
                chType[0] = 'P';
                chType[1] = NULL;
                break;
            case MEM_EXTERNAL:
                chType[0] = 'X';
                chType[1] = NULL;
                break;
            case MEM_INTERNAL:
                chType[0] = 'I';
                chType[1] = NULL;
                break;
            case MEM_SFR:
                chType[0] = 'R';
                chType[1] = NULL;
                break;
            case MEM_BIT:
                chType[0] = 'B';
                chType[1] = NULL;
                break;
            case MEM_BANK1:
                chType[0] = 'P';
                chType[1] = '0';
                chType[2] = NULL;
                break;
            case MEM_BANK2:
                chType[0] = 'P';
                chType[1] = '1';
                chType[2] = NULL;
                break;
            case MEM_BANK3:
                chType[0] = 'P';
                chType[1] = '2';
                chType[2] = NULL;
                break;
            case MEM_BANK4:
                chType[0] = 'P';
                chType[1] = '3';
                chType[2] = NULL;
                break;
            default:
                ASSERT( FALSE );
                break;
        }
        wsprintf(pszData, "( %s:%04X ) = %02X,  ", 
                    chType, m_SrcAddr.m_uAddr, (unsigned char)pszData[0]);
        strcat(m_pszResult, pszData);
    }
        
    if ( !GetDiffCell(m_DestAddr, pszData) ) {
        DisplayErrorMessage();
        return;
    }
    else {
        char chType[3];
        switch ( m_DestAddr.m_uchType ) {
            case MEM_PROGRAM:
                chType[0] = 'P';
                chType[1] = NULL;
                break;
            case MEM_EXTERNAL:
                chType[0] = 'X';
                chType[1] = NULL;
                break;
            case MEM_INTERNAL:
                chType[0] = 'I';
                chType[1] = NULL;
                break;
            case MEM_SFR:
                chType[0] = 'R';
                chType[1] = NULL;
                break;
            case MEM_BIT:
                chType[0] = 'B';
                chType[1] = NULL;
                break;
            case MEM_BANK1:
                chType[0] = 'P';
                chType[1] = '0';
                chType[2] = NULL;
                break;
            case MEM_BANK2:
                chType[0] = 'P';
                chType[1] = '1';
                chType[2] = NULL;
                break;
            case MEM_BANK3:
                chType[0] = 'P';
                chType[1] = '2';
                chType[2] = NULL;
                break;
            case MEM_BANK4:
                chType[0] = 'P';
                chType[1] = '3';
                chType[2] = NULL;
                break;
            default:
                ASSERT( FALSE );
                break;
        }
        wsprintf(pszData, "( %s:%04X ) = %02X", 
                    chType, m_DestAddr.m_uAddr, (unsigned char)pszData[0]);
        strcat(m_pszResult, pszData);
    }
    
    // Display the Compare result.
    ShowLine(m_pszResult);

}   // End of CMemoryCompare::DisplayDifferent().


BOOL CMemoryCompare::GetDiffCell(CMemoryAddr DiffAddr, char* pszData)
{
    // Assertion of the input parameters.
    ASSERT( pszData );
    
    // Call Abi routine.
    m_nErrorID = AbiGetMemN((ADDR&) DiffAddr, (ADDR&) DiffAddr, pszData);
    if ( 0 != m_nErrorID ) {
        return (FALSE);
    }
        
    return (TRUE);

}   // End of CMemoryCompare::GetDiffCell().

STATUS CMemoryCompare::MyAbiCompare(ADDR addr1, ADDR addr2, ADDR destAddr,
                             ADDR* retAddr)
{
	if(addr1.addrType==addr2.addrType)
		return My2AbiCompare(addr1, addr2, destAddr,retAddr);

ADDR tmpAddr;
STATUS retAbi;
DWORD len;

	ASSERT(addr1.addrType<addr2.addrType);
	while(addr1.addrType<=addr2.addrType)
	{
		tmpAddr.addrType=addr1.addrType;
		if(addr1.addrType!=addr2.addrType)
			tmpAddr.addr=0xffff;
		else
			tmpAddr.addr=addr2.addr;
		len=DWORD(tmpAddr.addr)-addr1.addr+1;
		retAbi=My2AbiCompare(addr1, tmpAddr, destAddr,retAddr);
		if(retAbi!=5)
			return retAbi;
		//not found:
		addr1.addrType++;
		addr1.addr=0;
		if(destAddr.addr+len>0xffff)
			destAddr.addrType++;
		destAddr.addr=WORD(destAddr.addr+len);
	}
	return retAbi;
}

STATUS CMemoryCompare::My2AbiCompare(ADDR addr1, ADDR addr2, ADDR destAddr,
							ADDR* retAddr)
{
	ASSERT(addr1.addrType==addr2.addrType);
	ASSERT(addr1.addr<=addr2.addr);

DWORD len=DWORD(addr2.addr)-addr1.addr+1;
ADDR tmpAddr;
STATUS retAbi;

	if(destAddr.addr+len-1<=0xffff)
		return AbiCompare(addr1, addr2, destAddr, retAddr);
	tmpAddr.addrType=addr1.addrType;
	tmpAddr.addr=addr1.addr+0xffff-destAddr.addr;
	retAbi=AbiCompare(addr1, tmpAddr, destAddr, retAddr);
	if(retAbi!=5)
		return retAbi;
	//not found:
	tmpAddr.addr++;
	destAddr.addrType++;
	destAddr.addr=0;
	return AbiCompare(tmpAddr, addr2, destAddr, retAddr);
}

BOOL CMemoryCompare::MemServerCompare(ADDRESS Start, ADDRESS End,
		ADDRESS Target, ADDRESS& Source, char* pszResult)
{
    // Assertion of the input parameters.

    // Set the server flag.
    m_isServer = TRUE;
        
    // Set the parameters.
    m_StartAddr = CMemoryAddr(Start);
    m_EndAddr = CMemoryAddr(End);
    m_TargetAddr = CMemoryAddr(Target);
    
    // Memory Compare kernel routine.
    MemoryCompareKernel();
    if ( m_bServerRet ) {
        strcpy(pszResult, m_pszResult);
        Source.adrAddress = m_SrcAddr.m_uAddr;
        Source.adrSpace = (::ADDR_SPACE)m_SrcAddr.m_uchType;
    }
    return (m_bServerRet);

}   // End of CMemoryCompare::MemServerCompare().

//////////////////////////////// End of File ////////////////////////////////
