// Debugger.cpp: implementation of the CDebugger class.
//


#include "stdafx.h"
#include "Debugger.h"
#include "Config.h"
#include "Board.h"
#include "BKErrMsgSys.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#define new DEBUG_NEW
#endif

int CDebugger::m_outLevel = 0;


#define SRC             2
#define DST             0

static const COLORREF g_crDebugColorHighLighting[] =
{
	RGB(0, 0, 0), //HLCOLOR_DEFAULT
	RGB(0x66, 0, 0), //HLCOLOR_ADDRESS
	RGB(0, 0, 0xcc), //HLCOLOR_MNEMONIC
	RGB(0, 0x66, 0xcc), //HLCOLOR_REGISTER
	RGB(0xff, 0x66, 0), //HLCOLOR_NUMBER
	RGB(0x33, 0x33, 0x33) //HLCOLOR_SYMBOL
};


const CString CDebugger::m_strRegNames[8] =
{
	_T(COLORED_TAG)_T("3R0"),
	_T(COLORED_TAG)_T("3R1"),
	_T(COLORED_TAG)_T("3R2"),
	_T(COLORED_TAG)_T("3R3"),
	_T(COLORED_TAG)_T("3R4"),
	_T(COLORED_TAG)_T("3R5"),
	_T(COLORED_TAG)_T("3SP"),
	_T(COLORED_TAG)_T("3PC")
};
// Формат отображения режимов адресации
const CString CDebugger::m_strAddrFormat[8] =
{
	_T("%s"),
	_T(COLORED_TAG)_T("5(%s")_T(COLORED_TAG)_T("5)"),
	_T(COLORED_TAG)_T("5(%s")_T(COLORED_TAG)_T("5)+"),
	_T(COLORED_TAG)_T("5@(%s")_T(COLORED_TAG)_T("5)+"),
	_T(COLORED_TAG)_T("5-(%s")_T(COLORED_TAG)_T("5)"),
	_T(COLORED_TAG)_T("5@-(%s")_T(COLORED_TAG)_T("5)"),
	_T(COLORED_TAG)_T("4%o")_T(COLORED_TAG)_T("5(%s")_T(COLORED_TAG)_T("5)"),
	_T(COLORED_TAG)_T("5@")_T(COLORED_TAG)_T("4%o")_T(COLORED_TAG)_T("5(%s")_T(COLORED_TAG)_T("5)")
};
// Формат отображения режимов адресации, если регистр PC
const CString CDebugger::m_strAddrFormat_PC[8] =
{
	_T(COLORED_TAG)_T("3PC"),
	_T(COLORED_TAG)_T("5(")_T(COLORED_TAG)_T("3PC")_T(COLORED_TAG)_T("5)"),
	_T(COLORED_TAG)_T("5#")_T(COLORED_TAG)_T("4%o"),
	_T(COLORED_TAG)_T("5@#")_T(COLORED_TAG)_T("1%o"),
	_T(COLORED_TAG)_T("5-(")_T(COLORED_TAG)_T("3PC")_T(COLORED_TAG)_T("5)"),
	_T(COLORED_TAG)_T("5@-(")_T(COLORED_TAG)_T("3PC")_T(COLORED_TAG)_T("5)"),
	_T(COLORED_TAG)_T("1%o"),
	_T(COLORED_TAG)_T("5@")_T(COLORED_TAG)_T("1%o")
};
// Формат отображения аргумента - адрес
const CString CDebugger::m_strArgFormat_Addr = _T(COLORED_TAG)_T("1%06o");
// Формат отображения аргумента - число
const CString CDebugger::m_strArgFormat_Number = _T(COLORED_TAG)_T("4%o");
//запятая между аргументом 1 и 2
const CString CDebugger::m_strArgFormat_Comma = _T(COLORED_TAG)_T("5,");
//////////////////////////////////////////////////////////////////////
// Construction/Destruction


CDebugger::CDebugger()
	: m_pChip(nullptr)
	, m_pCtrl(nullptr)
	, m_pInstrRefsMap(nullptr)
	, m_wAddress(g_Config.m_nAdrAsm)
	, m_bPrevCmdC(false)
	, m_wPC(0)
	, m_wInstr(0)
	, m_wNextAddr(0)
{
	m_hBPIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_DBG_BPT));
	m_hCurrIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_DBG_CUR));
	InitMaps();
}

CDebugger::~CDebugger()
{
	g_Config.m_nAdrAsm = m_wAddress;

	if (m_hBPIcon)
	{
		DestroyIcon(m_hBPIcon);
	}

	if (m_hCurrIcon)
	{
		DestroyIcon(m_hCurrIcon);
	}

	SAFE_DELETE_ARRAY(m_pInstrRefsMap);
}

void CDebugger::AttachChip(CMotherBoard *pChip)
{
	m_pChip = pChip;

	if (m_pChip)
	{
		m_pChip->AttachDebugger(this);
	}
}

//поиск в списке точек останова, заданной точки останова
bool CDebugger::IsBpeakpointExists(CBreakPoint &breakpoint)
{
	if (m_breakpointList.GetCount())
	{
		POSITION pos = m_breakpointList.GetHeadPosition();

		while (pos)
		{
			CBreakPoint &curr = m_breakpointList.GetNext(pos);

			if ((curr.GetType() == breakpoint.GetType())
			        && (curr.GetAddress() == breakpoint.GetAddress()))
			{
				return true;
			}
		}
	}

	return false;
}


//поиск в списке точек останова, точки с заданным адресом
bool CDebugger::GetDebugPCBreak(uint16_t addr)
{
	//оставим это излишество на случай, если решим алгортимы поменять
	return IsBpeakpointAtAddress(addr);
}

//поиск в списке точек останова, точки с заданным адресом
bool CDebugger::IsBpeakpointAtAddress(uint16_t addr)
{
	if (m_breakpointList.GetCount())
	{
		POSITION pos = m_breakpointList.GetHeadPosition();

		while (pos)
		{
			CBreakPoint &curr = m_breakpointList.GetNext(pos);

			if (curr.IsAddress() && curr.GetAddress() == addr)
			{
				return true;
			}
		}
	}

	return false;
}


bool CDebugger::SetSimpleBreakpoint(uint16_t addr)
{
	CBreakPoint breakpoint(addr);

	if (IsBpeakpointExists(breakpoint))
	{
		return false;
	}

	m_breakpointList.AddTail(breakpoint);
	return true;
}


bool CDebugger::SetSimpleBreakpoint()
{
	return SetSimpleBreakpoint(GetCursorAddress());
}


