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


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

#include "Platform.h"
#include "BK001001.h"

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


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

IMPLEMENT_DYNAMIC(CBKMSTD10, CBKMPIDevice)

CBKMSTD10::CBKMSTD10()
    = default;

CBKMSTD10::~CBKMSTD10()
    = default;

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

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

bool CBKMSTD10::OnInitDevice()
{
	static const CBKMPIDevice::BoardRomList_t m_arrMSTD10RomList[MSTD10RomListSize] =
	{
		// инициализируем список загружаемых ПЗУ
		{ 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, MSTD10RomListSize);
}

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::SetByteTInternal(const uint16_t addr, uint8_t value, 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;
		m_pMemory[addr] = value;
		return true;
	}

	nTC = 0;
	return false;
}

bool CBKMSTD10::SetWordTInternal(const uint16_t addr, uint16_t value, 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;
		*(reinterpret_cast<uint16_t *>(&m_pMemory[addr & 0177776])) = value;
		return true;
	}

	nTC = 0;
	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;
}

CString CBKMSTD10::GetMemoryMapViewData(const int seg)
{
	BKMEMBank_t &mb = m_pMemoryMap[seg];
	int n = 0;
	if (mb.bReadable) n |= 2;
	if (mb.bWritable) n |= 1;
	return g_arStrMMVw1[n];
}


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

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

bool CBKMSTD10::RestoreMemoryMap(DWORD 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);
}

