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

/***************************************************************************
**
** File name :  MEMSVR.CPP
**				-- derived from MEMDUMP.CPP, MEMFILL.CPP, MEMTEST.CPP,
**				   MEMSRCH.CPP
**
** Author:      Chris Fang
** Description: implement file of memory server.
**
** coding from: Sep 20, 1996
** Finished date:
**
**
**    Copyright (C) 1996 Microtek International, Inc.
**    All Rights Reserved
**
****************************************************************************/

                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/
#include "stdafx.h"

#include "memsvr.h"
#include "abiextfn.h"
#include "uicom2.h"
#include "hosterrs.h"
#include "srcdef.h"
#include "ep196.h"

                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

#define SPACE_DEFAULT SPACE_P0

                       /****************************
                        *                          *
                        *     EXTERN PROTOTYPES    *
                        *                          *
                        ****************************/
//extern DWORD dwpMax;
//extern DWORD dwxMax;
//extern DWORD dwiMax;

extern void ShowLine(char *);
extern int TestKey(WORD wKey);
extern int GetBankNum(void);
extern BOOL IsMapCombination(void);

                       /****************************
                        *                          *
                        *     GLOBAL PROTOTYPES    *
                        *                          *
                        ****************************/
char*	gpstr_DumpHead=
	"          00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F   ASCII CODE";
	

