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

/***************************************************************************
**
** File name : TRCMAN.CPP 
** Author: Richard
** Description:
**
** Copyright (C) 1997 Microtek International, Inc.
** All Rights Reserved
**
****************************************************************************/

#include "stdafx.h"

#include "trcserve.h" 
#include "trcpub.h"  
#include "hosterrs.h"
#include "trcins.h"       
#include "trcwin.h"

#define MAX_TRACE_READ		100   
#define MAX_TRACE_INS_READ	200     
#define MAX_INS_DISASM		200
#define MAX_TRACE_STORE		600  
#define REDUNDANT_RATE		2
#define REDUNDANT_OFFSET 	10  


extern int  TestKey(WORD);

/****************************************************************************
**	class CCtlTraceManage
**  class for trace manage for trace window
**	Coding from: May 7
**	Finish date:
****************************************************************************/

CTraceManage::CTraceManage()
{    
	m_wID = 1;
	m_bValid = FALSE;           
	m_pTraceInfo = NULL;       
	
	m_bInsValid = FALSE;
	m_pInsInfo = NULL;
	
	m_pInsFrame = NULL;

	ResetContents(&m_qualify);
	ResetContents(&m_tmpQualify);         
}

CTraceManage::~CTraceManage()
{                    
	if (m_pTraceInfo){
		delete [] m_pTraceInfo;  
		m_pTraceInfo = NULL;
	}
	
	if (m_pInsInfo){
		delete [] m_pInsInfo;
		m_pInsInfo = NULL;
	}    
	
	if (m_pInsFrame){
		delete [] m_pInsFrame;
		m_pInsFrame = NULL;
	}
}

void CTraceManage::ClearCache()
{
	m_bValid = FALSE;
	m_bInsValid = FALSE;
}

void CTraceManage::SetFilter(QUALIFY_INFO& qualify)
{ 
	m_nClearFlag = OP_SET;
	memcpy(&m_tmpQualify, &qualify, sizeof(QUALIFY_INFO)); 
	memcpy(&m_qualify, &qualify, sizeof(QUALIFY_INFO));
}

DWORD CTraceManage::TS_GetLastFrame()
{
	if (!m_pTraceInfo){              
		m_pTraceInfo = new TRACE_INFO[MAX_TRACE_STORE];
		if (!m_pTraceInfo) return 0;
	}   
	
	if (!m_pInsInfo){
		m_pInsInfo = new IntroInsData[MAX_TRACE_STORE];
		if (!m_pInsInfo) return 0;
	}                       
	
	if (!m_pInsFrame){
		m_pInsFrame = new CInsFrame[MAX_TRACE_STORE];
		if (!m_pInsFrame) return 0;
	}
	
	if (IsTraceClear()) return 0;
	
	if (GetTraceDepth(m_depth))	
		return m_depth.endFrame;
	else return 0;
}

/****************************************************************************
** nFlag = -1 means reading trace buffer beginning with dwCurFrame - 1, 
** nFlag = -2 means reading trace buffer beginning with dwCurFrame - dwFrameNum
** nFlag =  0 means reading trace buffer beginning with dwCurFrame
** nFlag =  1 means reading trace buffer beginning with dwCurFrame + 1
** nFlag =  2 means reading trace buffer beginning with dwCurFrame + dwFrameNum
*****************************************************************************/
int CTraceManage::TS_GetBusRecord(int nFlag, DWORD& dwCurFrame, DWORD& dwFrameNum, 
		FrameData* pReturnBuf)
{                                                 
	DWORD dwFrom = dwCurFrame;
	
	if (IsTraceClear()){
		dwFrameNum = 0;
		return 1;      
	}

//	SaveCurTraceStatus();
	if (IsEpRunning())
		SetTraceStatus(CCtlTrace::TRACE_OFF);

	BOOL bFirst = TRUE;
	
	int nReturn;
	while(1)
	{  
		if (TestKey(VK_ESCAPE)){
			dwFrameNum = 0;
			return -1;
		}
	
		if (!m_bValid){       
			GetTraceDepth(m_depth);
			DWORD dwBegin = SetRedundantBegin(nFlag, dwFrom, dwFrameNum);
			if ((nReturn = ResetTraceBuf(dwBegin, dwFrameNum)) < 0)
			{
				dwFrameNum = 0;
				return nReturn;
			}          
			bFirst = FALSE;
		}
        
        if (m_dwFrameNum==0) // if no data in trace buffer
        {
        	if (bFirst){
        		m_bValid = FALSE;
        		continue;
        	}
        	
        	dwFrameNum = 0;
        	return 1;
        }

		switch(HitTest(nFlag, dwCurFrame, dwFrameNum))
		{	
			case ALL_EXIST:
				ConvertBusForWin(dwCurFrame, dwFrameNum, pReturnBuf);
				return 0;
			case PART_EXIST: // FW trace buffer only exist part of needed data
				ConvertBusForWin(dwCurFrame, dwFrameNum, pReturnBuf);
				return 0;
			case NEED_MORE:
			{
				if ((nReturn = MustReadAndMerge(m_readInfo.nDirect, 
						m_readInfo.start.m_dwExtSite,
						m_readInfo.dwNum)) < 0)
				{
					dwFrameNum = 0;
					return nReturn;
				}
				ConvertBusForWin(dwCurFrame, dwFrameNum, pReturnBuf);
				return 0;
			}
			case SMALLER:                      
				if (IsEncounter(FRAME_HEAD)){
					dwFrameNum = 0;
					return 1;
				}        
				
				dwFrom = bFirst ? dwCurFrame : m_pTraceInfo[0].frameNo-1;
				m_bValid = FALSE;
				break;			
			case LARGER:
				if (IsEncounter(FRAME_TAIL)){
					dwFrameNum = 0;
					return 1;  
				}
				dwFrom = bFirst ? dwCurFrame : m_pTraceInfo[m_dwFrameNum-1].frameNo;
				m_bValid = FALSE;
				break;
			default: ASSERT(0);    
		}
	}

//	RestoreLastTraceStatus();
}

