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

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

#include "stdafx.h"
#include "resource.h"

#include <ctype.h> 

#include "trcpub.h"
#include "trcserve.h"
#include "hosterrs.h" 
#include "ep196.h"         
#include "cpusvr.h"
#include "mainfrm.h"

CBusEvent ev1(1), ev2(2);
CExtEvent ev3;                           

CLevel Le1(1), Le2(2);

CTrigger Trig;

CQualify  qlfy;  

CCtlTrace trace;
CCtlList  list;                  
CControl  cntl;
CInPort	  inport;
COutPort  outport;
CTraceManage traceMan;

extern CMDIChildWnd*	gp_TraceWnd;

extern void ShowLine(char*);    

static char BASED_CODE MICROTEK_CONFIG_MARK[] = "Microtek Config:";
static char BASED_CODE MICROTEK_EVENT_MARK[] = "Microtek Event:";
static char BASED_CODE MICROTEK_QUALIFY_MARK[] = "Microtek Qualify:";


BOOL InitTrace()
{	
	if (emuClrAllEvent() != ICE_OK) return FALSE;
	if (!ev1.Init()) return FALSE;
	if (!ev2.Init()) return FALSE;
	if (!ev3.Init()) return FALSE;
	if (!Le1.Init()) return FALSE;
	if (!Le2.Init()) return FALSE;
	if (!Trig.Init()) return FALSE;
	if (!qlfy.Init()) return FALSE;
	if (!trace.Init()) return FALSE;
	if (!cntl.Init()) return FALSE; 
	return TRUE;
}

void Ev1Cmd(int nArgc, char* pszArgv[])
{           
   ev1.ShellCmd(nArgc, pszArgv); 
}  

void Ev2Cmd(int nArgc, char* pszArgv[])
{           
   ev2.ShellCmd(nArgc, pszArgv); 
}  

void Ev3Cmd(int nArgc, char* pszArgv[])
{           
   ev3.ShellCmd(nArgc, pszArgv); 
}   

void EventCmd(int nArgc, char* pszArgv[])
{
  char * ArgPointTmp[40];
  int ArgMaxTmp;
  static char Argtmp[256];    
                
  Argtmp[0]=0;              
  ArgMaxTmp = nArgc;
  for (int i=0; i< ArgMaxTmp ; i++) ArgPointTmp[i] = pszArgv[i];
  
  if (1==nArgc) 
   { 
    strcpy(Argtmp,"EV1");
    ArgPointTmp[0]=Argtmp;
    Ev1Cmd(nArgc,ArgPointTmp);

    strcpy(Argtmp,"EV2");
    ArgPointTmp[0]=Argtmp;
    Ev2Cmd(ArgMaxTmp,ArgPointTmp); 
    
    strcpy(Argtmp,"EV3");
    ArgPointTmp[0]=Argtmp;
    Ev3Cmd(ArgMaxTmp,ArgPointTmp); 
    return;
    }
    
  if(0 == stricmp(pszArgv[1], "1"))
   {
    strcpy(Argtmp,"EV1"); 
    ArgPointTmp[0]=Argtmp;
    
    for (int i=1; i< ArgMaxTmp-1 ; i++) ArgPointTmp[i] = ArgPointTmp[i+1];
   
    ArgMaxTmp--;
    Ev1Cmd(ArgMaxTmp,ArgPointTmp);
    return;
    }      
   
  if(0 == stricmp(pszArgv[1], "2"))
  {
   strcpy(Argtmp,"EV2");
   ArgPointTmp[0]=Argtmp;
   
   for (int i=1; i< ArgMaxTmp-1 ; i++) ArgPointTmp[i] = ArgPointTmp[i+1];
   ArgMaxTmp--;
   Ev2Cmd(ArgMaxTmp,ArgPointTmp);
   return;
   }
   
  if(0 == stricmp(pszArgv[1], "3"))
  {
   strcpy(Argtmp,"EV3"); 
   ArgPointTmp[0]=Argtmp;
   
   for (int i=1; i< ArgMaxTmp-1 ; i++) ArgPointTmp[i] = ArgPointTmp[i+1];
   
   ArgMaxTmp--;
   Ev3Cmd(ArgMaxTmp,ArgPointTmp);
   return;
   }
   
  if(0 == stricmp(pszArgv[1], "CLEAR"))
  {
    strcpy(Argtmp,"EV1");
    ArgPointTmp[0]=Argtmp;
    Ev1Cmd(nArgc,ArgPointTmp);
    
    strcpy(Argtmp,"EV2");
    ArgPointTmp[0]=Argtmp;
    Ev2Cmd(ArgMaxTmp,ArgPointTmp); 
    return;
   }
         
  ShowLine("Syntax error???");
}

