// BKMSTD10_EXT32.cpp: implementation of the CBKMSTD10_EXT32 class.
//


#include "pch.h"
#include "resource.h"
#include "BKMSTD10_EXT32.h"

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

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

CBKMSTD10_EXT32::CBKMSTD10_EXT32()
	: m_nPage(0)
{}

CBKMSTD10_EXT32::~CBKMSTD10_EXT32()
    = default;

BK_DEV_MPI CBKMSTD10_EXT32::GetBoardModel()
{
	return BK_DEV_MPI::MSTD10_EXT32;
}

void CBKMSTD10_EXT32::MemoryManager()
{
	CBKMSTD10::MemoryManager();
	m_MemoryMap[BRD_10_CUSTOM_BNK].bReadable = TRUE;
	m_MemoryMap[BRD_10_CUSTOM_BNK].bWritable = TRUE;
	m_MemoryMap[BRD_10_CUSTOM_BNK].nBank = m_nPage;
	m_MemoryMap[BRD_10_CUSTOM_BNK].nOffset = BANK_TO_OFFSET(m_nPage);
	m_MemoryMap[BRD_10_CUSTOM_BNK].nTimingCorrection = RAM_TIMING_CORR_VALUE_S;
}


void CBKMSTD10_EXT32::SetMemoryPage(int nPage)
{
	m_nPage = nPage & 3;
	// и диспетчер памяти, мы тут должны замапить в 4й банк нужный нам банк из доп. памяти
	MemoryManager();
}


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

	if (nBank == BRD_10_CUSTOM_BNK) // 140000-160000
	{
		register const BKMEMBank_t &memoryBank = m_MemoryMap[nBank];

		if (memoryBank.bReadable)
		{
			nTC = memoryBank.nTimingCorrection;
			*pValue = m_pMemory[memoryBank.nOffset + (addr & 017777)];
			return true;
		}
	}

	return CBKMSTD10::GetByteT(addr, pValue, nTC);
}

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

	if (nBank == BRD_10_CUSTOM_BNK) // 140000-160000
	{
		register const BKMEMBank_t &memoryBank = m_MemoryMap[nBank];

		if (memoryBank.bReadable)
		{
			nTC = memoryBank.nTimingCorrection;
			*pValue = *(uint16_t *)&m_pMemory[memoryBank.nOffset + (addr & 017776)];
			return true;
		}
	}

	return  CBKMSTD10::GetWordT(addr, pValue, nTC);
}

bool CBKMSTD10_EXT32::SetByteT(register const uint16_t addr, register uint8_t value, int &nTC)
{
	register const int nBank = ADDRESS_TO_BANK(addr);

	if (nBank == 4) // 4 банк - ПЗУ монитора.
	{
		nTC = ROM_TIMING_CORR_VALUE;
		SetMemoryPage(value);
		return true;
	}

	// в банк 6 мапится дополнительная память
	if (nBank == BRD_10_CUSTOM_BNK) // 140000-160000
	{
		register const BKMEMBank_t &memoryBank = m_MemoryMap[nBank];

		if (memoryBank.bWritable)
		{
			nTC = memoryBank.nTimingCorrection;
			m_pMemory[memoryBank.nOffset + (addr & 017777)] = value;
			return true;
		}
	}

	return false;
}


bool CBKMSTD10_EXT32::SetWordT(register const uint16_t addr, register uint16_t value, int &nTC)
{
	register const int nBank = ADDRESS_TO_BANK(addr);

	if (nBank == 4) // 4 банк - ПЗУ монитора.
	{
		nTC = ROM_TIMING_CORR_VALUE;
		SetMemoryPage(value);
		return true;
	}

	// в банк 6 мапится дополнительная память
	if (nBank == BRD_10_CUSTOM_BNK) // 140000-160000
	{
		register const BKMEMBank_t &memoryBank = m_MemoryMap[nBank];

		if (memoryBank.bWritable)
		{
			nTC = memoryBank.nTimingCorrection;
			*(reinterpret_cast<uint16_t *>(&m_pMemory[memoryBank.nOffset + (addr & 017776)])) = value;
			return true;
		}
	}

	return false;
}

bool CBKMSTD10_EXT32::RestoreCustomData(DWORD id, CMSFManager *pMsf)
{
	if (pMsf->IsLoad())
	{
		bool bRet = pMsf->GetBlockCustomData(id, reinterpret_cast<uint8_t *>(&m_nPage), sizeof(DWORD));

		if (bRet)
		{
			MemoryManager();
		}

		return bRet;
	}

	return pMsf->SetBlockCustomData(id, reinterpret_cast<uint8_t *>(&m_nPage), sizeof(DWORD));
}