void CTraceManage::ConvertBusForWin(DWORD& dwCurFrame, DWORD& dwFrameNum, 
		FrameData* pReturnBuf)
{
	dwFrameNum = m_dwValidNum;
	dwCurFrame = m_pTraceInfo[m_dwFromSite].frameNo;
	
	for (DWORD i=m_dwFromSite; i<m_dwValidNum+m_dwFromSite; i++, pReturnBuf++)
	{                                              
		pReturnBuf->physicalNo = m_pTraceInfo[i].frameNo;
		pReturnBuf->dwAddr = m_pTraceInfo[i].address; // & 0x3ffff;
		
		wsprintf(pReturnBuf->frameNo, "%04X ", pReturnBuf->physicalNo);
//		pReturnBuf->frameNo[4] = ' '; // for chris, strange to understand
		
		wsprintf(pReturnBuf->addr, "P%1d:%04X ", 
			GetAddrBank(pReturnBuf->dwAddr), (WORD)(pReturnBuf->dwAddr));
			
//		pReturnBuf->addr[7] = ' ';  
		
		if (pReturnBuf->dwAddr & 0x80000000) // WORD data
			wsprintf(pReturnBuf->data, "%04X ", m_pTraceInfo[i].datum);
		else
			wsprintf(pReturnBuf->data, "  %02X ", 
				(pReturnBuf->dwAddr & 1) ? (BYTE)(m_pTraceInfo[i].datum>>8)
					: (BYTE)(m_pTraceInfo[i].datum));
//		pReturnBuf->data[4] = ' ';
		
		wsprintf(pReturnBuf->status, " %-2s", 
			GetStatusStr(m_pTraceInfo[i].status));
//		pReturnBuf->status[2] = ' ';			
		
		wsprintf(pReturnBuf->spare, "%-5s ", 
			GetSpareStr(m_pTraceInfo[i].bExternal));
//		pReturnBuf->spare[5] = ' ';			
		
		wsprintf(pReturnBuf->portdata, "%02X ", m_pTraceInfo[i].bExternal);
//		pReturnBuf->portdata[2] = ' ';
	}
}		
		
			
BOOL CTraceManage::MergeTraceBuf(int nFlag, DWORD dwValid, DWORD dwNeed,
		TRACE_INFO* pTraceInfo)
{                       
	if (dwValid==0) return TRUE;
	BOOL bAdjust = FALSE;
	
	DWORD dwOldLen;
	if (dwValid+m_dwFrameNum>MAX_TRACE_STORE)
	{
		dwOldLen = MAX_TRACE_STORE-dwValid;
		bAdjust = TRUE;
	}
	else dwOldLen = m_dwFrameNum;
					
	TRACE_INFO *pNewBuf = new TRACE_INFO[dwOldLen+dwValid];
	
	if (!pNewBuf) return FALSE;

	// merge two buffer, I try to store all new trace buffer data
	// some all trace buffer data may be cut down
	switch(nFlag){
		case UP:                        
			memcpy(pNewBuf, pTraceInfo, (int)dwValid*sizeof(TRACE_INFO));
			memcpy(pNewBuf+dwValid, m_pTraceInfo, 
					(int)dwOldLen*sizeof(TRACE_INFO));
				
			if (dwValid > dwNeed)
			{		
				m_dwFromSite = dwValid-dwNeed;
				m_dwValidNum += dwNeed;
			}
			else{
				m_dwFromSite = 0;
				m_dwValidNum += dwValid;
			}
			if (bAdjust) m_dwValidTo = pNewBuf[MAX_TRACE_STORE-1].frameNo;
			break;
		case DOWN:
			memcpy(pNewBuf, m_pTraceInfo+m_dwFrameNum-dwOldLen, 
				(int)dwOldLen*sizeof(TRACE_INFO));
			memcpy(pNewBuf+dwOldLen, pTraceInfo, (int)dwValid*sizeof(TRACE_INFO));
			
			if (dwValid > dwNeed)
				m_dwValidNum += dwNeed;
			else m_dwValidNum += dwValid;
			
			if (m_dwFromSite >= m_dwFrameNum)
			 // pay attention to this case
			 // this case in according to HitTest case important
				if (m_dwValidNum > m_dwFromSite-m_dwFrameNum)
					m_dwValidNum -= m_dwFromSite-m_dwFrameNum;
				else m_dwValidNum = 0;
				
			if (dwOldLen<m_dwFrameNum) // have move 
				m_dwFromSite -= m_dwFrameNum-dwOldLen;

			if (bAdjust) m_dwValidFrom = pNewBuf[0].frameNo;
	
			break;
		default: ASSERT(0);				
	}	                   
	
	m_dwFrameNum = dwValid + dwOldLen;  
	memcpy(m_pTraceInfo, pNewBuf, (int)(m_dwFrameNum)*sizeof(TRACE_INFO));
	
	delete [] pNewBuf;
	
	return TRUE;
}

/***************************************************************************
** If display filter is changed or trace buffer contents is changed,
** we need call this function to reset trace buffer
** When I think no valid data exist in trace buffer,
** use this rountine to load new trace data to cache.
***************************************************************************/

int CTraceManage::ResetTraceBuf(DWORD dwStart, DWORD dwNum)
{
	ClearEncounter(FRAME_HEAD);
	ClearEncounter(FRAME_TAIL);
	m_dwFrameNum = dwNum;  
	
	m_bValid = TRUE;            
	m_bInsValid = FALSE;     
	
	ASSERT(m_pTraceInfo);

	emuGetTraceDepth(m_wID, &m_depth);

	while( GetTraceBuffer(dwStart, m_dwFrameNum, m_pTraceInfo) >=0 )
	{                   
		m_dwValidFrom = dwStart;

		if (m_dwFrameNum > 0) return 0;
		
		if (TestKey(VK_ESCAPE)){
			m_dwFrameNum = 0;
			m_bValid = FALSE;
			return -1;
		}
		
		if (IsEncounter(FRAME_HEAD)) return TRUE;
		dwStart = (dwStart-m_depth.startFrame>=MAX_TRACE_READ) ?
					dwStart-MAX_TRACE_READ : m_depth.startFrame;
	}
				
	m_dwFrameNum = 0; 
	m_bValid = FALSE;
	return 1;
}

int CTraceManage::GetTraceBuffer(DWORD dwStart, DWORD& dwNeed, 
				TRACE_INFO* pTraceBuf)
{
	if (dwStart >= m_depth.endFrame)
	{// had encoutered tail
		SetEncounter(FRAME_TAIL);
		dwNeed = 0;
		return 0;
	}
	
	if (dwStart <= m_depth.startFrame){
		SetEncounter(FRAME_HEAD);
		dwStart = m_depth.startFrame; 
	}
	
	BYTE byRead;
	BYTE byEnd;

	DWORD dwHasRead = 0;	
	DWORD dwCurFrom = dwStart;
	int nReturn;
	
	TRACE_INFO pTempTraceBuf[MAX_TRACE_READ];
	
	while(dwHasRead<dwNeed){           
		
		if (TestKey(VK_ESCAPE)) return -1;

		DWORD dwEndFrame = (m_depth.endFrame >= dwCurFrom+MAX_TRACE_READ) ?
							dwCurFrom+MAX_TRACE_READ-1 : m_depth.endFrame-1;

		ShowReadTraceCurSite(dwCurFrom);							
		nReturn = emuListTraceBuff(dwCurFrom, dwEndFrame,
					&m_tmpQualify, &byRead, pTempTraceBuf, &byEnd);
					
		if (nReturn != ICE_OK){
			DisplayErrorMessage(nReturn+ER_ICE_OK, SHOWMESSAGEBOX);
			return -2; 
		}    
		
		m_dwValidTo = dwEndFrame;

		if (byRead>0) // if read trace data from FW
		{
			if (dwHasRead+byRead>MAX_TRACE_STORE)
			{
				memcpy(pTraceBuf+dwHasRead, pTempTraceBuf, 
					(int)(MAX_TRACE_STORE-dwHasRead)*sizeof(TRACE_INFO));
				dwHasRead = MAX_TRACE_STORE;
				m_dwValidTo = pTraceBuf[MAX_TRACE_STORE-1].frameNo;
			}					
			else{
				memcpy(pTraceBuf+dwHasRead, pTempTraceBuf, 
					byRead*sizeof(TRACE_INFO));
				dwHasRead += byRead;
			}
		
			dwCurFrom = pTempTraceBuf[byRead-1].frameNo+1;
		}
		else dwCurFrom += MAX_TRACE_READ;
					
		if (byEnd==1 || dwCurFrom>=m_depth.endFrame){
			SetEncounter(FRAME_TAIL);
			break; // end of buffer          
		}
	}			                       
	dwNeed = dwHasRead;
	return 0;
}