extern const char*  g_pszAttrComOverlay;
extern const char*  g_pszAttrComTarget;
extern const char*  g_pszAttrSepOverlay;
extern const char*  g_pszAttrSepTarget;
	

                       /****************************
                        *                          *
                        *      EXECUTABLE CODE     *
                        *                          *
                        ****************************/

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   MemoryCmd().
//
//  Description: The main control routine of Memory command.
//				 Just support the same bank.
//
//  Input:  nArgc - Number of input parameters.
//          pszArgv - Input parameters.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
//Memory      adr1 [adr2|Length length]
void MemoryCmd(int nArgc, char* pszArgv[])
{
unsigned char	result;
BYTE*			pBuf=new BYTE[0x100], *pCurpos;
char			pstrData[4], strMsg[100];
WORD			wBufSize=0x100, wGetSize, wShowSize, wBegPos;
BOOL			bAbort;
DWORD			dwEndAddr;
ADDRESS			begAddr, endAddr;
ADDR_RETCODE	retAR;
CString			strData, strAscii, strAdr;

	// Assertion of the input parameters.
	ASSERT( 2 == nArgc || 3 == nArgc || 4 == nArgc );
	if(!GetCpuStatus(result)||!pBuf)
		return;
	if ( 1 == result )
	{
		ErrGetErrorText(ER_EMU_GOFLY_ERR_MSG, strMsg);
		ShowLine(strMsg);
		return;
	}
	if(nArgc==3||nArgc==4)
		GetAddrRange(nArgc, pszArgv, begAddr, endAddr);
	else
	{
		retAR=AdrTextToAddr(pszArgv[1], begAddr);
		ASSERT(retAR==ADR_OK);
		if(begAddr.adrSpace==SPACE_UNDEFINE)
			begAddr.adrSpace=SPACE_DEFAULT;
		endAddr.adrSpace=begAddr.adrSpace;
		//set endAddr to max addr of this space!!
		if(endAddr.adrSpace==SPACE_I)
			endAddr.adrAddress=0xff;
		else
			endAddr.adrAddress=0xffff;
    }
	ASSERT(endAddr.adrAddress>=begAddr.adrAddress);
	ShowLine(gpstr_DumpHead);
	do
	{
		dwEndAddr=endAddr.adrAddress;
		if(dwEndAddr-begAddr.adrAddress>=wBufSize)
			dwEndAddr=(begAddr.adrAddress+wBufSize-1)-
				(begAddr.adrAddress%0x10);
		wGetSize=WORD(dwEndAddr-begAddr.adrAddress+1);
		if(MemServerDump(pBuf, begAddr, wGetSize, 3)!=wGetSize)
			break;		//abi error, error message already given.
		pCurpos=pBuf;
		//display cycle:
		do
		{
			wShowSize=WORD(0x10-begAddr.adrAddress%0x10);
			if(begAddr.adrAddress+wShowSize-1>dwEndAddr)
			{
				ASSERT(dwEndAddr-begAddr.adrAddress+1<0x10000);
				wShowSize=WORD(dwEndAddr-begAddr.adrAddress+1);
			}
			wBegPos=WORD(begAddr.adrAddress%0x10);
			strAdr.Empty();
			strData.Empty();
			strAscii.Empty();
			AdrDadAddrToHex(begAddr, strAdr);
			for(WORD i=0; i<0x10; i++)
			{
				if(i<wBegPos||i>=wBegPos+wShowSize)
				{
					strData+="   ";
					strAscii+=" ";
					continue;
				}
				strAscii+=(pCurpos[i-wBegPos]>=0x20&&pCurpos[i-wBegPos]<=0x7e)
						?pCurpos[i-wBegPos]:'.';
				sprintf(pstrData, "%02X ", (int)pCurpos[i-wBegPos]);
				strData+=pstrData;
			}
			wsprintf(strMsg, "%-9s %-48s  %-16s",
				(const char*)strAdr, (const char*)strData, 
				(const char*)strAscii);
			ShowLine(strMsg);
			begAddr.adrAddress=begAddr.adrAddress+wShowSize;
			pCurpos+=wShowSize;
			bAbort=EscapeAbort();
		}while(begAddr.adrAddress<=dwEndAddr&&!bAbort);
		begAddr.adrAddress=dwEndAddr+1;
	}while(begAddr.adrAddress<=endAddr.adrAddress&&!bAbort);
	delete pBuf;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   ByteCmd().
//
//  Description: The main control routine of Byte command.
//
//  Input:  nArgc - Number of input parameters.
//          pszArgv - Input parameters.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
//BYte        adr data1 [..data32]
void ByteCmd(int nArgc, char* pszArgv[])
{
unsigned char result;
char strMsg[100], buf[33];
int nLength;
ADDRESS begAddr, endAddr;
ADDR_RETCODE retAR;

	ASSERT(3==nArgc);
	if(!GetCpuStatus(result))
		return;
	if(1 == result)
	{
		ErrGetErrorText(ER_EMU_GOFLY_ERR_MSG, strMsg);
		ShowLine(strMsg);
		return;
	}
	retAR=AdrTextToAddr(pszArgv[1], begAddr);
	ASSERT(retAR=ADR_OK);
	if(begAddr.adrSpace==SPACE_UNDEFINE)
		begAddr.adrSpace=SPACE_DEFAULT;
	if(!SetData(pszArgv[2], buf, nLength, 1))
		return;
	endAddr.adrSpace=begAddr.adrSpace;
	endAddr.adrAddress=begAddr.adrAddress+nLength-1;
	MemServerFill(begAddr, endAddr, buf, nLength, 3);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   WordCmd().
//
//  Description: The main control routine of Word command.
//
//  Input:  nArgc - Number of input parameters.
//          pszArgv - Input parameters.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
//Word        adr data1 [..data16]
void WordCmd(int nArgc, char* pszArgv[])
{
unsigned char result;
char strMsg[100], buf[33];
int nLength;
ADDRESS begAddr, endAddr;
ADDR_RETCODE retAR;

	ASSERT(3==nArgc);
	if(!GetCpuStatus(result))
		return;
	if(1 == result)
	{
		ErrGetErrorText(ER_EMU_GOFLY_ERR_MSG, strMsg);
		ShowLine(strMsg);
		return;
	}
	retAR=AdrTextToAddr(pszArgv[1], begAddr);
	ASSERT(retAR=ADR_OK);
	if(begAddr.adrSpace==SPACE_UNDEFINE)
		begAddr.adrSpace=SPACE_DEFAULT;
	if(!SetData(pszArgv[2], buf, nLength, 2))
		return;
	endAddr.adrSpace=begAddr.adrSpace;
	endAddr.adrAddress=begAddr.adrAddress+nLength-1;
	MemServerFill(begAddr, endAddr, buf, nLength, 3);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   LongCmd().
//
//  Description: The main control routine of Long command.
//
//  Input:  nArgc - Number of input parameters.
//          pszArgv - Input parameters.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
//LONg        adr data1 [..data8]
void LongCmd(int nArgc, char* pszArgv[])
{
unsigned char result;
char strMsg[100], buf[33];
int nLength;
ADDRESS begAddr, endAddr;
ADDR_RETCODE retAR;

	ASSERT(3==nArgc);
	if(!GetCpuStatus(result))
		return;
	if(1 == result)
	{
		ErrGetErrorText(ER_EMU_GOFLY_ERR_MSG, strMsg);
		ShowLine(strMsg);
		return;
	}
	retAR=AdrTextToAddr(pszArgv[1], begAddr);
	ASSERT(retAR=ADR_OK);
	if(begAddr.adrSpace==SPACE_UNDEFINE)
		begAddr.adrSpace=SPACE_DEFAULT;
	if(!SetData(pszArgv[2], buf, nLength, 4))
		return;
	endAddr.adrSpace=begAddr.adrSpace;
	endAddr.adrAddress=begAddr.adrAddress+nLength-1;
	MemServerFill(begAddr, endAddr, buf, nLength, 3);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   FillCmd().
//
//  Description: The main control routine of Fill command.
//
//  Input:  nArgc - Number of input parameters.
//          pszArgv - Input parameters.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
//Fill        adr1 {adr2|Length length} {"string"|data..}
//data: as byte cmd
void FillCmd(int nArgc, char* pszArgv[])
{
unsigned char	result;
char			strMsg[100];
int				nDataindex, nLength;
ADDRESS			begAddr, endAddr;

	// Assertion of the input parameters.
	ASSERT( 4 == nArgc || 5 == nArgc );
	if(!GetCpuStatus(result))
		return;
	if ( 1 == result )
	{
		ErrGetErrorText(ER_EMU_GOFLY_ERR_MSG, strMsg);
		ShowLine(strMsg);
		return;
	}
	GetAddrRange(nArgc, pszArgv, begAddr, endAddr);
	nDataindex=nArgc-1;
	if(pszArgv[nDataindex][0]=='\"')
	{
		strncpy(strMsg, &pszArgv[nDataindex][1], 99);
		strMsg[99]=NULL;
		nLength=strlen(strMsg);
		if(strMsg[nLength-1]=='\"')
		{
			nLength--;
			strMsg[nLength]=NULL;
		}
	}
	else if(!SetData(pszArgv[nDataindex], strMsg, nLength, 1))
		return;
	MemServerFill(begAddr, endAddr, strMsg, nLength, 3);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   TestCmd().
//
//  Description: The main control routine of Test command.
//
//  Input:  nArgc - Number of input parameters.
//          pszArgv - Input parameters.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
//TEst        adr1 {adr2|Length length}
void TestCmd(int nArgc, char* pszArgv[])
{
unsigned char	result;
ADDRESS			begAddr, endAddr;
char			strMsg[100];
CString			cstrMsg;

	// Assertion of the input parameters.
	ASSERT( 3 == nArgc || 4 == nArgc );
	if(!GetCpuStatus(result))
		return;
	if ( 1 == result )
	{
		ErrGetErrorText(ER_EMU_GOFLY_ERR_MSG, strMsg);
		ShowLine(strMsg);
		return;
	}
	GetAddrRange(nArgc, pszArgv, begAddr, endAddr);
	MemServerTest(begAddr, endAddr, begAddr, cstrMsg, 3);
	ShowLine(cstrMsg.GetBuffer(cstrMsg.GetLength()+1));
	cstrMsg.ReleaseBuffer();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   TestCmd().
//
//  Description: The main control routine of Test command.
//
//  Input:  nArgc - Number of input parameters.
//          pszArgv - Input parameters.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
//verify        

void VerifyCmd(int nArgc, char* pszArgv[])
{
CString			cstrMsg;
U16 isVerify; 
STATUS nResult;
	// Assertion of the input parameters.
	ASSERT( 1 == nArgc || 2 == nArgc );
	if(STATUS_HALT != GetCpuStatus2())
	{
		ErrGetErrorText(ER_EMU_GOFLY_ERR_MSG, cstrMsg);
		ShowLine(cstrMsg.GetBuffer(cstrMsg.GetLength()+2));
		return;
	}
	
	if(1 == nArgc) {
		nResult = emuGetVerify(&isVerify);
		if(nResult!=ICE_OK)
		{      
			ErrGetErrorText(ER_ICE_OK+nResult, cstrMsg);
			ShowLine(cstrMsg.GetBuffer(cstrMsg.GetLength()+2));
			return;		
		} 
		if(isVerify == 0) 
			ShowLine("Verify off.");
		else 
			ShowLine("Verify on.");	
	} else {
		cstrMsg = pszArgv[1];
		cstrMsg.MakeUpper();
		if(cstrMsg == "ON") {
			isVerify = 1;
		} else {
			isVerify = 0;
		} 
		nResult = emuSetVerify(isVerify);
		
		if(nResult!=ICE_OK)
		{      
			ErrGetErrorText(ER_ICE_OK+nResult, cstrMsg);
			ShowLine(cstrMsg.GetBuffer(cstrMsg.GetLength()+2));
			return;		
		} 
		if(isVerify == 0) 
			ShowLine("Verify off.");
		else 
			ShowLine("Verify on.");	
	}
		
}


/////////////////////////////////////////////////////////////////////////////
//
//  Name:   SearchCmd().
//
//  Description: The main control routine of Search command.
//
//  Input:  nArgc - Number of input parameters.
//          pszArgv - Input parameters.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
//SEarch      adr1 {adr2|Length length} {[Insensitive] "string"|data..}
void SearchCmd(int nArgc, char* pszArgv[])
{
unsigned char	result;
int				nLength;
BOOL			bInsensitive=FALSE;
ADDRESS			begAddr, endAddr;
char			strMsg[100];
CString			cstrMsg;

	// Assertion of the input parameters.
	ASSERT( 4 == nArgc || 5 == nArgc || 6 == nArgc);
	if(!GetCpuStatus(result))
		return;
	if ( 1 == result )
	{
		ErrGetErrorText(ER_EMU_GOFLY_ERR_MSG, strMsg);
		ShowLine(strMsg);
		return;
	}
	GetAddrRange(nArgc, pszArgv, begAddr, endAddr);
	if(pszArgv[nArgc-1][0]=='\"')
	{
		strncpy(strMsg, &pszArgv[nArgc-1][1], 99);
		strMsg[99]=NULL;
		nLength=strlen(strMsg);
		if(strMsg[nLength-1]=='\"')
		{
			nLength--;
			strMsg[nLength]=NULL;
		}
		if(!stricmp(pszArgv[nArgc-2], "insensitive"))
			bInsensitive=TRUE;
	}
	else if(!SetData(pszArgv[nArgc-1], strMsg, nLength, 1))
		return;
	MemServerSearch(begAddr, endAddr, strMsg, nLength, bInsensitive,
					begAddr, cstrMsg, 3);
	ShowLine(cstrMsg.GetBuffer(cstrMsg.GetLength()+1));
	cstrMsg.ReleaseBuffer();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   CopyCmd().
//
//  Description: The main control routine of Copy command.
//
//  Input:  nArgc - Number of input parameters.
//          pszArgv - Input parameters.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
//Copy        adr1 {adr2|Length length} adr3
void CopyCmd(int nArgc, char* pszArgv[])
{
unsigned char	result;
ADDRESS			begAddr, endAddr, TargetbegAddr;
ADDR_RETCODE	retAR;
char			strMsg[100];
CString			cstrMsg;

	// Assertion of the input parameters.
	ASSERT( 4 == nArgc || 5 == nArgc || 6 == nArgc);
	if(!GetCpuStatus(result))
		return;
	if ( 1 == result )
	{
		ErrGetErrorText(ER_EMU_GOFLY_ERR_MSG, strMsg);
		ShowLine(strMsg);
		return;
	}
	GetAddrRange(nArgc, pszArgv, begAddr, endAddr);
	retAR=AdrTextToAddr(pszArgv[nArgc-1], TargetbegAddr);
	ASSERT(retAR==ADR_OK);
	if(TargetbegAddr.adrSpace==SPACE_UNDEFINE)
		TargetbegAddr.adrSpace=SPACE_DEFAULT;
	MemServerCopy(begAddr, endAddr, TargetbegAddr, cstrMsg, 3);
	ShowLine(cstrMsg.GetBuffer(cstrMsg.GetLength()+1));
	cstrMsg.ReleaseBuffer();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   CompareCmd().
//
//  Description: The main control routine of Compare command.
//
//  Input:  nArgc - Number of input parameters.
//          pszArgv - Input parameters.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
//COMpare     adr1 {adr2|Length length} adr3
void CompareCmd(int nArgc, char* pszArgv[])
{
unsigned char	result;
ADDRESS			begAddr, endAddr, TargetbegAddr;
ADDR_RETCODE	retAR;
char			strMsg[100];
CString			cstrMsg;

	// Assertion of the input parameters.
	ASSERT( 4 == nArgc || 5 == nArgc || 6 == nArgc);
	if(!GetCpuStatus(result))
		return;
	if ( 1 == result )
	{
		ErrGetErrorText(ER_EMU_GOFLY_ERR_MSG, strMsg);
		ShowLine(strMsg);
		return;
	}
	GetAddrRange(nArgc, pszArgv, begAddr, endAddr);
	retAR=AdrTextToAddr(pszArgv[nArgc-1], TargetbegAddr);
	ASSERT(retAR==ADR_OK);
	if(TargetbegAddr.adrSpace==SPACE_UNDEFINE)
		TargetbegAddr.adrSpace=SPACE_DEFAULT;
	MemServerCompare(begAddr, endAddr, TargetbegAddr,begAddr, cstrMsg, 3);
	ShowLine(cstrMsg.GetBuffer(cstrMsg.GetLength()+1));
	cstrMsg.ReleaseBuffer();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   ChecksumCmd().
//
//  Description: The main control routine of Checksum command.
//
//  Input:  nArgc - Number of input parameters.
//          pszArgv - Input parameters.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
//CHecksum    adr1 {adr2|Length length}
void ChecksumCmd(int nArgc, char* pszArgv[])
{
unsigned char	result;
WORD			wChecksum;
ADDRESS			begAddr, endAddr;
char			strMsg[100];
CString			cstrMsg;

	// Assertion of the input parameters.
	ASSERT( 3 == nArgc || 4 == nArgc );
	if(!GetCpuStatus(result))
		return;
	if ( 1 == result )
	{
		ErrGetErrorText(ER_EMU_GOFLY_ERR_MSG, strMsg);
		ShowLine(strMsg);
		return;
	}
	GetAddrRange(nArgc, pszArgv, begAddr, endAddr);
	MemServerChecksum(begAddr, endAddr, wChecksum, cstrMsg, 3);
	ShowLine(cstrMsg.GetBuffer(cstrMsg.GetLength()+1));
	cstrMsg.ReleaseBuffer();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   MapCmd().
//
//  Description: The main control routine of Map command.
//
//  Input:  nArgc - Number of input parameters.
//          pszArgv - Input parameters.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
//MAp         [{ALl adrtype}|{adr1 {adr2|Length length}} map_attribute]
void MapCmd(int nArgc, char* pszArgv[])
{
unsigned char	result;
ADDRESS			begAddr, endAddr;
WORD			wMapAttr;
char			strMsg[100];
CString			cstrMsg;

	ASSERT( 1 == nArgc || 4 == nArgc || 5 == nArgc || 6 == nArgc);
	if(!GetCpuStatus(result))
		return;
	if ( 1 == result )
	{
		ErrGetErrorText(ER_EMU_GOFLY_ERR_MSG, strMsg);
		ShowLine(strMsg);
		return;
	}
	if(nArgc==1)
	{
		char* p = new char[100];
		int	nBank=GetBankNum();
		BOOL bCombination=IsMapCombination();
		wsprintf(p, "Emulation Memory Size = %d KB.",
					64*nBank/(bCombination?1:2));
		ShowLine(p);
		delete p;
		ShowLine("Map Resolution = 128 Bytes.");
		//show sepraion or combination
//		wsprintf(strMsg, "Current Bank Number: %d in %s.", 
//			nBank/(bCombination?1:2),
//			bCombination?"combination":"separation");
		wsprintf(strMsg, "Current Bank Number: %d.", 
			nBank/(bCombination?1:2));
		ShowLine(strMsg);
		ShowLine("-------------------------------");
		ShowLine("Start      End        Attr");
        ShowMapInfo(MEM_P0);
        if(nBank==2)
        {
        	if(bCombination)
        		ShowMapInfo(MEM_P1);
        	else
        		ShowMapInfo(MEM_X0);
        }
        else if(nBank==4)
        {
        	if(bCombination)
        	{
        		ShowMapInfo(MEM_P1);
        		ShowMapInfo(MEM_P2);
        		ShowMapInfo(MEM_P3);
        	}
        	else
        	{
        		ShowMapInfo(MEM_P1);
        		ShowMapInfo(MEM_X0);
        		ShowMapInfo(MEM_X1);
        	}
        }
		return;
	}
	//Map All X: O
	else if(((4==nArgc) || (5==nArgc))&&(!stricmp(pszArgv[1], "All")))
	{
		if(!stricmp(pszArgv[2], "P0:"))
			begAddr.adrSpace=SPACE_P0;
		else if(!stricmp(pszArgv[2], "P1:"))
			begAddr.adrSpace=SPACE_P1;
		else if(!stricmp(pszArgv[2], "P2:"))
			begAddr.adrSpace=SPACE_P2;
		else if(!stricmp(pszArgv[2], "P3:"))
			begAddr.adrSpace=SPACE_P3;
		else if(!stricmp(pszArgv[2], "X0:"))
			begAddr.adrSpace=SPACE_X0;
		else if(!stricmp(pszArgv[2], "X1:"))
			begAddr.adrSpace=SPACE_X1;
		else if(!stricmp(pszArgv[2], "I:"))
			begAddr.adrSpace=SPACE_I;
		else
			ASSERT(0);
		begAddr.adrAddress=0;
		endAddr.adrSpace=begAddr.adrSpace;
		endAddr.adrAddress=0xffff;
	}
	else
		GetAddrRange(nArgc, pszArgv, begAddr, endAddr);

/*
	if (!stricmp(pszArgv[nArgc-1], "Overlay"))
		wMapAttr=(WORD)MAP_ORW;
	else if (!stricmp(pszArgv[nArgc-1], "OR"))
		wMapAttr=(WORD)MAP_OR;
	else if (!stricmp(pszArgv[nArgc-1], "Guard"))
		wMapAttr=(WORD)MAP_GUARD;
	else if (!stricmp(pszArgv[nArgc-1], "Target"))
		wMapAttr=(WORD)MAP_ERW;
	else
		ASSERT(0);
*/

	char szBuf[255];                
	
	if (!stricmp(pszArgv[nArgc-1], "Overlay"))
		wMapAttr = (WORD)MAP_ERW;
	else if (!stricmp(pszArgv[nArgc-1], "Target"))
		wMapAttr = (WORD)MAP_ORW;
	else {
		wsprintf(szBuf, "%s %s", pszArgv[nArgc-2], pszArgv[nArgc-1]);
			
		if (!stricmp(szBuf, g_pszAttrComOverlay))
			wMapAttr=(WORD)MAP_ERW;
		else if (!stricmp(szBuf, g_pszAttrComTarget))
			wMapAttr=(WORD)MAP_ORW;
		else if (!stricmp(szBuf, g_pszAttrSepOverlay))
			wMapAttr=(WORD)MAP_OR;
		else if (!stricmp(szBuf, g_pszAttrSepTarget))
			wMapAttr=(WORD)MAP_GUARD;
		else
			ASSERT(0);
	}
	MemServerSetMap(begAddr, endAddr, wMapAttr, cstrMsg, 3);
	ShowLine(cstrMsg.GetBuffer(cstrMsg.GetLength()+1));
	cstrMsg.ReleaseBuffer();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   MemServerDump().
//
//  Description: The main control routine of Memory Server.
//
//  Input:  addr - Start address.
//          size - Dumped size.
//          region - Memory region.
//
//  Output: pbDump - To store the Dump contents.
//
//  Return: The size which has been dumped.
//
/////////////////////////////////////////////////////////////////////////////
WORD MemServerDump(BYTE* pbDump, ADDRESS begAddress, WORD size, int nFromWhere)
{
	// Assertion of the input parameters.
	ASSERT( pbDump );

WORD	loop=size/100, w;
WORD	remain=size%100;
DWORD	dwstartaddr=begAddress.adrAddress;
BYTE*	pbuf=pbDump;
STATUS	retAbi;
RET_ADDR	retAddr;
ADDR	begAddr;
CString msg;

	begAddr.addrType=begAddress.adrSpace;
	begAddr.addr=begAddress.adrAddress;
	for(w=0; w<loop; w++, begAddr.addr+=100, pbuf+=100)
	{
		retAbi=emuGetMemN(begAddr, 100, pbuf, &retAddr);
		if(retAbi!=ICE_OK)
		{
			ErrorHandler(ER_ICE_OK+retAbi, nFromWhere);
			return WORD(begAddr.addr-dwstartaddr);
		}
	}
	if(remain)
	{
		retAbi=emuGetMemN(begAddr, remain, pbuf, &retAddr);
		if(retAbi!=ICE_OK)
		{
			ErrorHandler(ER_ICE_OK+retAbi, nFromWhere);
			return WORD(begAddr.addrType-dwstartaddr);
		}
	}
	return size;
}   // End of CMemoryDump::MemServerDump().

//old version of MemServerDump:
WORD MemServerDump(BYTE* bDump, DWORD dwBegAddr, WORD size, WORD wAddrSpace)
{
ADDRESS begAddr;
	begAddr.adrAddress=dwBegAddr;
	begAddr.adrSpace=(BYTE)wAddrSpace;

	return MemServerDump(bDump, begAddr, size, 2);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   MemServerFill.
//
//  Description: The main control routine of Fill Server.
//
//  Input:  addr - Start address.
//          data - Value which will be filled.
//          region - Memory region.
//
//  Output: 
//
//  Return: Error ID.
//
/////////////////////////////////////////////////////////////////////////////
STATUS MemServerFill(ADDRESS Address, BYTE data, int nFromWhere)
{
	// Assertion of the input parameters.
STATUS	retAbi;
ADDR	Addr;
RET_ADDR retAddr;

	Addr.addrType=Address.adrSpace;
	Addr.addr=Address.adrAddress;
	// Call ABI routine.
	retAbi=emuSetMemN(Addr, &data, 1, &retAddr);
	// Update Source window.
	if(Addr.addrType==MEM_P0||Addr.addrType==MEM_P1
		||Addr.addrType==MEM_P2||Addr.addrType==MEM_P3)
	{
		::SrcUpdateSourceWindow(::srcUpdate);
		::SrcUpdateBrowseWindow(::brwUpdate);
	}
	
	if (ICE_OK!=retAbi)
	    ErrorHandler(ER_ICE_OK+retAbi, nFromWhere);
	else if(nFromWhere==3)
		ShowLine("Memory fill OK!");
	return (retAbi);
}

//old version of MemServerFill:
STATUS MemServerFill(DWORD dwBegAddr, BYTE data, WORD wAddrSpace)
{
ADDRESS begAddr;
	begAddr.adrAddress=dwBegAddr;
	begAddr.adrSpace=(BYTE)wAddrSpace;

	return MemServerFill(begAddr, data, 2);
}

STATUS MemServerFill(ADDRESS begAddress, ADDRESS endAddress,
					char* szPattern, int nPatlen, int nFromWhere)
{
	ASSERT(szPattern);
	ASSERT(nPatlen<0x100);
	
STATUS	retAbi;
ADDR	begAddr;
RET_ADDR retAddr;

	begAddr.addrType=begAddress.adrSpace;
	begAddr.addr=begAddress.adrAddress;

	// Call ABI routine.
	retAbi=emuFill(begAddr, endAddress.adrAddress-begAddress.adrAddress+1,
		(WORD)nPatlen, (U8*)szPattern, &retAddr);

	// Update Source window.
	if(begAddr.addrType==MEM_P0||begAddr.addrType==MEM_P1
		||begAddr.addrType==MEM_P2||begAddr.addrType==MEM_P3)
	{
		::SrcUpdateSourceWindow(::srcUpdate);
		::SrcUpdateBrowseWindow(::brwUpdate);
	}
	
	if (ICE_OK!=retAbi)
		ErrorHandler(ER_ICE_OK+retAbi, nFromWhere);
	else if(nFromWhere==3)
		ShowLine("Memory fill OK!");
	return (retAbi);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   MemServerTest.
//
//  Description: The main control routine of Test Server.
//
//  Input:  begAddress - Start address.
//          endAddress - End address.
//			nFromWhere - 1: from memory group; 3: from shell
//
//  Output: adrBadAddress  - Bad address.
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
STATUS MemServerTest(ADDRESS begAddress, ADDRESS endAddress,
					ADDRESS& adrBadAddress, CString& strMsg, int /*nFromWhere*/)
{
	// Assertion of the input parameters.
STATUS	retAbi;
CString strAdr;
ADDR	begAddr;
RET_ADDR retAddr;

	adrBadAddress.adrSpace=0;
	begAddr.addrType=begAddress.adrSpace;
	begAddr.addr=begAddress.adrAddress;

	retAbi=emuTest(begAddr, endAddress.adrAddress-begAddress.adrAddress+1,
		&retAddr);
	if(begAddr.addrType==MEM_P0||begAddr.addrType==MEM_P1
		||begAddr.addrType==MEM_P2||begAddr.addrType==MEM_P3)
	{
		::SrcUpdateSourceWindow(::srcUpdate);
		::SrcUpdateBrowseWindow(::brwUpdate);
	}
	if(retAbi==ICE_OK)
		strMsg="Memory test OK.";
	else if(retAbi==ICE_ERROR_WRITE||retAbi==ICE_TEST_FAIL||
		 retAbi==ICE_NOT_READY||retAbi==ICE_ERROR_READ)
	{
		adrBadAddress.adrSpace=(BYTE)retAddr.addrType;
		adrBadAddress.adrAddress=retAddr.addr;
		AdrDadAddrToHex(adrBadAddress, strAdr);
        strMsg="Memory test fail at "+strAdr+".";
	}
	else
		ErrGetErrorText(ER_ICE_OK+retAbi, strMsg);
	return retAbi;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   MemServerSearch.
//
//  Description: The main control routine of Search Server.
//
//  Input:  wStartAddr - Start address.
//          wEndAddr   - End address.
//          region 	   - Memory region.
//			pszPattern - Search context.
//			bInsensitive-FALSE: match case; TRUE: not care case.
//
//  Output: dwRetAddr  - Found address.
//
//  Return: TRUE 	   - Found.
//			FALSE      - Not found.
//
/////////////////////////////////////////////////////////////////////////////
STATUS MemServerSearch(ADDRESS begAddress, ADDRESS endAddress,
					char* pszPattern, int nPatlen, BOOL bInsensitive,
					ADDRESS& retAddress, CString& strMsg, int /*nFromWhere*/)
{
	// Assertion of the input parameters.
	ASSERT(nPatlen<=32);
    
STATUS	retAbi;
CString strAdr;
ADDR	begAddr;
RET_ADDR retAddr;

	retAddress.adrSpace=0;
	begAddr.addrType=begAddress.adrSpace;
	begAddr.addr=begAddress.adrAddress;

    ASSERT(nPatlen<0x100);

	retAbi=emuSearch(begAddr, endAddress.adrAddress-begAddress.adrAddress+1,
		(U8*)pszPattern, (WORD)nPatlen, (U8)bInsensitive, &retAddr);

    if (ICE_NO_MATCH==retAbi)
		strMsg="Search result: not found.";
    else if(ICE_OK==retAbi)
	{
		retAddress.adrSpace=(BYTE)retAddr.addrType;
		retAddress.adrAddress=retAddr.addr;
		AdrDadAddrToHex(retAddress, strAdr);
		strMsg="Search result: found at "+strAdr+".";
    }
    else
		ErrGetErrorText(ER_ICE_OK+retAbi, strMsg);
	return retAbi;
}

STATUS MemServerCopy(ADDRESS begAddress, ADDRESS endAddress,
			ADDRESS TargetbegAddress, CString& strMsg, int /*nFromWhere*/)
{
STATUS retAbi;
ADDR	begAddr, TargetbegAddr;
ADDRESS errAddress;
RET_ADDR addrRet1, addrRet2;
CString strAdr;

	begAddr.addrType=begAddress.adrSpace;
	begAddr.addr=begAddress.adrAddress;

	TargetbegAddr.addrType=TargetbegAddress.adrSpace;
	TargetbegAddr.addr=TargetbegAddress.adrAddress;

	retAbi=emuCopy(begAddr, endAddress.adrAddress-begAddress.adrAddress+1,
		TargetbegAddr, &addrRet1, &addrRet2);
	if(begAddr.addrType==MEM_P0||begAddr.addrType==MEM_P1
		||begAddr.addrType==MEM_P2||begAddr.addrType==MEM_P3)
	{
		::SrcUpdateSourceWindow(::srcUpdate);
		::SrcUpdateBrowseWindow(::brwUpdate);
	}
	if (ICE_OK==retAbi)
		strMsg="Memory copy OK.";
	else if(retAbi==ICE_ERROR_WRITE||retAbi==ICE_NOT_READY)
	{
		errAddress.adrSpace=(BYTE)addrRet1.addrType;
		errAddress.adrAddress=addrRet1.addr;
    	AdrDadAddrToHex(errAddress, strAdr);
		strMsg="Error occur at "+strAdr+".";
    }
    else
		ErrGetErrorText(ER_ICE_OK+retAbi, strMsg);
	return (retAbi);
}

STATUS MemServerCompare(ADDRESS begAddress, ADDRESS endAddress,
					ADDRESS TargetbegAddress,
					ADDRESS& resultAddress, CString& strMsg, int /*nFromWhere*/)
{
STATUS retAbi;
CString strAdr;
ADDR	begAddr, TargetbegAddr;
RET_ADDR findAddr1, findAddr2;

	begAddr.addrType=begAddress.adrSpace;
	begAddr.addr=begAddress.adrAddress;

	TargetbegAddr.addrType=TargetbegAddress.adrSpace;
	TargetbegAddr.addr=TargetbegAddress.adrAddress;

	retAbi=emuCompare(begAddr, endAddress.adrAddress-begAddress.adrAddress+1,
		TargetbegAddr, &findAddr1, &findAddr2);
	if (ICE_NO_DIFF==retAbi)
	    strMsg="Not found difference.";
    else if(ICE_OK==retAbi)
	{
		resultAddress.adrSpace=(BYTE)findAddr1.addrType;
		resultAddress.adrAddress=findAddr1.addr;
    	AdrDadAddrToHex(resultAddress, strAdr);
		strMsg="Found difference at "+strAdr+".";
    }
    else
		ErrGetErrorText(ER_ICE_OK+retAbi, strMsg);
	return retAbi;
}

STATUS MemServerChecksum(ADDRESS begAddress, ADDRESS endAddress,
					WORD& result, CString& strMsg, int /*nFromWhere*/)
{
STATUS retAbi;
ADDR	begAddr;
ADDRESS resultAddress;
RET_ADDR  retAddr;
char	buf[20];
CString strAdr;

	begAddr.addrType=begAddress.adrSpace;
	begAddr.addr=begAddress.adrAddress;

	retAbi=emuChecksum(begAddr, endAddress.adrAddress-begAddress.adrAddress+1,
		&result, &retAddr);
	if(ICE_OK==retAbi)
	{
		sprintf(buf, "%4X.", result);
		strMsg="Memory checksum: ";
		strMsg+=buf;
	}
	else if(ICE_NOT_READY==retAbi)
	{
		resultAddress.adrSpace=(BYTE)retAddr.addrType;
		resultAddress.adrAddress=retAddr.addr;
		AdrDadAddrToHex(resultAddress, strAdr);
		strMsg="Error occur at "+strAdr+".";
    }
    else
    	ErrGetErrorText(ER_ICE_OK+retAbi, strMsg);
	return retAbi;
}

STATUS MemServerGetMap(ADDRESS& begAddress, ADDRESS& endAddress,
					WORD& wMapAttr, CString& strMsg, int nFromWhere)
{
STATUS retAbi;
ADDR	begAddr, endAddr;
MAP_INFO mapData;

	begAddr.addrType=begAddress.adrSpace;
	begAddr.addr=begAddress.adrAddress;
	endAddr.addrType=endAddress.adrSpace;
	//endAddr.addr=endAddress.adrAddress;
	endAddr.addr=0xffff;

	retAbi=emuGetMap(begAddr, endAddr, &mapData);
	if(ICE_OK!=retAbi)
	{
		ErrGetErrorText(ER_ICE_OK+retAbi, strMsg);
		return retAbi;
	}
	begAddress.adrAddress=mapData.addr1.addr;
	endAddress.adrAddress=mapData.addr2.addr;
	wMapAttr=mapData.attr;
    ASSERT(begAddress.adrAddress<0x10000);
    return retAbi;
}

STATUS MemServerSetMap(ADDRESS begAddress, ADDRESS endAddress,
					WORD wMapAttr, CString& strMsg, int nFromWhere)
{
STATUS retAbi;
ADDR	begAddr, endAddr;

	begAddr.addrType=begAddress.adrSpace;
	begAddr.addr=begAddress.adrAddress;
	endAddr.addrType=endAddress.adrSpace;
	endAddr.addr=endAddress.adrAddress;

	retAbi=emuSetMap(begAddr, endAddr, wMapAttr);
	if(ICE_OK==retAbi)
		strMsg="Map set OK.";
    else
    	ErrGetErrorText(ER_ICE_OK+retAbi, strMsg);
	if(begAddr.addrType==MEM_P0||begAddr.addrType==MEM_P1
		||begAddr.addrType==MEM_P2||begAddr.addrType==MEM_P3)
	{
		::SrcUpdateSourceWindow(::srcUpdate);
		::SrcUpdateBrowseWindow(::brwUpdate);
	}
	
	return retAbi;
}

void ShowMapInfo(int nMemSpace)
{
STATUS	retSvr;
WORD	wMapAttr;
ADDRESS begAddr, endAddr;
CString strAdr, strMsg;

	begAddr.adrAddress=0;
	endAddr.adrAddress=0xffff;
	begAddr.adrSpace=endAddr.adrSpace=(BYTE)nMemSpace;

	do
	{
		retSvr=MemServerGetMap(begAddr, endAddr, wMapAttr, strMsg, 3);
		if(retSvr!=ICE_OK)
		{
			ShowLine(strMsg.GetBuffer(strMsg.GetLength()+1));
			strMsg.ReleaseBuffer();
			return;
		}
		AdrDadAddrToHex(begAddr, strAdr);
		strMsg=strAdr+"    ";
		AdrDadAddrToHex(endAddr, strAdr);
		strMsg+=strAdr+"    ";

		if(wMapAttr==MAP_ERW)
			strMsg+=g_pszAttrComOverlay;
		else if(wMapAttr==MAP_ORW)
			strMsg+=g_pszAttrComTarget;
		else if(wMapAttr==MAP_OR)
			strMsg+=g_pszAttrSepOverlay;
		else if(wMapAttr==MAP_GUARD)
			strMsg+=g_pszAttrSepTarget;
		else
			ASSERT(0);


		ShowLine(strMsg.GetBuffer(strMsg.GetLength()+1));
		strMsg.ReleaseBuffer();
		begAddr.adrAddress=endAddr.adrAddress+1;
	}while(begAddr.adrAddress<0x10000);
}

BOOL GetAddrRange(int nArgc, char* pszArgv[],
			ADDRESS& begAddr, ADDRESS& endAddr)
{
ADDR_RETCODE	retAR;

	ASSERT(nArgc>=3);
	retAR=AdrTextToAddr(pszArgv[1], begAddr);
	ASSERT(retAR==ADR_OK);
	if(begAddr.adrSpace==SPACE_UNDEFINE)
		begAddr.adrSpace=SPACE_DEFAULT;
	if(stricmp(pszArgv[2], "length"))
	{
		retAR=AdrTextToAddr(pszArgv[2], endAddr);
		ASSERT(retAR==ADR_OK);
		if(endAddr.adrSpace==SPACE_UNDEFINE)
			endAddr.adrSpace=begAddr.adrSpace;
		ASSERT(endAddr.adrSpace==begAddr.adrSpace);
	}
	else
	{
		//length is Hex
		retAR=AdrTextToAddr(pszArgv[3], endAddr);
		ASSERT(retAR==ADR_OK);
		endAddr.adrSpace=begAddr.adrSpace;
		endAddr.adrAddress=begAddr.adrAddress+endAddr.adrAddress-1;
	}
	return TRUE;
}

BOOL SetData(char* pInput, char* pOutput, int& nLength, int type)
{
	ASSERT(type==1||type==2||type==4);
DWORD data;
char seps[]   = " ,\t\n";
char *token;
int index=0;
WORD* pWord=(WORD*)pOutput;
DWORD* pDword=(DWORD*)pOutput;

	token=strtok(pInput, seps);
	while(token)
	{
		data=strtoul(token, NULL, 16);
		if(type==1)
		{
			pOutput[index++]=char(data);
		}
		else if(type==2)
		{
			pWord[index++]=WORD(data);
		}
		else if(type==4)
		{
			pDword[index++]=data;
		}
		token=strtok(NULL, seps);
	}
	if(type==1)
	{
		nLength=index;
		pOutput[index]=NULL;
	}
	else if(type==2)
	{
		nLength=index*2;
		pOutput[nLength]=NULL;
	}
	else if(type==4)
	{
		nLength=index*4;
		pOutput[nLength]=NULL;
	}
	return TRUE;
}

BOOL EscapeAbort(void)
{
    // Test the key value.
    if ( 1 == ::TestKey(VK_ESCAPE)) {
        ShowLine("Abort by user.");
        return (TRUE);
    }
    else {
        return (FALSE);
    }

}   // End of CMemoryBase::EscapeAbort().

//nFromWhere: 1 - from dialog;
//			  2	- from memory window;
//			  3 - from shell  window.
void ErrShow(CString& strMsg, int nFromWhere)
{
	if(nFromWhere==1)
		return;
	else if(nFromWhere==2)
		AfxMessageBox(strMsg);
	else if(nFromWhere==3)
	{
		ShowLine(strMsg.GetBuffer(strMsg.GetLength()+1));
		strMsg.ReleaseBuffer();
	}
	else
		ASSERT(0);
}

//nFromWhere: 1 - from dialog;
//			  2	- from memory window;
//			  3 - from shell  window.
void ErrorHandler(U32 errorCode, int nFromWhere)
{
CString strMsg;

	if(nFromWhere==1)
		return;
	ErrGetErrorText(errorCode, strMsg);
	ErrShow(strMsg, nFromWhere);
}