void Lv1Cmd(int nArgc, char* pszArgv[])
{           

   Le1.ShellCmd(nArgc, pszArgv);  
}

void Lv2Cmd(int nArgc, char* pszArgv[])
{                                
    
   Le2.ShellCmd(nArgc, pszArgv);
}

void LevelCmd(int nArgc, char* pszArgv[])
{
  char * ArgPointTmp[40];
  int ArgMaxTmp;
  static char Argtmp[256];    
                
  Argtmp[0]=0;              
  ArgMaxTmp = nArgc;
  for (int i=0; i< ArgMaxTmp ; i++) ArgPointTmp[i] = pszArgv[i];
  
  if (1==nArgc) 
   { 
    Argtmp[0]=0;
    strcat(Argtmp,"LV1");      ArgPointTmp[0]=Argtmp;
    Lv1Cmd(nArgc,ArgPointTmp);
    Argtmp[0]=0;
    strcat(Argtmp,"LV2");      ArgPointTmp[0]=Argtmp;
    Lv2Cmd(ArgMaxTmp,ArgPointTmp); 
    return;
    }
    
  if(0 == stricmp(pszArgv[1], "1"))
   {
    Argtmp[0]=0;
    strcat(Argtmp,"LV1");      ArgPointTmp[0]=Argtmp;
    for (int i=1; i< ArgMaxTmp-1 ; i++) ArgPointTmp[i] = ArgPointTmp[i+1];
    ArgMaxTmp--;
    Lv1Cmd(ArgMaxTmp,ArgPointTmp);
    return;
    }      
   
  if(0 == stricmp(pszArgv[1], "2"))
  {
   Argtmp[0]=0;
   strcat(Argtmp,"LV2");      ArgPointTmp[0]=Argtmp;
   for (int i=1; i< ArgMaxTmp-1 ; i++) ArgPointTmp[i] = ArgPointTmp[i+1];
   ArgMaxTmp--;
   Lv2Cmd(ArgMaxTmp,ArgPointTmp);
   return;
   }      
  ShowLine("Syntax error???");  
  }

void TriggerCmd(int nArgc, char* pszArgv[])
{ 
  Trig.ShellCmd(nArgc,pszArgv);
}                      

void QualifyCmd(int nArgc,char* pszArgv[])
{
  qlfy.ShellCmd(nArgc, pszArgv);
}

void TraceCmd(int nArgc, char* pszArgv[])
{
	trace.ShellCmd(nArgc, pszArgv);
}

void ListCmd(int nArgc, char* pszArgv[])
{
	list.ShellCmd(nArgc, pszArgv);
}

void ControlCmd(int nArgc, char* pszArgv[])
{
	cntl.ShellCmd(nArgc, pszArgv);
}

void InportCmd(int nArgc, char* pszArgv[])
{
	inport.ShellCmd(nArgc, pszArgv);                              
}                                   

void OutportCmd(int nArgc, char* pszArgv[])
{
	outport.ShellCmd(nArgc, pszArgv);
}


extern BOOL RestoreMapFromFile(CArchive& ar, BOOL bAction);             // Restore the map setting from the file
extern void SaveMapToFile(CArchive& ar);                // Save the map setting to the file

extern BYTE GetSpace(int index);

void SaveEventToFile(CArchive& ar)
{
	ASSERT(ar.IsStoring());
	
	CString strMark = MICROTEK_EVENT_MARK;
	ar << strMark;
	
	ev1.Serialize(ar);
	ev2.Serialize(ar);
	ev3.Serialize(ar);
	Le1.Serialize(ar);
	Le2.Serialize(ar);
	Trig.Serialize(ar);
}

void SaveQualifyToFile(CArchive& ar)
{              
	ASSERT(ar.IsStoring());

	CString strMark = MICROTEK_QUALIFY_MARK;
	ar << strMark;
	
	qlfy.Serialize(ar);
}                      

