#pragma once

#define SECTOR_SIZEB 512
#define SECTOR_SIZEW 256

//это сектор. чтобы удобнее было делать одновременно байтовый и словный доступ
typedef union
{
	uint8_t b[SECTOR_SIZEB];
	uint16_t w[SECTOR_SIZEW];
} USector;

//структура параметров образа
struct IMGFormat
{
	bool bHDI;  //признак образа в формате HDI
	bool bSamara; //флаг формата самара
	int nLogDiskNum; //количество разделов
	uint16_t C; //геометрия: количество дорожек
	uint16_t H; //геометрия: количество головок
	uint16_t S; //геометрия: количество секторов на дорожке
	uint16_t nCyl;  //текущий номер дорожки при формировании образа
	uint16_t nHead; //текущий номер головки при формировании образа
	uint16_t nSector;   //текущий номер сектора при формировании образа
	IMGFormat()
	{
		this->bHDI = false;
		this->bSamara = false;
		this->nLogDiskNum = 0;
		this->C = 0;
		this->H = 0;
		this->S = 0;
		this->nCyl = 0;
		this->nHead = 0;
		this->nSector = 0;
	}
	IMGFormat(const IMGFormat *src)
	{
		this->bHDI = src->bHDI;
		this->bSamara = src->bSamara;
		this->nLogDiskNum = src->nLogDiskNum;
		this->C = src->C;
		this->H = src->H;
		this->S = src->S;
		this->nCyl = src->nCyl;
		this->nHead = src->nHead;
		this->nSector = src->nSector;
	}
	IMGFormat &operator = (const IMGFormat &src)
	{
		this->bHDI = src.bHDI;
		this->bSamara = src.bSamara;
		this->nLogDiskNum = src.nLogDiskNum;
		this->C = src.C;
		this->H = src.H;
		this->S = src.S;
		this->nCyl = src.nCyl;
		this->nHead = src.nHead;
		this->nSector = src.nSector;
		return *this;
	}
};

//структура опций
struct ProrgamOptions
{
	bool bAltPro; //флаг альтпро
	bool bSamara; //флаг самара
	bool bCreate; //true - создание образа, false - разбор
	bool bConvert; //true - конвертация образа, false - нет
	bool bHDI;  //флаг создания образа в формате HDI
	uint16_t C; //геометрия: количество дорожек создаваемого образа
	uint16_t H; //геометрия: количество головок создаваемого образа
	uint16_t S; //геометрия: количество секторов на дорожке создаваемого образа
	wstring strPath; //путь куда сохранять образы разделов, или где искать их при сборке
	wstring strAppPath; //текущий путь, откуда запустили прогу
	wstring strImgName; //задаваемое имя образа.
	ProrgamOptions()
	{
		bAltPro = true;
		bSamara = bHDI = bCreate = bConvert = false;
		C = 80;
		H = 4;
		S = 24;
		strPath.clear();
		strAppPath.clear();
		strImgName.clear();
	}
};

//константы для доступа к данным таблицы разделов АльтПро

//номер блока, где находится таблица разделов АльтПро
#define AHDD_PT_SEC 7
#define AHDD_PART_W 251
#define AHDD_LOGD_W 252
#define AHDD_SEC_W  253
#define AHDD_HEAD_W 254
#define AHDD_CYL_W  255

#define AHDD_PART_B 0766
#define AHDD_LOGD_B 0770
#define AHDD_UNI_B  0771
#define AHDD_SEC_B  0772
#define AHDD_HEAD_B 0774
#define AHDD_DRV_B  0775
#define AHDD_CYL_B  0776

//константы для доступа к данным таблицы разделов Самара

//номер блока, где находится таблица разделов Самара
#define SHDD_PT_SEC     1

#define SHDD_BOOT_W     0   //# устр. для загрузки по умолч. (0 - А, 2 - С ...)
#define SHDD_CYLVOL_W   1   //объём цилиндра (общее количество секторов на дорожке) == H * S
#define SHDD_HEAD_SEC_W 2   //количество секторов на дорожке & номер последней головки (H - 1)
#define SHDD_PART_W     3   //таблица разделов

#define SHDD_BOOT_B     0   //# устр. для загрузки по умолч. (0 - А, 2 - С ...)
#define SHDD_CYLVOL_B   2   //объём цилиндра (общее количество секторов на дорожке) == H * S
#define SHDD_SEC_B      4   //количество секторов на дорожке
#define SHDD_HEAD_B     5   //номер последней головки (H - 1)
#define SHDD_PART_B     6   //таблица разделов

//константы для доступа к данным начального блока раздела Самара
#define SHDD_NLD_W      0   //номер лог. диска 
#define SHDD_LD_LEN_W   1   //размер лог. диска в блоках
#define SHDD_LD_FLAGS_W 2   //флаги - признаки
#define SHDD_ADR_BOOT_W 3   //адрес загрузки загрузчика лог. диска
#define SHHD_ADR_PAR_W  4   //адрес блока параметров для загрузчика
#define SHDD_PAGE_W     5   //состояние регистра страниц



void Usage();

bool AnalyseImage(FILE *f, IMGFormat *pFormat);
bool AssemblyImage(FILE *f, IMGFormat *imgf);

bool CheckFormat(FILE *f, IMGFormat *imgf);
bool CheckAltPro(FILE *f, IMGFormat *imgf);
bool CheckSamara(FILE *f, IMGFormat *imgf);

void InverseSector(USector &sector);
void MakeOutDir(bool bChangeOnly = false);
bool ReadLogDiskImage(FILE *f, IMGFormat *imgf, wstring &strName);
bool WriteLogDiskImage(FILE *f, int nld, int nLen);
bool WriteEmptySectors(FILE *f, IMGFormat *imgf, int nWriteNum = 0);
void WriteEmptyTail(FILE *f, IMGFormat *imgf);

bool SplitAltPro(FILE *f, IMGFormat *imgf);
bool SplitSamara(FILE *f, IMGFormat *imgf);

bool AssemblyAltPro(FILE *f, IMGFormat *imgf);
bool AssemblySamara(FILE *f, IMGFormat *imgf);

bool ConvertLogDiskImage(FILE *inf, FILE *outf, IMGFormat *OutImgf, int nLenBlk);
bool ConvertAltPro2Samara(FILE *f, IMGFormat *imgf);
bool ConvertSamara2Altpro(FILE *f, IMGFormat *imgf);

