
/***************************************************************************
**
**    $Header:   D:/EPSLDV1/SRC/LOG/MEMDUMP.CPP   1.8   20 Jun 1996 09:30:38   ZJRD  $
**
**    $Log:   D:/EPSLDV1/SRC/LOG/MEMDUMP.CPP  $
** 
**    Rev 1.8   20 Jun 1996 09:30:38   ZJRD
** EasyPack/SLD Version 1.20a
** 
**    Rev 1.6   10 Jun 1996 10:25:16   ZJRD
** EasyPack/SLD Version 1.20
** 
**    Rev 1.4   29 May 1996 09:38:08   ZJRD
** No change.
** 
**    Rev 1.3   16 May 1996 09:00:26   ZJRD
** No change.
** 
**    Rev 1.2   10 May 1996 09:14:52   ZJRD
** EasyPack/SLD Version 1.93
** 
**    Rev 1.1   02 May 1996 10:22:44   ZJRD
** EasyPack/SLD Version 1.92
** 
**    Rev 1.31   18 Apr 1996 13:02:28   Shirley
** No change.
** 
**    Rev 1.30   12 Apr 1996 10:41:22   Shirley
** EasyPack/SLD Version 1.90
** 
**    Rev 1.28   15 Feb 1996 08:56:20   Shirley
** No change.
** 
**    Rev 1.27   12 Feb 1996 14:07:38   Shirley
** No change.
** 
**    Rev 1.26   06 Feb 1996 15:34:06   Shirley
** No change.
** 
**    Rev 1.25   06 Feb 1996 13:48:00   Shirley
** No change.
** 
**    Rev 1.24   01 Feb 1996 10:19:16   Shirley
** No change.
** 
**    Rev 1.23   26 Jan 1996 09:14:26   Shirley
** No change.
** 
**    Rev 1.22   25 Jan 1996 13:14:20   Shirley
** No change.
** 
**    Rev 1.21   24 Jan 1996 10:33:14   Shirley
** No change.
** 
**    Rev 1.20   23 Jan 1996 11:27:00   Shirley
** No change.
** 
**    Rev 1.19   18 Jan 1996 10:11:48   Shirley
** No change.
** 
**    Rev 1.18   15 Jan 1996 16:14:04   Shirley
** No change.
** 
**    Rev 1.17   04 Jan 1996 11:12:52   Shirley
** No change.
** 
**    Rev 1.16   30 Nov 1995 09:12:10   Shirley
** No change.
** 
**    Rev 1.15   28 Nov 1995 15:34:12   Shirley
** No change.
** 
**    Rev 1.14   21 Nov 1995 11:21:54   Shirley
** No change.
** 
**    Rev 1.13   13 Nov 1995 09:23:34   Shirley
** No change.
** 
**    Rev 1.12   12 Nov 1995 11:34:28   Shirley
** No change.
** 
**    Rev 1.11   08 Nov 1995 16:32:26   Shirley
** No change.
** 
**    Rev 1.10   08 Nov 1995 12:41:48   Shirley
** No change.
** 
**    Rev 1.9   02 Nov 1995 10:06:08   Shirley
** No change.
** 
**    Rev 1.8   27 Oct 1995 16:48:18   Shirley
** No change.
** 
**    Rev 1.7   27 Oct 1995 13:46:20   Shirley
** No change.
** 
**    Rev 1.6   25 Oct 1995 14:27:38   Shirley
** No change.
** 
**    Rev 1.5   18 Oct 1995 14:52:50   Shirley
** EasyPack/SLD Version 0.1e
** 
**    Rev 1.4   13 Oct 1995 13:21:26   Shirley
** No change.
** 
**    Rev 1.3   29 Sep 1995 09:52:32   Shirley
** No change.
** 
**    Rev 1.2   20 Sep 1995 10:55:46   Shirley
** No change.
** 
**    Rev 1.1   15 Sep 1995 09:45:56   Shirley
** No change.
** 
**    Rev 1.0   07 Sep 1995 09:54:46   Shirley
** Initial revision.
**
****************************************************************************/

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


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