int CTraceManage::MustReadTraceUp(DWORD dwEnd, DWORD& dwNeed,
		TRACE_INFO* pTraceBuf)
{
	BYTE byRead;
	BYTE byEnd;

	DWORD dwHasRead = 0;	       
	DWORD dwEachRead;
	
	DWORD dwCurFrom = dwEnd;
	int nReturn;
	
	TRACE_INFO pTempTraceBuf[MAX_TRACE_READ];
	
	ASSERT(((int)dwEnd) >= 0);
	while(dwHasRead<dwNeed){
	    if (dwCurFrom <= m_depth.startFrame){
    	   	SetEncounter(FRAME_HEAD); 
       		break;
    	}
    	// scroll MAX_TRACE_READ UP
    	if (dwCurFrom >= m_depth.startFrame+MAX_TRACE_READ)
    	{
    		dwEachRead = MAX_TRACE_READ;
    		dwCurFrom -= MAX_TRACE_READ - 1;
    	}
    	else{
    		dwEachRead = dwCurFrom - m_depth.startFrame + 1;
    		dwCurFrom = m_depth.startFrame;
    		SetEncounter(FRAME_HEAD);
    	}
    	
		m_dwValidFrom = dwCurFrom;    	
		
		ShowReadTraceCurSite(dwCurFrom);
		nReturn = emuListTraceBuff(dwCurFrom, dwCurFrom+dwEachRead-1,
					&m_tmpQualify, &byRead, pTempTraceBuf, &byEnd);
		if (nReturn != ICE_OK) return -2;     
		
		if (byRead > 0)
		{
			if (dwHasRead+byRead>=MAX_TRACE_READ)
			{
				memcpy(pTraceBuf, pTempTraceBuf+byRead+dwHasRead-MAX_TRACE_READ,
						(int)(MAX_TRACE_READ-dwHasRead)*sizeof(TRACE_INFO));
				dwHasRead = MAX_TRACE_READ;
				m_dwValidFrom = pTraceBuf[0].frameNo;
			}						
			else					
			{
				memcpy(pTraceBuf+MAX_TRACE_READ-dwHasRead-byRead, 
						pTempTraceBuf, byRead*sizeof(TRACE_INFO));
				dwHasRead += byRead;
			}
		}
					
	}			                           
	
	if ((dwHasRead !=0) && (dwHasRead != MAX_TRACE_READ))
	{ // need move valid trace data ahead
		memcpy(pTempTraceBuf, pTraceBuf+MAX_TRACE_READ-dwHasRead,
			(int)dwHasRead*sizeof(TRACE_INFO));
		memcpy(pTraceBuf, pTempTraceBuf, (int)dwHasRead*sizeof(TRACE_INFO));
	}	                                 
	
	dwNeed = dwHasRead;
	return 0;
}

/**************************************************************************
** if nFlag == UP, must read dwNeed frame before dwBoundary
** if nFlag == DOWN, must read dwNeed frame behind dwBoundary
**
***************************************************************************/
int CTraceManage::MustReadTrace(int nFlag, DWORD dwBoundary, DWORD& dwNeed,
		TRACE_INFO* pTraceBuf)
{
	if (nFlag==UP) return MustReadTraceUp(dwBoundary, dwNeed, pTraceBuf);
	else return GetTraceBuffer(dwBoundary, dwNeed, pTraceBuf);
}

int CTraceManage::MustReadAndMerge(int nFlag, DWORD dwBoundary,
				DWORD dwNeed)
{           
	TRACE_INFO pMoreTrace[MAX_TRACE_READ];

	DWORD dwRead = dwNeed;
	
	int nReturn;	
	if ( (nReturn = MustReadTrace(nFlag, dwBoundary, dwRead, pMoreTrace)) < 0)
		return nReturn;
						
	if (!MergeTraceBuf(nFlag, dwRead, dwNeed, pMoreTrace))
		return -3;	  
	
	return nReturn;
}
		
void CTraceManage::SetEncounter(int nFlag)
{
	m_nEncounter |= nFlag;
}

void CTraceManage::ClearEncounter(int nFlag)
{
	m_nEncounter &= ~nFlag;
}                          


DWORD CTraceManage::SetRedundantBegin(int nFlag, DWORD dwCurFrame, DWORD dwNeedNum)
{
	 // we change nFlag and dwNeedNum so as to let user call this function 
	 // more conviently.                
	int nDirect = nFlag;
	DWORD dwLine = dwNeedNum;

	if (dwCurFrame<=m_depth.startFrame) return m_depth.startFrame;
	
	GetScrollInfo(nDirect, dwLine, nFlag, dwNeedNum);
	
	switch(nFlag){
		case UP:       
			if (dwCurFrame-m_depth.startFrame>
					dwNeedNum*REDUNDANT_RATE+REDUNDANT_OFFSET)
				return dwCurFrame-dwNeedNum*REDUNDANT_RATE-REDUNDANT_OFFSET;
			else return m_depth.startFrame;
			break;
		case CUR:
			if (dwCurFrame-m_depth.startFrame>REDUNDANT_OFFSET)
				return dwCurFrame-REDUNDANT_OFFSET;
			else return m_depth.startFrame;
			break;
		case DOWN:
			return dwCurFrame;
		default:
			ASSERT(0);			
	}    
	return m_depth.startFrame;
}

