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

#include "uicom2.h"
#include "memwin.h"
#include "colors.h"
#include "bankinit.h"
#include "ep196.h"
#include "abiextfn.h"
//#include "contain.h"
#include "ldrexp.h"
#include "cpusvr.h"

#include "srcdef.h"
#include "trcpub.h"
#include "cpuwin.h"
#include "stkexp.h"

#include "stdlib.h"
#include "direct.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

BOOL	gb_isMemOn[MAX_MEM_WND] = {FALSE};
BOOL	gb_isCpuOn = FALSE;
BOOL	gb_isTraceOn = FALSE;
BOOL    isVariableOn = FALSE;        
BOOL 	isStackOn = FALSE;    
extern BOOL    isShellOn    ;      
extern BOOL gb_isPeriOn;

CMDIChildWnd*	gp_MemWnd[MAX_MEM_WND];
CMDIChildWnd*	gp_CpuWnd;
CMDIChildWnd*	gp_TraceWnd;
CMDIChildWnd    * pVariableWnd = NULL;
CMDIChildWnd    * pStackWnd = NULL;
extern CMDIChildWnd    * pShellWnd;  
extern CMDIChildWnd* 	gp_PeriWnd; 

extern void ShlOpenWindow(CMDIFrameWnd * pParent, BOOL isHide);
extern void CpuOpenWindow(CMDIFrameWnd * pParent, BOOL isHide);
extern void TrcOpenWindow(CMDIFrameWnd * pParent);
extern void NewMemoryOpenWindow(CMDIFrameWnd *pParent,int no);
extern void StkOpenWindow(CMDIFrameWnd* /* pParent */);
extern void VarOpenWindow(CMDIFrameWnd* /* pParent */);
extern void PeriOpenWindow(CMDIFrameWnd * /*pParentWnd*/);
extern void VarUpdateWholeWindow();
extern void StkUpdateStackWindow(BOOL bUpdateStackOnly = FALSE);