#include <ctype.h>
#include "memdump.h"
#include "hosterrs.h"
extern RETCODE EXPORT ErrGetErrorText(U32 errorCode, LPSTR lpszError ...);
extern RETCODE EXPORT ErrGetErrorText(U32 errorCode, CString& strError ...);

extern DWORD dwpMax;
extern DWORD dwxMax;
extern DWORD dwiMax;
extern DWORD dwrMax;

/////////////////////////////////////////////////////////////////////////////
// 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 MemoryCmd(int nArgc, char* pszArgv[]);
long MemServerDump(BYTE* bDump, long lAddr, long lSize, int nType);
extern BOOL GetCpuStatus(unsigned char&);
extern void ShowLine(char *);


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


/////////////////////////////////////////////////////////////////////////////
// External function prototypes.
#ifndef _SERVER_NO_ABI
    extern STATUS AbiGetMemN(ADDR addr1, ADDR addr2, char* pchBuff);
#endif  // _SERVER_NO_ABI



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

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

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   MemoryCmd().
//
//  Description: The main control routine of Memory command.
//
//  Input:  nArgc - Number of input parameters.
//          pszArgv - Input parameters.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
void MemoryCmd(int nArgc, char* pszArgv[])
{
    // Assertion of the input parameters.
    ASSERT( 2 == nArgc || 3 == nArgc || 4 == nArgc );
    for ( int i = 0; i < nArgc; i++ ) {
        ASSERT( pszArgv[i] );
    }
    
    // Dump EMM contents.
    char error[128];
    
    CMemoryDump* pMemoryDump = new CMemoryDump;
    if ( !pMemoryDump ) {
        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 {
            pMemoryDump->DumpAction(nArgc, pszArgv);
            delete pMemoryDump;
          }           
       }   
    }

//    CMemoryDump objDump;
//    objDump.GetMemoryDump(nArgc, pszArgv);

}   // End of MemoryCmd().


/////////////////////////////////////////////////////////////////////////////
//
//  Name:   MemServerDump().
//
//  Description: The main control routine of Memory Server.
//
//  Input:  lAddr - Start address.
//          lSize - Dumped size.
//          nType - Memory space type.
//
//  Output: pbDump - To store the Dump contents.
//
//  Return: The size which has been dumped.
//
/////////////////////////////////////////////////////////////////////////////
long MemServerDump(BYTE* pbDump, long lAddr, long lSize, int nType)
{
    // Assertion of the input parameters.
    ASSERT( pbDump );
    ASSERT( lSize >= 1 && lSize <= 256 );
    ASSERT( nType >= 1 && nType <= 5 );
    
    // Dump EMM contents.
    CMemoryDump* pMemoryDump = new CMemoryDump;
    if ( !pMemoryDump ) {
        AfxMessageBox("Insufficient Memory !");
        ASSERT( FALSE );
        return (0);
    }
    else {
        long lRetAddr = 
            pMemoryDump->MemServerDump((char*)pbDump, (WORD&)lAddr,
                                       (int&)lSize, nType);
        delete pMemoryDump;
        return (lRetAddr);
    }
    
//    CMemoryDump objDump;
//    long lRetAddr = 
//      objDump.MemServerDump((char*)pbDump,(WORD&)lAddr,(int&)lSize,nType);
//    return (lRetAddr);

}   // End of MemServerDump().



/////////////////////////////////////////////////////////////////////////////
// Implementation codes of class: CMemoryDump.

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

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


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

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



