#pragma once
#include "FDDStd326.h"

template<typename T>
constexpr auto BANK_TO_OFFSET_ALTPRO(T bnk)
{
	return (bnk << 12);
}
template<typename T>
constexpr auto ADDRESS_TO_BANK_ALTPRO(T a)
{
	return ((a >> 12) & 07);
}

constexpr auto ALTPRO_A16M_FDDROM_BNK = 4;

constexpr auto ALTPRO_A16M_START_MODE = 0160;
constexpr auto ALTPRO_A16M_STD10_MODE = 060;
constexpr auto ALTPRO_A16M_OZU10_MODE = 0120;
constexpr auto ALTPRO_A16M_BASIC_MODE = 020;
constexpr auto ALTPRO_A16M_STD11_MODE = 0140;
constexpr auto ALTPRO_A16M_OZU11_MODE = 040;
constexpr auto ALTPRO_A16M_OZUZZ_MODE = 0100;
constexpr auto ALTPRO_A16M_HLT11_MODE = 0;


class CFDD_A16M : public CFDDStd326
{
		DECLARE_DYNAMIC(CFDD_A16M)

	protected:
		AltProCtrlData_t    m_sCustom;
		bool                m_bA16M_Trigger;
		uint16_t            m_nAltproMode;      // код режима работы контроллера Альтпро
		uint16_t            m_nAltProMemBank;   // номер банка памяти контроллера Альтпро

		virtual bool        InitMemoryModules(const BoardRomList_t arrBoardRomList[], int size) override;

		void                SetBank(const int nModeNumber);
		virtual void        OnLoadRomModule(const int nSize, const int nBank) override;
		virtual void        MemoryManager() override;
		virtual bool        OnInitDevice() override;

	public:
		CFDD_A16M();
		virtual ~CFDD_A16M() override;
		virtual bool        InitialSetDevice() override;

		virtual BK_DEV_MPI GetBoardModel() const override
		{
			return BK_DEV_MPI::A16M;
		}

		virtual bool        InitDevice(uint16_t addrStart) override;
		// Virtual method called after reset command
		virtual void        OnReset() override;

		// Методы, эмулирующие поведение регистров
		virtual bool        GetSystemRegister(const uint16_t addr, void *pDst, UINT dwFlags = 0) override;
		virtual bool        SetSystemRegister(const uint16_t addr, uint16_t value, UINT dwFlags = 0) override;

		// Methods for Set/Get byte/word
		virtual bool        GetByteT(const uint16_t addr, uint8_t *pValue, int &nTC) override;
		virtual bool        GetWordT(const uint16_t addr, uint16_t *pValue, int &nTC) override;
		virtual bool        SetByteT(const uint16_t addr, uint8_t value, int &nTC) override;
		virtual bool        SetWordT(const uint16_t addr, uint16_t value, int &nTC) override;
		virtual bool        GetByteTInternal(const uint16_t addr, uint8_t *pValue, int &nTC) override;
		virtual bool        GetWordTInternal(const uint16_t addr, uint16_t *pValue, int &nTC) override;

		virtual bool        RestoreCustomData(DWORD id, CMSFManager *pMsf) override;

		inline uint16_t     GetAltProMode() const
		{
			return LOWORD(m_sCustom.nAltProMode);
		}

		void                SetAltProMode(uint16_t w)
		{
			m_sCustom.nAltProMode = w & ALTPRO_MODE_MASK;
			MemoryManager();
		}

		inline uint16_t     GetAltProCode() const
		{
			return LOWORD(m_sCustom.nAltProMemBank);
		}

		void                SetAltProCode(uint16_t w)
		{
			m_sCustom.nAltProMemBank = w;
			MemoryManager();
		}

		inline uint16_t     GetAltProExtCode() const
		{
			return LOWORD(m_sCustom.nExtCodes);
		}

		virtual void        Change_AltPro_Mode(uint16_t w);
};
/*
Здесь своя карта памяти и своё распределение на банки.
Нужно: 4кб на ПЗУ и 16 кб на ОЗУ
Вся память делится на банки по 4Кб.

000000--банк 0 ---сегмент 0 ОЗУ
010000--банк 1 ---сегмент 1 ОЗУ
020000--банк 2 ---сегмент 2 ОЗУ
030000--банк 3 ---сегмент 3 ОЗУ
040000--банк 4 ---ПЗУ ----------
050000--банк 5 ---резерв на случай 8КБ ПЗУ
060000--конец

Здесь m_MemoryMap указывает на верхнюю половину АП
m_MemoryMap[0] = 100000
m_MemoryMap[1] = 110000
m_MemoryMap[2] = 120000
m_MemoryMap[3] = 130000
m_MemoryMap[4] = 140000
m_MemoryMap[5] = 150000
m_MemoryMap[6] = 160000
m_MemoryMap[7] = 170000

*/