BOOL RestoreEventFromFile(CArchive& ar, BOOL bAction)
{ // bAction = TRUE, restore it; Otherwise, skip it
	
	ASSERT(ar.IsLoading());      
	
	CString strMark;
	ar >> strMark;
	
	if (strMark.Compare(MICROTEK_EVENT_MARK) != 0)
		return FALSE;
		
		
	for(int i=0; i<2; i++){
		CBusEvent tmpEvent;     
		tmpEvent.Serialize(ar); // read event i+1 

		if (bAction){
			BOOL bClearFlag;
			BUS_EVENT evData;
			tmpEvent.DumpEvent(bClearFlag, evData);
			if (i==0) ev1.SetByWin(bClearFlag, evData);
			else ev2.SetByWin(bClearFlag, evData);
		}
	} 
		
	CExtEvent tmpExt;
	tmpExt.Serialize(ar);
		
	if(bAction){
		WORD extData;
		tmpExt.DumpEvent(extData);
		ev3.SetByWin(extData);
	}
		
	for(i=0; i<2; i++){
		CLevel tmpLevel;
		tmpLevel.Serialize(ar); // read event i+1 
		
		if(bAction){
			TRIGGER_LEVEL lvData;
			tmpLevel.DumpLevel(lvData);
			if (i==0) Le1.SetByWin(lvData);
			else Le2.SetByWin(lvData);
		}
	} 
		
	CTrigger tmpTrig;
	tmpTrig.Serialize(ar);
 
 	if (bAction){
		TRIGGER_LOGIC trigData;
		BOOL bTrigStatus;
		
		tmpTrig.DumpTrig(trigData);
		Trig.SetByWin(trigData); 
	
		tmpTrig.DumpTrigStatus(bTrigStatus);
		Trig.SetStatusByWin(bTrigStatus);
	}   
	
	return TRUE;
}

BOOL RestoreQualifyFromFile(CArchive& ar, BOOL bAction)
{ // bAction = TRUE, restore it; Otherwise, skip it
	ASSERT(ar.IsLoading());

	CString strMark;
	ar >> strMark;
	
	if (strMark.Compare(MICROTEK_QUALIFY_MARK) != 0)
		return FALSE;
	
	CQualify tmpQlfy;
	tmpQlfy.Serialize(ar);
	
	if (bAction){
		QUALIFY qlfyData;
		tmpQlfy.DumpQualify(qlfyData);
		qlfy.SetByWin(qlfyData);		
	}           
	
	return TRUE;
}

void SaveConfigHead(CArchive& ar, WORD option)
{
    CString strMark;
    strMark = MICROTEK_CONFIG_MARK;
    
    ar << strMark;      
    
    BYTE byBank = GetSpace(-1);                     
    ar << byBank; 
    
    ar << GetCpuId();  
    
    ar << option;
}                

BOOL RestoreConfigHead(CArchive& ar, WORD& option, BOOL bShowMsg)
{
	CString strMark;
	
	ar >> strMark;
	
	if (strMark.Compare(MICROTEK_CONFIG_MARK) != 0){  
		if (bShowMsg)
	        MessageBox(NULL,"Invalid Config File, can not restore.",
                   NULL,MB_OK|MB_ICONQUESTION);
		return FALSE;
	}
	       
	BYTE byBank;	       
	ar >> byBank;
	
	if (byBank != GetSpace(-1)){                   
		if (bShowMsg)
	    	MessageBox(NULL,"Different bank setting, can not restore.",
                   NULL,MB_OK|MB_ICONQUESTION);
		return FALSE;
	}
	      
	WORD wCpuID;	      
	ar >> wCpuID;

/*	
	if (wCpuID != GetCpuId()){
		if (bShowMsg)
	    	MessageBox(NULL,"Different cpu type, can not restore.",
                   NULL,MB_OK|MB_ICONQUESTION);
		return FALSE;
	}
*/
	ar >> option;
	return TRUE;
}			