bool CDebugger::RemoveBreakpoint(uint16_t addr)
{
	POSITION pos = m_breakpointList.GetHeadPosition();

	while (pos)
	{
		POSITION oldPos = pos;
		CBreakPoint &curr = m_breakpointList.GetNext(pos);

		if (curr.IsAddress() && curr.GetAddress() == addr)
		{
			m_breakpointList.RemoveAt(oldPos);
			return true;
		}
	}

	return false;
}


bool CDebugger::RemoveBreakpoint()
{
	return RemoveBreakpoint(GetCursorAddress());
}


void CDebugger::ClearBreakpointList()
{
	m_breakpointList.RemoveAll();
}

void CDebugger::DrawDebuggerLine(int nNum, CDC *pDC, CRect *pRcSubs)
{
	if (!m_pChip) // Нет чипа - нечего рисовать
	{
		return;
	}

	// Дизассемблируем машинный код
	uint16_t instrOpcode[3];
	CString strInstruction;
	CString strArgument;
	CString strCode;
	register uint16_t wLineAddr = GetLineAddress(nNum);
	register int len = DebugInstruction(wLineAddr, strInstruction, strArgument, instrOpcode);
	// Выводим маркер
	DrawMarker(wLineAddr, pDC, pRcSubs[MARK_COLUMN]);
	// Выводим адрес
	pDC->SetTextColor(g_crDebugColorHighLighting[HLCOLOR_ADDRESS]);
	WordToOctString(wLineAddr, strCode);
	pDC->DrawText(strCode, &pRcSubs[ADDR_COLUMN], DT_LEFT | DT_VCENTER | DT_END_ELLIPSIS);
	// Выводим мнемонику
	pDC->SetTextColor(g_crDebugColorHighLighting[HLCOLOR_MNEMONIC]);
	pDC->DrawText(strInstruction, &pRcSubs[INSTR_COLUMN], DT_LEFT | DT_VCENTER | DT_END_ELLIPSIS);
	// Выводим аргументы мнемоники
	DrawColoredText(pDC, pRcSubs[ARG_COLUMN], strArgument);
	// Выводим комментарий. Это у нас просто машинные инструкции ассемблерной команды
	WordToOctString(instrOpcode[0], strCode); //код инструкции у нас по любому всегда есть

	//а дальше от 0 до 2-х слов аргументов
	for (int i = 1; i < len; ++i)
	{
		strCode += _T(' ') + WordToOctString(instrOpcode[i]);
	}

	pDC->SetTextColor(g_crDebugColorHighLighting[HLCOLOR_DEFAULT]);
	pDC->DrawText(strCode, &pRcSubs[COM_COLUMN], DT_LEFT | DT_VCENTER | DT_END_ELLIPSIS);
}

void CDebugger::DrawColoredText(CDC *pDC, CRect &rect, CString &str)
{
	CRect pos = rect;
	bool bEnd = false;
	register int beginpos = str.Find(_T(COLORED_TAG), 0); //находим позицию тега
	TCHAR clrbuf[2] = {0, 0};

	if (beginpos < 0 || str.IsEmpty())
	{
		//не надо ничего рисовать
		//pDC->DrawText(str, &pos, DT_LEFT | DT_VCENTER);
	}
	else
	{
		while (!bEnd)
		{
			register int clpos = beginpos + COLORED_TAG_LENGTH;
			clrbuf[0] = str.GetAt(clpos); //номер цвета
			register int colornum = _ttoi(clrbuf);
			register int endpos = str.Find(_T(COLORED_TAG), clpos++); //находим позицию следующего тега, всё что между ними - рисовать заданным цветом

			if (endpos == -1) //если не нашли, то конец строки
			{
				endpos = str.GetLength();
				bEnd = true;
			}

			pDC->SetTextColor(g_crDebugColorHighLighting[colornum]);
			CString substr = str.Mid(clpos, endpos - clpos);
			CSize size = pDC->GetTextExtent(substr); //текущая позиция вывода текста
			pDC->DrawText(substr, &pos, DT_LEFT | DT_VCENTER);
			pos.left += size.cx;

			if (pos.left >= rect.right)
			{
				bEnd = true;
			}

			beginpos = endpos;
		}
	}
}


void CDebugger::DrawMarker(uint16_t address, CDC *pDC, CRect &rc)
{
	if (IsBpeakpointAtAddress(address))
	{
		::DrawIconEx(pDC->m_hDC, rc.left, rc.top, m_hBPIcon, 16, 16, 0, nullptr, DI_NORMAL);
	}

	if (m_pChip->IsCPUBreaked() && address == m_pChip->GetRON(CCPU::R_PC))
	{
		::DrawIconEx(pDC->m_hDC, rc.left, rc.top, m_hCurrIcon, 16, 16, 0, nullptr, DI_NORMAL);
	}
}


void CDebugger::StepForward()
{
	m_wAddress += CalcInstructionLength(m_pChip->GetWordIndirect(m_wAddress));
}


void CDebugger::StepBackward()
{
	m_wAddress -= sizeof(uint16_t);
}


bool CDebugger::IsInstructionOut(uint16_t instruction)
{
	// No fields
	switch (instruction)
	{
		case PI_BPT:
		case PI_IOT:
			m_outLevel++;
			return false;
	}

	// Branchs & interrupts
	switch (instruction & ~0377)
	{
		case PI_EMT:
		case PI_TRAP:
			m_outLevel++;
			return false;
	}

	// Three fields
	switch (instruction & ~0777)
	{
		case PI_JSR:
			m_outLevel++;
			return false;
	}

	if (
	    // No fields
	    (instruction == PI_RTI || instruction == PI_RTT) ||
	    // One field
	    ((instruction & ~7) == PI_RTS)
	)
	{
		if (--m_outLevel == -1)
		{
			return true;
		}
	}

	return false;
}


bool CDebugger::IsInstructionOver(uint16_t instruction)
{
	// No fields
	switch (instruction)
	{
		case PI_BPT:
		case PI_IOT:
			return true;
	}

	// Branchs & interrupts
	switch (instruction & ~0377)
	{
		case PI_EMT:
		case PI_TRAP:
			return true;
	}

	// Three fields
	switch (instruction & ~0777)
	{
		case PI_JSR:
		case PI_SOB:
			return true;
	}

	return false;
}


uint16_t CDebugger::GetCursorAddress()
{
	ASSERT(m_pCtrl);
	int nLine = m_pCtrl->GetSelectionMark();
	return GetLineAddress(nLine);
}


uint16_t CDebugger::GetBottomAddress()
{
	ASSERT(m_pCtrl);
	int nLast = m_pCtrl->GetItemCount();
	return GetLineAddress(nLast);
}


