// MSF.h: defines for the CMSFManager class.
//

#pragma once

constexpr uint32_t MSF_BLOCKTYPE_EXT_MASK = 0x10000;

enum class MSF_BLOCKTYPE : uint32_t
{
	UNKNOWN = uint32_t(-1),
	BASEMEMORY = 0,
	CPU_REGISTERS,
	PREVIEW,
	B10EXT16,       // deprecated
	B10EXT32,       // deprecated
	PLATFORM,
	PORT_REGS,
	MEMMAP,
	BASEMEMORY11M,  // deprecated
	MEMORY_SMK512,  // deprecated
	CONFIG,
	FRAMEDATA,
	WAVE = 200,
	// расширенные блоки с доп.полями
	BASEMEMORYEX = MSF_BLOCKTYPE_EXT_MASK,
	CPU_REGISTERSEX,
	PREVIEWEX,
	PLACEHOLDER1,
	PLACEHOLDER2,
	PLATFORMEX,
	PORT_REGSEX,
	MEMMAPEX,
	PLACEHOLDER3,
	PLACEHOLDER4,
	CONFIGEX,
	FRAMEDATAEX,
	CUSTOMEX,

};

#pragma pack(push)
#pragma pack(4)
// первый блок - заголовок файла
struct MSF_FILE_HEADER
{
	uint32_t    type{ 0 };      // тип мсф файла. идентификатор, всегда 65536
	uint32_t    version{ 0 };   // версия мсф файла.
	uint32_t    reserved{ 0 };  // для обратной совместимости
};

// для обратной совместимости, нужно уметь читать старые tap файлы.
struct MSF_BLOCK_HEADER
{
	MSF_BLOCKTYPE type{ MSF_BLOCKTYPE::UNKNOWN }; // тип блока (MSF_BLOCKTYPE)
	uint32_t    length{ 0 };    // размер блока = размер заголовка + размер данных

	MSF_BLOCK_HEADER &operator = (const MSF_BLOCK_HEADER &src)
	{
		this->type = src.type;
		this->length = src.length;
		return *this;
	}
	bool operator==(const MSF_BLOCK_HEADER &other) const
	{
		return type == other.type && length == other.length;
	}
	bool operator!=(const MSF_BLOCK_HEADER &other) const
	{
		return type != other.type && length != other.length;
	}
};

constexpr uint32_t MSF_EX_FLAG_COMPRESSED = 1; // флаг сжатых данных в блоке

// заголовок блока
struct MSF_BLOCK_HEADEREX
{
	MSF_BLOCK_HEADER hdr{};
	uint32_t        id{ 0 };        // идентификатор устройства, которому принадлежит блок
	uint32_t        flags{ 0 };     // флаги
	uint32_t        unpSize{ 0 };   // размер распакованного массива

	MSF_BLOCK_HEADEREX &operator = (const MSF_BLOCK_HEADEREX &src)
	{
		this->hdr = src.hdr;
		this->id = src.id;
		this->flags = src.flags;
		this->unpSize = src.unpSize;
		return *this;
	}

	bool operator==(const MSF_BLOCK_HEADEREX &other) const
	{
		return hdr == other.hdr && id == other.id && flags == other.flags && unpSize == other.unpSize;
	}
	bool operator!=(const MSF_BLOCK_HEADEREX &other) const
	{
		return hdr != other.hdr && id != other.id && flags != other.flags && unpSize != other.unpSize;
	}
};



struct MSF_CPU_REGISTERS
{
	uint16_t    r0{0};
	uint16_t    r1{0};
	uint16_t    r2{0};
	uint16_t    r3{0};
	uint16_t    r4{0};
	uint16_t    r5{0};
	uint16_t    sp{0};
	uint16_t    pc{0};
	uint16_t    psw{ 0 };
};

struct MSF_PORT_REGS
{
	uint16_t    p0177660{ 0 };
	uint16_t    p0177662_in{ 0 };
	uint16_t    p0177662_out{ 0 };
	uint16_t    p0177664{ 0 };
	uint16_t    p0177700{ 0 };
	uint16_t    p0177702{ 0 };
	uint16_t    p0177704{ 0 };
	uint16_t    p0177706{ 0 };
	uint16_t    p0177710{ 0 };
	uint16_t    p0177712{ 0 };
	uint16_t    p0177714_in{ 0 };
	uint16_t    p0177714_out{ 0 };
	uint16_t    p0177716_in{ 0 };
	uint16_t    p0177716_out_tap{ 0 };
	uint16_t    p0177716_out_mem{ 0 };
};

struct MSF_FRAMEDATA
{
	// состояние ВЕ таймера
	int         nTimerSpeed{ 0 };
	int         nTimerDiv{ 0 };

	// состояние экрана
	int         nVideoAddress{ 0 }; // видео адрес, младшие 6 бит - счётчик строк внутри строки
	int         bHgate{ 0 }; // флаг отсчёта служебных видеоциклов в строке
	int         bVgate{ 0 }; // флаг отсчёта служебных строк
	int         nVGateCounter{ 0 }; // дополнительный счётчик служебных строк
	int         nLineCounter{ 0 }; // счётчик видео строк

	// состояние фрейма
	int         nCPUTicks{ 0 };
	double      fMediaTicks{ 0.0 };
	double      fMemoryTicks{ 0.0 };
	double      fFDDTicks{ 0.0 };
	double      fAZVideoTicks{ 0.0 };
};

struct MSF_DEVICE_ID
{
	uint32_t    nBKBoardModel{ 0 };     // модель устройства (см. enum BK_DEV_MPI)
	uint32_t    nUniqueID{ 0 };         // уникальный идентификатор
	// на случай, если будет в списке несколько одинаковых BK_DEV_MPI.
};

struct MSF_PLATFORM_DATA
{
	uint32_t    nPlatformConfig{ 0 };   // номер конфигурации (см enum CONF_BKMODEL)
	uint32_t    nDevNum{ 0 };           // количество устройств в конфигурации
	std::vector<MSF_DEVICE_ID> pDevices; // список устройств размером nDevNum (фактически, с точки зрения физического хранения данных, - это обычный массив)
};

// описатель блока
struct MSF_BLOCK_INFO
{
	size_t              offset{ 0 }; // смещение до следующего блока.
	// заполняется при разборе файла
	// в самом файле не содержится.
	MSF_BLOCK_HEADEREX  header{}; // заголовок блока
};

#pragma pack(pop)
