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

/***************************************************************************
**
** File name : dadshell.cpp
** Author:John Zhou
** Description:
**    Functions defined in this file are prepared for the using of shell window.
**
**
**    Finished date: 1995.4.28
**
**
**    Copyright (C) 1995 Microtek International, Inc.
**    All Rights Reserved
**
****************************************************************************/

#include "stdafx.h"
#include "dadshell.h"
#include "address.h"

#include "srcdef.h"
#include "uicom2.h"

C196DAD dad196;      
CBaseDAD* pDad196 = &dad196;
static char strShellAddr[20];

//convert function
ADDR_RETCODE AdrDadAddrToHexEx( const ADDR addr, LPSTR adrstr )
{ 
	ADDRESS tmpAddr;      
	tmpAddr.adrSpace = (ADDR_SPACE)addr.addrType;
	tmpAddr.adrAddress = addr.addr;
	return AdrDadAddrToHex(tmpAddr,adrstr);
 } 
 
ADDR_RETCODE AdrTextToAddrEx(const LPSTR  adrstr, ADDR &addr)
{ 
	ADDRESS tmpAddr;
	ADDR_RETCODE nAddrRet = AdrTextToAddr(adrstr,tmpAddr);	
	addr.addrType = tmpAddr.adrSpace;
	addr.addr = tmpAddr.adrAddress;
	return nAddrRet;
 }
//this function defined for shell window's disassemble commmand using(only called by Chen)
void DisassembleCmd(int nArgc,char *psgArgv[])
{                
	
    STATUS  nErrorID;
    long lLen;
    ADDR_RETCODE nAddrRet;
    ADDR addrStart,addr2;                  
    C196DADMem tmpDADMem;
    CBaseDADMem* pDADMem = &tmpDADMem; 
    char strAdrSave[20];
 
	switch(nArgc) {            
    	case 1: //get PC from ABI      
    	nErrorID = emuGetReg(0, REG_PC ,&(addrStart.addr));
		    if(ICE_OK != nErrorID) { 
		        ShowLine("Communication error!");
		        return;
		    }     
		    addrStart.addrType = ((addrStart.addr>>16) & 3) 
		    						+ MEM_P0;
		    addrStart.addr = addrStart.addr&0xffff;
		    lLen = DISASMLEN;
		    break;
           
   		case 2:  
   			nAddrRet = AdrTextToAddrEx(psgArgv[1],addrStart);            
   			if (ADR_OK != nAddrRet) ASSERT(FALSE);
   			if (addrStart.addrType > MEM_X3 || addrStart.addrType<MEM_P0) {
   				ShowLine("address wrong!");
   				return;
   			}
		    lLen = DISASMLEN;   		
            break;
   		case 3:
   			nAddrRet = AdrTextToAddrEx(psgArgv[1],addrStart);            
   			if (ADR_OK != nAddrRet) ASSERT(FALSE);
   			if (addrStart.addrType > MEM_X3 || addrStart.addrType<MEM_P0) {
   				ShowLine("address wrong!");
   				return;
   			}
   			nAddrRet = AdrTextToAddrEx(psgArgv[2],addr2);            
   			if (ADR_OK != nAddrRet) ASSERT(FALSE);
   			if(addr2.addrType == SPACE_UNDEFINE) addr2.addrType = addrStart.addrType;
   			if (addr2.addrType > MEM_X3 || addr2.addrType<MEM_P0) {
   				ShowLine("address wrong!");
   				return;
   			}                     
   			lLen = addr2.addr - addrStart.addr +1;
            break; 
   		case 4:   
   			nAddrRet = AdrTextToAddrEx(psgArgv[1],addrStart);            
   			if (ADR_OK != nAddrRet) ASSERT(FALSE);
   			if (addrStart.addrType > MEM_X3 || addrStart.addrType<MEM_P0) {
   				ShowLine("address wrong!");
   				return;
   			}
   			nAddrRet = AdrTextToAddrEx(psgArgv[3],addr2);            
   			if (ADR_OK != nAddrRet) ASSERT(FALSE);
   			lLen = addr2.addr;
            break; 
   		default:
   			addrStart.addrType = MEM_P0;
   			addrStart.addr = 0;
            lLen=1;        
    } 
    
    C196DADSym pSym;         
    C196DADSym::m_isSymbolic = TRUE;
    CString strShell = "LOC      OBJ CODE       SOURCE CODE ";
    ShowLine(strShell.GetBuffer(strShell.GetLength()+5));
    strShell.ReleaseBuffer();
    //PREPARE MEMORY
    if ( !pDADMem->SetAddr(addrStart) ) {
    	ShowLine("READING ERROR!");
    	return;
    }
    if ( !pDADMem->UpdateBuffer() ) {
    	ShowLine("READING ERROR!");
    	return;
    }
    pDADMem->SetMaxAddr(0xffff); 
    
    pDad196->Baby.Clear();                
    //set 196 sfr window map
    ((C196DAD*)pDad196)->SetCurWindow(::GetCurHWindow());
    
 	while( 0 < lLen ) {     
 		pDad196->Baby.Clear();  
 		//save current address      
 		ADDR addrTmp;
 		pDADMem->GetAddr(addrTmp);              
 		nAddrRet = AdrDadAddrToHexEx(addrTmp,strAdrSave);            
		if (ADR_OK != nAddrRet) ASSERT(FALSE);
		
		if (!pDad196->Das(*pDADMem)) { 		
			//show error infor 
			pDADMem->SetAddr(addrTmp); 
			lLen--;
			strShell = strAdrSave;
			if (strShell.GetLength() >= 8) 
				strShell = strShell.Mid(strShell.GetLength()-8,6);
			strShell += "  ";		      
			//show wrong code            
			BYTE bTmp;             
			char pcTmp[10];
			pDADMem->ReadByte(bTmp);
			sprintf(pcTmp,"%02X",bTmp);
			strShell += pcTmp;
			BYTE bTmpLen = (BYTE)strShell.GetLength();
			for (int i=0;i<24-bTmpLen;i++) 
				strShell += ' ';
			//show "?"
			//requie by Dome Lui to covert "?" to "DB"
			strShell += "DB ";
			strShell += pcTmp;
			ShowLine(strShell.GetBuffer(strShell.GetLength()+10));
			strShell.ReleaseBuffer(); 	
			continue;	
		}

		lLen -= pDad196->GetUsedDasByte();
		//show the result
		strShell = pSym<<pDad196->m_CurrentAddr;
		if("" != strShell) 
			ShowLine(strShell.GetBuffer(strShell.GetLength()+10));
		strShell = strAdrSave;
		if (strShell.GetLength() >= 8) 
			strShell = strShell.Mid(strShell.GetLength()-8,6);
		strShell += "  ";	
		
		strShell += pDad196->Baby.GetCodeStr();
		BYTE bTmpLen = (BYTE)strShell.GetLength();
		for (int i=0;i<24-bTmpLen;i++) 
			strShell += ' ';
		strShell += pDad196->Baby.m_Instruction.GetStr();
		ShowLine(strShell.GetBuffer(strShell.GetLength()+10));
		strShell.ReleaseBuffer(); 
		
		if(TestKey(VK_ESCAPE)) return;
 	}
 }
 
              