uint16_t CDebugger::GetRegister(int reg)
{
	ASSERT(m_pChip);

	if (m_pChip)
	{
		return m_pChip->GetRON(reg);
	}

	return 0;
}

//////////////////////////////////////////////////////////////////////
//используется для получения значений портов и только
uint16_t CDebugger::GetPortValue(int addr)
{
	ASSERT(m_pChip);

	if (m_pChip)
	{
		switch (addr)
		{
			case SYS_PORT_177660:
				return m_pChip->m_reg177660;

			case SYS_PORT_177662_IN:
				return m_pChip->m_reg177662in;

			case SYS_PORT_177662_OUT:
				return m_pChip->m_reg177662out;

			case SYS_PORT_177664:
				return m_pChip->m_reg177664;

			case SYS_PORT_177700:
				return m_pChip->GetWordIndirect(0177700);

			case SYS_PORT_177702:
				return m_pChip->GetWordIndirect(0177702);

			case SYS_PORT_177704:
				return m_pChip->GetWordIndirect(0177704);

			case SYS_PORT_177706:
				return m_pChip->GetWordIndirect(0177706);

			case SYS_PORT_177710:
				return m_pChip->GetWordIndirect(0177710);

			case SYS_PORT_177712:
				return m_pChip->GetWordIndirect(0177712);

			case SYS_PORT_177714_IN:
				return m_pChip->m_reg177714in;

			case SYS_PORT_177714_OUT:
				return m_pChip->m_reg177714out;

			case SYS_PORT_177716_IN:
				return m_pChip->m_reg177716in;

			case SYS_PORT_177716_OUT_TAP:
				return m_pChip->m_reg177716out_tap;

			case SYS_PORT_177716_OUT_MEM:
				return m_pChip->m_reg177716out_mem;
		}

		ASSERT(FALSE);
	}

	return 0;
}
//получение состояния режимов контроллера АльтПро
uint16_t CDebugger::GetAltProData(int reg)
{
	ASSERT(m_pChip);

	if (m_pChip)
	{
		switch (reg)
		{
			case 0:
				return m_pChip->GetAltProMode();

			case 1:
				return m_pChip->GetAltProCode();
		}

		ASSERT(FALSE);
	}

	return 0;
}
//получение состояния режимов контроллера FDD
uint16_t CDebugger::GetFDDData(int reg)
{
	ASSERT(m_pChip);

	if (m_pChip)
	{
		switch (reg)
		{
			case 0:
				return m_pChip->GetFDD()->GetStateDebug();

			case 1:
				return m_pChip->GetFDD()->GetCmdDebug();

			case 2:
				return m_pChip->GetFDD()->GetDataDebug();

			case 3:
				return m_pChip->GetFDD()->GetWriteDataDebug();
		}

		ASSERT(FALSE);
	}

	return 0;
}
uint16_t CDebugger::GetDebugHDDRegs(int nDrive, int num, bool bReadMode)
{
	ASSERT(m_pChip);

	if (m_pChip)
	{
		return m_pChip->GetFDD()->ReadDebugHDDRegisters(nDrive, static_cast<HDD_REGISTERS>(num), bReadMode);
	}

	return 0;
}

uint16_t CDebugger::GetDebugMemDumpWord(uint16_t addr)
{
	if (m_pChip)
	{
		return m_pChip->GetWordIndirect(addr & 0177776);
	}

	return 0;
}
uint8_t CDebugger::GetDebugMemDumpByte(uint16_t addr)
{
	if (m_pChip)
	{
		return m_pChip->GetByteIndirect(addr);
	}

	return 0;
}


uint16_t CDebugger::GetLineAddress(int nNum)
{
	if (nNum < 0)
	{
		return 0;
	}

	uint16_t wCurAddr = m_wAddress;

	while (nNum--)
	{
		wCurAddr += CalcInstructionLength(m_pChip->GetWordIndirect(wCurAddr));
	}

	return wCurAddr;
}


int CDebugger::CalcInstructionLength(uint16_t instr)
{
	m_wInstr = instr; //фиксируем опкод инструкции, длину которой подсчитываем
	CalcInstrLenRef &methodref = m_pInstrRefsMap[instr].InstrLenRef; //считаем
	return (this->*methodref)();
}

int CDebugger::CalcLenOneWord()
{
	return 2;
}

int CDebugger::CalcLenTwoFields()
{
	return 2 + CalcArgLength(DST);
}

int CDebugger::CalcLenFourFields()
{
	return 2 + CalcArgLength(DST) + CalcArgLength(SRC);
}


int CDebugger::CalcArgLength(int pos)
{
	register int reg = GetDigit(m_wInstr, pos++);
	register int meth = GetDigit(m_wInstr, pos);
	register int arg = 0;

	switch (meth)
	{
		/*
		case 0: // R0,      PC
		case 1: // (R0),    (PC)
		case 4: // -(R0),   -(PC)
		case 5: // @-(R0),  @-(PC)
		    break;
		*/
		case 2: // (R0)+,   #012345
		case 3: // @(R0)+,  @#012345
			if (reg == CCPU::R_PC)
			{
				arg = 2;
			}

			break;

		case 6: // 345(R0), 345
		case 7: // @345(R0),@345
			arg = 2;
			break;
	}

	return arg;
}


int CDebugger::DebugInstruction(uint16_t pc, CString &strInstr, CString &strArg, uint16_t *codes)
{
	ASSERT(m_pChip);
	int length = 1;

	if (m_pChip)
	{
		m_bPrevCmdCp = m_bPrevCmdC;
		m_bPrevCmdC = false;
		m_wPC = pc;
		m_wInstr = m_pChip->GetWordIndirect(pc);
		codes[0] = m_wInstr;
		m_strArg = _T("");
		m_strInstr = m_pInstrRefsMap[m_wInstr].Mnemonic;
		DisassembleInstrRef methodref = m_pInstrRefsMap[m_wInstr].DisasmInstrRef;
		length += (this->*methodref)(codes); //эта функция ещё формирует m_strInstr и m_strArg
		strInstr = m_strInstr;
		strArg = m_strArg;
	}

	return length;
}

int CDebugger::DisassembleNoArgs(uint16_t *codes)
{
	return 0;
}

int CDebugger::DisassembleUnknown(uint16_t *codes)
{
	m_strArg.Format(m_strArgFormat_Addr, m_wInstr);
	return 0;
}

