//
//	Потоковый дизассемблер для эмулятора CPU типа 1801ВМ1
//	by Patron
//	с адаптацией кода под мои нужды и интеграцией с классом CCPU, так что использует его переменные
//	Использует глобальные переменные:
//
//          PC           - счётчик команд, ссылка на m_RON[7]
//          m_PSW        - слово состояния CPU
//          m_RON        - массив регистров процессора
//          и ссылки на элементы этого массива R0..PC
//
//	Вызов:          DisAsm( );  // Дизассемблирует текущую инструкцию.
// NB: не надо тут осовременивать ничего. при использовании std::wstring и std::format
// начинает заметно тормозить.


#include "pch.h"
#include "CPU.h"
#include "Platform.h"

#pragma warning(disable:4996)

// EM_LOG(str) - вывод строки дизассемблинга в файл
#define EM_LOG(str)      fputws(str, m_hDisAsmLog)

// DebugOut(str) - вывод строки дизассемблинга на отладочную консоль
#define DebugOut(str)  g_pPaneOutputView->PutText(std::wstring(str))

// LNG(str) - подстановка перевода сообщения на выбранный язык при помощи API локализации
#define LNG(str)         str

#define GET_WORD(a) g_Platform.GetWordIndirect(a)
#define GET_BYTE(a) g_Platform.GetByteIndirect(a)

int                 nPrintPosition = 0;
std::array<int, 9>  nR_Operand;

////////////////////////////////////
void CCPU::OnStartStreamDisasm(const std::wstring &n)
{
	bHideDisAsm = false;
	nNestedTrapsTo4 = 0;
	nNestedTraps = 0;
	Last_TrapTo4_PC = 0177777;
	dPrevAddr.clear();
	dPrevAddr_Hidden.clear();
	nLoopStart = 0;
	nLoopPos = 0;
	nLoopLen = 0;
	nPrev_PC = 0;
	nLoopCount = 0;
	nLoopTopAddr = 0;
	PC_Next = 0177777;
	sHiddenCommandsCash.clear();
	sTrapMesCash.clear();
	nPrintPosition = 0;
	nR_Operand.fill(-1);

	if (!g_Config.m_bStreamDisasmAddrConsoleOut)
	{
		if (!m_hDisAsmLog)
		{
			const std::wstring name = _T("disasm_") + n + _T(".txt");
			const fs::path pathName = g_Config.m_strSavesPath / name;
			m_hDisAsmLog = _tfopen(pathName.c_str(), _T("wt"));
			ASSERT(m_hDisAsmLog);
		}
	}

	m_bDisAsmLog = true;
}

void CCPU::OnStopStreamDisasm()
{
	if (!g_Config.m_bStreamDisasmAddrConsoleOut)
	{
		if (m_hDisAsmLog)
		{
			fclose(m_hDisAsmLog);
			m_hDisAsmLog = nullptr;
		}
	}

	m_bDisAsmLog = false;
}

void CCPU::DisAsmPrint(const wchar_t *str)
{
#ifdef EM_LOG

	if (!g_Config.m_bStreamDisasmAddrConsoleOut)
	{
		if (!bHideDisAsm && m_hDisAsmLog)
		{
			EM_LOG(str);
		}
		else
		{
			sHiddenCommandsCash += str;
			// if( !nPrintPosition ) { EM_LOG(L"HIDE: "); }
			// EM_LOG(str);
		}
	}
	else
#endif
	{
		DebugOut(str);
	}

	nPrintPosition += wcslen(str);
}

void CCPU::SkipPrintToOperandPosition()
{
	if (g_Config.m_bStreamDisasmAddrConsoleOut)
	{
		while (nPrintPosition < 6)
		{
			DisAsmPrint(L" ");
		}
	}
	else
	{
		while (nPrintPosition < 6)
		{
			DisAsmPrint(L" ");
		}
	}

	nR_Operand.fill(-1);
}

void CCPU::SkipPrintToCommentsPosition()
{
	if (g_Config.m_bStreamDisasmAddrConsoleOut)
	{
		while (nPrintPosition < 28)
		{
			DisAsmPrint(L" ");
		}
	}
	else
	{
		while (nPrintPosition < 31)
		{
			DisAsmPrint(L" ");
		}
	}
}


int CCPU::PrintOperand(uint8_t nOpMode, int nOpSize)
{
	int nReg = nOpMode & 07;
	int nMode = (nOpMode & 070) >> 3;
	int nOffset = 0;
	uint16_t wAddr = 0;
	int nOppAddr = 0;
	bool bByteMode = (nOpSize == 1);
	wchar_t str[256];
	wchar_t acReg[32];

	if (nReg <= 5)
	{
		swprintf(acReg, L"R%u", nReg);
	}
	else
	{
		switch (nReg)
		{
			case 6:
				swprintf(acReg, L"SP");
				nOpSize = 2;
				break;

			case 7:
				swprintf(acReg, L"PC");
				nOpSize = 2;
				break;
		}
	}

	switch (nMode)
	{
		case 00:
		{
			swprintf(str, L"%s", acReg);
			nOppAddr = -1 * (nReg + 1);
		}
		break;

		case 01:
		{
			swprintf(str, L"(%s)", acReg);
			nOppAddr = m_RON[nReg];
		}
		break;

		case 02:
		{
			if (nReg != 7)
			{
				swprintf(str, L"(%s)+", acReg);

				if (!g_Config.m_bStreamDisasmAddrConsoleOut)
				{
					nOppAddr = m_RON[nReg];
					nR_Operand[nReg] = (uint16_t)(m_RON[nReg] + nOpSize);
				}
				else
				{
					nOppAddr = m_RON[nReg] - nOpSize;
					nR_Operand[nReg] = m_RON[nReg];
				}
			}
			else
			{
				wAddr = PC & (~1);
				int nData = (GET_WORD(wAddr));
				PC += 2;
				swprintf(str, L"#%06o", nData);
				nOppAddr = wAddr;
			}
		}
		break;

		case 03:
		{
			if (nReg != 7)
			{
				swprintf(str, L"@(%s)+", acReg);

				if (!g_Config.m_bStreamDisasmAddrConsoleOut)
				{
					nOppAddr = GET_WORD(m_RON[nReg]);
					nR_Operand[nReg] = (uint16_t)(m_RON[nReg] + 2);
				}
				else
				{
					nOppAddr = GET_WORD(m_RON[nReg] - 2);
					nR_Operand[nReg] = m_RON[nReg];
				}
			}
			else
			{
				wAddr = GET_WORD(PC);
				PC += 2;
				swprintf(str, L"@#%06o", wAddr);
				nOppAddr = wAddr;
			}
		}
		break;

		case 04:
		{
			swprintf(str, L"-(%s)", acReg);

			if (!g_Config.m_bStreamDisasmAddrConsoleOut)
			{
				nOppAddr = m_RON[nReg] - nOpSize;
				nR_Operand[nReg] = (uint16_t)(m_RON[nReg] - 2);
			}
			else
			{
				nOppAddr = m_RON[nReg];
				nR_Operand[nReg] = m_RON[nReg];
			}
		}
		break;

		case 05:
		{
			swprintf(str, L"@-(%s)", acReg);

			if (!g_Config.m_bStreamDisasmAddrConsoleOut)
			{
				nOppAddr = GET_WORD(m_RON[nReg] - 2);
				nR_Operand[nReg] = (uint16_t)(m_RON[nReg] - 2);
			}
			else
			{
				nOppAddr = GET_WORD(m_RON[nReg]);
				nR_Operand[nReg] = m_RON[nReg];
			}
		}
		break;

		case 06:
		{
			nOffset = (GET_WORD(PC));
			PC += 2;

			if (nReg != 7)
			{
				swprintf(str, L"%06o(%s)", nOffset, acReg);
			}
			else
			{
				wAddr = PC + nOffset;
				swprintf(str, L"%06o", wAddr);
			}

			nOppAddr = uint16_t((uint16_t)nOffset + m_RON[nReg]);
		}
		break;

		case 07:
		{
			nOffset = (GET_WORD(PC));
			PC += 2;

			if (nOffset)
			{
				swprintf(str, L"@%06o(%s)", nOffset, acReg);
			}
			else
			{
				swprintf(str, L"@(%s)", acReg);
			}

			nOppAddr = GET_WORD((uint16_t)(m_RON[nReg] + (uint16_t)nOffset));
		}
		break;
	}

	DisAsmPrint(str);

	if (!bByteMode && nOppAddr >= 0)
	{
		nOppAddr &= (~1);
	}

	return nOppAddr;
}