void  SaveConfig(const char* filename, WORD option)
{   
	ASSERT(option != 0);
	
	CFile file;
	
	if (!file.Open(filename, CFile::modeCreate|CFile::modeWrite))
	{
		file.Abort();
        MessageBox(NULL,"Error Create Config File",
                   NULL,MB_OK|MB_ICONHAND|MB_ICONSTOP);
        return;
    }
    CArchive ar(&file,CArchive::store);
    
	SaveConfigHead(ar, option);
	    
    if (option & STORE_MAP)
    	SaveMapToFile(ar);
    
    if (option & STORE_EVENT)
		SaveEventToFile(ar);
	
	if (option & STORE_QUALIFY)
		SaveQualifyToFile(ar);
		
	ar.Close();
	file.Close();
}
		
    	
void RestoreConfig(const char* filename, WORD option)
{ 
	CFile file;
	
	if (!file.Open(filename, CFile::modeRead))
	{
		file.Abort();
        MessageBox(NULL,"Error Open Config File",
                   NULL,MB_OK|MB_ICONHAND|MB_ICONSTOP);
        return;
    }
    CArchive ar(&file,CArchive::load);
    
    
    WORD wOldOption;

	if (!RestoreConfigHead(ar, wOldOption, TRUE)){
		ar.Close();
		file.Close();
		return;
	}
	
   	WORD wRestoreOption = wOldOption & option;
    if (wRestoreOption == 0){
    	ar.Close();
    	file.Close();
        MessageBox(NULL,"There are no related information in the config file.",
                   NULL,MB_OK|MB_ICONHAND|MB_ICONSTOP);
    	return;                
	}    
    
    if (wRestoreOption != option){
    	CString	strBuf = "Config file only contain ";
    	
    	if (wOldOption & STORE_MAP)
    		strBuf += "Map ";
    	if (wOldOption & STORE_EVENT)
    		strBuf += "Event ";
    	if (wOldOption & STORE_QUALIFY)
    		strBuf += "Qualify ";
    		
    	strBuf += "data.\nDo you want to continue?";
    	
    	if (MessageBox(NULL, strBuf, "Do you want to continue", 
    		MB_YESNO | MB_ICONQUESTION) != IDYES)
    	{
    		ar.Close();
    		file.Close();
    		return;
    	}
    }	
    
    if (wOldOption & STORE_MAP)
    	RestoreMapFromFile(ar, option & STORE_MAP);
    
    if (wOldOption & STORE_EVENT)
		RestoreEventFromFile(ar, option & STORE_EVENT);
	
	if (wOldOption & STORE_QUALIFY)
		RestoreQualifyFromFile(ar, option & STORE_QUALIFY);

	ar.Close();
	file.Close();
}


/* when user clear trace buffer in shell window or from menu
   I have to record this flag to indicate trace is empty
   when user let EP run again, we need let trace buffer is valid again
*/

BOOL IsTraceClear()
{
	return trace.IsClear();
}    

void ClearTraceCache()
{
	traceMan.ClearCache();
}

#ifdef __cplusplus
extern "C" {
#endif	// __cplusplus

void WINAPI ValidTraceBuffer()
{
	trace.ValidBuffer();  
	ClearTraceCache();
}

void WINAPI TraceWnd(unsigned char nStatus)
{                 
	int nErrorID;
	
	nErrorID = emuSetTraceStatus(nStatus);
	if(ICE_OK != nErrorID)
    {
    	trace.DisplayErrorMessage(ER_ICE_OK+nErrorID);
    }
	else SetTraceOn(nStatus);  // for John
}            

BOOL WINAPI GetElapseTimeStr(char* szStr)
{                    
	return list.GetElapseTimeStr(szStr);
}
	

#ifdef __cplusplus
}
#endif	// __cplusplus

void  RefreshTraceWnd()
{
	if (gp_TraceWnd)
		gp_TraceWnd->PostMessage(WM_COMMAND,ID_VIEW_REFRESH, NULL);
}

void  TS_TraceClear()
{
	trace.SetClearFlag();
}

DWORD TS_GetLastFrame()
{   
	return traceMan.TS_GetLastFrame();
}

int  TS_GetBusRecord(int nFlag, DWORD& dwCurFrame, DWORD& dwFrameNum, 
				FrameData* pReturnBuf)
{                              
	return traceMan.TS_GetBusRecord(nFlag, dwCurFrame, dwFrameNum,
			pReturnBuf);
}	                      

int  TS_GetInsRecord(int nFlag, DWORD& dwCurFrame, BYTE& byIntNo, DWORD& dwFrameNum, 
				InsData* pReturnBuf)
{                              
	return traceMan.TS_GetInsRecord(nFlag, dwCurFrame, byIntNo, dwFrameNum,
			pReturnBuf);
}	                      

BOOL  TS_GetBusEv(int nEvID, BOOL& bClearFlag, BUS_EVENT& evData)
{
	switch(nEvID){
		case 1:
			return ev1.DumpEvent(bClearFlag, evData);
		case 2:
			return ev2.DumpEvent(bClearFlag, evData);
		default: ASSERT(0);
	}
	
	return FALSE;
}
			
STATUS	TS_SetBusEv(int nEvID, BOOL bClearFlag, BUS_EVENT evData)
{
	switch(nEvID){
		case 1:
			return ev1.SetByWin(bClearFlag, evData);
		case 2:
			return ev2.SetByWin(bClearFlag, evData);
		default: ASSERT(0);
	}
	
	return ICE_OK;
}

	
BOOL 	TS_GetExtEv(WORD& evData)
{
	return ev3.DumpEvent(evData);
}

STATUS 	TS_SetExtEv(WORD evData)
{                                
	return ev3.SetByWin(evData);
}
                     