int CDebugger::DisassembleCLS(uint16_t *codes)
{
	if (m_wInstr == PI_CCC)
	{
		m_strInstr = _T("CCC");
	}
	else if (m_wInstr & 0xf) //если признаки есть
	{
		m_strInstr = _T("CL");

		if (m_wInstr & (1 << PSW_N_POS))
		{
			m_strInstr += _T('N');
		}

		if (m_wInstr & (1 << PSW_Z_POS))
		{
			m_strInstr += _T('Z');
		}

		if (m_wInstr & (1 << PSW_V_POS))
		{
			m_strInstr += _T('V');
		}

		if (m_wInstr & (1 << PSW_C_POS))
		{
			m_strInstr += _T('C');
		}
	}

	return 0;
}

int CDebugger::DisassembleSET(uint16_t *codes)
{
	if (m_wInstr == PI_SCC)
	{
		m_strInstr = _T("SCC");
	}
	else if (m_wInstr & 0xf) //если признаки есть
	{
		m_strInstr = _T("SE");

		if (m_wInstr & (1 << PSW_N_POS))
		{
			m_strInstr += _T('N');
		}

		if (m_wInstr & (1 << PSW_Z_POS))
		{
			m_strInstr += _T('Z');
		}

		if (m_wInstr & (1 << PSW_V_POS))
		{
			m_strInstr += _T('V');
		}

		if (m_wInstr & (1 << PSW_C_POS))
		{
			m_strInstr += _T('C');
		}
	}

	return 0;
}

int CDebugger::DisassembleRTS(uint16_t *codes)
{
	int r = GetDigit(m_wInstr, 0);

	if (r == CCPU::R_PC)
	{
		m_strInstr = _T("RETURN");
	}
	else
	{
		m_strArg = m_strRegNames[r];
	}

	return 0;
}

int CDebugger::DisassembleOneField(uint16_t *codes)
{
	m_strArg = m_strRegNames[GetDigit(m_wInstr, 0)];
	return 0;
}

int CDebugger::DisassembleTwoField(uint16_t *codes)
{
	return ConvertArgToString(DST, m_wPC + 2, m_strArg, codes[1]);
}

int CDebugger::DisassembleMARK(uint16_t *codes)
{
	m_strArg.Format(m_strArgFormat_Number, m_wInstr & 077);
	return 0;
}

int CDebugger::DisassembleEMT(uint16_t *codes)
{
	m_strArg.Format(m_strArgFormat_Number, LOBYTE(m_wInstr));
	return 0;
}

int CDebugger::DisassembleBR(uint16_t *codes)
{
	m_strArg.Format(m_strArgFormat_Addr, m_wPC + ((short)(char)LOBYTE(m_wInstr) * 2) + 2);
	return 0;
}

int CDebugger::DisassembleBCC(uint16_t *codes)
{
	if (m_bPrevCmdCp)
	{
		m_strInstr = _T("BHIS");
	}

	return DisassembleBR(codes);
}

int CDebugger::DisassembleBCS(uint16_t *codes)
{
	if (m_bPrevCmdCp)
	{
		m_strInstr = _T("BLO");
	}

	return DisassembleBR(codes);
}

int CDebugger::DisassembleJSR(uint16_t *codes)
{
	int r = GetDigit(m_wInstr, 2);
	CString strDst;
	int length = ConvertArgToString(DST, m_wPC + 2, strDst, codes[1]);

	if (r == CCPU::R_PC)
	{
		m_strInstr = _T("CALL");
		m_strArg = strDst;
	}
	else
	{
		m_strArg = m_strRegNames[r] + m_strArgFormat_Comma + strDst;
	}

	return length;
}

int CDebugger::DisassembleMUL(uint16_t *codes)
{
	CString strDst;
	int length = ConvertArgToString(DST, m_wPC + 2, strDst, codes[1]);
	m_strArg = strDst + m_strArgFormat_Comma + m_strRegNames[GetDigit(m_wInstr, 2)];
	return length;
}

int CDebugger::DisassembleXOR(uint16_t *codes)
{
	CString strDst;
	int length = ConvertArgToString(DST, m_wPC + 2, strDst, codes[1]);
	m_strArg = m_strRegNames[GetDigit(m_wInstr, 2)] + m_strArgFormat_Comma + strDst;
	return length;
}

int CDebugger::DisassembleSOB(uint16_t *codes)
{
	CString strDst;
	strDst.Format(m_strArgFormat_Addr, m_wPC - (m_wInstr & 077) * 2 + 2);
	m_strArg = m_strRegNames[GetDigit(m_wInstr, 2)] + m_strArgFormat_Comma + strDst;
	return 0;
}

int CDebugger::DisassembleFourField(uint16_t *codes)
{
	CString strSrc;
	CString strDst;
	int length = ConvertArgToString(SRC, m_wPC + 2, strSrc, codes[1]);
	length += ConvertArgToString(DST, m_wPC + 2 + length * 2, strDst, codes[length + 1]);
	m_strArg = strSrc + m_strArgFormat_Comma + strDst;
	return length;
}

int CDebugger::DisassembleCMP(uint16_t *codes)
{
	m_bPrevCmdC = true;
	return DisassembleFourField(codes);
}

int CDebugger::ConvertArgToString(int arg, uint16_t pc, CString &strSrc, uint16_t &code)
{
	ASSERT(m_pChip);
	register int reg = GetDigit(m_wInstr, arg++);
	register int param = GetDigit(m_wInstr, arg);

	if (CCPU::R_R0 <= reg && reg <= CCPU::R_SP)
	{
		if (param >= 6)
		{
			register uint16_t word = m_pChip->GetWordIndirect(pc);
			strSrc.Format(m_strAddrFormat[param], word, m_strRegNames[reg]);
			code = word;
			return 1;
		}
		else
		{
			strSrc.Format(m_strAddrFormat[param], m_strRegNames[reg]);
		}
	}
	else
	{
		if (param == 2 || param == 3)
		{
			register uint16_t word = m_pChip->GetWordIndirect(pc);
			strSrc.Format(m_strAddrFormat_PC[param], word);
			code = word;
			return 1;
		}
		else if (param >= 6)
		{
			register uint16_t word = m_pChip->GetWordIndirect(pc);
			strSrc.Format(m_strAddrFormat_PC[param], (uint16_t)(pc + word + 2));
			code = word;
			return 1;
		}
		else
		{
			strSrc = m_strAddrFormat_PC[param];
		}
	}

	return 0;
}