extern void FreshPer();

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   isspace
//
//  Description: Test if the specified char is a white space
//
//  Input:  
//      ch -- the char to test
//
//  Output: None
//
//  Return: TRUE -- the char is a white space
//
/////////////////////////////////////////////////////////////////////////////
static BOOL isspace(char ch)
{
    return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r';
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   SkipHeadWS
//
//  Description: Skip head white space of the string
//
//  Input:  
//      psz -- the string
//
//  Output: None
//
//  Return: the string that been processed
//
/////////////////////////////////////////////////////////////////////////////
static char * SkipHeadWS(char * psz)
{
    while(isspace(*psz))    ++ psz;
    return psz;
}              

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
static void CutTailWS(char * psz)
{
    int l = strlen(psz);
    if(!l)  return;     
    psz += l - 1;
    while(isspace(*psz))    -- psz;
    *(psz+1) = '\0';
}                

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Transfer a string to a decimal number
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
static BOOL Dec2Num(char * psz, DWORD & dwVal)
{
    char * p = psz;
                   
    int l = strlen(p);
    if(l == 0)  return FALSE;
                              
    DWORD dw = 1;                              
    dwVal = 0;      
    p += l - 1;
    for(int i = 0; i < l; i ++, p --, dw *= 10) {
        if(*p < '0' || *p > '9')    return FALSE;
        dwVal += (*p - '0') * dw;
    }
    return TRUE;    
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
static BOOL Hex2Num(char * psz, DWORD & dwVal)
{
    char * p = psz;
                   
    int l = strlen(p);
    if(l == 0)  return FALSE;
                              
    DWORD dw = 1;                              
    dwVal = 0;      
    p += l - 1;
    for(int i = 0; i < l; i ++, p --, dw *= 16) {
        if(*p >= '0' && *p <= '9')  dwVal += (*p - '0') * dw;
        else if(*p >= 'a' && *p <= 'f') dwVal += (*p - 'a' + 10) * dw;
        else if(*p >= 'A' && *p <= 'F') dwVal += (*p - 'A' + 10) * dw;
        else    return FALSE;
    }
    return TRUE;    
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL Str2Num(char * psz, DWORD & dwVal)
{
    char * p = SkipHeadWS(psz);

    CutTailWS(p);                   
                 
    if(*p == '0' && (*(p+1) == 'x' || *(p+1) == 'X')) {
        p += 2;
        return  Hex2Num(p, dwVal);
    }                               
    else return Dec2Num(p, dwVal);
}
//start of repaint section                                       

#ifdef __cplusplus
extern "C" {
#endif	// __cplusplus                                       
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Uodate CPU window
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void WINAPI RepaintCPU(void)
{
	// Added by Chen, 06/05/96.
	// Return if EP is not halt. 
	
	unsigned char uchStatus;
	if ( FALSE == ::GetCpuStatus(uchStatus) ) {
		return;
	}
	else if ( STATUS_HALT != uchStatus && STATUS_GOMONI != uchStatus ) {
		return;
	}
    if(gb_isCpuOn) {
    	gp_CpuWnd->SendMessage(XM_REPAINT);
    	gp_CpuWnd->UpdateWindow();	
    }	
    	//((CCpuWindow*)gp_CpuWnd)->OnXMRepaint(0,0);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Update memory window
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void WINAPI RepaintMemory(void)
{
	// Added by Chen, 06/05/96.
	// Return if EP is not halt.
	unsigned char uchStatus;
	if ( FALSE == ::GetCpuStatus(uchStatus) ) {
		return;
	}
	else if ( STATUS_HALT != uchStatus && STATUS_GOMONI != uchStatus ) {
		return;
	}

    if(gb_isMemOn[0]) {
        gp_MemWnd[0]->SendMessage(XM_REPAINT);
    	gp_MemWnd[0]->UpdateWindow();
    }	
//    if(isMemOn[1])     pMemWnd[1]->SendMessage(XM_REPAINT);
//    if(isMemOn[2])     pMemWnd[2]->SendMessage(XM_REPAINT);
}


void WINAPI RepaintPeri(void)
{
	// Added by Chen, 06/05/96.
	// Return if EP is not halt.
	unsigned char uchStatus;
	if ( FALSE == ::GetCpuStatus(uchStatus) ) {
		return;
	}
	else if ( STATUS_HALT != uchStatus && STATUS_GOMONI != uchStatus ) {
		return;
	}
    if(gb_isPeriOn)  { 
    	FreshPer();
    	gp_PeriWnd->UpdateWindow();
    }	
}

void WINAPI RepaintWindows(void)
{
	// Added by Chen, 06/05/96.
	// Return if EP is not halt.
	/*
	unsigned char uchStatus;
	if ( FALSE == ::GetCpuStatus(uchStatus) ) {
		return;
	}
	else if ( STATUS_HALT != uchStatus && STATUS_GOMONI != uchStatus ) {
		return;
	}
    */
    
	// Update source window
	::SrcUpdateSourceWindow(::srcStep);

      RepaintCPU();
//    RepaintBMemory();
//    if(IsRunAccess())
      RepaintMemory();
      RepaintVariable();
      RepaintStack();
//      RepaintTrace();
      RepaintPeri();
//    FreshPer();
      
      // Message progress
}

void WINAPI OnEmulation(void)
{           
	RepaintWindows();
}

//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
////////////////////implement by other////////////////////
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////

void WINAPI RepaintStack(void)
{                       
	// Added by Chen, 06/05/96.
    // Return if EP is not halt.
    Stk_SetStkDirty();
    unsigned char uchStatus;
    if ( FALSE == ::GetCpuStatus(uchStatus) ) {
        return;
    }
    else if ( STATUS_HALT != uchStatus && STATUS_GOMONI != uchStatus ) {
        return;
    }

//    if(isStackOn)     pStackWnd->SendMessage(XM_REPAINT);
    
    if(isStackOn)   {
    	StkUpdateStackWindow();         
    	pStackWnd->UpdateWindow();
    }	
    
}

void WINAPI RepaintVariable(void)
{ 
	// Added by Chen, 06/05/96.
    // Return if EP is not halt.
    unsigned char uchStatus;
    if ( FALSE == ::GetCpuStatus(uchStatus) ) {
        return;
    }
    else if ( STATUS_HALT != uchStatus && STATUS_GOMONI != uchStatus ) {
        return;
    }
//    if (isVariableOn)   pVariableWnd->SendMessage(XM_REPAINT);

    if(isVariableOn) {
    	VarUpdateWholeWindow();
    	pVariableWnd->UpdateWindow();
    }	
}

BOOL WINAPI GetCpuStatus(BYTE& uchStatus) {

	U32 dwTmp;
	if(ICE_OK != emuGetCpuStatus(&dwTmp)) return FALSE; 	
	
	if((dwTmp&0x08) == 0x08) {
		SetTraceOn(1);
	} else {
		SetTraceOn(0);
	}               
	
	if((dwTmp&0x10) == 0x0) {
		uchStatus = (BYTE)STATUS_HALT;
		if(STATUS_HALT != GetCpuStatus2() && STATUS_HALT == uchStatus) {
			// Add elapse timer.
	        char timeStr[30];
		    if(GetElapseTimeStr(timeStr)) {
		    	UpdateStatusBar(6, timeStr);
		    }
		}
		SetCpuStatus2(uchStatus);
		return TRUE;
	}               
	dwTmp = (dwTmp&0x380)>>7;
	switch(dwTmp) {
		case 0: uchStatus = (BYTE)STATUS_SLEEPING; break;
		case 1: uchStatus = (BYTE)STATUS_IDLE; break;
		case 2: uchStatus = (BYTE)STATUS_POWERDOWN; break;
		default: uchStatus = (BYTE)STATUS_GO; break;
	}                        
	if(STATUS_HALT != GetCpuStatus2() && STATUS_HALT == uchStatus) {
		// Add elapse timer.
        char timeStr[30];
	    if(GetElapseTimeStr(timeStr)) {
	    	UpdateStatusBar(6, timeStr);
	    }
	}
	SetCpuStatus2(uchStatus);                             
	return TRUE;
}

void WINAPI DoReset()
{   
	ADDRESS addr;
	unsigned long lTmp;
	int nBank;
	LdrGetStartAddress(lTmp, nBank);
//	addr.adrSpace = (BYTE)(lTmp>>16);  
//	addr.adrAddress = lTmp&0xffff;
	addr.adrSpace = 0;
	addr.adrAddress = 0x2080;
	
	CpuReset(addr);
}

static CString strcwd;

void WINAPI SetCurLoadPath()
{
    CString strPath="";
    char path_buffer[_MAX_PATH];
    char drive[_MAX_DRIVE];
    char dir[_MAX_DIR];
    char path_buffer2[_MAX_PATH];
    
    _getcwd(strcwd.GetBuffer(_MAX_PATH), _MAX_PATH-1);
    strcwd.ReleaseBuffer();
    strcwd.MakeUpper();
    
    ((CEp196App*)AfxGetApp())->GetLatestFile(strPath);
    
    if (strPath.IsEmpty()) return;
//	strPath = AfxGetApp()->GetProfileString("Recent File List", "File1");
//	if(_stricmp(strPath,"")==0) return; 
	
	strPath.MakeUpper();
	if(strPath.GetLength() > _MAX_PATH) return ;
	strcpy(path_buffer, strPath);
	_splitpath( path_buffer, drive, dir, NULL, NULL );
    _makepath(path_buffer2, drive, dir, NULL, NULL);
    
    _chdrive(toupper(path_buffer2[0])-'A'+1);
    _chdir(path_buffer2);                   
    return ;     
}

void WINAPI RestoreLastPath()
{
//    char drive[_MAX_DRIVE];
//    char dir[_MAX_DIR];
    char path_buffer[_MAX_PATH];
    
	strcpy(path_buffer, strcwd);
    
    _chdrive(toupper(path_buffer[0])-'A'+1);
    _chdir(path_buffer);                   
    return ;     
	
} 

#ifdef __cplusplus
}
#endif	// __cplusplus          

ADDRESS GetLoadPC(void)
{
	ADDRESS addr;

	addr.adrSpace=0;
	addr.adrAddress=0;
	return addr;
}

BOOL IsMapCombination(void)
{
extern int g_nMemMode;
	return g_nMemMode==0;
}

int GetBankNum(void)
{
extern int g_nMemMode;
extern int g_nBankNumber;

	if(g_nMemMode==0)
		return g_nBankNumber?g_nBankNumber*2:1;
	else
		return g_nBankNumber?4:2;
}


/////////////////////////////////////////////////////////////////////////////
// Save/Restore window Position & size

static char BASED_CODE szSection[] = "WindowPos";
static char * szWindowPos[] = {
    // sorted by window ID
    "MainFrame",    
    "CPU",
    "Shell",
    "Trace",
    "Memory1",          
    "Memory2",
    "Memory3",
    "Source",
    "Browse",
    "Stack",
    "Variable",
    "Peripheral",
};    
static char szFormat[] = "%d %u,%u,%d,%d,%d,%d,%d,%d,%d,%d";

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL ReadWindowPlacement(int nWID2, LPWINDOWPLACEMENT pwp, BOOL &isOpened)
{
    CString strBuffer = AfxGetApp()->
        GetProfileString(szSection, szWindowPos[nWID2]);
    if (strBuffer.IsEmpty())
        return FALSE;

    WINDOWPLACEMENT wp;                  
    int nOpened;
    int nRead = sscanf(strBuffer, szFormat, &nOpened,
        &wp.flags, &wp.showCmd,
        &wp.ptMinPosition.x, &wp.ptMinPosition.y,
        &wp.ptMaxPosition.x, &wp.ptMaxPosition.y,
        &wp.rcNormalPosition.left, &wp.rcNormalPosition.top,
        &wp.rcNormalPosition.right, &wp.rcNormalPosition.bottom);

    if (nRead != 11)
//    if (nRead != WID2_COUNT)
        return FALSE;

    wp.length = sizeof wp;
    *pwp = wp;     
    isOpened = nOpened;
    return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void WriteWindowPlacement(int nWID2, LPWINDOWPLACEMENT pwp, BOOL isOpened)
    // write a window placement to settings section of app's ini file
{
    char szBuffer[100];
    
    sprintf(szBuffer, szFormat, isOpened,
        pwp->flags, pwp->showCmd,
        pwp->ptMinPosition.x, pwp->ptMinPosition.y,
        pwp->ptMaxPosition.x, pwp->ptMaxPosition.y,
        pwp->rcNormalPosition.left, pwp->rcNormalPosition.top,
        pwp->rcNormalPosition.right, pwp->rcNormalPosition.bottom);

    AfxGetApp()->WriteProfileString(szSection, szWindowPos[nWID2], szBuffer);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void SaveWindowPlacement(void)
{
    WINDOWPLACEMENT wp;
    CWnd * pWnd;
    BOOL isOpened;

    wp.length = sizeof wp;          
    
    // Save Mainframe
    for(int i = 0; i < WID2_COUNT; i ++) {
        if(i == WID2_MAIN) { 
            pWnd = AfxGetApp()->m_pMainWnd;
            isOpened = TRUE;
        } else if(i == WID2_CPU) {
            pWnd = gp_CpuWnd;
            isOpened = gb_isCpuOn;
        } else if(i == WID2_PERI) {
            pWnd = gp_PeriWnd;
            isOpened = gb_isPeriOn;
        } else if(i == WID2_SHELL) {
            pWnd = pShellWnd;
            isOpened = isShellOn;
        } else if(i == WID2_TRACE) {
            pWnd = gp_TraceWnd;
            isOpened = gb_isTraceOn;
        } else if(i == WID2_MEMORY) {
            pWnd = gp_MemWnd[0];
            isOpened = gb_isMemOn[0];
        } else if(i == WID2_MEM2) {
            pWnd = gp_MemWnd[1];
            isOpened = gb_isMemOn[1];
        } else if(i == WID2_MEM3) {
            pWnd = gp_MemWnd[2];
            isOpened = gb_isMemOn[2];
        } else if(i == WID2_SOURCE) {
        	pWnd = ::SrcGetSourceWindow();
            isOpened = ::SrcIsSourceWindowOpened();
        } else if(i == WID2_STACK) {
            pWnd = pStackWnd;
            isOpened = isStackOn;
        } else if(i == WID2_VARIABLE) {
            pWnd = pVariableWnd;
            isOpened = isVariableOn;
        } else if(i == WID2_BROWSE) {
            pWnd = ::SrcGetBrowseWindow();
            isOpened = ::SrcIsBrowseWindowOpened();
        } 
             
        //if(NULL == pWnd) continue;
        if(isOpened && pWnd->GetWindowPlacement(&wp))
        {
            wp.flags = 0;
            if (pWnd->IsZoomed())
                wp.flags |= WPF_RESTORETOMAXIMIZED;
        }
        WriteWindowPlacement(i, &wp, isOpened);
    }
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL RestoreWindowPlacement(void)
{
    WINDOWPLACEMENT wp;
    CWnd * pWnd;
    BOOL isOpened;
    BOOL isInit = FALSE;

    wp.length = sizeof wp;          
    
    // Save Mainframe
    for(int i = 0; i < WID2_COUNT; i ++) {
        if(!ReadWindowPlacement(i, &wp, isOpened) || !isOpened) continue;
        if(i == WID2_MAIN) { 
            pWnd = AfxGetApp()->m_pMainWnd;
        } else if(i == WID2_CPU) {
            CpuOpenWindow((CMDIFrameWnd *)(AfxGetApp()->m_pMainWnd), TRUE);
            pWnd = gp_CpuWnd;      
        } else if(i == WID2_PERI) {
            PeriOpenWindow((CMDIFrameWnd *)(AfxGetApp()->m_pMainWnd));
            pWnd = gp_PeriWnd;      
        } else if(i == WID2_SHELL) {
            ShlOpenWindow((CMDIFrameWnd *)(AfxGetApp()->m_pMainWnd), TRUE);
            pWnd = pShellWnd;
        } else if(i == WID2_TRACE) {
            TrcOpenWindow((CMDIFrameWnd *)(AfxGetApp()->m_pMainWnd));
            pWnd = gp_TraceWnd;
        } else if(i == WID2_MEMORY) {
            NewMemoryOpenWindow((CMDIFrameWnd *)(AfxGetApp()->m_pMainWnd), 0);
            pWnd = gp_MemWnd[0];
        } else if(i == WID2_SOURCE) {
			::SrcOpenSourceWindow();
        	pWnd = ::SrcGetSourceWindow();
        } else if(i == WID2_STACK) {
            StkOpenWindow((CMDIFrameWnd *)(AfxGetApp()->m_pMainWnd));
            pWnd = pStackWnd;
        } else if(i == WID2_VARIABLE) {
            VarOpenWindow((CMDIFrameWnd *)(AfxGetApp()->m_pMainWnd));
            pWnd = pVariableWnd;
        } else if(i == WID2_MEM2||i == WID2_MEM3) {
        /*
            BMemOpenWindow((CMDIFrameWnd *)(AfxGetApp()->m_pMainWnd));
            pWnd = pBMemWnd;
        */    
        } else if ( i == WID2_BROWSE ) {
			::SrcOpenBrowseWindow();
            pWnd = ::SrcGetBrowseWindow();
        }       	
        isInit = TRUE;
        pWnd->SetWindowPlacement(&wp);
        if(i != WID2_MAIN)    
            ((CMDIChildWnd *)pWnd)->MDIActivate();
    }             
        
    return isInit;
}