BOOL 	TS_GetLevel(int nLvID, TRIGGER_LEVEL& lvData)
{
	switch(nLvID){
		case 1:
			return Le1.DumpLevel(lvData);
		case 2:
			return Le2.DumpLevel(lvData);
		default: ASSERT(0);
	}
	
	return FALSE;
}
		
STATUS 	TS_SetLevel(int nLvID, TRIGGER_LEVEL lvData)
{
	switch(nLvID){
		case 1:
			return Le1.SetByWin(lvData);
		case 2:
			return Le2.SetByWin(lvData);
		default: ASSERT(0);
	}
	
	return ICE_OK;
}                     
			
BOOL 	TS_GetTrigger(TRIGGER_LOGIC& trigData)
{
	return Trig.DumpTrig(trigData);
}

STATUS 	TS_SetTrigger(TRIGGER_LOGIC trigData)
{
	return Trig.SetByWin(trigData);
}

BOOL 	TS_GetTrigStatus(BOOL& bTrigStatus)
{
	return Trig.DumpTrigStatus(bTrigStatus);
}

STATUS 	TS_SetTrigStatus(BOOL bTrigStatus)
{
	return Trig.SetStatusByWin(bTrigStatus);
}

BOOL 	TS_GetQualify(BOOL bHard, QUALIFY& qlfyData)
{
	if (bHard)
		return qlfy.DumpQualify(qlfyData);
	else return traceMan.DumpQualify(qlfyData);
}

STATUS 	TS_SetQualify(BOOL bHard, QUALIFY qlfyData)
{
	if (bHard)
		return qlfy.SetByWin(qlfyData);
	else{
		traceMan.SetFilter(qlfyData); 
		ClearTraceCache();
		return ICE_OK;
	}
}

BOOL 	TS_GetTraceOnGo(BOOL& trcData)
{
	return trace.DumpStatus(trcData);
}

STATUS 	TS_SetTraceOnGo(BOOL trcData)
{
	return trace.SetByWin(trcData);
}

BOOL 	TS_GetWildCard(	BOOL bAddr, int nValBits, U32 dwVal, 
		U32 dwValMask, char* pBuf)
{  
	CTraceBase trcBase;
	
	int nType = bAddr ?  CTraceBase::ADDR_TYPE : CTraceBase::DATA_TYPE;
	
	trcBase.StrFromValueMask(pBuf, dwVal, dwValMask, nValBits, nType);
	
	return TRUE;
}

BOOL 	TS_SetWildCard(BOOL bAddr, int /*nValBits*/, U32& dwVal, 
		U32& dwValMask, const char* pBuf)
{
	CTraceBase trcBase;
	
	int nType = bAddr ?  CTraceBase::ADDR_TYPE : CTraceBase::DATA_TYPE;
	
	if (trcBase.IsBinary(pBuf, nType))
		trcBase.ValueMaskFromStr(pBuf, dwVal, dwValMask, 2, nType);
	else
		trcBase.ValueMaskFromStr(pBuf, dwVal, dwValMask, 16, nType);
	
	return TRUE;		
}	

BOOL	TS_SaveTraceToFile(int nTraceMode, const char* szFileName, DWORD dwStart,
					DWORD dwEnd, BOOL bOverWrite)
{
	return traceMan.SaveTraceToFile(nTraceMode, szFileName, dwStart, dwEnd, bOverWrite);
}

BOOL SetTraceStatus(int nStatus)
{                 
	int nErrorID;
	
	nErrorID = emuSetTraceStatus((BYTE)nStatus);
	if(ICE_OK != nErrorID)
    {
    	trace.DisplayErrorMessage(ER_ICE_OK+nErrorID);
    	return FALSE;
    }
	else SetTraceOn((BYTE)nStatus);  // for John
	    
    return TRUE;
}  

BOOL SaveCurTraceStatus()
{
	return trace.GetCurStatus();
}

BOOL RestoreLastTraceStatus()
{
	return trace.RestoreSet();
}          

void ShowMsgToStatusBar(const char* szMsg)
{
	UpdateStatusBar(0, szMsg);
		
	MSG msg;
	
	HWND hStatusBar = ((CMainFrame*)(AfxGetApp()->m_pMainWnd)
						)->m_wndStatusBar.m_hWnd;

	while (PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE)) {
	    TranslateMessage(&msg);
	    DispatchMessage(&msg);
	}

/*	
	while (PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE)) {
	    TranslateMessage(&msg);
	    DispatchMessage(&msg);
	}  
*/
}

void ShowReadTraceCurSite(DWORD dwCur)
{
	char szBuf[200];
	
	wsprintf(szBuf, "Read trace from 0X%lX", dwCur);
	
	ShowMsgToStatusBar(szBuf);
}

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