/*
расчёт следующего адреса, который будет после выполнения текущей инструкции.
вход: pc - текущий адрес.
выход:
    true - если адрес можно рассчитать
    addr - расчётный адрес.
    false - если адрес не получается рассчитать
    addr = адрес следующий за инструкцией
*/
bool CDebugger::CalcNextAddr(uint16_t pc, uint16_t &addr)
{
	m_wPC = pc;
	m_wInstr = m_pChip->GetWordIndirect(pc);
	m_wNextAddr = m_wPC + CalcInstructionLength(m_wInstr);
	CalcNextAddrRef &methodref = m_pInstrRefsMap[m_wInstr].NextAddrRef;
	bool bRet = (this->*methodref)();
	addr = m_wNextAddr;
	return bRet;
}

bool CDebugger::CalcNextAddrRegular()
{
	//тут перехватываем и обрабатываем ситуации типа MOV xxx,PC
	register uint16_t opcode = m_wInstr & 0170077;

	switch (opcode)
	{
		case 010007:
			m_wNextAddr = GetArg(0);
			break;

		case 060007:
			m_wNextAddr = m_wPC + 2 + GetArg(0);
			break;

		case 0160007:
			m_wNextAddr = m_wPC + 2 - GetArg(0);
			break;
	}

	return true;
}

bool CDebugger::CalcNextAddrUNKNOWN()
{
	return false;
}

bool CDebugger::CalcNextAddrRTI()
{
	m_wNextAddr = m_pChip->GetWordIndirect(GetRegister(CCPU::R_SP));
	return true;
}

bool CDebugger::CalcNextAddrRTS()
{
	register int reg = GetDigit(m_wInstr, 0);

	if (reg == 7)
	{
		m_wNextAddr = m_pChip->GetWordIndirect(GetRegister(CCPU::R_SP));
	}
	else
	{
		m_wNextAddr = GetRegister(reg);
	}

	return true;
}

bool CDebugger::CalcNextAddrJMP()
{
	register int meth = GetDigit(m_wInstr, 1);

	if (meth == 0)
	{
		return false;
	}
	else
	{
		m_wNextAddr = GetArgAddr(meth, GetDigit(m_wInstr, 0));
	}

	return true;
}

//вход: type = 0 - источник, 1 - приёмник
// нужно, чтобы высчитать адрес перехода для команд типа mov xxx,PC
// необходимо учесть, что когда сюда попадаем у нас PC на 2 меньше чем надо.
int CDebugger::GetArg(int type)
{
	register int reg = GetDigit(m_wInstr, (type == 0) ? 2 : 0);
	register uint16_t offs = (reg == CCPU::R_PC) ? 2 : 0;
	register uint16_t r = GetRegister(reg); //содержимое регистра
	register int meth = GetDigit(m_wInstr, (type == 0) ? 3 : 1);
	register int arg = 0;
	register uint16_t index;

	switch (meth)
	{
		case 0: // R0,      PC
			arg = r;
			break;

		case 1: // (R0),    (PC)
		case 2: // (R0)+,   #012345
			arg = m_pChip->GetWordIndirect(r + offs);
			break;

		case 3: // @(R0)+,  @#012345
			arg = m_pChip->GetWordIndirect(r + offs);
			arg = m_pChip->GetWordIndirect(arg);
			break;

		case 4: // -(R0),   -(PC)
			arg = m_pChip->GetWordIndirect(r + offs - 2);
			break;

		case 5: // @-(R0),  @-(PC)
			arg = m_pChip->GetWordIndirect(r + offs - 2);
			arg = m_pChip->GetWordIndirect(arg);
			break;

		case 6: // 345(R0), 345
			index = m_pChip->GetWordIndirect(GetRegister(CCPU::R_PC) + 2);
			arg = m_pChip->GetWordIndirect((uint16_t)(index + r + offs + offs));
			break;

		case 7: // @345(R0),@345
			index = m_pChip->GetWordIndirect(GetRegister(CCPU::R_PC) + 2);
			arg = m_pChip->GetWordIndirect((uint16_t)(index + r + offs + offs)); //offs удвоенное, т.к. после чтения индекса PC ещё увеличивается на 2
			arg = m_pChip->GetWordIndirect(arg);
			break;
	}

	return arg;
}


//нужно, чтобы высчитать адрес перехода для JMP и JSR
// необходимо учесть, что когда сюда попадаем у нас PC на 2 меньше чем надо.
int CDebugger::GetArgAddr(int meth, int reg)
{
	register uint16_t offs = (reg == CCPU::R_PC) ? 2 : 0;
	register uint16_t r = GetRegister(reg);
	register int arg = 0;
	register uint16_t index;

	switch (meth)
	{
		case 0: // R0,      PC
			arg = reg;
			break;

		case 1: // (R0),    (PC)
		case 2: // (R0)+,   #012345
			arg = r + offs;
			break;

		case 3: // @(R0)+,  @#012345
			arg = m_pChip->GetWordIndirect(r + offs);
			break;

		case 4: // -(R0),   -(PC)
			arg = r + offs - 2;
			break;

		case 5: // @-(R0),  @-(PC)
			arg = m_pChip->GetWordIndirect(r + offs - 2);
			break;

		case 6: // 345(R0), 345
			index = m_pChip->GetWordIndirect(GetRegister(CCPU::R_PC) + 2);
			arg = index + r + offs + offs;
			break;

		case 7: // @345(R0),@345
			index = m_pChip->GetWordIndirect(GetRegister(CCPU::R_PC) + 2);
			arg = m_pChip->GetWordIndirect((uint16_t)(index + r + offs + offs)); //offs удвоенное, т.к. после чтения индекса PC ещё увеличивается на 2
			break;
	}

	return arg;
}

bool CDebugger::CalcNextAddrMARK()
{
	m_wNextAddr = GetRegister(CCPU::R_R5);
	return true;
}

bool CDebugger::CalcNextAddrSOB()
{
	register int reg = GetDigit(m_wInstr, 2);
	m_wNextAddr -= ((GetRegister(reg) - 1) ? (m_wInstr & (uint16_t)077) * 2 : 0);
	return true;
}

bool CDebugger::CalcNextAddrBR()
{
	register short br = ((short)(char)LOBYTE(m_wInstr)) * 2;
	m_wNextAddr += br;
	return true;
}

bool CDebugger::CalcNextAddrBNE()
{
	register short br = ((short)(char)LOBYTE(m_wInstr)) * 2;
	m_wNextAddr += (m_pChip->GetPSWBit(PSW_Z_POS) ? 0 : br);
	return true;
}

bool CDebugger::CalcNextAddrBEQ()
{
	register short br = ((short)(char)LOBYTE(m_wInstr)) * 2;
	m_wNextAddr += (m_pChip->GetPSWBit(PSW_Z_POS) ? br : 0);
	return true;
}