void CTraceManage::GetScrollInfo(int nFlag, DWORD dwNeedNum,
		int& nDirect, DWORD& dwLineNum)
{
	switch(nFlag){
		case PAGE_UP:
			nDirect = UP;
			dwLineNum = dwNeedNum;
			break;
		case LINE_UP:
			nDirect = UP;
			dwLineNum = (DWORD)LINE_FRAME;
			break;
		case CURLINE:
			nDirect = CUR;
			dwLineNum = dwNeedNum;
			break;
		case LINE_DOWN:
			nDirect = DOWN;
			dwLineNum = (DWORD)LINE_FRAME;
			break;
		case PAGE_DOWN:
			nDirect = DOWN;
			dwLineNum = dwNeedNum;  
			break;
		default: 
			nDirect = nFlag;
			dwLineNum = dwNeedNum;
	}
}	

/***************************************************************************
** Test whether the trace buffer data is in trace cache buffer 
** precondition if nFlag==PAGE_UP or PAGE_DOWN, dwNeedNum equal one page length
** Given user call this routine properly,
** or this routine may not work properly
***************************************************************************/
int CTraceManage::HitTest(int nFlag, DWORD dwCurFrame, DWORD dwNeedNum)
{
	// find site of current frame in trace buffer
	int nCurSite = SettleSite(dwCurFrame); 
	
	switch(nCurSite){
		case SMALLER:    
			if (IsEncounter(FRAME_HEAD)){
				nCurSite = 0;
				break;
			}                    
			else return SMALLER;
		case LARGER:   
			if (IsEncounter(FRAME_TAIL))
				nCurSite = (int)(m_dwFrameNum-1);
			else return LARGER;				
		default:
			break;
	}
	
	ASSERT(nCurSite >= 0);
	
	DWORD dwScrollLine;
	int	  nDirect;
	GetScrollInfo(nFlag, dwNeedNum, nDirect, dwScrollLine);
	
	// dwNeedNum equal one page frame number	
	DWORD dwCurSite = (DWORD)nCurSite;
	switch(nFlag){
		case PAGE_UP: 
		case LINE_UP: // scroll up	
			if (dwCurSite>=dwScrollLine) // can scroll up in the trace buffer
			{
				m_dwFromSite = dwCurSite-dwScrollLine;
				if (m_dwFrameNum-m_dwFromSite>=dwNeedNum)
				{ // all in cache trace buffer
					m_dwValidNum = dwNeedNum;
					return ALL_EXIST;       
				}
				else{
					// some tail data is not in the cache buffer
					m_dwValidNum = m_dwFrameNum-m_dwFromSite;
					
					if (IsEncounter(FRAME_TAIL))
					// It is already the last frame
						return PART_EXIST;         
					
					// we need get more trace data from FW
					m_readInfo.nDirect = DOWN;
					m_readInfo.start.m_dwExtSite = m_pTraceInfo[m_dwFrameNum-1].frameNo+1;
					m_readInfo.dwNum = dwNeedNum-m_dwValidNum;
					return NEED_MORE;
				}
			}
			else{                          
			    // some head data is not in cache buffer
				m_dwFromSite = 0;
				
				if (m_dwFrameNum>=dwNeedNum+dwCurSite-dwScrollLine)
				{ // tail data is all in cache buffer  
					m_dwValidNum = dwNeedNum-dwScrollLine+dwCurSite;
					
					if (IsEncounter(FRAME_HEAD))
					{
					// It is the first frame already
						m_dwValidNum = m_dwFrameNum>dwNeedNum? 
									dwNeedNum : m_dwFrameNum;
						return PART_EXIST;			
					}
					
					m_readInfo.nDirect = UP;
					m_readInfo.start.m_dwExtSite = m_pTraceInfo[0].frameNo-1;
					m_readInfo.dwNum = dwScrollLine-dwCurSite;
					return NEED_MORE;
				}
				else{
				// some head data and tail data is not in cache buffer
				// I do not expect this case will happen
					if(IsEncounter(FRAME_HEAD))
					{
						m_dwValidNum = m_dwFrameNum;
						
						if (IsEncounter(FRAME_TAIL))
							return PART_EXIST;          
							
						// I think the case below will never occur	
						m_readInfo.nDirect = DOWN;	
						m_readInfo.start.m_dwExtSite = m_pTraceInfo[m_dwFrameNum-1].frameNo+1;
						m_readInfo.dwNum = dwNeedNum - m_dwValidNum;
						return NEED_MORE;
					}
					else{
						if (IsEncounter(FRAME_TAIL))
						{   
							m_dwValidNum = m_dwFrameNum;
							m_readInfo.nDirect = UP;
							m_readInfo.start.m_dwExtSite = m_pTraceInfo[0].frameNo-1;
							m_readInfo.dwNum = dwScrollLine-dwCurSite;
							return NEED_MORE;
						}
						
						ASSERT(0); // I think this case neve occur
					}
				}
			}									
		case CURLINE:
			m_dwFromSite = dwCurSite;
			if (m_dwFrameNum-dwCurSite>=dwNeedNum)
			{ // all data in cache buffer
				m_dwValidNum = dwNeedNum;
				return ALL_EXIST;       
			}
			else{ // some tail data is not in cache buffer
				m_dwValidNum = m_dwFrameNum-dwCurSite;
				
				if (IsEncounter(FRAME_TAIL))
					return PART_EXIST;
				
				m_readInfo.nDirect = DOWN;
				m_readInfo.start.m_dwExtSite = m_pTraceInfo[m_dwFrameNum-1].frameNo+1;
				m_readInfo.dwNum = dwNeedNum-m_dwValidNum;
				return NEED_MORE;
			}
		case LINE_DOWN:
		case PAGE_DOWN: // scroll down
			m_dwFromSite = dwCurSite + dwScrollLine;

			if (m_dwFrameNum-dwCurSite>dwScrollLine)
			{ // can scroll down
				if (m_dwFrameNum-m_dwFromSite >= dwNeedNum)
				{ // all data in cache buffer
					m_dwValidNum = dwNeedNum;
					return ALL_EXIST;       
				}
				else{// some tail data is not in trace buffer
					m_dwValidNum = m_dwFrameNum-m_dwFromSite;
					
					if (IsEncounter(FRAME_TAIL))
					{         
						
						m_dwValidNum = m_dwFrameNum - m_dwFromSite;
						
//						if (m_dwValidNum==0){
//							m_dwValidNum = 1;
//							m_dwFromSite = m_dwFrameNum -1;
//						}
							
						return PART_EXIST;
					}
					
					m_readInfo.nDirect = DOWN;
					m_readInfo.start.m_dwExtSite = m_pTraceInfo[m_dwFrameNum-1].frameNo+1;
					m_readInfo.dwNum = dwNeedNum-m_dwValidNum;
					return NEED_MORE;
				}            
			}
			else
			{  // no data is in cache buffer   
				// case important
				m_dwValidNum = 0;
				
				if (IsEncounter(FRAME_TAIL))
				{
					m_dwFromSite = m_dwFrameNum -1;
					m_dwValidNum = 1;
					return PART_EXIST;
				}
				
				m_readInfo.nDirect = DOWN;
				m_readInfo.start.m_dwExtSite = m_pTraceInfo[dwCurSite].frameNo+1;
				m_readInfo.dwNum = dwNeedNum+m_dwFromSite - m_dwFrameNum;
				
				return NEED_MORE;
			}
		default: ASSERT(0);
	}                          
	return SMALLER;
}

