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

/***************************************************************************
**
** File name : simulate.cpp
** Author:John Zhou
** Description:
**    simulator for 251
**
**
**    Finished date: 1995.10.4
**
**
**    Copyright (C) 1995 Microtek International, Inc.
**    All Rights Reserved
**
****************************************************************************/
#include "stdafx.h"   
#include "simulate.h"

void upperit(char far* p, int l)
{
int i;
	for(i=0; i<l; i++)
		if(p[i]>='a'&&p[i]<='z')
			p[i]+='A'-'a';
}

/********************** for class CSimulate251Mem *******************************/
// 
//	CLASS NAME : CSimulate251Mem
//
//  HEAD FILE  : Simulate.H
//
/**************************************************************************/
CFile* CSimulate251Mem::GetPoint(ADDR addrInput)
{                
	if (addrInput.addrType == /*MEM_SFR*/10) {
		if (addrInput.addr >= 0x200) return NULL;
		return &m_pMemS;
	}                  
	
	switch (addrInput.addr>>16) {
		case 0x00 : return &m_pMem0;
		case 0x01 : return &m_pMem1;
		case 0xfe : return &m_pMemFE;
		case 0xFF : return &m_pMemFF;
	}
	return NULL;
 }
 
BOOL CSimulate251Mem::GetMem(ADDR addrStart,ADDR addrEnd,BYTE* pbBuffer)
{ 
	CFile* bpTmp = GetPoint(addrStart);
	if (NULL == bpTmp) return FALSE;       
	bpTmp->Seek(addrStart.addr&0x0000ffff, CFile::begin);
	bpTmp->Read(pbBuffer, addrEnd.addr-addrStart.addr+1);
	
	return TRUE;
 }
 
BOOL CSimulate251Mem::SetMem(ADDR addrStart,BYTE* pbBuffer,DWORD dwLen)
{               
	CFile* bpTmp = GetPoint(addrStart);
	if (NULL == bpTmp) return TRUE;           
	bpTmp->Seek(addrStart.addr&0x0000ffff, CFile::begin);
	bpTmp->Write(pbBuffer, dwLen);
	
	return TRUE;
 }
 
BOOL CSimulate251Mem::FillMem(ADDR addrStart,ADDR addrEnd,BYTE* pbBuffer,WORD wLen)
{
	CFile* bpTmp = GetPoint(addrStart);
	if (NULL == bpTmp) return TRUE;           
	bpTmp->Seek(addrStart.addr&0x0000ffff, CFile::begin);
	for (int i=0;i<(addrEnd.addr-addrStart.addr+1)/wLen;i++) {
		bpTmp->Write(pbBuffer, wLen);
	}
	if (0 != (addrEnd.addr-addrStart.addr)%wLen) {
		bpTmp->Write(pbBuffer, (addrEnd.addr-addrStart.addr)%wLen);
	}	
	
	return TRUE;
 }
 
BOOL CSimulate251Mem::GetCheckSum(ADDR addrStart, ADDR addrEnd, WORD* wChecksum)
{   
	CFile* bpTmp = GetPoint(addrStart);
	if (NULL == bpTmp) return TRUE;           
	bpTmp->Seek(addrStart.addr&0x0000ffff, CFile::begin);
	wChecksum = 0; 
	BYTE* bpBuff = new BYTE[addrEnd.addr-addrStart.addr+1]; 
	bpTmp->Read(bpBuff,addrEnd.addr-addrStart.addr+1);                                  
	for (DWORD dw=0;dw<=addrEnd.addr-addrStart.addr+1;dw++) {
		wChecksum += bpBuff[dw];
	}	          
	delete bpBuff;
	return TRUE;
 }
 
BOOL CSimulate251Mem::TestMem(ADDR addrStart, ADDR addrEnd)
{                              
	return TRUE;
 }
 
BOOL CSimulate251Mem::CopyMem(ADDR addrStart, ADDR addrEnd, ADDR addrDest)
{   
    CFile* bpTmp2 = GetPoint(addrStart);
	if (NULL == bpTmp2) return TRUE;   
	bpTmp2->Seek(addrStart.addr&0x0000ffff, CFile::begin);
	BYTE* bpBuff = new BYTE[addrEnd.addr-addrStart.addr+1]; 
	bpTmp2->Read(bpBuff,addrEnd.addr-addrStart.addr+1);                                  
            
	CFile* bpTmp1 = GetPoint(addrDest);
	if (NULL == bpTmp1) return TRUE;   
	bpTmp1->Seek(addrDest.addr&0x0000ffff, CFile::begin);
	bpTmp1->Write(bpBuff,addrEnd.addr-addrStart.addr+1);                                  
	
	delete bpBuff;
	return TRUE;
 }
 