int CCPU::PrintOperand2(uint8_t nOpMode, int nOpSize)
{
	int nReg = nOpMode & 07;
	int nMode = (nOpMode & 070) >> 3;
	int nOffset = 0;
	uint16_t wAddr = 0;
	int nOppAddr = 0;
	bool bByteMode = (nOpSize == 1);
	wchar_t str[256];
	wchar_t acReg[32];

	if (nReg <= 5)
	{
		swprintf(acReg, L"R%u", nReg);
	}
	else
	{
		switch (nReg)
		{
			case 6:
				swprintf(acReg, L"SP");
				break;

			case 7:
				swprintf(acReg, L"PC");
				break;
		}
	}

	switch (nMode)
	{
		case 00:
		{
			swprintf(str, L"%s", acReg);
			nOppAddr = -1 * (nReg + 1);
		}
		break;

		case 01:
		{
			swprintf(str, L"(%s)", acReg);

			if (nR_Operand[nReg] < 0)
			{
				nOppAddr = m_RON[nReg];
			}
			else
			{
				nOppAddr = nR_Operand[nReg];
			}
		}
		break;

		case 02:
		{
			if (nReg != 7)
			{
				swprintf(str, L"(%s)+", acReg);

				if (nR_Operand[nReg] < 0)
				{
					if (!g_Config.m_bStreamDisasmAddrConsoleOut)
					{
						nOppAddr = m_RON[nReg];
					}
					else
					{
						nOppAddr = m_RON[nReg] - nOpSize;
					}
				}
				else
				{
					nOppAddr = nR_Operand[nReg];
				}
			}
			else
			{
				wAddr = PC & (~1);
				int nData = (GET_WORD(wAddr));
				PC += 2;
				swprintf(str, L"#%06o", nData);
				nOppAddr = wAddr;
			}
		}
		break;

		case 03:
		{
			if (nReg != 7)
			{
				swprintf(str, L"@(%s)+", acReg);

				if (nR_Operand[nReg] < 0)
				{
					if (!g_Config.m_bStreamDisasmAddrConsoleOut)
					{
						nOppAddr = GET_WORD(m_RON[nReg]);
					}
					else
					{
						nOppAddr = GET_WORD(m_RON[nReg] - 2);
					}
				}
				else
				{
					nOppAddr = GET_WORD(nR_Operand[nReg]);
				}
			}
			else
			{
				wAddr = GET_WORD(PC);
				PC += 2;
				swprintf(str, L"@#%o", wAddr);
				nOppAddr = wAddr;
			}
		}
		break;

		case 04:
		{
			swprintf(str, L"-(%s)", acReg);

			if (nR_Operand[nReg] < 0)
			{
				if (!g_Config.m_bStreamDisasmAddrConsoleOut)
				{
					nOppAddr = m_RON[nReg] - nOpSize;
				}
				else
				{
					nOppAddr = m_RON[nReg];
				}
			}
			else
			{
				nOppAddr = nR_Operand[nReg] - nOpSize;
			}
		}
		break;

		case 05:
		{
			swprintf(str, L"@-(%s)", acReg);

			if (nR_Operand[nReg] < 0)
			{
				if (!g_Config.m_bStreamDisasmAddrConsoleOut)
				{
					nOppAddr = GET_WORD(m_RON[nReg] - 2);
				}
				else
				{
					nOppAddr = GET_WORD(m_RON[nReg]);
				}
			}
			else
			{
				nOppAddr = GET_WORD(nR_Operand[nReg] - 2);
			}
		}
		break;

		case 06:
		{
			nOffset = (GET_WORD(PC));
			PC += 2;

			if (nReg != 7)
			{
				swprintf(str, L"%06o(%s)", nOffset, acReg);
			}
			else
			{
				wAddr = PC + nOffset;
				swprintf(str, L"%06o", wAddr);
			}

			if (nR_Operand[nReg] < 0)
			{
				nOppAddr = uint16_t((uint16_t)nOffset + m_RON[nReg]);
			}
			else
			{
				nOppAddr = uint16_t((uint16_t)nOffset + nR_Operand[nReg]);
			}
		}
		break;

		case 07:
		{
			nOffset = (GET_WORD(PC));
			PC += 2;

			if (nOffset)
			{
				swprintf(str, L"@%06o(%s)", nOffset, acReg);
			}
			else
			{
				swprintf(str, L"@(%s)", acReg);
			}

			if (nR_Operand[nReg] < 0)
			{
				nOppAddr = GET_WORD((uint16_t)(m_RON[nReg] + (uint16_t)nOffset));
			}
			else
			{
				nOppAddr = GET_WORD((uint16_t)(nR_Operand[nReg] + (uint16_t)nOffset));
			}
		}
		break;
	}

	DisAsmPrint(str);

	if (!bByteMode && nOppAddr >= 0)
	{
		nOppAddr &= (~1);
	}

	return nOppAddr;
}