bool CDebugger::CalcNextAddrBGE()
{
	register bool bn = m_pChip->GetPSWBit(PSW_N_POS);
	register bool bv = m_pChip->GetPSWBit(PSW_V_POS);
	register short br = ((short)(char)LOBYTE(m_wInstr)) * 2;
	m_wNextAddr += ((bn == bv) ? br : 0);
	return true;
}

bool CDebugger::CalcNextAddrBLT()
{
	register bool bn = m_pChip->GetPSWBit(PSW_N_POS);
	register bool bv = m_pChip->GetPSWBit(PSW_V_POS);
	register short br = ((short)(char)LOBYTE(m_wInstr)) * 2;
	m_wNextAddr += ((bn != bv) ? br : 0);
	return true;
}

bool CDebugger::CalcNextAddrBGT()
{
	register bool bn = m_pChip->GetPSWBit(PSW_N_POS);
	register bool bz = m_pChip->GetPSWBit(PSW_Z_POS);
	register bool bv = m_pChip->GetPSWBit(PSW_V_POS);
	register short br = ((short)(char)LOBYTE(m_wInstr)) * 2;
	m_wNextAddr += ((bz || (bn != bv)) ? 0 : br);
	return true;
}

bool CDebugger::CalcNextAddrBLE()
{
	register bool bn = m_pChip->GetPSWBit(PSW_N_POS);
	register bool bz = m_pChip->GetPSWBit(PSW_Z_POS);
	register bool bv = m_pChip->GetPSWBit(PSW_V_POS);
	register short br = ((short)(char)LOBYTE(m_wInstr)) * 2;
	m_wNextAddr += ((bz || (bn != bv)) ? br : 0);
	return true;
}

bool CDebugger::CalcNextAddrBPL()
{
	register short br = ((short)(char)LOBYTE(m_wInstr)) * 2;
	m_wNextAddr += (m_pChip->GetPSWBit(PSW_N_POS) ? 0 : br);
	return true;
}

bool CDebugger::CalcNextAddrBMI()
{
	register short br = ((short)(char)LOBYTE(m_wInstr)) * 2;
	m_wNextAddr += (m_pChip->GetPSWBit(PSW_N_POS) ? br : 0);
	return true;
}

bool CDebugger::CalcNextAddrBHI()
{
	register bool bz = m_pChip->GetPSWBit(PSW_Z_POS);
	register bool bc = m_pChip->GetPSWBit(PSW_C_POS);
	register short br = ((short)(char)LOBYTE(m_wInstr)) * 2;
	m_wNextAddr += ((bz || bc) ? 0 : br);
	return true;
}

bool CDebugger::CalcNextAddrBLOS()
{
	register bool bz = m_pChip->GetPSWBit(PSW_Z_POS);
	register bool bc = m_pChip->GetPSWBit(PSW_C_POS);
	register short br = ((short)(char)LOBYTE(m_wInstr)) * 2;
	m_wNextAddr += ((bz || bc) ? br : 0);
	return true;
}

bool CDebugger::CalcNextAddrBVC()
{
	register short br = ((short)(char)LOBYTE(m_wInstr)) * 2;
	m_wNextAddr += (m_pChip->GetPSWBit(PSW_V_POS) ? 0 : br);
	return true;
}

bool CDebugger::CalcNextAddrBVS()
{
	register short br = ((short)(char)LOBYTE(m_wInstr)) * 2;
	m_wNextAddr += (m_pChip->GetPSWBit(PSW_V_POS) ? br : 0);
	return true;
}

bool CDebugger::CalcNextAddrBCC()
{
	register short br = ((short)(char)LOBYTE(m_wInstr)) * 2;
	m_wNextAddr += (m_pChip->GetPSWBit(PSW_C_POS) ? 0 : br);
	return true;
}

bool CDebugger::CalcNextAddrBCS()
{
	register short br = ((short)(char)LOBYTE(m_wInstr)) * 2;
	m_wNextAddr += (m_pChip->GetPSWBit(PSW_C_POS) ? br : 0);
	return true;
}

void CDebugger::RegisterMethodRef(uint16_t start, uint16_t end, CString &mnemonic, CalcInstrLenRef ilenmref, CalcNextAddrRef nxamref, DisassembleInstrRef dsimref)
{
	for (int opcode = start; opcode <= end; ++opcode)
	{
		m_pInstrRefsMap[opcode].Mnemonic = mnemonic;
		m_pInstrRefsMap[opcode].InstrLenRef = ilenmref;
		m_pInstrRefsMap[opcode].NextAddrRef = nxamref;
		m_pInstrRefsMap[opcode].DisasmInstrRef = dsimref;
	}
}