BOOL CSimulate251Mem::SearchMem(ADDR addrStart, ADDR addrEnd, SEARCH_INFO si,
		                        ADDR& addrRet)
{               
	return FALSE;
	/*
	*addrRet=0;
    BOOL bGot = FALSE;
    
    if(addrEnd-addrStart+1<si.srchBufLen)
    	return ICE_NOT_FOUND;
    	
	CFile* bpTmp = GetPoint(addrStart);
	if (NULL == bpTmp) return TRUE;           
	bpTmp->Seek(addrStart.addr&0x0000ffff, CFile::begin);
	BYTE* bpBuff = new BYTE[addrEnd.addr-addrStart.addr+1]; 
	bpTmp->Read(bpBuff,addrEnd.addr-addrStart.addr+1);                                  
	
	if(!si.caseFlag) {
		upperit(bpBuff,addrEnd.addr-addrStart.addr+1);
		upperit(si.srchBuf,si.srchBufLen);
	}	
	
	for(DWORD dwTmp=0;dwTmp<addrEnd.addr-addrStart.addr+1-si.srchBufLen+1;
		dwTmp++) {
		if(!memcmp(bpBuff++, si.srchBuf, si.srchBufLen)) {
			bGot=TRUE;
			break;
		}
	}
	
	delete bpBuff;
	if(bGot)
	{
		return ICE_FOUND;
	}
	return ICE_NOT_FOUND;
	
	return TRUE;*/
	
 }
 		                        
BOOL CSimulate251Mem::CompareMem(ADDR addrStart, ADDR addrEnd, ADDR addrDest,
         				         ADDR* addrRet)
{               
	CFile* bpTmp2 = GetPoint(addrStart);
	if (NULL == bpTmp2) return TRUE;   
	bpTmp2->Seek(addrStart.addr&0x0000ffff, CFile::begin);
	BYTE* bpBuff2 = new BYTE[addrEnd.addr-addrStart.addr+1]; 
	bpTmp2->Read((void*)bpBuff2,addrEnd.addr-addrStart.addr+1);                                  
            
	CFile* bpTmp1 = GetPoint(addrDest);
	if (NULL == bpTmp1) return TRUE;   
	bpTmp1->Seek(addrDest.addr&0x0000ffff, CFile::begin);
	BYTE* bpBuff1 = new BYTE[addrEnd.addr-addrStart.addr+1];
	bpTmp1->Read(bpBuff1,addrEnd.addr-addrStart.addr);                                  
	
	for (DWORD dwTmp=0;dwTmp<addrEnd.addr-addrStart.addr;dwTmp++) {
		if (bpBuff1[dwTmp] != bpBuff2[dwTmp]) {
			addrRet->addr = addrStart.addr + dwTmp;
			delete bpBuff1;
			delete bpBuff2;
			return ICE_OK;
		}
	}
	
	delete bpBuff1;
	delete bpBuff2;
	return ICE_NO_DIFF;
 }
void CSimulate251Mem::PrepareFile()
{
	char radom;
	
	if(!m_pMem0.Open("memory00.dat", CFile::modeReadWrite)) {
		m_pMem0.Open("memory00.dat", 
						CFile::modeReadWrite|CFile::modeCreate);
		m_pMem0.SetLength(0x10000);
		m_pMem0.Seek(0, CFile::begin);
		for(long l=0; l<0x10000; l++)
		{
			radom=rand()&0xff;
			m_pMem0.Write(&radom, 1);
		}
	}
	
	if(!m_pMem1.Open("memory01.dat", CFile::modeReadWrite)) {
		m_pMem1.Open("memory01.dat", 
						CFile::modeReadWrite|CFile::modeCreate);
		m_pMem1.SetLength(0x10000);
		m_pMem1.Seek(0, CFile::begin);
		for(long l=0; l<0x10000; l++)
		{
			radom=rand()&0xff;
			m_pMem1.Write(&radom, 1);
		}
	}
	
	if(!m_pMemFE.Open("memoryfe.dat", CFile::modeReadWrite)) {
		m_pMemFE.Open("memoryfe.dat", 
						CFile::modeReadWrite|CFile::modeCreate);
		m_pMemFE.SetLength(0x10000);
		m_pMemFE.Seek(0, CFile::begin);
		for(long l=0; l<0x10000; l++)
		{
			radom=rand()&0xff;
			m_pMemFE.Write(&radom, 1);
		}
	}
	
	if(!m_pMemFF.Open("memoryff.dat", CFile::modeReadWrite)) {
		m_pMemFF.Open("memoryff.dat", 
						CFile::modeReadWrite|CFile::modeCreate);
		m_pMemFF.SetLength(0x10000);
		m_pMemFF.Seek(0, CFile::begin);
		for(long l=0; l<0x10000; l++)
		{
			radom=rand()&0xff;
			m_pMemFF.Write(&radom, 1);
		}
	}
	
	if(!m_pMemS.Open("memorys.dat", CFile::modeReadWrite)) {
		m_pMemS.Open("memorys.dat", 
						CFile::modeReadWrite|CFile::modeCreate);
		m_pMemS.SetLength(0x200);
		m_pMemS.Seek(0, CFile::begin);
		for(long l=0; l<0x200; l++)
		{
			radom=rand()&0xff;
			m_pMemS.Write(&radom, 1);
		}
	}

 }
          				         