int CTraceManage::SettleSite(DWORD dwCurFrame)
{
	int nReturn;
	nReturn = FindMatch(0, m_dwFrameNum-1, dwCurFrame);
	
	switch(nReturn){
		case SMALLER:
			if (dwCurFrame >= m_dwValidFrom) return 0;
			break;
		case LARGER:
			if (dwCurFrame <= m_dwValidTo) return (int)(m_dwFrameNum - 1);
			break;
	}
	
	return nReturn;
}

// because this frame is sorted,we can search the specific frame quickly
int CTraceManage::FindMatch(DWORD wFrom, DWORD wEnd, DWORD dwCurFrame)
{                                                             
	ASSERT(wEnd>=wFrom);              
	ASSERT(wEnd<m_dwFrameNum);
	if (m_pTraceInfo[wFrom].frameNo > dwCurFrame) return SMALLER;
	if (m_pTraceInfo[wEnd].frameNo < dwCurFrame) return LARGER;
	
	switch(wEnd-wFrom){
		case 0: // one item
			return (int)wFrom;
		case 1: // two item
			if (m_pTraceInfo[wFrom].frameNo==(WORD)dwCurFrame) 
				return (int)wFrom;
			else return (int)wEnd;
		default:   
		{
			DWORD wMiddle = (wFrom+wEnd)/2;
			int nReturn = FindMatch(wFrom, wMiddle, dwCurFrame);
			if (nReturn != LARGER) return nReturn;
			
			nReturn = FindMatch(wMiddle+1, wEnd, dwCurFrame);
			if (nReturn != SMALLER) return nReturn;
			
			// larger than first half, less than last half, so return 
			// first item of the last half
			return (int)wMiddle+1;
		}   
	}
}                          

BOOL CTraceManage::SaveTraceToFile(int nTraceMode, const char* szFileName, DWORD dwStart,
			DWORD dwEnd, BOOL bOverWrite)
{
	switch(nTraceMode){
		case CTraceWindow::TRACEMODE_BUS:
			return SaveTraceBusToFile(szFileName, dwStart, dwEnd, bOverWrite);
		case CTraceWindow::TRACEMODE_INSTRUCTION:
			return SaveTraceInsToFile(szFileName, dwStart, dwEnd, bOverWrite);
		default: ASSERT(0);
	}                  
	return TRUE;
}
			
                                 
BOOL CTraceManage::SaveTraceBusToFile(const char* szFileName, DWORD dwStart,
			DWORD dwEnd, BOOL bOverWrite)
{
	CFile traceFile;

	if (bOverWrite)
	{
		if (!traceFile.Open(szFileName, CFile::modeCreate | CFile::modeWrite))
			return FALSE;
	}
	else
	{
		if (!traceFile.Open(szFileName, CFile::modeReadWrite))
			return FALSE;                                  
		traceFile.SeekToEnd();			
	}
			
//	SaveCurTraceStatus();
	::SetTraceStatus(CCtlTrace::TRACE_OFF);
	
    TRACE_INFO pTraceBuf[MAX_TRACE_READ];

	BYTE byRead;
	BYTE byEnd;
    for(DWORD i=dwStart; i<=dwEnd; i+=MAX_TRACE_READ)
    {                                     
    	DWORD dwRealEnd = (dwEnd-i+1>MAX_TRACE_READ) ? i+MAX_TRACE_READ-1
    					: dwEnd;

		ShowReadTraceCurSite(i);    					
		int nReturn = emuListTraceBuff(i, dwRealEnd,
					&m_tmpQualify, &byRead, pTraceBuf, &byEnd);
		
		if (nReturn != ICE_OK){
			traceFile.Close();
			return FALSE;
		}
							
		for(BYTE k=0; k<byRead; k++)
		{
			char szBuf[256]; 
			DumpTraceBuf(szBuf, pTraceBuf+k);
			traceFile.Write(szBuf, strlen(szBuf));
			traceFile.Write("\n", strlen("\n"));
		}
	}
	    
	traceFile.Close();
	
	RestoreLastTraceStatus();         
	
	return TRUE;
}

BOOL CTraceManage::SaveTraceInsToFile(const char* szFileName, DWORD dwStart,
			DWORD dwEnd, BOOL bOverWrite)
{
	CFile traceFile;

	if (bOverWrite)
	{
		if (!traceFile.Open(szFileName, CFile::modeCreate | CFile::modeWrite))
			return FALSE;
	}
	else
	{
		if (!traceFile.Open(szFileName, CFile::modeReadWrite))
			return FALSE;                                  
		traceFile.SeekToEnd();			
	}
			
//	SaveCurTraceStatus();

	::SetTraceStatus(CCtlTrace::TRACE_OFF);

	InsData pInsBuf[20];
	BYTE    byIntNo = 0;
	DWORD	dwInsNum = 11;
	BOOL    bFirst = TRUE;
		
    while(dwStart<=dwEnd)
    {
		if (TS_GetInsRecord(0, dwStart, byIntNo, dwInsNum, pInsBuf) != 0)
			break;
		
		for(DWORD k=bFirst? 0 : 1; k<dwInsNum; k++)
		{	
			char szBuf[256]; 
			
			if (pInsBuf[k].physicalNo > dwEnd)
				break;
				
			wsprintf(szBuf, " %6s   %10s    %s\n", 
					pInsBuf[k].frameNo,
					pInsBuf[k].addr, 
					pInsBuf[k].instruction);
			traceFile.Write(szBuf, strlen(szBuf));
		}       
		
		if (dwInsNum < 11) break;
		
		dwStart = pInsBuf[dwInsNum-1].physicalNo;
		byIntNo = pInsBuf[dwInsNum-1].intNo;
		
		bFirst = FALSE;
	}
	    
	traceFile.Close();
	
	RestoreLastTraceStatus();         
	
	return TRUE;
}

/***************************************************************************
** 
** Below routines are used in trace instruction mode
**
***************************************************************************/
DWORD CTraceManage::SetInsRedundantBegin(int nFlag, DWORD dwCurFrame, DWORD dwNeedNum)
{
	 // we change nFlag and dwNeedNum so as to let user call this function 
	 // more conviently.                
	int nDirect = nFlag;
	DWORD dwLine = dwNeedNum;
	
	if (dwCurFrame<=m_depth.startFrame) return m_depth.startFrame;

	GetScrollInfo(nDirect, dwLine, nFlag, dwNeedNum);
	
	switch(nFlag){
		case UP:       
			if (dwCurFrame-m_depth.startFrame> dwNeedNum*REDUNDANT_RATE
					+ REDUNDANT_OFFSET + MAX_HEAD_FRAME_GAP)
				return dwCurFrame-dwNeedNum*REDUNDANT_RATE-REDUNDANT_OFFSET
						-MAX_HEAD_FRAME_GAP;                           
						
			else return m_depth.startFrame;
			break;
		case CUR:                             
		case DOWN:
			if (dwCurFrame-m_depth.startFrame>REDUNDANT_OFFSET+MAX_HEAD_FRAME_GAP)
				return dwCurFrame-REDUNDANT_OFFSET-MAX_HEAD_FRAME_GAP;
			else return m_depth.startFrame;
			break;
		default:
			ASSERT(0);			
	}    
	return m_depth.startFrame;
}

