Документация по формату MSF (черновик).

# Формат файла .MSF версии 2.2 (Memory state file) для эмулятора БК 0010(01) и БК 0011(М)

Файлы данного формата обычно хранят в себе полный слепок всей памяти БК на момент сохранения, состояние регистров, уменьшенную копию экрана, фрагмент файла конфигурации с текущими настройками и опциями, а также любую другую информацию, необходимую для последующего восстановления работы. Формат является бинарным, и представляет собой теговую структуру. Каждый тег представляет собой заголовок, и данные некоторого типа. Теги могут располагаться в любом порядке (кроме первого заголовочного тега MSF_FILE_HEADER), а также быть вложенными один в другой (но на практике оказалось, что в этом нет необходимости, незачем переусложнять). Теоретически любой из тегов, являющийся не критически важным, может быть пропущен, а также могут присутствовать теги, которые незнакомы эмулятору данной версии, и будут без проблем пропущены. Таким образом, теоретически осуществляется совместимость форматов разных версий в обе стороны.

Но практически - нет. MSF младших версий не поддерживается из-за того, что там нет критически важных блоков, без которых невозможно восстановить состояние эмулятора. И соответственно, невозможна дальнейшая эмуляция.

Формат 2.2 принципиально не совместим с форматом 1.9 из-за полной переделки принципа эмуляции и внутреннего устройства данных эмулируемых устройств. Без проблем понимаются только tap файлы, которые к тому же умышленно сохраняются в старом формате, чтобы было можно использовать их и в старых версиях эмулятора.

## Описание структуры

Файл – это последовательность тегов, с выравниванием по байту.

Тег заголовка | Тег 1 | Тег 2 | … | Тег N

### Формат тега заголовка

Тип | Имя | Размер в байтах | Описание
--- | --- | --- | ---
uint32_t | type | 4 | Тип MSF файла. Идентификатор (сигнатура), всегда 65536
uint32_t | version | 4 | Версия MSF файла. В настоящее время 21
uint32_t | reserved | 4 | Зарезервировано для обратной совместимости с файлами версии 1.9, всегда 0

### Формат тегов данных

Заголовок тега бывает обычный, и расширенный. Определяется по типу тега.

Обычный заголовок.

Тип | Имя | Размер в байтах | Описание
--- | --- | --- | ---
uint32_t | type | 4 | Тип блока (тега)
uint32_t | length | 4 | размер блока = размер этого заголовка + размер данных
uint8_t |  | N | Массив данных.

Расширенный заголовок.

Тип | Имя | Размер в байтах | Описание
--- | --- | --- | ---
uint32_t | type | 4 | Тип блока (тега)
uint32_t | length | 4 | размер блока = размер этого заголовка + размер данных
uint32_t | id | 4 | идентификатор устройства, которому принадлежит блок данных
uint32_t | flags | 4 | Флаги, обозначающие разные режимы обработки. На данный момент существует всего один флаг. MSF_EX_FLAG_COMPRESSED = 1 Обозначает, что данные в блоке сжаты алгоритмом LZW. Тем же, что используется в tap файлах.
uint32_t | unpSize | 4 | Размер не сжатых данных, чтобы можно было без проблем расжимать архив.
uint8_t |  | N | Массив данных.

### Типы тегов

