

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

/***************************************************************************
**
** File name : dadextfn.h
**
** Description:
**
** Programmer: JOHN CHOW
**
**
**    Copyright (C) 1996 Microtek International, Inc.
**    All Rights Reserved
**
****************************************************************************/

/***********************************************************************/
//		The following notes will explain how to use these class to 
//		perform the DAD function for source, memory and trace
//	1.for source and memory disassemble
//	  step one: CDADExtFnBase* pClass = new CDADExtFnCom(addrStart,addrEnd);
//			or: CDADExtFnBase* pClass = new CDADExtFnCom(addrStart,instrLen);
//	  step two: int nResult = pClass->GetResult();
//				switch (nResult) {
//					CDADExtFnBase::DAD_OK : //for ok
//					CDADExtFnBase::DAD_READ_ERR : //abi error
//					CDADExtFnBase::DAD_NEED_MORE : //though I give you last
//												   //instruction, but the 
//												   //addrEnd is overflow
//					CDADExtFnBase::DAD_ADDR_INVALID : meet invalid address 
//				}
//	  step three: //if DAD_OK
//	  			pClass->GetCodeList() //GET CODE LIST(eg:"01FE03")
//	  			pClass->GetInstrList() //GET INSTRUCTION LIST(eg:"NOP")
//	  			pClass->GetSymList()  //GET SYMBOL LIST(eg:"#GATES") 
//	  			pClass->GetAddrList() //GET ADDRESS STR LIST(eg:"p0:0000")
//  2.for source and memory assemble
//	  step one: CDADExtFnBase* pClass = new CDADExtFnCom(addr,strAsm);
//	  step two: int nResult = pClass->GetResult();
//				switch (nResult) {
//					CDADExtFnBase::DAD_OK : //ok
//					CDADExtFnBase::DAD_WRITE_ERR : //abi error
//					CDADExtFnBase::DAD_ASM_ERROR : //strAsm has no meaning
//				}
//	  step three: //if DAD_OK
//				BYTE bLen = pClass->GetAsmCodeLen(); //get this instruction
//												     //code length,so you can
//	   												 //make next address.
//	3.for trace ---------- wait for check
//  4.for emulation server to get next addresses
//		step one:CDADExtFnBase* pClass = new CDADExtFnEmuAddr(addrStart);
//	    step two: int nResult = pClass->GetResult();
//				switch (nResult) {
//					CDADExtFnBase::DAD_OK : //for ok
//					CDADExtFnBase::DAD_READ_ERR : //abi error
//					CDADExtFnBase::DAD_NEED_MORE : //though I give you last
//												   //instruction, but the 
//												   //addrEnd is overflow
//					CDADExtFnBase::DAD_ADDR_INVALID : meet invalid address 
//				}        
//	    step three : Addr tmpAddr;
//				for (int i=0;i<pClass->GetLen();i++) 
//					tmpAddr = pClass->GetAddr(i);	
//				}
//appendix 1
//you can use GetIsDirtyResultArray() to get the information if disassemble result is dirty("?")
//appendix 2
//how to get the instruction type(normal,jump or maybe jump)
//if disasm is ok then, you can use:
//int nType = ((m_pDadOk->Baby).GetInstructionType(); 
//switch(nType) {
//	case CAnalyseInstruction::TYPE_NORMAL:
//  case CAnalyseInstruction::TYPE_JUMP: 
//  case CAnalyseInstruction::TYPE_MAYBE_JUMP: 
// }


#ifndef _DADEXTFN_
#define _DADEXTFN_

#include "stdafx.h"
#include "abibase.h"
#include "dad196.h"
#define DAD_ADDR_MAX 0xffff
//EXTERNAL FUNCTION
extern ADDR_RETCODE AdrDadAddrToHexEx( const ADDR addr, LPSTR adrstr );
extern ADDR_RETCODE AdrTextToAddrEx(const LPSTR  adrstr, ADDR &addr);
//these class is defined for dad functions called by mem and trc and src
/********************** for class CDADExtFnBase *******************************/
class CDADExtFnBase : public CObject                         
{                    
//member
protected:
	ADDR m_addrStart;
	ADDR m_addrEnd;
	int m_nResult;
	