int  CTraceManage::TS_GetInsRecord(int nFlag, DWORD& dwCurFrame, BYTE& byIntNo,
		DWORD& dwInsNum, InsData* pReturnBuf)
{
	GetTraceDepth(m_depth);
    if (dwCurFrame<m_depth.startFrame){	
    	dwCurFrame=m_depth.startFrame;
    	byIntNo = 0;
    }
    
    if (dwCurFrame>m_depth.endFrame){
    	dwCurFrame=m_depth.endFrame;
    	byIntNo = 1;
    }
    
	DWORD dwFrom = dwCurFrame;
	
	int nReturn;
	
	if (IsTraceClear()){ // user clear trace buffer
		dwInsNum = 0;
		return 1;      
	}

	if (IsEpRunning()) // let trace off to read trace buffer
		SetTraceStatus(CCtlTrace::TRACE_OFF);

	BOOL bFirst = TRUE;
	int nInsBegin;                 
	
	while(1)
	{  
		if (TestKey(VK_ESCAPE)){
			dwInsNum = 0;
			return -1;
		}
	
		if (!m_bValid){   
			DWORD dwBegin = SetInsRedundantBegin(nFlag, dwFrom, dwInsNum);
			if ((nReturn = ResetTraceBuf(dwBegin, MAX_TRACE_INS_READ)) < 0)
			{
				dwInsNum = 0;
				return nReturn;
			}          
			bFirst = FALSE;
			nInsBegin = 0;
		}                                    
        else if (m_dwFrameNum>0){ // Although there are frames in trace buffer, these frames may
        	// be not useful for me to disassemble.
        	nInsBegin = SettleSite(dwFrom);
        	if (nInsBegin > MAX_HEAD_FRAME_GAP)
        		nInsBegin -= MAX_HEAD_FRAME_GAP;
        	else if (IsEncounter(FRAME_HEAD))
        		nInsBegin = 0;
        	else{
        		m_bValid = FALSE;
        		continue;
        	}
        }
        	
        if (m_dwFrameNum==0) // if no data in trace buffer
        {
        	if (bFirst){ // we let it have a chance to read from FW
        		m_bValid = FALSE;
        		continue;
        	}
        	
        	dwInsNum = 0;
        	return 1;
        }        
		
		if (!m_bInsValid){ // if there are not any valid instruction in buffer
			if (!ResetInsBuf((DWORD)nInsBegin, dwInsNum)) //MAX_INS_DISASM))
			{
				dwInsNum = 0;
				return 1;
			}
		}
		
        if (m_dwInsNum == 0) // if no instruction
        {
        	dwInsNum = 0;
        	return 1;
        }

		switch(InsHitTest(nFlag, dwCurFrame, byIntNo, dwInsNum))
		{	
			case ALL_EXIST:
				ConvertInsForWin(dwCurFrame, byIntNo, dwInsNum, pReturnBuf);
				return 0;
			case PART_EXIST: // FW trace buffer only exist part of needed data
				ConvertInsForWin(dwCurFrame, byIntNo, dwInsNum, pReturnBuf);
				return 0;
			case NEED_MORE:
				if (bFirst) 
					dwFrom = dwCurFrame;
				else {
					if (m_readInfo.nDirect==UP)
						dwFrom = m_pTraceInfo[m_pInsFrame[0
							].m_frameCur.m_dwExtSite].frameNo - 1;
					else
						dwFrom = m_pTraceInfo[m_pInsFrame[m_dwInsNum-1
							].m_frameNext.m_dwExtSite-1].frameNo+1;
				}
				
				m_bValid = FALSE;
				break;
						
/*
				if (!MustDisasmAndMerge(m_readInfo.nDirect, 
					m_readInfo.start, m_readInfo.dwNum))
				{
					dwInsNum = 0;
					return TRUE;
				}
				
				ConvertInsForWin(dwCurFrame, dwInsNum, pReturnBuf);
				return TRUE;
*/
			case SMALLER:                                          
				if (bFirst)
					dwFrom = dwCurFrame;
				else{
					dwFrom = m_pTraceInfo[m_pInsFrame[0
						].m_frameCur.m_dwExtSite].frameNo - 1;
					}
				m_bValid = FALSE;
				break;			
			case LARGER:
				if (bFirst)
					dwFrom = dwCurFrame;
				else{
					dwFrom = m_pTraceInfo[m_pInsFrame[m_dwInsNum-1
						].m_frameNext.m_dwExtSite].frameNo;
					}
				m_bValid = FALSE;					
				break;
			default: ASSERT(0);    
		}
	}

//	RestoreLastTraceStatus();

}

int CTraceManage::InsSettleSite(DWORD dwCurFrame, BYTE byIntNo)
{                                     
	
	if ( (m_pTraceInfo[m_pInsFrame[0].m_frameCur.m_dwExtSite].frameNo > dwCurFrame)
	    || (m_pTraceInfo[m_pInsFrame[0].m_frameCur.m_dwExtSite].frameNo==dwCurFrame &&
	    	m_pInsFrame[0].m_frameCur.m_byIntSite > byIntNo))
		return SMALLER;                                     
		
	if ( (m_pTraceInfo[m_pInsFrame[m_dwInsNum-1].m_frameNext.m_dwExtSite-1].frameNo
			< dwCurFrame)
		|| (m_pTraceInfo[m_pInsFrame[m_dwInsNum-1].m_frameNext.m_dwExtSite-1].frameNo
			== dwCurFrame && m_pInsFrame[m_dwInsNum-1].m_frameCur.m_byIntSite < byIntNo))
		return LARGER;

	for(DWORD i=0; i<m_dwInsNum; i++)
	{
    	if ( (m_pTraceInfo[m_pInsFrame[i].m_frameCur.m_dwExtSite].frameNo
    			< dwCurFrame)
    		|| (m_pTraceInfo[m_pInsFrame[i].m_frameCur.m_dwExtSite].frameNo
    			== dwCurFrame && m_pInsFrame[i].m_frameCur.m_byIntSite < byIntNo))
			continue;
		
		return (int)i;
	}
	
	return 0;	
}
		
