// BKMSTD10.cpp: implementation of the CBKMSTD10 class.
//


#include "pch.h"
#include "BK001001.h"
#include "BKMSTD10.h"
#include "Platform.h"
#include "resource.h"


/////////////////////////////////////////////////////////////////////////////
// Construction/Destruction

CBKMSTD10::CBKMSTD10(CPlatform *p)
	: CBKMPIDevice(p)
{
	m_arStrMMVIndex = 1;
}


CBKMSTD10::~CBKMSTD10()
    = default;

bool CBKMSTD10::InitDevice(const uint16_t addrStart)
{
	// выключаем ПЗУ бейсика БК10
	if (const auto p = m_pPlatform->GetBoardPtr())
	{
		p->BasicRomOFF(true);
	}

	// инициализация карты памяти
	return OnInitDevice();
}

bool CBKMSTD10::OnInitDevice()
{
	static const std::array<CBKMPIDevice::BoardRomList_t, MSTD10RomListSize> m_arrMSTD10RomList =
	{
		{
			// инициализируем список загружаемых ПЗУ
			{ IDS_INI_BK10_RE2_018_FOCAL, BRD_10_FOCAL_BNK },
			{ IDS_INI_BK10_OPT_MSTD,      BRD_10_CUSTOM_BNK },
			{ IDS_INI_BK10_RE2_019_MSTD,  BRD_10_TESTS_BNK }
		}
	};
	// инициализация карты памяти
	return InitMemoryModules(m_arrMSTD10RomList);
}

bool CBKMSTD10::GetByteT(const uint16_t addr, uint8_t *pValue, int &nTC)
{
	const int nBank = ADDRESS_TO_BANK(addr);

	if ((nBank == BRD_10_FOCAL_BNK) ||
	        (nBank == BRD_10_TESTS_BNK && addr < m_nBKPortsIOArea))
	{
		nTC = m_pMemoryMap[nBank].nTimingCorrection;
		*pValue = m_pMemory[addr];
		return true;
	}

	nTC = 0;
	*pValue = 0;
	return false;
}

bool CBKMSTD10::GetWordT(const uint16_t addr, uint16_t *pValue, int &nTC)
{
	const int nBank = ADDRESS_TO_BANK(addr);

	if ((nBank == BRD_10_FOCAL_BNK) ||
	        (nBank == BRD_10_TESTS_BNK && addr < m_nBKPortsIOArea))
	{
		nTC = m_pMemoryMap[nBank].nTimingCorrection;
		*pValue = *(reinterpret_cast<uint16_t *>(&m_pMemory[addr & 0177776]));
		return true;
	}

	nTC = 0;
	*pValue = 0;
	return false;
}

bool CBKMSTD10::SetByteIndirect(const uint16_t addr, uint8_t value)
{
	const int nBank = ADDRESS_TO_BANK(addr);

	if ((nBank == BRD_10_FOCAL_BNK) ||
	        (nBank == BRD_10_TESTS_BNK && addr < m_nBKPortsIOArea))
	{
		m_pMemory[addr] = value;
		return true;
	}

	return false;
}

bool CBKMSTD10::SetWordIndirect(const uint16_t addr, uint16_t value)
{
	const int nBank = ADDRESS_TO_BANK(addr);

	if ((nBank == BRD_10_FOCAL_BNK) ||
	        (nBank == BRD_10_TESTS_BNK && addr < m_nBKPortsIOArea))
	{
		*(reinterpret_cast<uint16_t *>(&m_pMemory[addr & 0177776])) = value;
		return true;
	}

	return false;
}

bool CBKMSTD10::CheckReadWord(const uint16_t addr)
{
	const int nBank = ADDRESS_TO_BANK(addr);

	if ((nBank == BRD_10_FOCAL_BNK) ||
	        (nBank == BRD_10_TESTS_BNK && addr < m_nBKPortsIOArea))
	{
		return true;
	}

	return false;
}

void CBKMSTD10::MemoryManager()
{
	CBKMPIDevice::MemoryManager();
	m_pMemoryMap[BRD_10_FOCAL_BNK].bReadable = !!(m_nROMPresent & (1 << BRD_10_FOCAL_BNK));
	m_pMemoryMap[BRD_10_FOCAL_BNK].nTimingCorrection = ROM_TIMING_CORR_VALUE;
	m_pMemoryMap[BRD_10_TESTS_BNK].bReadable = !!(m_nROMPresent & (1 << BRD_10_TESTS_BNK));
	m_pMemoryMap[BRD_10_TESTS_BNK].nTimingCorrection = ROM_TIMING_CORR_VALUE;
	SetMemoryMapViewData(BRD_10_FOCAL_BNK);
	SetMemoryMapViewData(BRD_10_TESTS_BNK);
}

// вход - номер сегмента 0..7
void CBKMSTD10::SetMemoryMapViewData(const int seg)
{
	BKMEMBank_t &mb = m_pMemoryMap[seg];
	int n = 0;

	if (mb.bReadable)
	{
		n |= 2;
	}

	if (mb.bWritable)
	{
		n |= 1;
	}

	g_arStrMMVData[m_arStrMMVIndex][seg] = g_arStrMMVw1[n];

	// если текущее значение не "нет", то его применяем.
	if (n != 0)
	{
		g_arStrStDsData[seg * 2] = g_arStrMMVw1[n];
		g_arStrStDsData[seg * 2 + 1] = g_arStrMMVw1[n];
	}
}


bool CBKMSTD10::RestoreMemory(const uint32_t id, CMSFManager *pMsf)
{
	if (pMsf->IsLoad())
	{
		return pMsf->GetBlockBaseMemory(id, GetMainMemory(), m_nMemorySize);
	}

	return pMsf->SetBlockBaseMemoryEx(id, GetMainMemory(), m_nMemorySize, true);
}

bool CBKMSTD10::RestoreMemoryMap(const uint32_t id, CMSFManager *pMsf)
{
	if (pMsf->IsLoad())
	{
		return pMsf->GetBlockMemMap(id, m_pMemoryMap.data(), DEC_BANKS_NUM, m_nROMPresent);
	}

	return pMsf->SetBlockMemMap(id, m_pMemoryMap.data(), DEC_BANKS_NUM, m_nROMPresent);
}

