#include "stdafx.h"
#include "Resource.h"
#include "FDD_Samara.h"

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


CFDD_Samara::CFDD_Samara()
{
	BK_DEV_MPI bBoard = BK_DEV_MPI::NONE;

	if (g_Platform.GetBoardPtr())
	{
		bBoard = g_Platform.GetBoardPtr()->GetBoardModel();
	}

	// на БК10 подключается доп. 16 кб памяти по адресам 12000-160000
	// на БК11 - нет
	m_sCustom.b10 = (bBoard == BK_DEV_MPI::BK001001) || (bBoard == BK_DEV_MPI::BK0010);
}


CFDD_Samara::~CFDD_Samara()
{}

BK_DEV_MPI CFDD_Samara::GetBoardModel()
{
	return BK_DEV_MPI::SAMARA;
}

void CFDD_Samara::OnReset()
{
	CFDDStd326Mem::OnReset();
	InitHDD();
}


void CFDD_Samara::MemoryManager()
{
	if (m_sCustom.b10)
	{
		CFDDStd326Mem::MemoryManager();
	}
	else
	{
		CFDDStd326::MemoryManager();
	}
}

bool CFDD_Samara::OnInitDevice()
{
	static const CBKMPIDevice::BoardRomList_t m_arrFDDSamaraRomList[FDDRomListSize] =
	{
		// инициализируем список загружаемых ПЗУ
		{ IDS_INI_FDR_SAMARA, KNGMD_FDDROM_BNK }
	};
	// инициализация карты памяти
	return InitMemoryModules(m_arrFDDSamaraRomList, FDDRomListSize);
}

bool CFDD_Samara::GetSystemRegister(register uint16_t addr, register void *pDst, register bool bByteOperation)
{
	register uint16_t w = 0;
	register bool bReg = ReadHDDRegisters(addr, w);

	if (bByteOperation)
	{
		// register auto pDst_B = reinterpret_cast<uint8_t *>(pDst);
		*(reinterpret_cast<uint8_t *>(pDst)) = ((addr & 1) ? (w >> 8) : w) & 0377;
	}
	else
	{
		// register auto pDst_W = reinterpret_cast<uint16_t *>(pDst);
		*(reinterpret_cast<uint16_t *>(pDst)) = w;
	}

	return bReg;
}

bool CFDD_Samara::SetSystemRegister(register uint16_t addr, register uint16_t value, register bool bByteOperation)
{
	register uint16_t src = bByteOperation ? ((addr & 1) ? value << 8 : value & 0377) : value;
	return WriteHDDRegisters(addr, ~src);
}



bool CFDD_Samara::GetByteT(register uint16_t addr, register uint8_t *pValue, int &nTC)
{
	if (GetSystemRegister(addr, pValue, true))
	{
		nTC = REG_TIMING_CORR_VALUE;
		return true;
	}

	if (m_sCustom.b10)
	{
		return CFDDStd326Mem::GetByteT(addr, pValue, nTC);
	}
	else
	{
		return CFDDStd326::GetByteT(addr, pValue, nTC);
	}
}

bool CFDD_Samara::GetWordT(register uint16_t addr, register uint16_t *pValue, int &nTC)
{
	if (GetSystemRegister(addr, pValue, false))
	{
		nTC = REG_TIMING_CORR_VALUE;
		return true;
	}

	if (m_sCustom.b10)
	{
		return CFDDStd326Mem::GetWordT(addr, pValue, nTC);
	}
	else
	{
		return CFDDStd326::GetWordT(addr, pValue, nTC);
	}
}

bool CFDD_Samara::SetByteT(register uint16_t addr, register uint8_t value, int &nTC)
{
	if (SetSystemRegister(addr, value, true))
	{
		nTC = REG_TIMING_CORR_VALUE;
		return true;
	}

	if (m_sCustom.b10)
	{
		return CFDDStd326Mem::SetByteT(addr, value, nTC);
	}
	else
	{
		return CFDDStd326::SetByteT(addr, value, nTC);
	}
}