int CTraceManage::InsHitTest(int nFlag, DWORD dwCurFrame, BYTE byIntNo, DWORD dwNeedNum)
{
	// find site of current frame in trace buffer
	ASSERT(m_dwInsNum > 0);
	
	int nCurSite = InsSettleSite(dwCurFrame, byIntNo); 
	
	switch(nCurSite){
		case SETTLE_ERROR:
			return SETTLE_ERROR;
		case SMALLER:    
			if (IsEncounter(INS_HEAD)){
				nCurSite = 0;
				break;
			}                    
			else return SMALLER;
		case LARGER:   
			if (IsEncounter(INS_TAIL))
				nCurSite = (int)(m_dwInsNum-1);
			else return LARGER;		
		default:
			break;
	}
	
	ASSERT(nCurSite >= 0);
	
	DWORD dwScrollLine;
	int	  nDirect;
	GetScrollInfo(nFlag, dwNeedNum, nDirect, dwScrollLine);
	
	// dwNeedNum equal one page frame number	
	DWORD dwCurSite = (DWORD)nCurSite;
	
	CFramePos InsBegFrame = m_pInsFrame[0].m_frameCur;
	CFramePos InsEndFrame = m_pInsFrame[m_dwInsNum-1].m_frameNext;
	
	switch(nFlag){
		case PAGE_UP: 
		case LINE_UP: // scroll up	
			if (dwCurSite>=dwScrollLine) // can scroll up in the instruction buffer
			{
				m_dwFromSite = dwCurSite-dwScrollLine;
				
				if (m_dwInsNum-m_dwFromSite>=dwNeedNum)
				{ // all in cache instruction buffer
					m_dwValidNum = dwNeedNum;
					return ALL_EXIST;       
				}
				else{
					// some tail data is not in the cache instruction buffer
					m_dwValidNum = m_dwInsNum-m_dwFromSite;
					
					if (IsEncounter(INS_TAIL))
					// It is already the last instruction
						return PART_EXIST;         
					
					// we need assemble more trace data
					m_readInfo.nDirect = DOWN;
					m_readInfo.start = InsEndFrame;
					m_readInfo.start--;
					m_readInfo.dwNum = dwNeedNum-m_dwValidNum;
					return NEED_MORE;
				}
			}
			else{                          
			    // some head data is not in instruction buffer
				m_dwFromSite = 0;
				
				if (m_dwInsNum>=dwNeedNum+dwCurSite-dwScrollLine)
				{ // all tail data is in cache buffer  
					m_dwValidNum = dwNeedNum-dwScrollLine+dwCurSite;
					
					if (IsEncounter(INS_HEAD))
					{
					// It is the first instruction already
						m_dwValidNum = m_dwInsNum>dwNeedNum? 
									dwNeedNum : m_dwInsNum;
						return PART_EXIST;			
					}
					
					m_readInfo.nDirect = UP;
					m_readInfo.start = InsBegFrame;
					m_readInfo.start--;
					m_readInfo.dwNum = dwScrollLine-dwCurSite;
					return NEED_MORE;
				}
				else{
				// some head data and tail data is not in cache buffer
				// I do not expect this case will happen
					if(IsEncounter(INS_HEAD))
					{
						m_dwValidNum = m_dwInsNum;
						
						if (IsEncounter(INS_TAIL))
							return PART_EXIST;          
							
						// I think the case below will never occur	
						m_readInfo.nDirect = DOWN;	
						m_readInfo.start = InsEndFrame;
						m_readInfo.dwNum = dwNeedNum - m_dwValidNum;
						return NEED_MORE;
					}
					else{
						if (IsEncounter(INS_TAIL))
						{   
							m_dwValidNum = m_dwInsNum;
							m_readInfo.nDirect = UP;
							m_readInfo.start = InsBegFrame;
							m_readInfo.start --;
							m_readInfo.dwNum = dwScrollLine-dwCurSite;
							return NEED_MORE;
						}
						
						ASSERT(0); // I think this case never occur
					}
				}
			}									
		case CURLINE:
			m_dwFromSite = dwCurSite;
			if (m_dwInsNum-dwCurSite>=dwNeedNum)
			{ // all data in cache buffer
				m_dwValidNum = dwNeedNum;
				return ALL_EXIST;       
			}
			else{ // some tail data is not in cache buffer
				m_dwValidNum = m_dwInsNum-dwCurSite;
				
				if (IsEncounter(INS_TAIL))
					return PART_EXIST;
				
				m_readInfo.nDirect = DOWN;
				m_readInfo.start = InsEndFrame;
				m_readInfo.dwNum = dwNeedNum-m_dwValidNum;
				return NEED_MORE;
			}
		case LINE_DOWN:
		case PAGE_DOWN: // scroll down
			m_dwFromSite = dwCurSite + dwScrollLine;

			if (m_dwInsNum-dwCurSite>dwScrollLine)
			{ // can scroll down
				if (m_dwInsNum-m_dwFromSite >= dwNeedNum)
				{ // all data in cache buffer
					m_dwValidNum = dwNeedNum;
					return ALL_EXIST;       
				}
				else{// some tail data is not in instruction buffer
					m_dwValidNum = m_dwInsNum-m_dwFromSite;
					
					if (IsEncounter(INS_TAIL))
						return PART_EXIST;
					
					m_readInfo.nDirect = DOWN;
					m_readInfo.start = InsEndFrame;
					m_readInfo.dwNum = dwNeedNum-m_dwValidNum;
					return NEED_MORE;
				}            
			}
			else
			{  // no data is in cache buffer   
				// case important
				m_dwValidNum = 0;
				
				if (IsEncounter(INS_TAIL))
				{
					m_dwFromSite = m_dwInsNum -1;
					m_dwValidNum = 1;
					return PART_EXIST;
				}
				
				m_readInfo.nDirect = DOWN;
				m_readInfo.start = InsEndFrame;
				m_readInfo.dwNum = dwNeedNum+m_dwFromSite - m_dwInsNum;
				
				return NEED_MORE;
			}
		default: ASSERT(0);
	}                          
	return SMALLER;
}

BOOL CTraceManage::IsConnected(DWORD dwFirst, DWORD dwSecond)
{
	DWORD dwOff = (m_pTraceInfo[dwFirst].address & 0x80000000) ?  2 : 1;
		
	return (m_pTraceInfo[dwFirst].address & 0x3ffff) + dwOff ==
		(m_pTraceInfo[dwSecond].address & 0x3ffff);
}