/////////////////////////////////////////////////////////////////////////////
//
//  Name:   CMemoryDump::DumpAction().
//
//  Description: Get the current EMM contents.
//
//  Input:  None.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
void CMemoryDump::DumpAction(int nArgc, char* pszArgv[])
{
    // Assertion of the input parameters.
    ASSERT( 2 == nArgc || 3 == nArgc || 4 == nArgc );
    for ( int i = 0; i < nArgc; i++ ) {
        ASSERT( pszArgv[i] );
    }
    
    // Set Start address & End address.
    if ( 2 == nArgc ) {
        // Memory adr1.
        SetAddrVar(pszArgv[1], m_StartAddr);
        if ( ':' != pszArgv[1][1] ) {
            m_StartAddr.m_uchType = MEM_EXTERNAL;
        }
        switch ( m_StartAddr.m_uchType ) {
            case MEM_PROGRAM:
                if ( m_StartAddr > 0x0FF00 ) {
                    SetAddrVar("P:FFFF", m_EndAddr);
                }
                else {
                    SetAddrVar(pszArgv[1], "100", m_EndAddr);
                }
                m_EndAddr.m_uAddr = min(::dwpMax, m_EndAddr.m_uAddr);
                break;
            case MEM_EXTERNAL:
                if ( m_StartAddr > 0x0FF00 ) {
                    SetAddrVar("X:FFFF", m_EndAddr);
                }
                else {
                    SetAddrVar(pszArgv[1], "100", m_EndAddr);
                }
                m_EndAddr.m_uAddr = min(::dwxMax, m_EndAddr.m_uAddr);
                break;
            case MEM_INTERNAL:
                SetAddrVar("I:FF", m_EndAddr);
                m_EndAddr.m_uAddr = min(::dwiMax, m_EndAddr.m_uAddr);
                break;
            case MEM_SFR:
                SetAddrVar("R:FF", m_EndAddr);
                m_EndAddr.m_uAddr = min(::dwrMax, m_EndAddr.m_uAddr);
                break;
            case MEM_BIT:
                SetAddrVar("B:FF", m_EndAddr);
                break;
            default:
                ASSERT( FALSE );
                break;
        }
    }
    else if ( 3 == nArgc ) {
        // Memory adr1 adr2 
        SetAddrVar(pszArgv[1], m_StartAddr);
        SetAddrVar(pszArgv[2], m_EndAddr);
    }
    else if ( 4 == nArgc ) {
        // Memory adr1 Length length
        SetAddrVar(pszArgv[1], m_StartAddr);
        SetAddrVar(pszArgv[1], pszArgv[3], m_EndAddr);
    }
    else {
        ASSERT( FALSE );
        return;
    }
    
    // Set the default memory space.
    if ( ':' != pszArgv[1][1] ) {
        m_StartAddr.m_uchType = MEM_EXTERNAL;
    }
    m_EndAddr.m_uchType = m_StartAddr.m_uchType;
    
    // Display the head message.
    DisplayDumpHead();
        
    // Memory Dump kernel routine.
    MemoryDumpKernel();
        
}   // End of CMemoryDump::DumpAction().


void CMemoryDump::MemoryDumpKernel(void)
{
    // Assertion of the input parameters.

/*    
    // Get from EP each line.
    for ( unsigned short u = m_StartAddr.m_uAddr / 0x10;
        u <= m_EndAddr.m_uAddr / 0x10; u++ ) {
        // 
    }
*/    
    
    // Call Abi routine.
    CMemoryAddr StartAddr = m_StartAddr;
    CMemoryAddr EndAddr;
        
    do {

        EndAddr = m_EndAddr;
        if ( EndAddr - StartAddr >= MAX_DUMP_SIZE ) {
            EndAddr = (StartAddr+MAX_DUMP_SIZE-1)-(StartAddr.m_uAddr%0x10);
        }
        
        m_uSize = (EndAddr - StartAddr).m_uAddr + 1;
        m_nErrorID = AbiGetMemN((ADDR&)StartAddr, (ADDR&)EndAddr, m_pchDump);

        if ( EscapeAbort() ) {
            return;
        }
                    
        if ( ICE_OK != m_nErrorID ) {
            DisplayErrorMessage();
            return;
        }
        else {
            FormatDumpInfo(StartAddr);
            StartAddr = EndAddr + 1;
        }
        
    } while ( EndAddr < m_EndAddr );

}   // End of CMemoryDump::MemoryDumpKernel().