bool CFDD_Samara::SetWordT(register uint16_t addr, register uint16_t value, int &nTC)
{
	if (SetSystemRegister(addr, value, false))
	{
		nTC = REG_TIMING_CORR_VALUE;
		return true;
	}

	if (m_sCustom.b10)
	{
		return CFDDStd326Mem::SetWordT(addr, value, nTC);
	}
	else
	{
		return CFDDStd326::SetWordT(addr, value, nTC);
	}
}

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

		if (bRet)
		{
			MemoryManager();
		}

		return bRet;
	}
	else
	{
		return pMsf->SetBlockCustomData(id, reinterpret_cast<uint8_t *>(&m_sCustom), sizeof(CustomData_t));
	}
}

void CFDD_Samara::InitHDD()
{
	CString strHDDImgName = g_Config.GetHDDriveImgName(0);

	// если в канал Master что-то нужно примонтировать
	if (strHDDImgName.CompareNoCase(g_strEmptyUnit))
	{
		m_ATA_IDE.attach(strHDDImgName, 0, false);
	}

	strHDDImgName = g_Config.GetHDDriveImgName(1);

	// если в канал Slave что-то нужно примонтировать
	if (strHDDImgName.CompareNoCase(g_strEmptyUnit))
	{
		m_ATA_IDE.attach(strHDDImgName, 1, true);
	}

	m_ATA_IDE.reset();
}

bool CFDD_Samara::WriteHDDRegisters(register uint16_t num, register uint16_t data)
{
	// обработка регистров HDD Samara
	switch (num & 0177776)
	{
		case 0177620:
			m_ATA_IDE.write_regs(HDD_REGISTER::H3F7, data);
			break;

		case 0177622:
			m_ATA_IDE.write_regs(HDD_REGISTER::H3F6, data);
			break;

		case 0177640:
			m_ATA_IDE.write_regs(HDD_REGISTER::H1F7, data);
			break;

		case 0177642:
			m_ATA_IDE.write_regs(HDD_REGISTER::H1F6, data);
			break;

		case 0177644:
			m_ATA_IDE.write_regs(HDD_REGISTER::H1F5, data);
			break;

		case 0177646:
			m_ATA_IDE.write_regs(HDD_REGISTER::H1F4, data);
			break;

		case 0177650:
			m_ATA_IDE.write_regs(HDD_REGISTER::H1F3, data);
			break;

		case 0177652:
			m_ATA_IDE.write_regs(HDD_REGISTER::H1F2, data);
			break;

		case 0177654:
			m_ATA_IDE.write_regs(HDD_REGISTER::H1F1, data);
			break;

		case 0177656:
			m_ATA_IDE.write_regs(HDD_REGISTER::H1F0, data);
			break;

		default:
			return false;
	}

	return true;
}

bool CFDD_Samara::ReadHDDRegisters(register uint16_t num, register uint16_t &data)
{
	register uint16_t result;

	// обработка регистров HDD Samara
	switch (num & 0177776)
	{
		case 0177620:
			result = m_ATA_IDE.read_regs(HDD_REGISTER::H3F7);
			break;

		case 0177622:
			result = m_ATA_IDE.read_regs(HDD_REGISTER::H3F6);
			break;

		case 0177640:
			result = m_ATA_IDE.read_regs(HDD_REGISTER::H1F7);
			break;

		case 0177642:
			result = m_ATA_IDE.read_regs(HDD_REGISTER::H1F6);
			break;

		case 0177644:
			result = m_ATA_IDE.read_regs(HDD_REGISTER::H1F5);
			break;

		case 0177646:
			result = m_ATA_IDE.read_regs(HDD_REGISTER::H1F4);
			break;

		case 0177650:
			result = m_ATA_IDE.read_regs(HDD_REGISTER::H1F3);
			break;

		case 0177652:
			result = m_ATA_IDE.read_regs(HDD_REGISTER::H1F2);
			break;

		case 0177654:
			result = m_ATA_IDE.read_regs(HDD_REGISTER::H1F1);
			break;

		case 0177656:
			result = m_ATA_IDE.read_regs(HDD_REGISTER::H1F0);
			break;

		default:
			data = 0;
			return false;
	}

	data = ~result;
	return true;
}

uint16_t CFDD_Samara::ReadDebugHDDRegisters(int nDrive, HDD_REGISTER num, bool bReadMode)
{
	return m_ATA_IDE.get_debug_regs(nDrive, num, bReadMode);
}