/********************** for class CSimulate251Cpu *******************************/
// 
//	CLASS NAME : CSimulate251Cpu
//
//  HEAD FILE  : Simulate.H
//
/**************************************************************************/
BOOL CSimulate251Cpu::GetCpuId(BYTE *bCpuId) 
{ 
	*((WORD*)bCpuId) = m_wCpuId;
	bCpuId[2] = bCpuId[3] = bCpuId[4] = 0;
	return TRUE;
 }
 
BOOL CSimulate251Cpu::SetCpuId(WORD wSetCpuId, WORD *wGetCpuId) 
{                   
	m_wCpuId = *wGetCpuId = wSetCpuId;
	return TRUE;	
 }
 
BOOL CSimulate251Cpu::GetFwId(BYTE *bMajor,  BYTE *bMinor) 
{               
	*bMajor = m_bFWIdMajor;  
	*bMinor = m_bFWIdMinor;
	return TRUE;
 }
 
BOOL CSimulate251Cpu::GetCpuStatus(WORD *wCpuStatus) 
{               
	*wCpuStatus = m_wCpuStatus;        
	return TRUE;
 }
 
BOOL CSimulate251Cpu::GetAllReg(DWORD* dwRegValue)
{                    
	m_pdwReg[0] = m_dwPc; 
	for (int i=0;i<7;i++) dwRegValue[i] = m_pdwReg[i];
	return TRUE;
 }

BOOL CSimulate251Cpu::GetOneReg(WORD nRegId, DWORD* dwRegValue) 
{               
	if(nRegId>7) nRegId = 7;
	if (nRegId == 0) {
		*dwRegValue = m_dwPc;
		return TRUE;
	}	
	*dwRegValue = m_pdwReg[nRegId];
	return TRUE;
 }
 
BOOL CSimulate251Cpu::SetReg(WORD iRegId, DWORD dwRegValue) 
{               
	if(iRegId>7) iRegId = 7;
	if (iRegId == 0) {
		m_dwPc = dwRegValue;
		return TRUE;
	}
	m_pdwReg[iRegId] = dwRegValue;
	return TRUE;	
 }
 
BOOL CSimulate251Cpu::GetRegLen(WORD *wRegLen) 
{                            
	return 7;
 }
 
BOOL CSimulate251Cpu::GetFWSupport(WORD *wCpuNum, WORD* wCpuType) 
{                 
	*wCpuNum = 1;
	*wCpuType = 0;
	return TRUE;
 }
 
BOOL CSimulate251Cpu::GetTargetSupport(WORD *wCpuNum, WORD* wCpuType) 
{               
	*wCpuNum = 1;
	*wCpuType = 0;
	return TRUE;
 }
 
BOOL CSimulate251Cpu::Reset(ADDR addr) 
{               
	m_dwPc = addr.addr;
	m_wCpuStatus &= 0xfeff;
	return TRUE;
 }
 
BOOL CSimulate251Cpu::Abort() 
{ 
	m_wCpuStatus &= 0xfeff;
	return TRUE;
 }
 
BOOL CSimulate251Cpu::Go(FLAG runFlag, ADDR addrStart, ADDR addrEnd) 
{                       
	if (0 == addrEnd.addrType) {
		m_wCpuStatus &= 0xfcff;
		return TRUE;
	} 
	
	m_dwPc = addrEnd.addr;
	return TRUE;
 }
 