void CDebugger::InitMaps()
{
	if (m_pInstrRefsMap)
	{
		return;
	}

	m_pInstrRefsMap = new CDebugger::InstrFuncRefs[65536];

	if (m_pInstrRefsMap)
	{
		RegisterMethodRef(0000000, 0177777, CString(_T("WORD")),   &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrUNKNOWN, &CDebugger::DisassembleUnknown);   //uint16_t
		RegisterMethodRef(0000000, 0000000, CString(_T("HALT")),   &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrUNKNOWN, &CDebugger::DisassembleNoArgs);    //HALT
		RegisterMethodRef(0000001, 0000001, CString(_T("WAIT")),   &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleNoArgs);    //WAIT
		RegisterMethodRef(0000002, 0000002, CString(_T("RTI")),    &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrRTI,     &CDebugger::DisassembleNoArgs);    //RTI
		RegisterMethodRef(0000003, 0000003, CString(_T("BPT")),    &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleNoArgs);    //BPT
		RegisterMethodRef(0000004, 0000004, CString(_T("IOT")),    &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleNoArgs);    //IOT
		RegisterMethodRef(0000005, 0000005, CString(_T("RESET")),  &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleNoArgs);    //RESET
		RegisterMethodRef(0000006, 0000006, CString(_T("RTT")),    &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrRTI,     &CDebugger::DisassembleNoArgs);    //RTT
		RegisterMethodRef(0000010, 0000013, CString(_T("START")),  &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrUNKNOWN, &CDebugger::DisassembleNoArgs);    //START
		RegisterMethodRef(0000014, 0000017, CString(_T("STEP")),   &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrUNKNOWN, &CDebugger::DisassembleNoArgs);    //STEP
		RegisterMethodRef(0000100, 0000177, CString(_T("JMP")),    &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrJMP,     &CDebugger::DisassembleTwoField);  //JMP
		RegisterMethodRef(0000200, 0000207, CString(_T("RTS")),    &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrRTS,     &CDebugger::DisassembleRTS);       // RTS / RETURN
		RegisterMethodRef(0000240, 0000257, CString(_T("NOP")),    &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleCLS);       //CLS
		RegisterMethodRef(0000260, 0000277, CString(_T("NOP260")), &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleSET);       //SET
		RegisterMethodRef(0000300, 0000377, CString(_T("SWAB")),   &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //SWAB
		RegisterMethodRef(0000400, 0000777, CString(_T("BR")),     &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrBR,      &CDebugger::DisassembleBR);        //BR
		RegisterMethodRef(0001000, 0001377, CString(_T("BNE")),    &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrBNE,     &CDebugger::DisassembleBR);        //BNE
		RegisterMethodRef(0001400, 0001777, CString(_T("BEQ")),    &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrBEQ,     &CDebugger::DisassembleBR);        //BEQ
		RegisterMethodRef(0002000, 0002377, CString(_T("BGE")),    &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrBGE,     &CDebugger::DisassembleBR);        //BGE
		RegisterMethodRef(0002400, 0002777, CString(_T("BLT")),    &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrBLT,     &CDebugger::DisassembleBR);        //BLT
		RegisterMethodRef(0003000, 0003377, CString(_T("BGT")),    &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrBGT,     &CDebugger::DisassembleBR);        //BGT
		RegisterMethodRef(0003400, 0003777, CString(_T("BLE")),    &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrBLE,     &CDebugger::DisassembleBR);        //BLE
		RegisterMethodRef(0004000, 0004777, CString(_T("JSR")),    &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrJMP,     &CDebugger::DisassembleJSR);       // JSR / CALL
		RegisterMethodRef(0005000, 0005077, CString(_T("CLR")),    &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //CLR
		RegisterMethodRef(0005100, 0005177, CString(_T("COM")),    &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //COM
		RegisterMethodRef(0005200, 0005277, CString(_T("INC")),    &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //INC
		RegisterMethodRef(0005300, 0005377, CString(_T("DEC")),    &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //DEC
		RegisterMethodRef(0005400, 0005477, CString(_T("NEG")),    &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //NEG
		RegisterMethodRef(0005500, 0005577, CString(_T("ADC")),    &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //ADC
		RegisterMethodRef(0005600, 0005677, CString(_T("SBC")),    &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //SBC
		RegisterMethodRef(0005700, 0005777, CString(_T("TST")),    &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //TST
		RegisterMethodRef(0006000, 0006077, CString(_T("ROR")),    &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //ROR
		RegisterMethodRef(0006100, 0006177, CString(_T("ROL")),    &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //ROL
		RegisterMethodRef(0006200, 0006277, CString(_T("ASR")),    &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //ASR
		RegisterMethodRef(0006300, 0006377, CString(_T("ASL")),    &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //ASL
		RegisterMethodRef(0006400, 0006477, CString(_T("MARK")),   &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrMARK,    &CDebugger::DisassembleMARK);      //MARK
		RegisterMethodRef(0006500, 0006577, CString(_T("MFPI")),   &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrUNKNOWN, &CDebugger::DisassembleTwoField);  //MFPI
		RegisterMethodRef(0006600, 0006677, CString(_T("MTPI")),   &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrUNKNOWN, &CDebugger::DisassembleTwoField);  //MTPI
		RegisterMethodRef(0006700, 0006777, CString(_T("SXT")),    &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //SXT
		RegisterMethodRef(0010000, 0017777, CString(_T("MOV")),    &CDebugger::CalcLenFourFields, &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleFourField); //MOV
		RegisterMethodRef(0020000, 0027777, CString(_T("CMP")),    &CDebugger::CalcLenFourFields, &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleCMP);       //CMP
		RegisterMethodRef(0030000, 0037777, CString(_T("BIT")),    &CDebugger::CalcLenFourFields, &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleFourField); //BIT
		RegisterMethodRef(0040000, 0047777, CString(_T("BIC")),    &CDebugger::CalcLenFourFields, &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleFourField); //BIC
		RegisterMethodRef(0050000, 0057777, CString(_T("BIS")),    &CDebugger::CalcLenFourFields, &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleFourField); //BIS
		RegisterMethodRef(0060000, 0067777, CString(_T("ADD")),    &CDebugger::CalcLenFourFields, &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleFourField); //ADD
		RegisterMethodRef(0070000, 0070777, CString(_T("MUL")),    &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleMUL);       //MUL
		RegisterMethodRef(0071000, 0071777, CString(_T("DIV")),    &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleMUL);       //DIV
		RegisterMethodRef(0072000, 0072777, CString(_T("ASH")),    &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleMUL);       //ASH
		RegisterMethodRef(0073000, 0073777, CString(_T("ASHC")),   &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleMUL);       //ASHC
		RegisterMethodRef(0074000, 0074777, CString(_T("XOR")),    &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleXOR);       //XOR
		RegisterMethodRef(0075000, 0075007, CString(_T("FADD")),   &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleOneField);  //FADD
		RegisterMethodRef(0075010, 0075017, CString(_T("FSUB")),   &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleOneField);  //FSUB
		RegisterMethodRef(0075020, 0075027, CString(_T("FMUL")),   &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleOneField);  //FMUL
		RegisterMethodRef(0075030, 0075037, CString(_T("FDIV")),   &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleOneField);  //FDIV
		RegisterMethodRef(0077000, 0077777, CString(_T("SOB")),    &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrSOB,     &CDebugger::DisassembleSOB);       //SOB
		RegisterMethodRef(0100000, 0100377, CString(_T("BPL")),    &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrBPL,     &CDebugger::DisassembleBR);        //BPL
		RegisterMethodRef(0100400, 0100777, CString(_T("BMI")),    &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrBMI,     &CDebugger::DisassembleBR);        //BMI
		RegisterMethodRef(0101000, 0101377, CString(_T("BHI")),    &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrBHI,     &CDebugger::DisassembleBR);        //BHI
		RegisterMethodRef(0101400, 0101777, CString(_T("BLOS")),   &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrBLOS,    &CDebugger::DisassembleBR);        //BLOS
		RegisterMethodRef(0102000, 0102377, CString(_T("BVC")),    &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrBVC,     &CDebugger::DisassembleBR);        //BVC
		RegisterMethodRef(0102400, 0102777, CString(_T("BVS")),    &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrBVS,     &CDebugger::DisassembleBR);        //BVS
		RegisterMethodRef(0103000, 0103377, CString(_T("BCC")),    &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrBCC,     &CDebugger::DisassembleBCC);       //BHIS/BCC
		RegisterMethodRef(0103400, 0103777, CString(_T("BCS")),    &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrBCS,     &CDebugger::DisassembleBCS);       //BLO/BCS
		RegisterMethodRef(0104000, 0104377, CString(_T("EMT")),    &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleEMT);       //EMT
		RegisterMethodRef(0104400, 0104777, CString(_T("TRAP")),   &CDebugger::CalcLenOneWord,    &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleEMT);       //TRAP
		RegisterMethodRef(0105000, 0105077, CString(_T("CLRB")),   &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //CLRB
		RegisterMethodRef(0105100, 0105177, CString(_T("COMB")),   &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //COMB
		RegisterMethodRef(0105200, 0105277, CString(_T("INCB")),   &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //INCB
		RegisterMethodRef(0105300, 0105377, CString(_T("DECB")),   &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //DECB
		RegisterMethodRef(0105400, 0105477, CString(_T("NEGB")),   &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //NEGB
		RegisterMethodRef(0105500, 0105577, CString(_T("ADCB")),   &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //ADCB
		RegisterMethodRef(0105600, 0105677, CString(_T("SBCB")),   &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //SBCB
		RegisterMethodRef(0105700, 0105777, CString(_T("TSTB")),   &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //TSTB
		RegisterMethodRef(0106000, 0106077, CString(_T("RORB")),   &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //RORB
		RegisterMethodRef(0106100, 0106177, CString(_T("ROLB")),   &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //ROLB
		RegisterMethodRef(0106200, 0106277, CString(_T("ASRB")),   &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //ASRB
		RegisterMethodRef(0106300, 0106377, CString(_T("ASLB")),   &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //ASLB
		RegisterMethodRef(0106400, 0106477, CString(_T("MTPS")),   &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //MTPS
		RegisterMethodRef(0106500, 0106577, CString(_T("MFPD")),   &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrUNKNOWN, &CDebugger::DisassembleTwoField);  //MFPD
		RegisterMethodRef(0106600, 0106677, CString(_T("MTPD")),   &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrUNKNOWN, &CDebugger::DisassembleTwoField);  //MTPD
		RegisterMethodRef(0106700, 0106777, CString(_T("MFPS")),   &CDebugger::CalcLenTwoFields,  &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleTwoField);  //MFPS
		RegisterMethodRef(0110000, 0117777, CString(_T("MOVB")),   &CDebugger::CalcLenFourFields, &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleFourField); //MOVB
		RegisterMethodRef(0120000, 0127777, CString(_T("CMPB")),   &CDebugger::CalcLenFourFields, &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleCMP);       //CMPB
		RegisterMethodRef(0130000, 0137777, CString(_T("BITB")),   &CDebugger::CalcLenFourFields, &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleFourField); //BITB
		RegisterMethodRef(0140000, 0147777, CString(_T("BICB")),   &CDebugger::CalcLenFourFields, &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleFourField); //BICB
		RegisterMethodRef(0150000, 0157777, CString(_T("BISB")),   &CDebugger::CalcLenFourFields, &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleFourField); //BISB
		RegisterMethodRef(0160000, 0167777, CString(_T("SUB")),    &CDebugger::CalcLenFourFields, &CDebugger::CalcNextAddrRegular, &CDebugger::DisassembleFourField); //SUB
	}
	else
	{
		CBKMessageBox(g_pstrErrors[BK_ERROR_NOTENMEMR], MB_OK);
	}
}


bool CDebugger::OnDebugModify_Regs(int nAddress, uint16_t nValue)
{
	if (m_pChip)
	{
		if (CCPU::R_R0 <= nAddress && nAddress <= CCPU::R_PC)
		{
			m_pChip->SetRON(nAddress, nValue);
		}
		else if (CCPU::R_PSW == nAddress)
		{
			m_pChip->SetPSW(nValue);
		}
		else
		{
			ASSERT(FALSE);
		}

		if (nAddress == CCPU::R_PC)
		{
			SetCurrentAddress(nValue);
		}
	}

	return true;
}

bool CDebugger::OnDebugModify_Ports(int nAddress, uint16_t nValue)
{
	if (m_pChip)
	{
		switch (nAddress)
		{
			case SYS_PORT_177660:
				m_pChip->m_reg177660 = nValue;
				break;

			case SYS_PORT_177662_IN:
				m_pChip->m_reg177662in = nValue;
				break;

			case SYS_PORT_177662_OUT:
				m_pChip->SetWordIndirect(0177662, nValue);
				break;

			case SYS_PORT_177664:
				m_pChip->SetWordIndirect(0177664, nValue);
				break;

			case SYS_PORT_177700:
				m_pChip->SetWordIndirect(0177700, nValue);
				break;

			case SYS_PORT_177702:
				m_pChip->SetWordIndirect(0177702, nValue);
				break;

			case SYS_PORT_177704:
				m_pChip->SetWordIndirect(0177704, nValue);
				break;

			case SYS_PORT_177706:
				m_pChip->SetWordIndirect(0177706, nValue);
				break;

			case SYS_PORT_177710:
				m_pChip->SetWordIndirect(0177710, nValue);
				break;

			case SYS_PORT_177712:
				m_pChip->SetWordIndirect(0177712, nValue);
				break;

			case SYS_PORT_177714_IN:
				m_pChip->m_reg177714in = nValue;
				break;

			case SYS_PORT_177714_OUT:
				m_pChip->SetWordIndirect(0177714, nValue);
				break;

			case SYS_PORT_177716_IN:
				m_pChip->m_reg177716in = nValue;
				break;

			case SYS_PORT_177716_OUT_TAP:
				m_pChip->m_reg177716out_tap = nValue;
				break;

			case SYS_PORT_177716_OUT_MEM:
				m_pChip->Set177716RegMem(nValue);
				break;

			default:
				ASSERT(FALSE);
		}
	}

	return true;
}

bool CDebugger::OnDebugModify_Memory(int nAddress, uint16_t nValue)
{
	if (m_pChip)
	{
		m_pChip->SetWordIndirect(nAddress, nValue);
	}

	return true;
}

bool CDebugger::OnDebugModify_Memory(int nAddress, uint8_t nValue)
{
	if (m_pChip)
	{
		m_pChip->SetByteIndirect(nAddress, nValue);
	}

	return true;
}

bool CDebugger::OnDebugModify_AltProData(int nAddress, uint16_t nValue)
{
	if (m_pChip)
	{
		switch (nAddress)
		{
			case 0:
				m_pChip->SetAltProMode(nValue);
				break;

			case 1:
				m_pChip->SetAltProCode(nValue);
				break;
		}
	}

	return true;
}