BOOL CTraceManage::FindFlush(DWORD dwFrom, DWORD dwTo, DWORD& dwGap)
{ // find first discontinous trace frame
	ASSERT(dwFrom <= dwTo && dwTo <= m_pTraceInfo[m_dwFrameNum-1].frameNo);
	
	DWORD dwPrevFrame;
	
	for (DWORD i=dwFrom; i<=dwTo; i++)
	{                     
		if (GetStatus(m_pTraceInfo[i].status) == STATUS_S)
		{
			dwPrevFrame = i;
			break;
		}
	}
	
	if (i>=dwTo) return FALSE;
	
	for(i++; i<=dwTo; i++)
	{
		if (GetStatus(m_pTraceInfo[i].status) == STATUS_S)
		{
			if (IsConnected(dwPrevFrame, i))
				dwPrevFrame = i;
			else
			{ // some flush operation must occur
				dwGap = i;
				return TRUE;
			}
		}	                                    
	}			    
	
	return FALSE;			
}

BOOL CTraceManage::SetDisasmStart(CFramePos& frameStart)
{
	DWORD dwInsBegin;

	if (frameStart.m_dwExtSite > MAX_HEAD_FRAME_GAP)		 
	{
		if (FindFlush(frameStart.m_dwExtSite, 
				  frameStart.m_dwExtSite+MAX_HEAD_FRAME_GAP-1, dwInsBegin))
		{
			frameStart.m_dwExtSite = dwInsBegin;
			frameStart.m_byIntSite = 0;
			return TRUE;
		}
	}
	else SetEncounter(INS_HEAD);

	CFramePos endFrame;
	if (IsTraceCycleByte(m_dwFrameNum-1))
		endFrame.Set(m_dwFrameNum-1, 0);
	else endFrame.Set(m_dwFrameNum-1, 1);

	CDADTraceDq DadTraceDq;
	
	if (DadTraceDq.TryInsBegin(frameStart, endFrame)){
		return TRUE;                                
	}
	
	return FALSE;
}

BOOL CTraceManage::ResetInsBuf(DWORD dwFrameSite, DWORD /*dwNeed*/)
{
	ClearEncounter(INS_HEAD);
	ClearEncounter(INS_TAIL);
	
	m_bInsValid = FALSE;     
   
   	CFramePos frameSite(dwFrameSite, 0);
   	
	if (!SetDisasmStart(frameSite)) return FALSE;
     
    CFramePos endFrameSite;
    
    if (IsTraceCycleByte(m_dwFrameNum-1))
    	endFrameSite.Set(m_dwFrameNum-1, 0);
    else endFrameSite.Set(m_dwFrameNum-1, 1);
                                   
	if (IsEncounter(FRAME_TAIL)) SetEncounter(INS_TAIL);
	
	CDADTraceDq DadTraceDq;
	
	if (!DadTraceDq.DasTraceIns(frameSite, endFrameSite))
	{
		return FALSE;
	}
	            
	DadTraceDq.DumpDadIns(m_dwInsNum, m_pInsInfo, m_pInsFrame);
	
	m_bInsValid = TRUE;     

	return TRUE;
}	

/*
BOOL CTraceManage::MustDisasmAndMerge(int nFlag, CFramePos boundary,
				DWORD dwNeed)
{           
	TRACE_INFO pMoreTrace[MAX_TRACE_READ];
	
	DWORD dwRead = dwNeed * REDUNDANT_REAT + MAX_HEAD_FRAME_GAP; 
	DWORD dwFrameNeed = dwRead;
	
	DWORD m_dwTempFrom = m_dwFromSite;
	DWORD m_dwTempValid = m_dwValid;
	
	if (!MustReadTrace(nFlag, dwBoundary, dwRead, pMoreTrace))
		return FALSE;
						
	if (!MergeTraceBuf(nFlag, dwRead, dwNeed, pMoreTrace))
		return FALSE;	
		
	if (dw		
	
}				
*/

void CTraceManage::ConvertInsForWin(DWORD& dwCurFrame, BYTE& byIntNo,
			DWORD& dwInsNum, InsData* pReturnBuf)
{                                                                  
	dwInsNum = m_dwValidNum;
	
	dwCurFrame = m_pTraceInfo[ m_pInsFrame[m_dwFromSite
							 ].m_frameCur.m_dwExtSite].frameNo;      
	byIntNo = m_pInsFrame[m_dwFromSite].m_frameCur.m_byIntSite;							 
				
	
	for(DWORD i=0; i<dwInsNum; i++, pReturnBuf++)
	{                         
		pReturnBuf->physicalNo = (WORD)m_pTraceInfo[ 
						m_pInsFrame[m_dwFromSite+i
						].m_frameCur.m_dwExtSite].frameNo;
		pReturnBuf->intNo = m_pInsFrame[m_dwFromSite+i
						].m_frameCur.m_byIntSite;
		pReturnBuf->dwAddr = m_pInsInfo[m_dwFromSite+i].dwAddr;

		wsprintf(pReturnBuf->frameNo, "%04X ", pReturnBuf->physicalNo);
//		pReturnBuf->frameNo[4] = ' '; // for chris, strange to understand
		
		wsprintf(pReturnBuf->addr, "P%1d:%04X ", 
			GetAddrBank(pReturnBuf->dwAddr), (WORD)(pReturnBuf->dwAddr));
			
//		pReturnBuf->addr[7] = ' ';  

		strcpy(pReturnBuf->instruction, m_pInsInfo[m_dwFromSite+i].strIns);
//		pReturnBuf[i].strIns = m_pInsInfo[m_dwFromSite+i].strIns;    
	}
	
}

BOOL CTraceManage::IsEncounter(int nFlag)
{
	return (m_nEncounter & nFlag) ? TRUE : FALSE;
}

BOOL CTraceManage::IsTraceCycleByte(DWORD dwFrameNum)
{
	ASSERT(dwFrameNum < m_dwFrameNum);
	
	return (m_pTraceInfo[dwFrameNum].address & 0x80000000 ) == 0;
}                                                                

DWORD CTraceManage::TraceCycleAddr(DWORD dwFrameNum)
{
	ASSERT(dwFrameNum < m_dwFrameNum);
	
	return m_pTraceInfo[dwFrameNum].address & 0x3ffff;
}

int CTraceManage::TraceCycleStatus(DWORD dwFrameNum)
{
	ASSERT(dwFrameNum < m_dwFrameNum);
	
	return GetStatus(m_pTraceInfo[dwFrameNum].status);
}

BYTE CTraceManage::TraceCycleData(const CFramePos& frame)
{
	ASSERT(frame.m_dwExtSite < m_dwFrameNum);
	
	if (IsTraceCycleByte(frame.m_dwExtSite))
		return  (m_pTraceInfo[frame.m_dwExtSite].address & 1) ? 
			(BYTE)(m_pTraceInfo[frame.m_dwExtSite].datum >> 8) :
         	(BYTE)(m_pTraceInfo[frame.m_dwExtSite].datum);
    else
		return frame.m_byIntSite==0 ? 
			(BYTE)(m_pTraceInfo[frame.m_dwExtSite].datum) :
			(BYTE)(m_pTraceInfo[frame.m_dwExtSite].datum >> 8);
}	

/**********************************end of file*****************************/
       
       