Имя | Значение | Описание
--- | --- | ---
MSF_BLOCKTYPE::UNKNOWN | -1 | Не используется, предназначен для обработки ошибочных ситуаций
MSF_BLOCKTYPE::BASEMEMORY | 0 | Содержит полный слепок памяти устройства, включая загруженные дампы ПЗУ. Устарел, не используется, оставлен для совместимости
MSF_BLOCKTYPE::CPU_REGISTERS | 1 | Содержит значения регистров процессора
MSF_BLOCKTYPE::PREVIEW | 2 | Содержит малую копию экрана.
MSF_BLOCKTYPE::B10EXT16 | 3 | Устарел, не используется, оставлен для совместимости
MSF_BLOCKTYPE::B10EXT32 | 4 | Устарел, не используется, оставлен для совместимости
MSF_BLOCKTYPE::PLATFORM | 5 | Содержит параметры платформы и описание устройств, из которых состоит конфигурация
MSF_BLOCKTYPE::PORT_REGS | 6 | Содержит значения регистров и портов устройства. Устарел, не используется, оставлен для совместимости
MSF_BLOCKTYPE::MEMMAP | 7 | Содержит копию карты памяти. Устарел, не используется, оставлен для совместимости
MSF_BLOCKTYPE::BASEMEMORY11M | 8 | Устарел, не используется, оставлен для совместимости
MSF_BLOCKTYPE::MEMORY_SMK512 | 9 | Устарел, не используется, оставлен для совместимости
MSF_BLOCKTYPE::CONFIG | 10 | Содержит фрагмент ini файла конфигурации с настройками данной платформы.
MSF_BLOCKTYPE::FRAMEDATA | 11 | Содержит текущие параметры фрейма и внутренние счётчики.
MSF_BLOCKTYPE::WAVE | 200 | Используется в tap файлах для хранения контента.
Расширенные блоки |  |
MSF_BLOCKTYPE::BASEMEMORYEX | 0x10000 | Содержит полный слепок памяти устройства, включая загруженные дампы ПЗУ
MSF_BLOCKTYPE::CPU_REGISTERSEX | 0x10001 | Содержит значения регистров процессора
MSF_BLOCKTYPE::PREVIEWEX | 0x10002 | Содержит малую копию экрана.
MSF_BLOCKTYPE::PLACEHOLDER1 | 0x10003 | Заглушка
MSF_BLOCKTYPE::PLACEHOLDER2 | 0x10004 | Заглушка
MSF_BLOCKTYPE::PLATFORMEX | 0x10005 | Содержит параметры платформы и описание устройств, из которых состоит конфигурация
MSF_BLOCKTYPE::PORT_REGSEX | 0x10006 | Содержит значения регистров и портов устройства
MSF_BLOCKTYPE::MEMMAPEX | 0x10007 | Содержит копию карты памяти
MSF_BLOCKTYPE::PLACEHOLDER3 | 0x10008 | Заглушка
MSF_BLOCKTYPE::PLACEHOLDER4 | 0x10009 | Заглушка
MSF_BLOCKTYPE::CONFIGEX | 0x1000a | Содержит фрагмент ini файла конфигурации с настройками данной платформы.
MSF_BLOCKTYPE::FRAMEDATAEX | 0x1000b | Содержит текущие параметры фрейма и внутренние счётчики.
MSF_BLOCKTYPE::CUSTOMEX | 0x1000c | Содержит различные данные, специфичные для конкретного устройства.

Несмотря на то, что значения тегов по возможности такие же, как и в старой версии, их содержимое может быть не совместимо с содержимым старой версии.

Теги делятся на две категории: общего назначения и специального назначения. За исключением тега MSF_BLOCKTYPE::WAVE, он используется только для tap файлов и к файлам сохранения отношения не имеет.

Теги общего назначения – это MSF_BLOCKTYPE::PLATFORM[EX], MSF_BLOCKTYPE::PREVIEW[EX], MSF_BLOCKTYPE::CONFIG[EX], MSF_BLOCKTYPE::FRAMEDATA[EX] и MSF_BLOCKTYPE::CPU_REGISTERS[EX]. Эти теги в файле сохранения находятся в одном экземпляре. У всех расширенных тегов этой группы поле id содержит число -1.

Теги специального назначения - MSF_BLOCKTYPE::BASEMEMORYEX, MSF_BLOCKTYPE::PORT_REGSEX, MSF_BLOCKTYPE::MEMMAPEX, MSF_BLOCKTYPE::CUSTOMEX. Эти теги в файле сохранения содержатся для каждого устройства. У всех этих тегов поле id содержит идентификатор устройства, и все теги с одинаковым идентификатором относятся к одному устройству.

Тег MSF_BLOCKTYPE::CUSTOM опциональный, его может и не быть для заданного устройства.

### Тег MSF_BLOCKTYPE::PLATFORM[EX]

Самым главным тегом является MSF_BLOCKTYPE::PLATFORM, он содержит информацию о конфигурации устройства и количестве устройств в конфигурации. От этого зависит интерпретация тегов специального назначения. Тег MSF_BLOCKTYPE::PLATFORMEX не используется из-за своей избыточности.

Формат.

