// 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
IMPLEMENT_DYNAMIC(CBKMSTD10_EXT32, CBKMSTD10)

CBKMSTD10_EXT32::CBKMSTD10_EXT32()
	: m_sCustom{}
{
}

CBKMSTD10_EXT32::~CBKMSTD10_EXT32()
    = default;

bool CBKMSTD10_EXT32::InitialSetDevice()
{
	if (CBKMPIDevice::InitialSetDevice())
	{
		CString str; //заполним список окон

		for (int i = 0; i < 4; ++i)
		{
			str.Format(_T("БК10EXT:%d"), i);
			g_Platform.GetWndVectorPtr()->push_back({ str, 0140000, 020000, GetMainMemory() + (i * 020000) });
		}

		return true;
	}

	return false;
}

void CBKMSTD10_EXT32::MemoryManager()
{
	CBKMSTD10::MemoryManager();
	BKMEMBank_t &m = m_pMemoryMap[BRD_10_CUSTOM_BNK];
	m.bReadable = TRUE;
	m.bWritable = TRUE;
	m.nBank = m_sCustom.nPage;
	m.nOffset = BANK_TO_OFFSET(m_sCustom.nPage);
	m.nTimingCorrection = RAM_TIMING_CORR_VALUE_S;
}


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


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

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

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

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

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

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

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

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

bool CBKMSTD10_EXT32::SetByteT(const uint16_t addr, uint8_t value, int &nTC)
{
	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
	{
		const BKMEMBank_t &memoryBank = m_pMemoryMap[nBank];

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

	return false;
}


bool CBKMSTD10_EXT32::SetWordT(const uint16_t addr, uint16_t value, int &nTC)
{
	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
	{
		const BKMEMBank_t &memoryBank = m_pMemoryMap[nBank];

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

	return false;
}

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

		if (bRet)
		{
			MemoryManager();
		}

		return bRet;
	}

	return pMsf->SetBlockCustomData(MSF_BLOCKTYPE::CUSTOMEX, id, reinterpret_cast<uint8_t *>(&m_sCustom), sizeof(CustomData_t));
}

