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

#pragma once

enum MSF_BLOCKTYPE : DWORD
{
	MSF_BLOCKTYPE_UNKNOWN = DWORD(-1),
	MSF_BLOCKTYPE_PLATFORM = 0,
	MSF_BLOCKTYPE_PREVIEW,
	MSF_BLOCKTYPE_CONFIG,
	MSF_BLOCKTYPE_FRAMEDATA,
	MSF_BLOCKTYPE_CPU_REGISTERS,

	MSF_BLOCKTYPE_BASEMEMORY,
	MSF_BLOCKTYPE_PORT_REGS,
	MSF_BLOCKTYPE_MEMMAP,
	MSF_BLOCKTYPE_CUSTOM,
	MSF_BLOCKTYPE_WAVE = 200
};

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

// заголовок блока
struct MSF_BLOCK_HEADER
{
	DWORD   type;           // тип блока (MSF_BLOCKTYPE)
	DWORD   id;             // идентификатор устройства, которому принадлежит блок
	DWORD   length;         // размер блока = размер заголовка + размер данных

	bool operator == (const MSF_BLOCK_HEADER &r)
	{
		return (memcmp(this, &r, sizeof(MSF_BLOCK_HEADER)) == 0);
	}
	bool operator != (const MSF_BLOCK_HEADER &r)
	{
		return (memcmp(this, &r, sizeof(MSF_BLOCK_HEADER)) != 0);
	}
	MSF_BLOCK_HEADER &operator = (const MSF_BLOCK_HEADER &src)
	{
		memcpy(this, &src, sizeof(MSF_BLOCK_HEADER));
		return *this;
	}

};

// для обратной совместимости, нужно уметь читать старые tap файлы.
struct MSF_BLOCK_HEADER_OLD
{
	DWORD   type;
	DWORD   length;

	bool operator == (const MSF_BLOCK_HEADER_OLD &r)
	{
		return (memcmp(this, &r, sizeof(MSF_BLOCK_HEADER_OLD)) == 0);
	}
	bool operator != (const MSF_BLOCK_HEADER_OLD &r)
	{
		return (memcmp(this, &r, sizeof(MSF_BLOCK_HEADER_OLD)) != 0);
	}
	MSF_BLOCK_HEADER_OLD &operator = (const MSF_BLOCK_HEADER_OLD &src)
	{
		memcpy(this, &src, sizeof(MSF_BLOCK_HEADER_OLD));
		return *this;
	}

};



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

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

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

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

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

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

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

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

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

#pragma pack(pop)