Тип | Имя | Размер в байтах | Значение / Описание
--- | --- | --- | ---
uint32_t | type | 4 | MSF_BLOCKTYPE::PLATFORM // Тип блока (тега)
uint32_t | length | 4 | Размер блока = размер этого заголовка + размер данных
Данные тега, размер 8 + 8 * nDevNum
uint32_t | nPlatformConfig | 4 | Номер конфигурации (см enum CONF_BKMODEL в файле Config.h)
uint32_t | nDevNum | 4 | Количество устройств в конфигурации
{ |  |  |
uint32_t | nBKBoardModel | 4 | модель устройства (см. enum BK_DEV_MPI BKMODEL в файле Config.h)
uint32_t | nUniqueID | 4 | уникальный идентификатор на случай, если будет в списке несколько одинаковых BK_DEV_MPI. Именно этот идентификатор содержится в поле id тегов специального назначения.
} По количеству nDevNum

Значение уникального идентификатора начинается с числа 256. Для первого устройства – 256, для второго 257 и т.д.

### Тег MSF_BLOCKTYPE::PREVIEW[EX]

Этот тег содержит малую копию экрана. Она используется при загрузке файлов сохранения в диалоге их выбора при предпросмотре. Не является обязательным.

Формат.

Тип | Имя | Размер в байтах | Значение / Описание
--- | --- | --- | ---
uint32_t | type | 4 | MSF_BLOCKTYPE::PREVIEW // Тип блока (тега)
uint32_t | length | 4 | Размер блока = размер этого заголовка + размер данных
Данные тега, размер переменный
структура | BITMAPINFOHEADER | 40 | Стандартная структура BITMAPINFOHEADER
массив |  | Заранее не известно | Бинарные данные стандартного объекта HBITMAP

Расширенный формат.

Тип | Имя | Размер в байтах | Значение / Описание
--- | --- | --- | ---
uint32_t | type | 4 | MSF_BLOCKTYPE::PREVIEWEX // Тип блока (тега)
uint32_t | length | 4 | Размер блока = размер этого заголовка + размер данных
uint32_t | id | 4 | -1 // идентификатор устройства, которому принадлежит блок данных
uint32_t | flags | 4 | 1 // Флаги
uint32_t | unpSize | 4 | Размер распакованных данных
Данные тега, размер переменный
структура | BITMAPINFOHEADER | 40 | Стандартная структура BITMAPINFOHEADER
массив |  | Заранее не известно | Бинарные данные стандартного объекта HBITMAP, сжатые алгоритмом LZW.

### Тег MSF_BLOCKTYPE::CONFIG[EX]

Тип | Имя | Размер в байтах | Значение / Описание
--- | --- | --- | ---
uint32_t | type | 4 | MSF_BLOCKTYPE::CONFIG // Тип блока (тега)
uint32_t | length | 4 | Размер блока = размер этого заголовка + размер данных
Данные тега, размер переменный
массив |  | Заранее не известно | Текст в формате UTF16-LE, содержащий основную часть настроек заданной конфигурации.

Расширенный формат:

Тип | Имя | Размер в байтах | Значение / Описание
--- | --- | --- | ---
uint32_t | type | 4 | MSF_BLOCKTYPE::CONFIGEX // Тип блока (тега)
uint32_t | length | 4 | Размер блока = размер этого заголовка + размер данных
uint32_t | id | 4 | -1 // идентификатор устройства, которому принадлежит блок данных
uint32_t | flags | 4 | 1 // Флаги
uint32_t | unpSize | 4 | Размер распакованных данных
Данные тега, размер переменный
массив |  | Заранее не известно | Текст в формате UTF16-LE, содержащий основную часть настроек заданной конфигурации, сжатый алгоритмом LZW.

### Тег MSF_BLOCKTYPE::FRAMEDATA[EX]

Этот тег содержит текущие параметры фрейма и внутренние счётчики эмуляции экрана и ВЕ-таймера. Тег MSF_BLOCKTYPE::FRAMEDATAEX не используется из-за своей избыточности.

Формат.