void CMemoryDump::FormatDumpInfo(const CMemoryAddr& StartAddr)
{
    // Assertion of the input parameters.
    
    // Display the Dump contents.
    int nCount = 0;
    int nBegin = StartAddr.m_uAddr % 0x010;
    unsigned short ulEndAddr = 0;
    
    for ( int i = 0; i <= (nBegin+(int)m_uSize-1)/16; i++ ) {
        int nOffset = (StartAddr.m_uAddr + nCount) % 0x010;
        char pszTemp[5];
        
        memset(m_pszData, ' ', sizeof(m_pszData));
        m_pszData[nOffset*3] = 0;

        memset(m_pszASCII, ' ', sizeof(m_pszASCII)-1);
        m_pszASCII[16] = 0;

        char ch;
        switch ( StartAddr.m_uchType ) {
            case MEM_PROGRAM:
                ch = 'P';
                break;
            case MEM_EXTERNAL:
                ch = 'X';
                break;
            case MEM_INTERNAL:
                ch = 'I';
                break;
            case MEM_SFR:
                ch = 'R';
                break;
            case MEM_BIT:
                ch = 'B';
                break;
            default:
                ASSERT( FALSE );
                break;
        }
                                            
        wsprintf(m_pszAddr, "%c:%04X", ch, StartAddr.m_uAddr+nCount-nOffset);

        for ( int j = nOffset; j <= 0x0F; j++ ) {
            if ( ulEndAddr >= 
                (unsigned long)StartAddr.m_uAddr + (unsigned long)m_uSize ) {
                break;
            }
            m_pszASCII[j] = 
                //isprint(m_pchDump[nCount]) ? m_pchDump[nCount] : '.';
                (m_pchDump[nCount]>=0x20 && m_pchDump[nCount]<=0x7e) ? m_pchDump[nCount] : '.';
            wsprintf(pszTemp, "%02X", (unsigned char)m_pchDump[nCount]);
            strcat(m_pszData, pszTemp);
            strcat(m_pszData, " ");
            nCount++;
            ulEndAddr = StartAddr.m_uAddr + nCount;
        }
        
        wsprintf(m_pszResult, "%-6s  %-48s  %-16s",
                 m_pszAddr, m_pszData, m_pszASCII);
        ShowLine(m_pszResult);
    }
    
}   // End of CMemoryDump::FormatDumpInfo().


void CMemoryDump::DisplayDumpHead(void)
{
    // Assertion of the input parameters.
    
    char* pszDumpHead = 
    "        00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F   ASCII CODE";
    
    ShowLine(pszDumpHead);

}   // End of CMemoryDump::DisplayDumpHead().


/////////////////////////////////////////////////////////////////////////////
//
//  Name:   CMemoryDump::MemServerDump().
//
//  Description: Dump memory contents for UI.
//
//  Input:  uAddr - Start address.
//          nSize - Dumped size.
//          nType - Memory space type.
//
//  Output: pchDump - To store the Dump contents.
//
//  Return: The size which has been dumped.
//
/////////////////////////////////////////////////////////////////////////////
long CMemoryDump::MemServerDump(char* pchDump,WORD uAddr,int nSize,int nType)
{
    // Assertion of the input parameters.
    ASSERT( pchDump );
    ASSERT( nSize >= 1 && nSize <= 256 );
    ASSERT( nType >= 1 && nType <= 5 );

    // Set the parameters.
    CMemoryAddr StartAddr(uAddr, (unsigned char)nType);
    CMemoryAddr EndAddr(uAddr + nSize - 1, (unsigned char)nType);

    // Call ABI routine.
    m_nErrorID = AbiGetMemN((ADDR&)StartAddr, (ADDR&)EndAddr, pchDump);
    m_isServer = TRUE;
    if ( ICE_OK != m_nErrorID ) {
        DisplayErrorMessage();
    }

    return ((long)nSize);

}   // End of CMemoryDump::MemServerDump().


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