BOOL CSimulate251Cpu::StepOne() 
{               
	m_dwPc++;
	if (m_dwPc>=0x1000000) m_dwPc=0;
	return TRUE;
 }
 
BOOL CSimulate251Cpu::StepOver() 
{               
	m_dwPc++;
	if (m_dwPc>=0x1000000) m_dwPc=0;
	return TRUE;
 }
 
BOOL CSimulate251Cpu::StepRange(ADDR addrStart, ADDR addrEnd) 
{               
	m_dwPc = addrEnd.addr;
	return TRUE;
 }
 
BOOL CSimulate251Cpu::StepOverRange(ADDR addrStart, ADDR addrEnd) 
{               
	m_dwPc = addrEnd.addr;
	return TRUE;
 }
 
BOOL CSimulate251Cpu::SetVerify(FLAG uVerifyFlag)
{               
	if (0 == uVerifyFlag) m_wCpuStatus &=0xf7ff;
	else  m_wCpuStatus |=0x0800;
	return TRUE;
 }          

BOOL CSimulate251Cpu::GetVerify(FLAG& uVerifyFlag)
{               
	uVerifyFlag = m_wCpuStatus|0x0800;
	return TRUE;
 }          

/********************** for class CSimulate196Mem *******************************/
// 
//	CLASS NAME : CSimulate196Mem
//
//
/**************************************************************************/
CFile* CSimulate196Mem::GetPoint(ADDR addrInput)
{                
	if (addrInput.addrType == MEM_I) {
		if (addrInput.addr >= 0x200) return NULL;
		return &m_pMemI;
	}                  
	
	switch (addrInput.addrType) {
		case MEM_P0 : return &m_pMem0;
        case MEM_P1 : return &m_pMem1;
        case MEM_P2 : return &m_pMem2;
        case MEM_P3 : return &m_pMem3;
        case MEM_X0 : return &m_pMem0;
        case MEM_X1 : return &m_pMem1;
        case MEM_X2 : return &m_pMem2;
        case MEM_X3 : return &m_pMem3;
	}
	return NULL;
 }

void CSimulate196Mem::PrepareFile()
{
	char radom;
	
	if(!m_pMem0.Open("memory00.sim", CFile::modeReadWrite)) {
		m_pMem0.Open("memory00.sim", 
						CFile::modeReadWrite|CFile::modeCreate);
		m_pMem0.SetLength(0x10000);
		m_pMem0.Seek(0, CFile::begin);
		for(long l=0; l<0x10000; l++)
		{
			radom=rand()&0xff;
			m_pMem0.Write(&radom, 1);
		}
	}
	
	if(!m_pMem1.Open("memory01.sim", CFile::modeReadWrite)) {
		m_pMem1.Open("memory01.sim", 
						CFile::modeReadWrite|CFile::modeCreate);
		m_pMem1.SetLength(0x10000);
		m_pMem1.Seek(0, CFile::begin);
		for(long l=0; l<0x10000; l++)
		{
			radom=rand()&0xff;
			m_pMem1.Write(&radom, 1);
		}
	}
	
	if(!m_pMem2.Open("memoryfe.sim", CFile::modeReadWrite)) {
		m_pMem2.Open("memoryfe.sim", 
						CFile::modeReadWrite|CFile::modeCreate);
		m_pMem2.SetLength(0x10000);
		m_pMem2.Seek(0, CFile::begin);
		for(long l=0; l<0x10000; l++)
		{
			radom=rand()&0xff;
			m_pMem2.Write(&radom, 1);
		}
	}
	
	if(!m_pMem3.Open("memoryff.sim", CFile::modeReadWrite)) {
		m_pMem3.Open("memoryff.sim", 
						CFile::modeReadWrite|CFile::modeCreate);
		m_pMem3.SetLength(0x10000);
		m_pMem3.Seek(0, CFile::begin);
		for(long l=0; l<0x10000; l++)
		{
			radom=rand()&0xff;
			m_pMem3.Write(&radom, 1);
		}
	}
	
	if(!m_pMemI.Open("memorys.sim", CFile::modeReadWrite)) {
		m_pMemI.Open("memorys.sim", 
						CFile::modeReadWrite|CFile::modeCreate);
		m_pMemI.SetLength(0x200);
		m_pMemI.Seek(0, CFile::begin);
		for(long l=0; l<0x200; l++)
		{
			radom=rand()&0xff;
			m_pMemI.Write(&radom, 1);
		}
	}

 }
                      