#pragma once

#include "vm1_qbus_shared.h"


#include <string>

// EM_LOG(str) - вывод строки дизассемблинга в файл
//#define EM_LOG(str)      m_strStepsLog += (str)
#define EM_LOG(str)      fprintf(m_DisLog, "%s", str);fflush(m_DisLog)

// DisasmOut(str) - вывод строки дизассемблинга на отладочную консоль
//#define DisasmOut(str)

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

#define BIT_0             01
#define BIT_1             02
#define BIT_2             04
#define BIT_3            010
#define BIT_4            020
#define BIT_5            040
#define BIT_6           0100
#define BIT_7           0200
#define BIT_8           0400
#define BIT_9          01000
#define BIT_10         02000
#define BIT_11         04000
#define BIT_12        010000
#define BIT_13        020000
#define BIT_14        040000
#define BIT_15       0100000
#define BIT_16       0200000
#define BIT_17       0400000
#define BIT_18      01000000
#define BIT_19      02000000
#define BIT_20      04000000
#define BIT_21     010000000
#define BIT_22     020000000
#define BIT_23     040000000
#define BIT_24    0100000000
#define BIT_25    0200000000
#define BIT_26    0400000000
#define BIT_27   01000000000
#define BIT_28   02000000000
#define BIT_29   04000000000
#define BIT_30  010000000000
#define BIT_31  020000000000

class C1801VM1;

class CDebugger
{
		C1801VM1 *m_pCPUObj;

		///////////////////////////////////////////////////////
		// Эти перемнные нужно заменить на ссылки в эмулятор //
		///////////////////////////////////////////////////////

		uint16_t    m_Reg[8];                   // Регистры
		uint8_t    *aMemory;                   // Память
		bool    *abReadAccess;              // Признак возможности чтения для каждого байта массива памяти ( true - есть память, false - нет памяти )
		uint16_t    m_PSW;                      // Слово состояния процессора.

		///////////////////////////////////////////////////////
		FILE *m_DisLog;

		int m_nStartDisasm;

		bool        m_bDisAsmLog;      // флаг записи дизассемблинга в файл
		size_t      m_nPrintPosition;
		int         m_nR_Operand[9];
		std::string m_strStepsLog;

		void DisAsmPrint(char *str);
		void SkipPrintToOperandPosition();
		void SkipPrintToCommentsPosition();
		int PrintOperand(uint8_t nOpMode, int nOpSize = 2);
		int PrintOperand2(uint8_t nOpMode, int nOpSize = 2);

		void PrintPSW(char *str);
		bool SnapRON();

	public:
		CDebugger();
		~CDebugger();

		enum VM1REGS : int
		{
			R0 = 0,
			R1,
			R2,
			R3,
			R4,
			R5,
			R6,
			R7,
			R8,
			R9,
			R10,
			R11,
			R12,
			R13,
			PSW,
			Q,
			A,
			IR,
			X,
			Y
		};
		void DisAsm(int nClk);
		void AttachDebugger(C1801VM1 *pCPU)
		{
			m_pCPUObj = pCPU;
		}
		void AttachMemoryVP1037(uint8_t *pMem)
		{
			aMemory = pMem;
		}
		void AttachMemoryROMModule(uint8_t *pMem, size_t nSizeb)
		{
			//aMemory = pMem;
		}
		void AttachMemoryAccessMap(bool *pAcc)
		{
			abReadAccess = pAcc;
		}
		uint16_t GetRegister(VM1REGS nRegNum);
		VM1_QBUS_WIRES *GetWires();
		VM1_QBUS_REGS *GetRegs();

		uint16_t GetDebugMemDumpWord(uint16_t addr);
		uint8_t GetDebugMemDumpByte(uint16_t addr);
		BOOL OnDebugModify_Memory(int nAddress, uint16_t nValue);
		BOOL OnDebugModify_Memory(int nAddress, uint8_t nValue);
};