//this function prepared for chen(syntax) go give me the address                                               
void AssembleCmd(int nArgc,char *psgArgv[])
{
	STATUS  nErrorID;
    ADDR_RETCODE nAddrRet;
    ADDR addrStart; 
    //ADDRESS addrTmp;
     
	switch(nArgc) {            
    	case 1: //get PC from ABI    
		    nErrorID = emuGetReg(0, REG_PC ,&(addrStart.addr));
		    if(ICE_OK != nErrorID) { 
		        ShowLine("Communication error!");
		        return;
		    }
		    addrStart.addrType = ((addrStart.addr>>16) & 3)
		    					 + MEM_P0;
		    addrStart.addr = addrStart.addr&0xffff;
		    break;
           
   		case 2:  
   			nAddrRet = AdrTextToAddrEx(psgArgv[1],addrStart);            
   			if (ADR_OK != nAddrRet) ASSERT(FALSE);
   			if (addrStart.addrType > MEM_X3 || addrStart.addrType<MEM_P0) {
   				ShowLine("address wrong!");
   				return;
   			}
            break;
   		default:
   			addrStart.addrType = MEM_P0;
   			addrStart.addr = 0;
    } 
    
    nAddrRet = AdrDadAddrToHexEx(addrStart,strShellAddr);
    if (ADR_OK != nAddrRet) {
    	ShowLine("address server error!");
    	return;
    }
    //add ' '
    char tmpStr[15];
    strcpy(tmpStr," ");
    strcat(tmpStr,strShellAddr);
    strcpy(strShellAddr,tmpStr);
    strcat(strShellAddr,"   ");
                                 
    PromptStr[PMT_RND] = strShellAddr;
      
	return;  
 }  
     
//this function defined for Roger(Shell window) to call asssembly function                                                                
void DadAssemble(char *RogerInstr) 
{          
    ADDR addrStart;            
    C196DADMem tmpDADMem;
    CBaseDADMem* pDADMem = &tmpDADMem; 
    ADDR_RETCODE nAddrRet = AdrTextToAddrEx(strShellAddr,addrStart);            
	if (ADR_OK != nAddrRet) ASSERT(FALSE);
	if (addrStart.addrType > MEM_X3 || addrStart.addrType<MEM_P0) {
		ShowLine("address wrong!");
		return;
	}     
	
    if ( !pDADMem->SetAddr(addrStart) ) {
    	ShowLine("READING ERROR!");
    	return;
    }
    pDADMem->SetMaxAddr(0xffff);
	//if NULL input,return
	if( 0 == *RogerInstr ) {
	 	return;
	}	
  
 	if(strlen(RogerInstr)>99) {                                            
    	ShowLine("too much");
   		return;
    }
    //SET BINARY OR SOURCE MODE 
    pDad196->Baby.Clear();                
    ((C196DAD*)pDad196)->SetCurWindow(::GetCurHWindow());
    
    pDad196->Baby = RogerInstr;
	if (!pDad196->Asm(*pDADMem)) {
		if(pDad196->m_nDetailError == CBaseDADMem::ERR_MEM_READ ||
		   pDad196->m_nDetailError == CBaseDADMem::ERR_MEM_WRITE ) 		
		   ShowLine("H/W MEMORY READ/WRITE ERROR!");
		else ShowLine("ASM ERROR");
		return;
	}     
	
	//update shell window address                                      
	pDADMem->GetAddr(addrStart);
	nAddrRet = AdrDadAddrToHexEx(addrStart,strShellAddr);
	if (ADR_OK != nAddrRet) {
    	ShowLine("address server error!");
    	return;
    }
    //add ' '
    char tmpStr[15];
    strcpy(tmpStr," ");
    strcat(tmpStr,strShellAddr);
    strcpy(strShellAddr,tmpStr);
    strcat(strShellAddr,"   ");
	
	PromptStr[PMT_RND] = strShellAddr;         
	
	//update windows             
	if (addrStart.addrType >= MEM_P0 || addrStart.addrType<=MEM_P3) {
		::SrcUpdateSourceWindow(::srcUpdate);
		::SrcUpdateBrowseWindow(::brwUpdate);
	}

	RepaintMemory();
   
 }//function   
 
