/***************************************************************************
**
**    $Header:   D:/EP196/SRC/LOG/CPUDLG.CPP   1.0   19 May 1997 14:39:14   ZJRD  $
**
**    $Log:   D:/EP196/SRC/LOG/CPUDLG.CPP  $
** 
**    Rev 1.0   19 May 1997 14:39:14   ZJRD
** Initial revision.
** 
****************************************************************************/

/////////////////////////////////////////////////////////////////////////////
//
//  File name:  CPUCFG.CPP
//
//  Description:The implement file for the class: CRegcfgDialog, 
//				CRegisterDialog.
//
//  Author:     Roger Zhang
//
//  Date:       04/25/95, 10/11/96, by Chris Fang
//
//  Modification:
//
//      1. 04/25/95, Initial version 
//
//
//  Copyright (C) 1995 Microtek International. All rights reserved.
//
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "resource.h"
                          
#include "uicom2.h"
#include "cpucom.h"
#include "cpudlg.h"
#include "hosterrs.h" 
//added by dragon
#include "regsvr.h"       

#include "abiextfn.h"   
#include "bankinit.h"

//#include "contain.h"

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

#define _COLWD   130
#define _ROWHT   18
#define _LINEHT  4             
#define _ROWNUM	 8

static CRegvalList RValList;

/////////////////////////////////////////////////////////////////////////////
// CRegcfgDialog dialog

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
CRegcfgDialog::CRegcfgDialog(CWnd* pParent /*=NULL*/)
    : CDialog(CRegcfgDialog::IDD, pParent)
{                
    ASSERT(nCurRegs <= nMaxReg);

    for(int i = 0; i < nMaxReg; i ++)   m_Reg[i] = FALSE;
    for(i = 0; i < nCurRegs; i ++)  m_Reg[RegSelect[i]] = TRUE; 
    m_bScroll = FALSE;
    m_pScroll = NULL;
    //{{AFX_DATA_INIT(CRegcfgDialog)

    //}}AFX_DATA_INIT
}