Тип | Имя | Размер в байтах | Значение / Описание
--- | --- | --- | ---
uint32_t | type | 4 | MSF_BLOCKTYPE::FRAMEDATA // Тип блока (тега)
uint32_t | length | 4 | Размер блока = размер этого заголовка + размер данных
Данные тега, размер 8 * 4 + 3 * 8
| // состояние ВЕ таймера |
int | nTimerSpeed | 4 | текущее значение счётчика ВЕ таймера
int | nTimerDiv | 4 | текущий делитель ВЕ таймера
| // состояние экрана |
int | nVideoAddress | 4 | видео адрес, младшие 6 бит - счётчик строк внутри строки
int | bHgate | 4 | флаг отсчёта служебных видеоциклов в строке
int | bVgate | 4 | флаг отсчёта служебных строк
int | nVGateCounter | 4 | дополнительный счётчик служебных строк
int | nLineCounter | 4 | счётчик видео строк
| // состояние фрейма (значения внутренних счётчиков фрейма)
int | nCPUTicks | 4 |
double | fMediaTicks | 8 |
double | fMemoryTicks | 8 |
double | fFDDTicks | 8 |

### Тег MSF_BLOCKTYPE::CPU_REGISTERS[EX]

Тег содержит значения регистров общего назначения процессора 1801ВМ1. Тег MSF_BLOCKTYPE::REGISTERSEX не используется из-за своей избыточности.

Формат.

Тип | Имя | Размер в байтах | Значение / Описание
--- | --- | --- | ---
uint32_t | type | 4 | MSF_BLOCKTYPE::CPU_REGISTERS // Тип блока (тега)
uint32_t | length | 4 | Размер блока = размер этого заголовка + размер данных
Данные тега, размер 2 * 9
uint16_t | r0 | 2 |
uint16_t | r1 | 2 |
uint16_t | r2 | 2 |
uint16_t | r3 | 2 |
uint16_t | r4 | 2 |
uint16_t | r5 | 2 |
uint16_t | sp | 2 |
uint16_t | pc | 2 |
uint16_t | psw | 2 |

### Тег MSF_BLOCKTYPE::MEMMAPEX

Это очень важный тег специального назначения, для разных устройств содержимое имеет разный размер.

Тип | Имя | Размер в байтах | Значение / Описание
--- | --- | --- | ---
uint32_t | type | 4 | MSF_BLOCKTYPE::MEMMAPEX // Тип блока (тега)
uint32_t | length | 4 | Размер блока = размер этого заголовка + размер данных
uint32_t | id | 4 | идентификатор устройства, которому принадлежит блок данных
uint32_t | flags | 4 | 0 // Флаги
uint32_t | unpSize | 4 | 0 // Размер распакованных данных
Данные тега, размер 5*4 * n + 4
{ |  |  |
BOOL | bReadable | 4 | флаг, что память доступна для чтения
BOOL | bWritable | 4 | флаг, что память доступна для записи
uint32_t | nBank | 4 | номер банка памяти, размер зависит от конкретного устройства
uint32_t | nOffset | 4 | смещение в массиве памяти
int32_t | nTimingCorrection | 4 | значение корректировки тайминга при обращении к памяти, которая не управляется ВП1-037 (ПЗУ или ОЗУ СМК)
} по количеству банков памяти у устройства.
uint32_t | nROMPresent | 4 | Маска наличия заявленных ПЗУ для устройства.

По счастливому стечению обстоятельств, количество банков памяти для всех типов устройств одинаковое и равно 8, кроме AZBK, для него – 16.

Маска наличия ПЗУ служит для эмуляции отсутствия заявленного ПЗУ в системе. Например, можно сэмулировать отсутствие ПЗУ Бейсика в БК11(М), или отсутствие ПЗУ Фокала в БК0010 и т.п.

### Тег MSF_BLOCKTYPE::BASEMEMORYEX

Тип | Имя | Размер в байтах | Значение / Описание
--- | --- | --- | ---
uint32_t | type | 4 | MSF_BLOCKTYPE::BASEMEMORYEX // Тип блока (тега)
uint32_t | length | 4 | Размер блока = размер этого заголовка + размер данных
uint32_t | id | 4 | идентификатор устройства, которому принадлежит блок данных
uint32_t | flags | 4 | 1 // Флаги
uint32_t | unpSize | 4 | Размер распакованных данных
Данные тега, размер определяется устройством
массив |  | … | Полный массив памяти ОЗУ+ПЗУ для заданного устройства. Сжатый алгоритмом LZW

Для устройства без памяти, тегов MSF_BLOCKTYPE::MEMMAP и MSF_BLOCKTYPE::BASEMEMORY может и не быть.

### Тег MSF_BLOCKTYPE::PORT_REGSEX