// если nCode == -1, то выводится полный вид, с адресом и пояснениями
// если nCode == текущий опкод, то выводится просто дизассемблерный код
// без адреса и пояснений.
void CCPU::DisAsm(int nCode)
{
	wchar_t str[256];
	uint16_t nWord;
	uint16_t PC_res = PC;
	int nSize = dPrevAddr.size();

	if (nCode >= 0)
	{
		goto DE_TRACE;
	}

	bHideDisAsm = false;

	/*
	for( int i = 0 ; i < nSize ; i++ )
	{
	    wchar_t str[512];
	    swprintf(str,L"[%i:%06o]", i, dPrevAddr[i] );
	    EM_LOG(str);
	}
	EM_LOG(L"\n");
	//*/
	if (!g_Config.m_bStreamDisasmAddrConsoleOut && g_Config.m_nStreamDisasmMaxLoopCommandsToHide /*&& !St_StepMode()*/)
	{
		for (int i = 0; i < nSize; i++)
		{
			if (dPrevAddr[i] == PC)
			{
				bHideDisAsm = true;

				if (dPrevAddr[nSize - 1] == nPrev_PC)
				{
					nLoopPos = 0;
					nLoopTopAddr = nPrev_PC;

					if (nLoopStart < 0)
					{
						nLoopStart = i;
						nLoopCount = 1;
					}
					else if (i != nLoopStart)
					{
						if (--nLoopCount > 0)
						{
							swprintf(str, LNG(L"\n^^^ Last [%i] lines [%i] loops ^^^\n\n"), nSize - nLoopStart, nLoopCount + 1);
							//swprintf(str,LNG(L"\n^^^ =1= Last [%i] lines [%i] loops ^^^\n\n"), nSize - nLoopStart, nLoopCount+1 );
							EM_LOG(str);
							dPrevAddr.clear();
						}
						else
						{
							EM_LOG(sHiddenCommandsCash.c_str());
							dPrevAddr = dPrevAddr_Hidden;
						}

						int j = 0;
						nSize = dPrevAddr.size();
						bool bPC_Found = false;

						for (; j < nSize; j++)
						{
							if (dPrevAddr[j] == PC)
							{
								bPC_Found = true;
								break;
							}
						}

						if (bPC_Found)
						{
							nLoopStart = j;
							nLoopCount = 1;
						}
						else
						{
							nLoopStart = -1;
							nLoopCount = -1;
							bHideDisAsm = false;
						}
					}
					else
					{
						nLoopCount++;
					}

					sHiddenCommandsCash.clear();
					dPrevAddr_Hidden.clear();
				}
				else
				{
					nLoopPos++;
					int nIndex = nLoopStart + nLoopPos;

					if (nLoopStart >= 0 && i == nLoopStart)
					{
						for (int j = 0; j < nSize; j++)
						{
							if (dPrevAddr[j] == nPrev_PC && j < nSize - 1)
							{
								nIndex = j + 1;
								break;
							}
						}
					}

					//*
					if (nLoopStart >= 0 && nIndex >= dPrevAddr.size())
					{
						goto SKIP_ERASE;
					}//*/

					if (nLoopStart >= 0 && dPrevAddr[nIndex] != PC)
					{
						dPrevAddr.erase(dPrevAddr.begin() + nIndex, dPrevAddr.end());
SKIP_ERASE:
						nLoopPos = 0;

						if (--nLoopCount > 0)
						{
							swprintf(str, LNG(L"\n^^^ Last [%i] lines [%i] loops ^^^\n\n"), nSize - nLoopStart, nLoopCount + 1);
							//swprintf(str,LNG(L"\n^^^ =2= Last [%i] lines [%i] loops ^^^\n\n"), nSize - nLoopStart, nLoopCount+1 );
							EM_LOG(str);
						}

						EM_LOG(sHiddenCommandsCash.c_str());
						sHiddenCommandsCash.clear();
						dPrevAddr = dPrevAddr_Hidden;
						dPrevAddr_Hidden.clear();
						int j = 0;
						nSize = dPrevAddr.size();
						bool bPC_Found = false;

						for (; j < nSize; j++)
						{
							if (dPrevAddr[j] == PC)
							{
								bPC_Found = true;
								break;
							}
						}

						if (bPC_Found)
						{
							nLoopStart = j;
							nLoopCount = 1;
						}
						else
						{
							nLoopStart = -1;
							nLoopCount = -1;
							bHideDisAsm = false;
						}
					}
				}

				break;
			}
			else
			{
				if (dPrevAddr[i] > PC)
				{
					dPrevAddr.erase(dPrevAddr.begin() + i, dPrevAddr.end());
					break;
				}
			}
		}
	}

	if (!bHideDisAsm || !sTrapMesCash.empty())
	{
		if (nLoopCount > 0)
		{
			if (nPrev_PC != nLoopTopAddr)
			{
				if (--nLoopCount > 0)
				{
					swprintf(str, LNG(L"\n^^^ Last [%i] lines [%i] loops ^^^\n\n"), nSize - nLoopStart, nLoopCount + 1);
					//                  swprintf(str,LNG(L"\n^^^ =3= Last [%i] lines [%i] loops ^^^\n\n"), nSize - nLoopStart, nLoopCount+1 );
					EM_LOG(str);
				}

				EM_LOG(sHiddenCommandsCash.c_str());
				sHiddenCommandsCash.clear();
				dPrevAddr = dPrevAddr_Hidden;
				dPrevAddr_Hidden.clear();
			}
			else
			{
				swprintf(str, LNG(L"\n^^^ Last [%i] lines [%i] loops ^^^\n\n"), nSize - nLoopStart, nLoopCount + 1);
				//              swprintf(str,LNG(L"\n^^^ =4= Last [%i] lines [%i] loops ^^^\n\n"), nSize - nLoopStart, nLoopCount+1 );
				EM_LOG(str);
				dPrevAddr.clear();
			}

			nLoopStart = -1;
			nLoopCount = -1;
			sHiddenCommandsCash.clear();
			dPrevAddr_Hidden.clear();
		}
	}

	if (!sTrapMesCash.empty())
	{
		if (PC == GET_WORD(04) && !g_Platform.ReadAccess(nPrev_PC) && Last_TrapTo4_PC == nPrev_PC)
		{
			//  Зацикливание Trap_to_04
			if (nNestedTraps++ < 3)
			{
				goto SHOW_TRAP;
			}
		}
		else
		{
			nNestedTraps = 0;

			if (nNestedTrapsTo4 < 3)
			{
SHOW_TRAP:
				EM_LOG(sTrapMesCash.c_str());
				bHideDisAsm = false;
				dPrevAddr.clear();
				dPrevAddr_Hidden.clear();
			}
		}

		sTrapMesCash.clear();
	}

	nPrev_PC = PC;

	if (g_Platform.ReadAccess(PC))
	{
		bNoMemoryReported = false;

		if (!bHideDisAsm)
		{
			dPrevAddr.push_back(PC);

			if (dPrevAddr.size() > g_Config.m_nStreamDisasmMaxLoopCommandsToHide)
			{
				dPrevAddr.pop_front();
			}
		}
		else
		{
			dPrevAddr_Hidden.push_back(PC);
		}
	}

	////////////////////////////////////////////////////////
	bCallWasDone = false;

	if (!bNoMemoryReported)
	{
		if (!g_Config.m_bStreamDisasmAddrConsoleOut && PC != PC_Next)
		{
			DisAsmPrint(L"\n");
		}

		if (g_Config.m_bStreamDisasmAddrPrefixEna)
		{
			int seg = (PC >> 12) & 0xf;

			if (seg == 15 && PC >= 0177000)
			{
				seg++;
			}

			swprintf(str, L"%-7s:", g_arStrStDsData[seg].c_str());
			DisAsmPrint(str);
		}

		if (!g_Config.m_bStreamDisasmAddrConsoleOut)
		{
			swprintf(str, L"%06o [%06o]:  ", PC, m_PSW);
		}
		else
		{
			swprintf(str, L"%06o: ", PC);
		}

		DisAsmPrint(str);
	}

	if (!g_Platform.ReadAccess(PC))
	{
		if (!bNoMemoryReported)
		{
			bNoMemoryReported = true;
			wchar_t str[256];
			swprintf(str, L"%s..\n", LNG(L"No memory"));
			DisAsmPrint(str);
		}

		goto DONE;
	}

	bNoMemoryReported = false;
	nWord = GET_WORD(PC);
DE_TRACE:;

	if (nCode >= 0)
	{
		nWord = nCode;
	}

	PC += 2;
	nPrintPosition = 0;

	if (nWord == 0)
	{
		DisAsmPrint(L"HALT");
		goto DONE;
	}

	if (nWord == 1)
	{
		DisAsmPrint(L"WAIT");
		goto DONE;
	}

	if (nWord == 2)
	{
		DisAsmPrint(L"RTI");

		if (nCode >= 0)
		{
			goto DONE;
		}

		SkipPrintToCommentsPosition();
		swprintf(str, LNG(L"; %06o:%06o ->   PC\n"), SP & (~1), GET_WORD(SP));
		DisAsmPrint(str);
		DisAsmPrint(L"                                                      ");
		swprintf(str, LNG(L"; %06o:   %03o ->   PSW"), (SP + 2) & (~1), GET_BYTE(SP + 2));
		DisAsmPrint(str);
		goto DONE;
	}

	if (nWord == 3)
	{
		DisAsmPrint(L"BPT");

		if (nCode >= 0)
		{
			goto DONE;
		}

		SkipPrintToCommentsPosition();
		bool bOK = true;
		uint16_t wSP = (SP - 2) & (~1);

		if (g_Platform.WriteAccess(wSP))
		{
			swprintf(str, L";   PSW :%06o -> %06o:%06o\n", m_PSW, wSP, GET_WORD(wSP));
		}
		else if (g_Platform.ReadAccess(wSP))
		{
			bOK = false;
			swprintf(str, L";   PSW :%06o -> %06o: %s..\n", m_PSW, wSP, LNG(L"Read only"));
		}
		else
		{
			bOK = false;
			swprintf(str, L";   PSW :%06o -> %06o: %s..\n", m_PSW, wSP, LNG(L"No memory"));
		}

		DisAsmPrint(str);

		if (!bOK)
		{
			goto DONE;
		}

		DisAsmPrint(L"                                                      ");
		wSP = (SP - 4) & (~1);

		if (g_Platform.WriteAccess(wSP))
		{
			swprintf(str, L";   PC  :%06o -> %06o:%06o\n", PC, wSP, GET_WORD(wSP));
		}
		else if (g_Platform.ReadAccess(wSP))
		{
			bOK = false;
			swprintf(str, L";   PC  :%06o -> %06o: %s..\n", PC, wSP, LNG(L"Read only"));
		}
		else
		{
			bOK = false;
			swprintf(str, L";   PC  :%06o -> %06o: %s..\n", PC, wSP, LNG(L"No memory"));
		}

		DisAsmPrint(str);

		if (!bOK)
		{
			goto DONE;
		}

		DisAsmPrint(L"                                                      ");
		uint16_t addr = 014;

		if (g_Platform.ReadAccess(addr))
		{
			swprintf(str, L"; %06o:%06o ->   PC\n", addr, GET_WORD(addr));
		}
		else
		{
			bOK = false;
			swprintf(str, L"; %06o:       ->   PC\n", addr);
		}

		DisAsmPrint(str);

		if (!bOK)
		{
			goto DONE;
		}

		DisAsmPrint(L"                                                      ");
		addr += 2;

		if (g_Platform.ReadAccess(addr))
		{
			swprintf(str, L"; %06o:   %03o ->   PSW", addr, GET_BYTE(addr));
		}
		else
		{
			swprintf(str, L"; %06o:       ->   PSW", addr);
		}

		DisAsmPrint(str);
		goto DONE;
	}

	if (nWord == 4)
	{
		DisAsmPrint(L"IOT");

		if (nCode >= 0)
		{
			goto DONE;
		}

		SkipPrintToCommentsPosition();
		bool bOK = true;
		uint16_t wSP = (SP - 2) & (~1);

		if (g_Platform.WriteAccess(wSP))
		{
			swprintf(str, L";   PSW :%06o -> %06o:%06o\n", m_PSW, wSP, GET_WORD(wSP));
		}
		else if (g_Platform.ReadAccess(wSP))
		{
			bOK = false;
			swprintf(str, L";   PSW :%06o -> %06o: %s..\n", m_PSW, wSP, LNG(L"Read only"));
		}
		else
		{
			bOK = false;
			swprintf(str, L";   PSW :%06o -> %06o: %s..\n", m_PSW, wSP, LNG(L"No memory"));
		}

		DisAsmPrint(str);

		if (!bOK)
		{
			goto DONE;
		}

		DisAsmPrint(L"                                                      ");
		wSP = (SP - 4) & (~1);

		if (g_Platform.WriteAccess(wSP))
		{
			swprintf(str, L";   PC  :%06o -> %06o:%06o\n", PC, wSP, GET_WORD(wSP));
		}
		else if (g_Platform.ReadAccess(wSP))
		{
			bOK = false;
			swprintf(str, L";   PC  :%06o -> %06o: %s..\n", PC, wSP, LNG(L"Read only"));
		}
		else
		{
			bOK = false;
			swprintf(str, L";   PC  :%06o -> %06o: %s..\n", PC, wSP, LNG(L"No memory"));
		}

		DisAsmPrint(str);

		if (!bOK)
		{
			goto DONE;
		}

		DisAsmPrint(L"                                                      ");
		uint16_t addr = 020;

		if (g_Platform.ReadAccess(addr))
		{
			swprintf(str, L"; %06o:%06o ->   PC\n", addr, GET_WORD(addr));
		}
		else
		{
			bOK = false;
			swprintf(str, L"; %06o:       ->   PC\n", addr);
		}

		DisAsmPrint(str);

		if (!bOK)
		{
			goto DONE;
		}

		DisAsmPrint(L"                                                      ");
		addr += 2;

		if (g_Platform.ReadAccess(addr))
		{
			swprintf(str, L"; %06o:   %03o ->   PSW", addr, GET_BYTE(addr));
		}
		else
		{
			swprintf(str, L"; %06o:       ->   PSW", addr);
		}

		DisAsmPrint(str);
		goto DONE;
	}

	if (nWord == 5)
	{
		DisAsmPrint(L"RESET");
		goto DONE;
	}

	if (nWord == 6)
	{
		DisAsmPrint(L"RTT");

		if (nCode >= 0)
		{
			goto DONE;
		}

		SkipPrintToCommentsPosition();
		swprintf(str, LNG(L"; %06o:%06o ->   PC\n"), SP & (~1), GET_WORD(SP));
		DisAsmPrint(str);
		DisAsmPrint(L"                                                      ");
		swprintf(str, LNG(L"; %06o:   %03o ->   PSW"), (SP + 2) & (~1), GET_BYTE(SP + 2));
		DisAsmPrint(str);
		goto DONE;
	}

	if (nWord == 7)
	{
		swprintf(str, LNG(L"%06o - Strange Opcode"), nWord);
		DisAsmPrint(str);
		goto DONE;
	}

	if (nWord >= 010 && nWord <= 013)
	{
		DisAsmPrint(L"START");

		if (nCode >= 0)
		{
			goto DONE;
		}

		SkipPrintToCommentsPosition();

		if (g_Platform.ReadAccess(0177674))
		{
			swprintf(str, LNG(L"; %06o:%06o ->   PC\n"), 0177674, GET_WORD(0177674));
		}
		else
		{
			swprintf(str, LNG(L"; %06o:       ->   PC\n"), 0177674);
		}

		DisAsmPrint(str);
		DisAsmPrint(L"                                                      ");

		if (g_Platform.ReadAccess(0177676))
		{
			swprintf(str, LNG(L"; %06o:%06o ->   PSW\n"), 0177676, GET_WORD(0177676));
		}
		else
		{
			swprintf(str, LNG(L"; %06o:       ->   PSW\n"), 0177676);
		}

		DisAsmPrint(str);
		goto DONE;
	}

	if (nWord >= 014 && nWord <= 017)
	{
		DisAsmPrint(L"STEP");

		if (nCode >= 0)
		{
			goto DONE;
		}

		SkipPrintToCommentsPosition();

		if (g_Platform.ReadAccess(0177674))
		{
			swprintf(str, LNG(L"; %06o:%06o ->   PC\n"), 0177674, GET_WORD(0177674));
		}
		else
		{
			swprintf(str, LNG(L"; %06o:       ->   PC\n"), 0177674);
		}

		DisAsmPrint(str);
		DisAsmPrint(L"                                                      ");

		if (g_Platform.ReadAccess(0177676))
		{
			swprintf(str, LNG(L"; %06o:%06o ->   PSW"), 0177676, GET_WORD(0177676));
		}
		else
		{
			swprintf(str, LNG(L"; %06o:       ->   PSW"), 0177676);
		}

		DisAsmPrint(str);
		goto DONE;
	}

	if (nWord <= 0177)
	{
		if (nWord & 0100)
		{
			DisAsmPrint(L"JMP ");
			SkipPrintToOperandPosition();
			int nOppAddr = PrintOperand(nWord & 077);

			if (nCode >= 0)
			{
				goto DONE;
			}

			SkipPrintToCommentsPosition();

			if (nOppAddr >= 0)
			{
				uint16_t wOppAddr = nOppAddr;

				if (g_Platform.ReadAccess(wOppAddr))
				{
					swprintf(str, LNG(L";        %06o ->   PC"), wOppAddr);
				}
				else
				{
					swprintf(str, LNG(L";        %06o -- %s.."), wOppAddr, LNG(L"No memory"));
				}

				DisAsmPrint(str);
			}/*

            else
            {
                int nR = (-1*nOppAddr)-1;
                swprintf(str,LNG(L";   R%i  :%06o"), nR, m_RON[nR] );
                DisAsmPrint(str);
            }//*/
			goto DONE;
		}

		swprintf(str, LNG(L"%06o - Strange Opcode"), nWord);
		DisAsmPrint(str);
		goto DONE;
	}

	if (nWord <= 0207)
	{
		int nReg = nWord & 07;

		if (nReg != 7)
		{
			DisAsmPrint(L"RTS ");
			SkipPrintToOperandPosition();
			swprintf(str, L"R%u", nReg);
			DisAsmPrint(str);
		}
		else
		{
			DisAsmPrint(L"RETURN");
		}

		if (nCode >= 0)
		{
			goto DONE;
		}

		SkipPrintToCommentsPosition();
		swprintf(str, LNG(L"; %06o:%06o ->   R%i  "), SP & (~1), GET_WORD(SP), nReg);
		DisAsmPrint(str);
		goto DONE;
	}

	if (nWord < 0230)
	{
		swprintf(str, LNG(L"%06o - Strange Opcode"), nWord);
		DisAsmPrint(str);
		goto DONE;
	}

	if (nWord <= 0237)
	{
		//    int nPriority = nWord & 07;
		//    swprintf(str,"SPL %u\n", nPriority );
		swprintf(str, LNG(L"%06o - SPL - Opcode not supported"), nWord);
		DisAsmPrint(str);
		goto DONE;
	}

	if (nWord <= 0277)
	{
		uint16_t nMask, mask;

		switch (nWord)
		{
			case 0240:
				DisAsmPrint(L"NOP");
				break;

			case 0241:
				DisAsmPrint(L"CLC");
				break;

			case 0242:
				DisAsmPrint(L"CLV");
				break;

			case 0244:
				DisAsmPrint(L"CLZ");
				break;

			case 0250:
				DisAsmPrint(L"CLN");
				break;

			case 0257:
				DisAsmPrint(L"CCC");
				break;

			case 0261:
				DisAsmPrint(L"SEC");
				break;

			case 0262:
				DisAsmPrint(L"SEV");
				break;

			case 0264:
				DisAsmPrint(L"SEZ");
				break;

			case 0270:
				DisAsmPrint(L"SEN");
				break;

			case 0277:
				DisAsmPrint(L"SCC");
				break;

			default:
				if (nWord <= 0257)
				{
					// NOP .. CCC
					nMask = nWord & 017;
					DisAsmPrint(L"BIC_PSW ^b");

					for (mask = 010; mask; mask >>= 1)
					{
						swprintf(str, L"%u", ((nMask & mask) != 0));
						DisAsmPrint(str);
					}

					break;
				}

				if (nWord <= 0277)
				{
					// NOP2 .. SCC
					nMask = nWord & 017;
					DisAsmPrint(L"BIS_PSW ^b");

					for (mask = 010; mask; mask >>= 1)
					{
						swprintf(str, L"%u", ((nMask & mask) != 0));
						DisAsmPrint(str);
					}

					break;
				}

				swprintf(str, LNG(L"%06o - Strange Opcode"), nWord);
				DisAsmPrint(str);
				break;
		}

		goto DONE;
	}

	if (nWord <= 0377)
	{
		DisAsmPrint(L"SWAB ");

		if (nCode >= 0)
		{
			goto DONE;
		}

		SkipPrintToOperandPosition();
		int nOppAddr = PrintOperand(nWord & 077);

		if (nCode >= 0)
		{
			goto DONE;
		}

		SkipPrintToCommentsPosition();

		if (nOppAddr >= 0)
		{
			uint16_t wOppAddr = nOppAddr;
			uint16_t wOperand = GET_WORD(wOppAddr);

			if (g_Platform.ReadAccess(wOppAddr))
			{
				swprintf(str, LNG(L"; %06o:%06o"), wOppAddr, wOperand);
			}
			else
			{
				swprintf(str, LNG(L"; %06o:      "), wOppAddr);
			}

			DisAsmPrint(str);
		}
		else
		{
			int nR = (-1 * nOppAddr) - 1;
			swprintf(str, LNG(L";   R%i  :%06o"), nR, m_RON[nR]);
			DisAsmPrint(str);
		}

		goto DONE;
	}

	if (nWord <= 03777)
	{
		switch (nWord & 03400)
		{
			case 0400:
				DisAsmPrint(L"BR ");
				break;

			case 01000:
				DisAsmPrint(L"BNE ");
				break;

			case 01400:
				DisAsmPrint(L"BEQ ");
				break;

			case 02000:
				DisAsmPrint(L"BGE ");
				break;

			case 02400:
				DisAsmPrint(L"BLT ");
				break;

			case 03000:
				DisAsmPrint(L"BGT ");
				break;

			case 03400:
				DisAsmPrint(L"BLE ");
				break;

			default:
				swprintf(str, LNG(L"%06o - Strange Opcode"), nWord);
				DisAsmPrint(str);
				goto DONE;
		}

		int nOffset = (signed char)(nWord & 0377);
		nOffset *= 2;
		SkipPrintToOperandPosition();
		swprintf(str, L"%06o", uint16_t(PC + nOffset));
		DisAsmPrint(str);
		//      SkipPrintToCommentsPosition();
		//      if( ( nWord & 03400 ) != 0400 )
		//      {
		//        swprintf(str,";   PSW :%06o", PSW );
		//        DisAsmPrint(str);
		//      }
		goto DONE;
	}

	if (nWord <= 04777)
	{
		bCallWasDone = true;
		int nReg = (nWord & 0700) >> 6;

		if (nReg != 7)
		{
			DisAsmPrint(L"JSR ");
			SkipPrintToOperandPosition();
			swprintf(str, L"R%u, ", nReg);
			DisAsmPrint(str);
		}
		else
		{
			DisAsmPrint(L"CALL ");
			SkipPrintToOperandPosition();
		}

		PrintOperand(nWord & 077);

		if (nCode >= 0)
		{
			goto DONE;
		}

		SkipPrintToCommentsPosition();
		swprintf(str, LNG(L";   R%i  :%06o -> %06o"), nReg, m_RON[nReg], uint16_t((SP & (~1)) - 2));
		DisAsmPrint(str);
		goto DONE;
	}

	if (nWord <= 06377)
	{
		switch (nWord & 07700)
		{
			case 05000:
				DisAsmPrint(L"CLR ");
				break;

			case 05100:
				DisAsmPrint(L"COM ");
				break;

			case 05200:
				DisAsmPrint(L"INC ");
				break;

			case 05300:
				DisAsmPrint(L"DEC ");
				break;

			case 05400:
				DisAsmPrint(L"NEG ");
				break;

			case 05500:
				DisAsmPrint(L"ADC ");
				break;

			case 05600:
				DisAsmPrint(L"SBC ");
				break;

			case 05700:
				DisAsmPrint(L"TST ");
				break;

			case 06000:
				DisAsmPrint(L"ROR ");
				break;

			case 06100:
				DisAsmPrint(L"ROL ");
				break;

			case 06200:
				DisAsmPrint(L"ASR ");
				break;

			case 06300:
				DisAsmPrint(L"ASL ");
				break;
		}

		SkipPrintToOperandPosition();
		int nOppAddr = PrintOperand(nWord & 077);

		if (nCode >= 0)
		{
			goto DONE;
		}

		SkipPrintToCommentsPosition();

		if (nOppAddr >= 0)
		{
			uint16_t wOppAddr = nOppAddr;
			uint16_t wOperand = GET_WORD(wOppAddr);

			if (g_Platform.ReadAccess(wOppAddr))
			{
				swprintf(str, LNG(L"; %06o:%06o"), wOppAddr, wOperand);
			}
			else
			{
				swprintf(str, LNG(L"; %06o:      "), wOppAddr);
			}

			DisAsmPrint(str);
		}
		else
		{
			int nR = (-1 * nOppAddr) - 1;
			swprintf(str, LNG(L";   R%i  :%06o"), nR, m_RON[nR]);
			DisAsmPrint(str);
		}

		goto DONE;
	}

	if (nWord <= 06477)
	{
		DisAsmPrint(L"MARK ");
		SkipPrintToOperandPosition();
		swprintf(str, L"%i", (nWord & 077));
		DisAsmPrint(str);
		goto DONE;
	}

	if (nWord < 06700)
	{
		swprintf(str, LNG(L"%06o - Strange Opcode"), nWord);
		DisAsmPrint(str);
		goto DONE;
	}

	if (nWord <= 06777)
	{
		DisAsmPrint(L"SXT ");
		SkipPrintToOperandPosition();
		PrintOperand(nWord & 077);
		goto DONE;
	}

	if (nWord <= 07777)
	{
		swprintf(str, LNG(L"%06o - Strange Opcode"), nWord);
		DisAsmPrint(str);
		goto DONE;
	}

	if (nWord <= 017777)
	{
		DisAsmPrint(L"MOV ");
		/////////////////////
		goto TWO_OPS1; //
		/////////////////////
		/*
		  SkipPrintToOperandPosition();

		  int nOpp1Addr = PrintOperand( (nWord & 07700)>>6 );
		  DisAsmPrint(L", ");

		  int nOpp2Addr = PrintOperand2( nWord & 077 );

		  SkipPrintToCommentsPosition();

		  if( nOpp1Addr >= 0 && nOpp2Addr >= 0 )
		  {
		      uint16_t wOpp1Addr = nOpp1Addr;
		      uint16_t wOperand = GET_WORD( wOpp1Addr );
		      uint16_t wOpp2Addr = nOpp2Addr;

		      if( g_Platform.ReadAccess(wOpp1Addr) )
		      {
		        swprintf(str,LNG(L"; %06o:%06o -> %06o"), wOpp1Addr, wOperand, wOpp2Addr );
		      }
		      else
		      {
		        swprintf(str,LNG(L"; %06o:       -> %06o"), wOpp1Addr, wOpp2Addr );
		      }
		      DisAsmPrint(str);
		  }
		  else
		  if( nOpp1Addr < 0 && nOpp2Addr >= 0 )
		  {
		      int nR = (-1*nOpp1Addr)-1;
		      swprintf(str,LNG(L";   R%i  :%06o -> %06o"), nR, m_RON[nR], nOpp2Addr );
		      DisAsmPrint(str);
		  }
		  else
		  if( nOpp1Addr >= 0 && nOpp2Addr < 0 )
		  {
		      uint16_t wOpp1Addr = nOpp1Addr;
		      uint16_t wOperand = GET_WORD( wOpp1Addr );
		      int nR = (-1*nOpp2Addr)-1;

		      if( g_Platform.ReadAccess(wOpp1Addr) )
		      {
		        swprintf(str,LNG(L"; %06o:%06o ->   R%i"), wOpp1Addr, wOperand, nR );
		      }
		      else
		      {
		        swprintf(str,LNG(L"; %06o:       ->   R%i"), wOpp1Addr, nR );
		      }
		      DisAsmPrint(str);
		  }
		  else
		  // if( nOpp1Addr < 0 && nOpp2Addr < 0 )
		  {
		      int nRa = (-1*nOpp1Addr)-1;
		      int nRb = (-1*nOpp2Addr)-1;
		      swprintf(str,LNG(L";   R%i  :%06o ->   R%i"), nRa, m_RON[nRa], nRb );
		      DisAsmPrint(str);
		  }

		  DisAsmPrint(L"\n");
		  goto DONE;  //*/
	}

	if (nWord <= 067777)
	{
		switch (nWord & 070000)
		{
			case 020000:
				DisAsmPrint(L"CMP ");
				break;

			case 030000:
				DisAsmPrint(L"BIT ");
				break;

			case 040000:
				DisAsmPrint(L"BIC ");
				break;

			case 050000:
				DisAsmPrint(L"BIS ");
				break;

			case 060000:
				DisAsmPrint(L"ADD ");
				break;
		}

TWO_OPS1:
		SkipPrintToOperandPosition();
		int nOpp1Addr = PrintOperand((nWord & 07700) >> 6);
		DisAsmPrint(L", ");
		int nOpp2Addr = PrintOperand2(nWord & 077);

		if (nCode >= 0)
		{
			goto DONE;
		}

		SkipPrintToCommentsPosition();

		if (nOpp1Addr >= 0 && nOpp2Addr >= 0)
		{
			uint16_t wOpp1Addr = nOpp1Addr;
			uint16_t wOperand1 = GET_WORD(wOpp1Addr);
			uint16_t wOpp2Addr = nOpp2Addr;
			uint16_t wOperand2 = GET_WORD(wOpp2Addr);

			if (g_Platform.ReadAccess(wOpp1Addr) && g_Platform.ReadAccess(wOpp2Addr))
			{
				swprintf(str, LNG(L"; %06o:%06o -> %06o:%06o"), wOpp1Addr, wOperand1, wOpp2Addr, wOperand2);
			}
			else if (!g_Platform.ReadAccess(wOpp1Addr))
			{
				swprintf(str, LNG(L"; %06o:       -> %06o:%06o"), wOpp1Addr, wOpp2Addr, wOperand2);
			}
			else if (!g_Platform.ReadAccess(wOpp2Addr))
			{
				swprintf(str, LNG(L"; %06o:%06o -> %06o:"), wOpp1Addr, wOperand1, wOpp2Addr);
			}
			else
			{
				swprintf(str, LNG(L"; %06o:       -> %06o:"), wOpp1Addr, wOpp2Addr);
			}

			DisAsmPrint(str);
		}
		else if (nOpp1Addr < 0 && nOpp2Addr >= 0)
		{
			int nR = (-1 * nOpp1Addr) - 1;
			uint16_t wOpp2Addr = nOpp2Addr;
			uint16_t wOperand2 = GET_WORD(wOpp2Addr);

			if (g_Platform.ReadAccess(wOpp2Addr))
			{
				swprintf(str, LNG(L";   R%i  :%06o -> %06o:%06o"), nR, m_RON[nR], wOpp2Addr, wOperand2);
			}
			else
			{
				swprintf(str, LNG(L";   R%i  :%06o -> %06o:"), nR, m_RON[nR], wOpp2Addr);
			}

			DisAsmPrint(str);
		}
		else if (nOpp1Addr >= 0 && nOpp2Addr < 0)
		{
			uint16_t wOpp1Addr = nOpp1Addr;
			uint16_t wOperand = GET_WORD(wOpp1Addr);
			int nR = (-1 * nOpp2Addr) - 1;

			if (g_Platform.ReadAccess(wOpp1Addr))
			{
				swprintf(str, LNG(L"; %06o:%06o ->   R%i  :%06o"), wOpp1Addr, wOperand, nR, m_RON[nR]);
			}
			else
			{
				swprintf(str, LNG(L"; %06o:       ->   R%i  :%06o"), wOpp1Addr, nR, m_RON[nR]);
			}

			DisAsmPrint(str);
		}
		else
			// if( nOpp1Addr < 0 && nOpp2Addr < 0 )
		{
			int nRa = (-1 * nOpp1Addr) - 1;
			int nRb = (-1 * nOpp2Addr) - 1;
			swprintf(str, LNG(L";   R%i  :%06o ->   R%i  :%06o"), nRa, m_RON[nRa], nRb, m_RON[nRb]);
			DisAsmPrint(str);
		}

		goto DONE;
	}

	if (nWord < 074000)
	{
		swprintf(str, LNG(L"%06o - Strange Opcode"), nWord);
		DisAsmPrint(str);
		goto DONE;
	}

	if (nWord <= 074777)
	{
		DisAsmPrint(L"XOR ");
		SkipPrintToOperandPosition();
		int nR = (nWord & 0700) >> 6;
		swprintf(str, L"R%i, ", nR);
		DisAsmPrint(str);
		int nOppAddr = PrintOperand(nWord & 077);

		if (nCode >= 0)
		{
			goto DONE;
		}

		SkipPrintToCommentsPosition();

		if (nOppAddr >= 0)
		{
			uint16_t wOppAddr = (uint16_t)nOppAddr;
			uint16_t wOperand = GET_WORD(wOppAddr);

			if (g_Platform.ReadAccess(wOppAddr))
			{
				swprintf(str, LNG(L";   R%i  :%06o -> %06o:%06o"), nR, m_RON[nR], wOppAddr, wOperand);
			}
			else
			{
				swprintf(str, LNG(L";   R%i  :%06o -> %06o:"), nR, m_RON[nR], wOppAddr);
			}
		}
		else
		{
			int nRb = (-1 * nOppAddr) - 1;
			swprintf(str, LNG(L";   R%i  :%06o ->   R%i  :%06o"), nR, m_RON[nR], nRb, m_RON[nRb]);
		}

		DisAsmPrint(str);
		goto DONE;
	}

	if (nWord < 077000)
	{
		swprintf(str, LNG(L"%06o - Strange Opcode"), nWord);
		DisAsmPrint(str);
		goto DONE;
	}

	if (nWord <= 077777)
	{
		DisAsmPrint(L"SOB ");
		SkipPrintToOperandPosition();
		int nR = (nWord & 0700) >> 6;
		swprintf(str, L"R%i, %06o", nR, uint16_t(PC - (nWord & 077) * 2));
		DisAsmPrint(str);

		if (nCode >= 0)
		{
			goto DONE;
		}

		SkipPrintToCommentsPosition();
		swprintf(str, LNG(L";   R%i  :%06o"), nR, m_RON[nR]);
		DisAsmPrint(str);
		goto DONE;
	}

	if (nWord <= 0103777)
	{
		switch (nWord & 03400)
		{
			case 00:
				DisAsmPrint(L"BPL ");
				break;

			case 0400:
				DisAsmPrint(L"BMI ");
				break;

			case 01000:
				DisAsmPrint(L"BHI ");
				break;

			case 01400:
				DisAsmPrint(L"BLOS ");
				break;

			case 02000:
				DisAsmPrint(L"BVC ");
				break;

			case 02400:
				DisAsmPrint(L"BVS ");
				break;

			case 03000:
				DisAsmPrint(L"BCC ");
				break;

			case 03400:
				DisAsmPrint(L"BCS ");
				break;

			default:
				swprintf(str, LNG(L"%06o - Strange Opcode"), nWord);
				DisAsmPrint(str);
				goto DONE;
		}

		int nOffset = (signed char)(nWord & 0377);
		nOffset *= 2;
		SkipPrintToOperandPosition();
		swprintf(str, L"%06o", uint16_t(PC + nOffset));
		DisAsmPrint(str);
		//      SkipPrintToCommentsPosition();
		//      swprintf(str,";   PSW :%06o", PSW );
		//      DisAsmPrint(str);
		goto DONE;
	}

	if (nWord <= 0104377)
	{
		bCallWasDone = true;
		DisAsmPrint(L"EMT ");
		SkipPrintToOperandPosition();
		swprintf(str, L"%o", nWord & 0377);
		DisAsmPrint(str);

		if (nCode >= 0)
		{
			goto DONE;
		}

		SkipPrintToCommentsPosition();
		bool bOK = true;
		uint16_t wSP = (SP - 2) & (~1);

		if (g_Platform.WriteAccess(wSP))
		{
			swprintf(str, L";   PSW :%06o -> %06o:%06o\n", m_PSW, wSP, GET_WORD(wSP));
		}
		else if (g_Platform.ReadAccess(wSP))
		{
			bOK = false;
			swprintf(str, L";   PSW :%06o -> %06o: %s..\n", m_PSW, wSP, LNG(L"Read only"));
		}
		else
		{
			bOK = false;
			swprintf(str, L";   PSW :%06o -> %06o: %s..\n", m_PSW, wSP, LNG(L"No memory"));
		}

		DisAsmPrint(str);

		if (!bOK)
		{
			goto DONE;
		}

		DisAsmPrint(L"                                                      ");
		wSP = (SP - 4) & (~1);

		if (g_Platform.WriteAccess(wSP))
		{
			swprintf(str, L";   PC  :%06o -> %06o:%06o\n", PC, wSP, GET_WORD(wSP));
		}
		else if (g_Platform.ReadAccess(wSP))
		{
			bOK = false;
			swprintf(str, L";   PC  :%06o -> %06o: %s..\n", PC, wSP, LNG(L"Read only"));
		}
		else
		{
			bOK = false;
			swprintf(str, L";   PC  :%06o -> %06o: %s..\n", PC, wSP, LNG(L"No memory"));
		}

		DisAsmPrint(str);

		if (!bOK)
		{
			goto DONE;
		}

		DisAsmPrint(L"                                                      ");
		uint16_t addr = 030;

		if (g_Platform.ReadAccess(addr))
		{
			swprintf(str, L"; %06o:%06o ->   PC\n", addr, GET_WORD(addr));
		}
		else
		{
			bOK = false;
			swprintf(str, L"; %06o:       ->   PC\n", addr);
		}

		DisAsmPrint(str);

		if (!bOK)
		{
			goto DONE;
		}

		DisAsmPrint(L"                                                      ");
		addr += 2;

		if (g_Platform.ReadAccess(addr))
		{
			swprintf(str, L"; %06o:   %03o ->   PSW", addr, GET_BYTE(addr));
		}
		else
		{
			swprintf(str, L"; %06o:       ->   PSW", addr);
		}

		DisAsmPrint(str);
		goto DONE;
	}

	if (nWord <= 0104777)
	{
		bCallWasDone = true;
		DisAsmPrint(L"TRAP ");
		SkipPrintToOperandPosition();
		swprintf(str, L"%u.", nWord & 0377);
		DisAsmPrint(str);

		if (nCode >= 0)
		{
			goto DONE;
		}

		SkipPrintToCommentsPosition();
		bool bOK = true;
		uint16_t wSP = (SP - 2) & (~1);

		if (g_Platform.WriteAccess(wSP))
		{
			swprintf(str, L";   PSW :%06o -> %06o:%06o\n", m_PSW, wSP, GET_WORD(wSP));
		}
		else if (g_Platform.ReadAccess(wSP))
		{
			bOK = false;
			swprintf(str, L";   PSW :%06o -> %06o: %s..\n", m_PSW, wSP, LNG(L"Read only"));
		}
		else
		{
			bOK = false;
			swprintf(str, L";   PSW :%06o -> %06o: %s..\n", m_PSW, wSP, LNG(L"No memory"));
		}

		DisAsmPrint(str);

		if (!bOK)
		{
			goto DONE;
		}

		DisAsmPrint(L"                                                      ");
		wSP = (SP - 4) & (~1);

		if (g_Platform.WriteAccess(wSP))
		{
			swprintf(str, L";   PC  :%06o -> %06o:%06o\n", PC, wSP, GET_WORD(wSP));
		}
		else if (g_Platform.ReadAccess(wSP))
		{
			bOK = false;
			swprintf(str, L";   PC  :%06o -> %06o: %s..\n", PC, wSP, LNG(L"Read only"));
		}
		else
		{
			bOK = false;
			swprintf(str, L";   PC  :%06o -> %06o: %s..\n", PC, wSP, LNG(L"No memory"));
		}

		DisAsmPrint(str);

		if (!bOK)
		{
			goto DONE;
		}

		DisAsmPrint(L"                                                      ");
		uint16_t addr = 034;

		if (g_Platform.ReadAccess(addr))
		{
			swprintf(str, L"; %06o:%06o ->   PC\n", addr, GET_WORD(addr));
		}
		else
		{
			bOK = false;
			swprintf(str, L"; %06o:       ->   PC\n", addr);
		}

		DisAsmPrint(str);

		if (!bOK)
		{
			goto DONE;
		}

		DisAsmPrint(L"                                                      ");
		addr += 2;

		if (g_Platform.ReadAccess(addr))
		{
			swprintf(str, L"; %06o:   %03o ->   PSW", addr, GET_BYTE(addr));
		}
		else
		{
			swprintf(str, L"; %06o:       ->   PSW", addr);
		}

		DisAsmPrint(str);
		goto DONE;
	}

	if (nWord <= 0106377)
	{
		switch (nWord & 07700)
		{
			case 05000:
				DisAsmPrint(L"CLRB ");
				break;

			case 05100:
				DisAsmPrint(L"COMB ");
				break;

			case 05200:
				DisAsmPrint(L"INCB ");
				break;

			case 05300:
				DisAsmPrint(L"DECB ");
				break;

			case 05400:
				DisAsmPrint(L"NEGB ");
				break;

			case 05500:
				DisAsmPrint(L"ADCB ");
				break;

			case 05600:
				DisAsmPrint(L"SBCB ");
				break;

			case 05700:
				DisAsmPrint(L"TSTB ");
				break;

			case 06000:
				DisAsmPrint(L"RORB ");
				break;

			case 06100:
				DisAsmPrint(L"ROLB ");
				break;

			case 06200:
				DisAsmPrint(L"ASRB ");
				break;

			case 06300:
				DisAsmPrint(L"ASLB ");
				break;
		}

		SkipPrintToOperandPosition();
		int nOppAddr = PrintOperand(nWord & 077, 1);

		if (nCode >= 0)
		{
			goto DONE;
		}

		SkipPrintToCommentsPosition();

		if (nOppAddr >= 0)
		{
			uint16_t wOppAddr = nOppAddr;
			uint8_t cOperand = GET_BYTE(wOppAddr);

			if (g_Platform.ReadAccess(wOppAddr))
			{
				swprintf(str, LNG(L"; %06o:   %03o"), wOppAddr, cOperand);
			}
			else
			{
				swprintf(str, LNG(L"; %06o:      "), wOppAddr);
			}

			DisAsmPrint(str);
		}
		else
		{
			int nR = (-1 * nOppAddr) - 1;
			uint8_t cOperand = (uint8_t)m_RON[nR];
			swprintf(str, LNG(L";   R%i  :   %03o"), nR, cOperand);
			DisAsmPrint(str);
		}

		goto DONE;
	}

	if (nWord <= 0106477)
	{
		DisAsmPrint(L"MTPS ");
		SkipPrintToOperandPosition();
		int nOppAddr = PrintOperand(nWord & 077, 1);

		if (nCode >= 0)
		{
			goto DONE;
		}

		SkipPrintToCommentsPosition();

		if (nOppAddr >= 0)
		{
			uint16_t wOppAddr = nOppAddr;
			uint8_t cOperand = GET_BYTE(wOppAddr);

			if (g_Platform.ReadAccess(wOppAddr))
			{
				swprintf(str, LNG(L"; %06o:   %03o ->   PSW :%06o"), wOppAddr, cOperand, m_PSW);
			}
			else
			{
				swprintf(str, LNG(L"; %06o:       ->   PSW :%06o"), wOppAddr, m_PSW);
			}

			DisAsmPrint(str);
		}
		else
		{
			int nR = (-1 * nOppAddr) - 1;
			uint8_t cOperand = (uint8_t)m_RON[nR];
			swprintf(str, LNG(L";   R%i  :   %03o ->   PSW :%06o"), nR, cOperand, m_PSW);
			DisAsmPrint(str);
		}

		goto DONE;
	}

	if (nWord < 0106700)
	{
		swprintf(str, LNG(L"%06o - Strange Opcode"), nWord);
		DisAsmPrint(str);
		goto DONE;
	}

	if (nWord <= 0106777)
	{
		DisAsmPrint(L"MFPS ");
		SkipPrintToOperandPosition();
		int nOppAddr = PrintOperand(nWord & 077, 1);

		if (nCode >= 0)
		{
			goto DONE;
		}

		SkipPrintToCommentsPosition();

		if (nOppAddr >= 0)
		{
			uint16_t wOppAddr = nOppAddr;
			swprintf(str, LNG(L";   PSW :   %03o -> %06o"), (uint8_t)m_PSW, wOppAddr);
			DisAsmPrint(str);
		}
		else
		{
			int nR = (-1 * nOppAddr) - 1;
			swprintf(str, LNG(L";   PSW :   %03o ->   R%i"), (uint8_t)m_PSW, nR);
			DisAsmPrint(str);
		}

		goto DONE;
	}

	if (nWord < 0110000)
	{
		swprintf(str, LNG(L"%06o - Strange Opcode"), nWord);
		DisAsmPrint(str);
		goto DONE;
	}

	if (nWord <= 0117777)
	{
		DisAsmPrint(L"MOVB ");
		/////////////////////
		//  goto TWO_OPS2; //
		/////////////////////
		//*
		SkipPrintToOperandPosition();
		int nOpp1Addr = PrintOperand((nWord & 07700) >> 6, 1);
		DisAsmPrint(L", ");
		int nOpp2Addr = PrintOperand2(nWord & 077, 1);

		if (nCode >= 0)
		{
			goto DONE;
		}

		SkipPrintToCommentsPosition();

		if (nOpp1Addr >= 0 && nOpp2Addr >= 0)
		{
			uint16_t wOpp1Addr = nOpp1Addr;
			uint8_t cOperand = GET_BYTE(wOpp1Addr);
			uint16_t wOpp2Addr = nOpp2Addr;

			if (g_Platform.ReadAccess(wOpp1Addr))
			{
				swprintf(str, LNG(L"; %06o:   %03o -> %06o"), wOpp1Addr, cOperand, wOpp2Addr);

				if ((wOpp2Addr == 0177566 || wOpp1Addr == 0177562) && cOperand > ' ')
				{
					wchar_t str1[64];
					swprintf(str1, L"    '%c'", cOperand);
					wcscat(str, str1);
				}
			}
			else
			{
				swprintf(str, LNG(L"; %06o:       -> %06o"), wOpp1Addr, wOpp2Addr);
			}

			DisAsmPrint(str);
		}
		else if (nOpp1Addr < 0 && nOpp2Addr >= 0)
		{
			int nR = (-1 * nOpp1Addr) - 1;
			uint8_t cOperand = (uint8_t)m_RON[nR];
			swprintf(str, LNG(L";   R%i  :   %03o -> %06o"), nR, cOperand, nOpp2Addr);

			if (nOpp2Addr == 0177566 && cOperand > ' ')
			{
				wchar_t str1[64];
				swprintf(str1, L"    '%c'", cOperand);
				wcscat(str, str1);
			}

			DisAsmPrint(str);
		}
		else if (nOpp1Addr >= 0 && nOpp2Addr < 0)
		{
			uint16_t wOpp1Addr = nOpp1Addr;
			uint8_t cOperand = GET_BYTE(wOpp1Addr);
			int nR = (-1 * nOpp2Addr) - 1;

			if (g_Platform.ReadAccess(wOpp1Addr))
			{
				swprintf(str, LNG(L"; %06o:   %03o ->   R%i  "), wOpp1Addr, cOperand, nR);

				if (wOpp1Addr == 0177562 && cOperand > ' ')
				{
					wchar_t str1[64];
					swprintf(str1, L"    '%c'", cOperand);
					wcscat(str, str1);
				}
			}
			else
			{
				swprintf(str, LNG(L"; %06o:       ->   R%i"), wOpp1Addr, nR);
			}

			DisAsmPrint(str);
		}
		else
			// if( nOpp1Addr < 0 && nOpp2Addr < 0 )
		{
			int nRa = (-1 * nOpp1Addr) - 1;
			uint8_t cOperand = (uint8_t)m_RON[nRa];
			int nRb = (-1 * nOpp2Addr) - 1;
			swprintf(str, LNG(L";   R%i  :   %03o ->   R%i"), nRa, cOperand, nRb);
			DisAsmPrint(str);
		}

		goto DONE; //*/
	}

	if (nWord <= 0157777)
	{
		switch (nWord & 070000)
		{
			case 020000:
				DisAsmPrint(L"CMPB ");
				break;

			case 030000:
				DisAsmPrint(L"BITB ");
				break;

			case 040000:
				DisAsmPrint(L"BICB ");
				break;

			case 050000:
				DisAsmPrint(L"BISB ");
				break;
		}

TWO_OPS2:
		SkipPrintToOperandPosition();
		int nOpp1Addr = PrintOperand((nWord & 07700) >> 6, 1);
		DisAsmPrint(L", ");
		int nOpp2Addr = PrintOperand2(nWord & 077, 1);

		if (nCode >= 0)
		{
			goto DONE;
		}

		SkipPrintToCommentsPosition();

		if (nOpp1Addr >= 0 && nOpp2Addr >= 0)
		{
			uint16_t wOpp1Addr = nOpp1Addr;
			uint8_t cOperand1 = GET_BYTE(wOpp1Addr);
			uint16_t wOpp2Addr = nOpp2Addr;
			uint8_t cOperand2 = GET_BYTE(wOpp2Addr);

			if (g_Platform.ReadAccess(wOpp1Addr) && g_Platform.ReadAccess(wOpp2Addr))
			{
				swprintf(str, LNG(L"; %06o:   %03o -> %06o:   %03o"), wOpp1Addr, cOperand1, wOpp2Addr, cOperand2);
			}
			else if (!g_Platform.ReadAccess(wOpp1Addr))
			{
				swprintf(str, LNG(L"; %06o:       -> %06o:   %03o"), wOpp1Addr, wOpp2Addr, cOperand2);
			}
			else if (!g_Platform.ReadAccess(wOpp2Addr))
			{
				swprintf(str, LNG(L"; %06o:   %03o -> %06o:"), wOpp1Addr, cOperand1, wOpp2Addr);
			}
			else
			{
				swprintf(str, LNG(L"; %06o:       -> %06o:"), wOpp1Addr, wOpp2Addr);
			}

			DisAsmPrint(str);
		}
		else if (nOpp1Addr < 0 && nOpp2Addr >= 0)
		{
			int nR = (-1 * nOpp1Addr) - 1;
			uint8_t cOperand = (uint8_t)m_RON[nR];
			uint16_t wOpp2Addr = nOpp2Addr;
			uint8_t cOperand2 = GET_BYTE(wOpp2Addr);

			if (g_Platform.ReadAccess(wOpp2Addr))
			{
				swprintf(str, LNG(L";   R%i  :   %03o -> %06o:   %03o"), nR, cOperand, wOpp2Addr, cOperand2);
			}
			else
			{
				swprintf(str, LNG(L";   R%i  :   %03o -> %06o:"), nR, cOperand, wOpp2Addr);
			}

			DisAsmPrint(str);
		}
		else if (nOpp1Addr >= 0 && nOpp2Addr < 0)
		{
			uint16_t wOpp1Addr = nOpp1Addr;
			uint8_t cOperand = GET_BYTE(wOpp1Addr);
			int nR = (-1 * nOpp2Addr) - 1;

			if (g_Platform.ReadAccess(wOpp1Addr))
			{
				swprintf(str, LNG(L"; %06o:   %03o ->   R%i  :   %03o"), wOpp1Addr, cOperand, nR, (uint8_t)m_RON[nR]);
			}
			else
			{
				swprintf(str, LNG(L"; %06o:       ->   R%i  :   %03o"), wOpp1Addr, nR, (uint8_t)m_RON[nR]);
			}

			DisAsmPrint(str);
		}
		else
			// if( nOpp1Addr < 0 && nOpp2Addr < 0 )
		{
			int nRa = (-1 * nOpp1Addr) - 1;
			uint8_t cOperand = (uint8_t)m_RON[nRa];
			int nRb = (-1 * nOpp2Addr) - 1;
			swprintf(str, LNG(L";   R%i  :   %03o ->   R%i  :   %03o"), nRa, cOperand, nRb, (uint8_t)m_RON[nRb]);
			DisAsmPrint(str);
		}

		goto DONE;
	}

	if (nWord <= 0167777)
	{
		DisAsmPrint(L"SUB ");
		SkipPrintToOperandPosition();
		int nOpp1Addr = PrintOperand((nWord & 07700) >> 6);
		DisAsmPrint(L", ");
		int nOpp2Addr = PrintOperand2(nWord & 077);

		if (nCode >= 0)
		{
			goto DONE;
		}

		SkipPrintToCommentsPosition();

		if (nOpp1Addr >= 0 && nOpp2Addr >= 0)
		{
			uint16_t wOpp1Addr = nOpp1Addr;
			uint16_t wOperand1 = GET_WORD(wOpp1Addr);
			uint16_t wOpp2Addr = nOpp2Addr;
			uint16_t wOperand2 = GET_WORD(wOpp2Addr);

			if (g_Platform.ReadAccess(wOpp1Addr) && g_Platform.ReadAccess(wOpp2Addr))
			{
				swprintf(str, LNG(L"; %06o:%06o -> %06o:%06o"), wOpp1Addr, wOperand1, wOpp2Addr, wOperand2);
			}
			else if (!g_Platform.ReadAccess(wOpp1Addr))
			{
				swprintf(str, LNG(L"; %06o:       -> %06o:%06o"), wOpp1Addr, wOpp2Addr, wOperand2);
			}
			else if (!g_Platform.ReadAccess(wOpp2Addr))
			{
				swprintf(str, LNG(L"; %06o:%06o -> %06o:"), wOpp1Addr, wOperand1, wOpp2Addr);
			}
			else
			{
				swprintf(str, LNG(L"; %06o:       -> %06o:"), wOpp1Addr, wOpp2Addr);
			}

			DisAsmPrint(str);
		}
		else if (nOpp1Addr < 0 && nOpp2Addr >= 0)
		{
			int nR = (-1 * nOpp1Addr) - 1;
			uint16_t wOpp2Addr = nOpp2Addr;
			uint16_t wOperand2 = GET_WORD(wOpp2Addr);

			if (g_Platform.ReadAccess(wOpp2Addr))
			{
				swprintf(str, LNG(L";   R%i  :%06o -> %06o:%06o"), nR, m_RON[nR], wOpp2Addr, wOperand2);
			}
			else
			{
				swprintf(str, LNG(L";   R%i  :%06o -> %06o:"), nR, m_RON[nR], wOpp2Addr);
			}

			DisAsmPrint(str);
		}
		else if (nOpp1Addr >= 0 && nOpp2Addr < 0)
		{
			uint16_t wOpp1Addr = nOpp1Addr;
			uint16_t wOperand = GET_WORD(wOpp1Addr);
			int nR = (-1 * nOpp2Addr) - 1;

			if (g_Platform.ReadAccess(wOpp1Addr))
			{
				swprintf(str, LNG(L"; %06o:%06o ->   R%i  :%06o"), wOpp1Addr, wOperand, nR, m_RON[nR]);
			}
			else
			{
				swprintf(str, LNG(L"; %06o:       ->   R%i  :%06o"), wOpp1Addr, nR, m_RON[nR]);
			}

			DisAsmPrint(str);
		}
		else
			// if( nOpp1Addr < 0 && nOpp2Addr < 0 )
		{
			int nRa = (-1 * nOpp1Addr) - 1;
			int nRb = (-1 * nOpp2Addr) - 1;
			swprintf(str, LNG(L";   R%i  :%06o ->   R%i  :%06o"), nRa, m_RON[nRa], nRb, m_RON[nRb]);
			DisAsmPrint(str);
		}

		goto DONE;
	}

	swprintf(str, LNG(L"%06o - Strange Opcode"), nWord);
	DisAsmPrint(str);
DONE:

	if (nCode >= 0)
	{
		SkipPrintToCommentsPosition();
		DisAsmPrint(L";");
	}

	DisAsmPrint(L"\n");

	if (!g_Config.m_bStreamDisasmAddrConsoleOut)
	{
		PC_Next = PC;
	}

	PC = PC_res;
}