CRegcfgDialog::~CRegcfgDialog()
{
	if (m_pScroll) delete m_pScroll;
}
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CRegcfgDialog::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CRegcfgDialog)              
    //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CRegcfgDialog, CDialog)
    //{{AFX_MSG_MAP(CRegcfgDialog)
    ON_BN_CLICKED(IDC_REGCONFIG_UNSELECT, OnUnselectAll)
    ON_BN_CLICKED(IDC_REGCONFIG_SELECTALL, OnSelectAll)
	ON_WM_PAINT()
	ON_WM_VSCROLL()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CRegcfgDialog message handlers

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CRegcfgDialog::OnUnselectAll()
{
    // TODO: Add your control notification handler code here
    for(int i = 1; i < nMaxValidReg; i ++)                             
        m_btnReg[i].SetCheck(0);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CRegcfgDialog::OnSelectAll()
{
    // TODO: Add your control notification handler code here
    for(int i = 0; i < nMaxValidReg; i ++)   
        m_btnReg[i].SetCheck(1);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CRegcfgDialog::OnOK()
{
    // TODO: Add extra validation here
    for(int i = 0; i < nMaxValidReg; i ++) {  
        if(m_btnReg[i].GetCheck())  break;
    }
    if(i == nMaxValidReg)    ErrDisplayError(ER_PRE_SEL_REG);
    else {   
        for(i = 0; i < nMaxValidReg; i ++) {
            if(m_btnReg[i].GetCheck())  m_Reg[RegValid[i]] = TRUE;
            else m_Reg[RegValid[i]] = FALSE;
        }
        CDialog::OnOK();
    } 
}   

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL CRegcfgDialog::OnInitDialog()
{
    CDialog::OnInitDialog();
    
    // TODO: Add extra initialization here
    
    CRect rect;
    GetWindowRect(rect);
    int nMaxRows = (nMaxValidReg + 3)/4;
    int nRows;
    
    if (nMaxRows > _ROWNUM){
    	nRows = _ROWNUM;
    	m_bScroll = TRUE;
    }              
    else{
    	m_bScroll = FALSE;
    	nRows = nMaxRows; 
    }
    	
    int nOfs = _ROWHT * nRows;
    

    m_nMaxRow = nMaxRows;
    m_nPageRow = nRows;
    
    VERIFY(SetWindowPos(NULL, 40, 40, rect.Width(), rect.Height() + nOfs, 
    	SWP_NOZORDER|SWP_NOREDRAW|SWP_NOACTIVATE));

    CenterWindow();

    if (m_bScroll){
    	GetClientRect(m_rectFrame);
    	m_rectFrame.left += 2;
    	m_rectFrame.right -= 2;
    	m_rectFrame.top = 2;
    	m_rectFrame.bottom = 10+nOfs+10;
    }

    CButton * btn = (CButton *)GetDlgItem(IDOK);
    btn->GetWindowRect(rect);
    ScreenToClient(rect);
    rect.OffsetRect(0, nOfs);
    btn->MoveWindow(rect);
    
    btn = (CButton *)GetDlgItem(IDCANCEL);
    btn->GetWindowRect(rect);
    ScreenToClient(rect);
    rect.OffsetRect(0, nOfs);
    btn->MoveWindow(rect);
    
    btn = (CButton *)GetDlgItem(IDC_REGCONFIG_SELECTALL);
    btn->GetWindowRect(rect);
    ScreenToClient(rect);
    rect.OffsetRect(0, nOfs);
    btn->MoveWindow(rect);
    
    btn = (CButton *)GetDlgItem(IDC_REGCONFIG_UNSELECT);
    btn->GetWindowRect(rect);
    ScreenToClient(rect);
    rect.OffsetRect(0, nOfs);
    btn->MoveWindow(rect);
//    btn->EnableWindow(0);
    
    btn = (CButton *)GetDlgItem(ID_HELP);
    btn->GetWindowRect(rect);
    ScreenToClient(rect);
    rect.OffsetRect(0, nOfs);
    btn->MoveWindow(rect);
    
    for(int i = 0, j = 0; j < nRows && i < nMaxValidReg; j ++) {
        for(int k = 0; k < 4 && i < nMaxValidReg; k ++, i++) {  
            rect.SetRect(10 + k * _COLWD, 10 + j * _ROWHT, 
                10 + k * _COLWD + 125, 10 + j * _ROWHT + 16);
            
            m_btnReg[i].Create("O&verwrite",WS_VISIBLE|WS_CHILD|WS_TABSTOP
                |BS_AUTOCHECKBOX, rect, this, IDC_REGCONFIG_FIRSTREG + i);
            m_btnReg[i].SetFont(GetFont(), TRUE);   
            m_btnReg[i].SetWindowText(RegName[RegValid[i]]);
            if(m_Reg[RegValid[i]])    m_btnReg[i].SetCheck(1);
            else    m_btnReg[i].SetCheck(0);
        }
    }
    
    for (i=nRows*4; i<nMaxValidReg; i++){
        m_btnReg[i].Create("O&verwrite", WS_CHILD|WS_TABSTOP
              |BS_AUTOCHECKBOX, rect, this, IDC_REGCONFIG_FIRSTREG + i);
		
        m_btnReg[i].SetFont(GetFont(), TRUE);   
        m_btnReg[i].SetWindowText(RegName[RegValid[i]]);
        if(m_Reg[RegValid[i]])    m_btnReg[i].SetCheck(1);
        else    m_btnReg[i].SetCheck(0);
    }
         	
    m_btnReg[0].EnableWindow(0);   
    
    if (m_bScroll){   
    	rect = m_rectFrame;
    	rect.left = rect.right - 15;            
    	m_pScroll = new CScrollBar();
    	m_pScroll->Create(SBS_VERT|WS_VISIBLE|WS_CHILD, rect, this, 
    		CRegcfgDialog::ID_SCROLL);
		m_pScroll->SetScrollRange(0, nMaxRows-nRows, FALSE);
		m_pScroll->SetScrollPos(0, FALSE);
	}
	    		
    CenterWindow();
    
    return TRUE;  // return TRUE  unless you set the focus to a control
}

void CRegcfgDialog::DrawFrame(CDC * pdc, CRect rect,UINT flag)
{
    
    CPen* pOldPen,*pPen=new CPen;
    pPen->CreatePen(PS_SOLID, 1,RGB(0,0,0) );
    CPoint points[4];   
    if(flag==0){
        points[0]=CPoint(rect.left,rect.bottom);
    	points[1]=CPoint(rect.left,rect.top);
    	points[2]=CPoint(rect.right,rect.top);
    	points[3]=CPoint(rect.right,rect.bottom); 
     }
    else{ 	
        points[0]=CPoint(rect.left,rect.bottom);
    	points[1]=CPoint(rect.right,rect.bottom); 
    	points[2]=CPoint(rect.right,rect.top);
    	points[3]=CPoint(rect.left,rect.top);
     }
    pOldPen=pdc->SelectObject(pPen); 
    pdc->MoveTo(points[0]);
 	pdc->LineTo(points[1]);
 	pdc->LineTo(points[2]);
 	pdc->SelectObject(pOldPen);
 	
    pPen->DeleteObject();
       
    pPen->CreatePen(PS_SOLID,1,RGB(255,255,255) );
    pOldPen=pdc->SelectObject(pPen);
 	pdc->LineTo(points[3]);
 	pdc->LineTo(points[0]);
    pdc->SelectObject(pOldPen);
    pPen->DeleteObject();    
    delete pPen;
}    

void CRegcfgDialog::OnPaint()
{
	CPaintDC dc(this); // device context for painting
	
	// TODO: Add your message handler code here
	DrawFrame(&dc, m_rectFrame, 0);
	m_rectFrame.InflateRect(1, 1);
	DrawFrame(&dc, m_rectFrame, 1);
	m_rectFrame.InflateRect(-1, -1);	
	// Do not call CDialog::OnPaint() for painting messages
}

void CRegcfgDialog::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	// TODO: Add your message handler code here and/or call default
	if (!m_pScroll) return;
	
	if (pScrollBar == m_pScroll){ 
		int nMin, nMax;
		int nCurPos;        
		int nOldPos;
		m_pScroll->GetScrollRange(&nMin, &nMax);
		nOldPos = nCurPos = m_pScroll->GetScrollPos();
		switch(nSBCode){     
			case SB_TOP:
				nCurPos = nMin;
				break;
			case SB_BOTTOM:
				nCurPos = nMax;
				break;
			case SB_LINEDOWN:
				if(nCurPos < nMax) nCurPos++;
				break;
			case SB_LINEUP:
				if (nCurPos > nMin) nCurPos--;
				break;
			case SB_PAGEDOWN:
				nCurPos += 5;
				if (nCurPos > nMax) nCurPos = nMax;
				break;
			case SB_PAGEUP:
				nCurPos -= 5;
				if (nCurPos < nMin) nCurPos = nMin;
				break;
			case SB_THUMBPOSITION:
				nCurPos = nPos;
				break;
		}
		
        if (nOldPos != nCurPos){
        	m_pScroll->SetScrollPos(nCurPos, TRUE);
        	ScrollReg(nOldPos, nCurPos - nOldPos);
        }
	}	
	
//	CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
}

void CRegcfgDialog::ScrollReg(int nOldPos, int nRow)
{
	ASSERT(m_bScroll);
	ASSERT(nRow != 0);
	
	if (nRow > 0){ // scroll down                
		ASSERT((nOldPos+nRow)*4 < nMaxValidReg);
		for (int i=nOldPos*4; i<(nOldPos+nRow)*4; i++)
			m_btnReg[i].ShowWindow(SW_HIDE);          
		
		int nMaxShowReg = (nOldPos+nRow+m_nPageRow>=m_nMaxRow) ?
			nMaxValidReg : (nOldPos+nRow+m_nPageRow)*4;
		
		i = (nOldPos+nRow) *4;
		
    	for(int j = 0; j < m_nPageRow && i < nMaxValidReg; j ++) {
        	for(int k = 0; k < 4 && i < nMaxValidReg; k ++, i++)
				SetRegBoxSite(i, j, k);
        }                            
        
        for(i=(nOldPos+nRow)*4; i<nMaxShowReg; i++)
        	m_btnReg[i].ShowWindow(SW_SHOW);
    }                                       
    else{ //scroll up
    	ASSERT(nOldPos >= nRow);
    	
    	int nLastMaxShowReg = (nOldPos+m_nPageRow>=m_nMaxRow) ?
    		nMaxValidReg : (nOldPos+m_nPageRow)*4;
    	
    	for(int i=(nOldPos+nRow+m_nPageRow)*4; i<nLastMaxShowReg; i++)
    		m_btnReg[i].ShowWindow(SW_HIDE);
    		
    	i = (nOldPos+nRow)*4;
    	
    	for(int j = 0; j < m_nPageRow && i < nMaxValidReg; j++){
    		for(int k=0; k<4 && i < nMaxValidReg; k++, i++)
    			SetRegBoxSite(i,j, k);
    	}
    	
		int nMaxShowReg = (nOldPos+nRow+m_nPageRow>=m_nMaxRow) ?
			nMaxValidReg : (nOldPos+nRow+m_nPageRow)*4;
    	
    	for(i=(nOldPos+nRow)*4; i<nMaxShowReg; i++)
			m_btnReg[i].ShowWindow(SW_SHOW);
	}
}

void CRegcfgDialog::SetRegBoxSite(int nRegId, int nRow, int nCol)
{
	CRect rect;
	rect.SetRect(10 + nCol * _COLWD, 10 + nRow * _ROWHT,
	     10 + nCol * _COLWD + 125, 10 + nRow * _ROWHT + 16);
	m_btnReg[nRegId].MoveWindow(&rect, TRUE);                   
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Add new register value to the list
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CRegvalList::AddNew(DWORD uVal)
{           
    int i;
    //justify that uVal is new or old
    for(i = 0; i<m_nCount; i++){
        if(m_Val[i] == uVal)
           return;
    }
        
    if(m_nCount < MAX_RVAL_LIST) {
        m_Val[m_nCount++] = uVal;
    } else {
        for(i = 1; i < MAX_RVAL_LIST; i++)  m_Val[i-1] = m_Val[i];
        m_Val[MAX_RVAL_LIST] = uVal;
    }
}

/////////////////////////////////////////////////////////////////////////////
// CRegisterDialog dialog

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
CRegisterDialog::CRegisterDialog(int nRegIdx, CWnd* pParent /*=NULL*/)
 : m_nRegIdx(nRegIdx), CDialog(CRegisterDialog::IDD, pParent)
{
    m_dwByte = 2;
    //{{AFX_DATA_INIT(CRegisterDialog)
	//}}AFX_DATA_INIT
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CRegisterDialog::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CRegisterDialog)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CRegisterDialog, CDialog)
    //{{AFX_MSG_MAP(CRegisterDialog)
    ON_BN_CLICKED(IDC_REGISTER_DECRE, OnDecrement)
    ON_BN_CLICKED(IDC_REGISTER_INC, OnIncrement)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CRegisterDialog message handlers

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL CRegisterDialog::OnInitDialog()
{
    CDialog::OnInitDialog();
    
    CenterWindow();
                  
    CString str("Register : ");
    str += RegName[m_nRegIdx];                  
    SetWindowText(str);
    
    //added by dragon
    ///////////////////////////////////////
    CRegItem regItem;
    
    regItem.wSerial = (U16)m_nRegIdx;
    ByteFromRegID(&regItem);
    if(regItem.wLen==1){
       RegValue[m_nRegIdx] = U8(RegValue[m_nRegIdx]);
    }
    else RegValue[m_nRegIdx] = U16(RegValue[m_nRegIdx]);
    m_dwByte = regItem.wLen; 
    if(m_dwByte==0x4) m_dwByte==0x2;//for PC
    //////////////////////////////////////
    char psz[256];
    wsprintf(psz, "0x%X", RegValue[m_nRegIdx]);
    SetDlgItemText(IDC_REGISTER_HEX, psz);
    if(nCpuRadix == CPU_HEX) {
        SetDlgItemText(IDC_REGISTER_VAL, psz);
        wsprintf(psz, "%u", RegValue[m_nRegIdx]);
        SetDlgItemText(IDC_REGISTER_DEC, psz); 
    } else {
        wsprintf(psz, "%u", RegValue[m_nRegIdx]);
        SetDlgItemText(IDC_REGISTER_DEC, psz); 
        SetDlgItemText(IDC_REGISTER_VAL, psz);
    }
        
    for(int i = 0; i < RValList.m_nCount; i ++) {
        if(nCpuRadix == CPU_HEX)
            wsprintf(psz, "0x%X", RValList.m_Val[RValList.m_nCount - i - 1]);
        else
            wsprintf(psz, "%u", RValList.m_Val[RValList.m_nCount - i - 1]);
        ((CComboBox *)GetDlgItem(IDC_REGISTER_VAL))->AddString(psz);        
    }
                
    ((CComboBox *)GetDlgItem(IDC_REGISTER_VAL))->SetFocus();
    
    return FALSE;                     
//    return TRUE;  // return TRUE  unless you set the focus to a control
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//                         
/////////////////////////////////////////////////////////////////////////////
void CRegisterDialog::OnDecrement()
{
    // TODO: Add your control notification handler code here
    char pch[256];                    
    DWORD dw;
    
    int i, l = GetDlgItemText(IDC_REGISTER_VAL, pch, 255);
    if(!Str2Num(pch, dw)) {
        ErrDisplayError(ER_PRE_REG_VALUE);
        ((CComboBox *)GetDlgItem(IDC_REGISTER_VAL))->SetFocus();
        return;
    }
    -- dw;
	if((int(m_dwByte)==1&&dw>=0x100)){
	    dw = U8(dw);
	    MessageBeep(-1);
	}
	else if((int(m_dwByte)==2&&dw>=0x10000)){
	    dw = U16(dw);
	    MessageBeep(-1);
	}
    
    for(i = 0; i < l; i ++)
        if(pch[i] == 'x' || pch[i] == 'X')  break;
    if(i < l)   wsprintf(pch, "0x%lX", dw);
    else wsprintf(pch, "%lu", dw);
    SetDlgItemText(IDC_REGISTER_VAL, pch);
    ((CComboBox *)GetDlgItem(IDC_REGISTER_VAL))->SetFocus();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CRegisterDialog::OnIncrement()
{
    // TODO: Add your control notification handler code here
    
    char pch[256];                    
    DWORD dw;
    
    int i, l = GetDlgItemText(IDC_REGISTER_VAL, pch, 255);
    if(!Str2Num(pch, dw)) {
        ErrDisplayError(ER_PRE_REG_VALUE);       
        ((CComboBox *)GetDlgItem(IDC_REGISTER_VAL))->SetFocus();
        return;
    }
    ++ dw;

	if((int(m_dwByte)==1&&dw>=0x100)){
	    dw = U8(dw);
	    MessageBeep(-1);
	}
	else if((int(m_dwByte)==2&&dw>=0x10000)){
	    dw = U16(dw);
	    MessageBeep(-1);
	}
    for(i = 0; i < l; i ++)
        if(pch[i] == 'x' || pch[i] == 'X')  break;
    if(i < l)   wsprintf(pch, "0x%lX", dw);
    else wsprintf(pch, "%lu", dw);
    SetDlgItemText(IDC_REGISTER_VAL, pch);
    ((CComboBox *)GetDlgItem(IDC_REGISTER_VAL))->SetFocus();
}


/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CRegisterDialog::OnOK()
{
// TODO: Add extra validation here
char pch[256];                    
DWORD dw;

	GetDlgItemText(IDC_REGISTER_VAL, pch, 255);
	if(!Str2Num(pch, dw))
	{
		ErrDisplayError(ER_PRE_REG_VALUE);       
		((CComboBox *)GetDlgItem(IDC_REGISTER_VAL))->SetFocus();
		return;
	}
    
    // added by Richard
	if((int(m_dwByte)==1 && dw>=0x100)
		|| (int(m_dwByte)==2 && dw>=0x10000)){

		ErrDisplayError(ER_PRE_REG_VALUE);       
		((CComboBox *)GetDlgItem(IDC_REGISTER_VAL))->SetFocus();
		return;
	}

	ASSERT(m_nRegIdx>=0);
	//added by dragon
	
	// added by Richard
	if (m_nRegIdx==0){ // register PC
		int nCurBank = 1 << DllLdrGetBankNumber();
		if ((dw>>16) >= (DWORD)nCurBank){

			ErrDisplayError(ER_PRE_REG_VALUE);       
			((CComboBox *)GetDlgItem(IDC_REGISTER_VAL))->SetFocus();
			return;                    
		}		
	}
			
	if(CpuSetRegfromWnd((WORD)m_nRegIdx, dw))
	{
	    CpuGetAllReg();
	    DWORD dwRegVal;
	    int nStatus;
	    nStatus = emuGetReg(0, (WORD)m_nRegIdx, &dw);
	}
		
	RValList.AddNew(RegValue[m_nRegIdx]);
	CDialog::OnOK();
}

/////////////////////////////////(EOF)///////////////////////////////////////