	CObject* m_pContain;       
	CStringList m_listCode;    //for disassemble result
	CStringList m_listInstr;   //
	CStringList m_listSym;     //
	CStringList m_listAddr;    //         
	CWordArray m_arrayIsDirtyResult;
	CString m_strAsm;          //for assemble input
	BYTE m_bAsmCodeLen;
	WORD m_wNeedInstrLen;      //for disasm
	
	C196DAD m_dad196;      
	C196DADMem m_DADMem; 
	CBaseDAD* m_pDadOk;
	
public:
	enum { DAD_OK, DAD_READ_ERR, DAD_WRITE_ERR, DAD_NEED_MORE,
		   DAD_ASM_ERROR, DAD_ADDR_INVALID };
//construct & destruct
protected:
	CDADExtFnBase() {
	    m_dad196.SetCurWindow(0);
	    m_pDadOk = &m_dad196;	
	};
//operator
public:          
	int GetResult() { return m_nResult; };
	BYTE GetAsmCodeLen() { return m_bAsmCodeLen; };
	void SetAddress(ADDR addrStart,ADDR addrEnd) {
		m_addrStart.addrType = addrStart.addrType;
		m_addrStart.addr = addrStart.addr;
		m_addrEnd.addrType = addrEnd.addrType;
		m_addrEnd.addr = addrEnd.addr;
	};		                
	void SetAsmStr(CString str) { m_strAsm = str; };
	CStringList& GetCodeList() { return m_listCode; };
	CStringList& GetInstrList() { return m_listInstr; };
	CStringList& GetSymList() { return m_listSym; };
	CStringList& GetAddrList() { return m_listAddr; };
	CWordArray& GetIsDirtyResultArray() { return m_arrayIsDirtyResult;};
	void Disasm(BOOL isUpdateMem = TRUE);
	void Asm(BOOL isUpdateMem = TRUE);
	
};	

/********************** for class CDADExtFnBase *******************************/
class CDADExtFnCom : public CDADExtFnBase
{  
//construct
public:   
	//disasm construct
	CDADExtFnCom(ADDR addrStart,ADDR addrEnd) {
                m_wNeedInstrLen = (WORD)(addrEnd.addr - addrStart.addr +1);
		SetAddress(addrStart,addrEnd);
		Disasm();
	};
	CDADExtFnCom(ADDR addrStart,WORD wNeedInstrLen) {
		m_wNeedInstrLen = wNeedInstrLen;
		ADDR addrEnd;
		addrEnd.addrType = addrStart.addrType;
		addrEnd.addr = DAD_ADDR_MAX;
		SetAddress(addrStart,addrEnd);
		Disasm();
	};		          
	//asm construct
	CDADExtFnCom(ADDR addr,CString strAsm) {
		SetAddress(addr,addr);
		SetAsmStr(strAsm);
		Asm();
	};
 };

/********************** for class CDADExtFnEmuAddr *******************************/
//defined for emulation to get next address
class CDADExtFnEmuAddr : public CDADExtFnCom
{
//construct
public:
	CDADExtFnEmuAddr(ADDR addrStart) : CDADExtFnCom(addrStart,1) {
		Disasm();
		return;
	};          
//operator
public:
	BYTE GetLen() {
		if (CDADExtFnBase::DAD_OK != GetResult()) return 0;
		return (BYTE)((m_pDadOk->Baby).m_NextAddrSet.GetSize());
	};
	ADDR GetAddr(int i) {
		ASSERT(i < GetLen());
		return ((CNextIceAddr*)((m_pDadOk->Baby).m_NextAddrSet)[i])->GetNextIceAddr();
	}
	
 };


#endif