Содержит значения портов и регистров заданного устройства. Формат зависит от заданного устройства.

Формат для устройств типа BK_BOARD_TYPE_MDL (материнские платы)

Тип | Имя | Размер в байтах | Значение / Описание
--- | --- | --- | ---
uint32_t | type | 4 | MSF_BLOCKTYPE::PORT_REGSEX // Тип блока (тега)
uint32_t | length | 4 | Размер блока = размер этого заголовка + размер данных
uint32_t | id | 4 | идентификатор устройства, которому принадлежит блок данных
uint32_t | flags | 4 | 0 // Флаги
uint32_t | unpSize | 4 | 0 // Размер распакованных данных
Данные тега, размер 2 * 15
uint16_t | p0177660 | 2 | Содержимое регистра 177660
uint16_t | p0177662_in | 2 | Содержимое регистра 177662 по чтению
uint16_t | p0177662_out | 2 | Содержимое регистра 177662 по записи
uint16_t | p0177664 | 2 | Содержимое регистра 177664
uint16_t | p0177700 | 2 | Содержимое регистра 177700
uint16_t | p0177702 | 2 | Содержимое регистра 177702
uint16_t | p0177704 | 2 | Содержимое регистра 177704
uint16_t | p0177706 | 2 | Содержимое регистра 177706
uint16_t | p0177710 | 2 | Содержимое регистра 177710
uint16_t | p0177712 | 2 | Содержимое регистра 177712
uint16_t | p0177714_in | 2 | Содержимое регистра 177714 по чтению
uint16_t | p0177714_out | 2 | Содержимое регистра 177714 по записи
uint16_t | p0177716_in | 2 | Содержимое регистра 177716 по чтению
uint16_t | p0177716_out_tap | 2 | Содержимое регистра 177716 по записи
uint16_t | p0177716_out_mem | 2 | Содержимое регистра 177716 управления памятью по записи

Некоторые регистры излишни, например 177700..177704 не используются и не изменяются, их сохранение сделано на перспективу.

p0177662_out и p0177716_out_mem в конфигурациях БК-0010 не используются, но сохраняются по причине общей процедуры для всех конфигураций материнских плат БК.

Формат для устройства типа AZBK

В качестве данных сохраняются все регистры AZBK, их много, структура большая, поэтому см. описание структуры sAZRegisters_t в файле AZBK.h

Данные тут не приводятся, потому что сам AZBK ещё не имеет окончательного варианта.

### Тег MSF_BLOCKTYPE::CUSTOMEX

Этот тег имеет самый многовариантный формат.

Тип | Имя | Размер в байтах | Значение / Описание
--- | --- | --- | ---
uint32_t | type | 4 | MSF_BLOCKTYPE::CUSTOMEX // Тип блока (тега)
uint32_t | length | 4 | Размер блока = размер этого заголовка + размер данных
uint32_t | id | 4 | идентификатор устройства, которому принадлежит блок данных
uint32_t | flags | 4 | 0 // Флаги
uint32_t | unpSize | 4 | 0 // Размер распакованных данных
Данные тега, размер переменный

Кастомные структуры, которые сохраняются в разных конфигурациях:

BK_DEV_MPI::BK0011, BK_DEV_MPI::BK0011M – структура CustomData_t в файле BK0011M.h

bool | bWnd1Off | 1 | флаг выключения окна 1 контроллером АльтПро

BK_DEV_MPI::MSTD10_EXT32 – структура CustomData_t в файле BKMSTD10_EXT32.h

int | nPage | 4 | номер подключенной страницы в окно

BK_DEV_MPI::A16M, BK_DEV_MPI::SMK512– структура AltProCtrlData_t в файле Config.h

DWORD | nAltProMemBank | 4 | код подключения страницы памяти контроллера
DWORD | nExtCodes | 4 | доп коды контроллера, типа 10 - подкл. бейсика и 4 - блокировка регистров 177130 и 177132 по чтению
DWORD | nAltProMode | 4 | код режима контроллера

BK_DEV_MPI::SAMARA – структура CustomData_t в файле FDD_Samara.h

bool | b10 | 1 | флаг, что подключено к БК10

BK_DEV_MPI::AZBK – структура sAZCustom_t в файле AZBK.h

Данные тут не приводятся, потому что сам AZBK ещё не имеет окончательного варианта.