STP

Введение

STP – это родной формат компилированного модуля ZX Spectrum Sound Tracker Pro (см. описание STF).

Компилятор встроен прямо в редактор и в разных версиях Sound Tracker Pro имеет те или иные ошибки.

В некоторых компиляторах это ошибка оптимизации, при которой, удаляя вроде бы лишний (повторяющийся) орнамент, забывают про включённую до этого команду скольжения, и она начинает дублироваться на последующие ноты. Яркий пример: модуль "IMP49:FOOLISH GIRL", или Sumea_FN.stp Visual'а (по последнему нигде нет исходного STF, чтобы перекомпилировать без ошибок).

В других этой ошибки нет, но остаётся много лишнего мусора и исчезают команды установки громкости 1 (хотя это уже незаметно на слух – слишком мала громкость).

К сожалению, нумерации версий редактора нет, поэтому выбирать для себя, какой из имеющихся у вас на руках лучше, придётся методом проб и ошибок.

Если ваша цель – просто откомпилировать STF, то это можно сделать с помощью встроенного в Ay_Emul компилятора: я исправил все обнаруженные ошибки родных компиляторов и проработал оптимизацию по размеру.

Формат STP хорошо описал VfNG в электронной газете Echo № 3 (приведён в конце). Поэтому если в дальнейшем тексте будут некоторые неясные моменты, можете сперва прочитать его.

Некоторые замечания по формату

Когда я выбирал расширение STP для использования данного формата в Ay_Emul, не озвучил один важный момент (в прочем, эту ошибку допустил и с другими форматами). Многие форматы компилированных модулей имеют два состояния: инициализированные и не инициализированные. В родном проигрывателе перед началом проигрывания вызывается специальная подпрограмма инициализации. В большинстве форматов она просто готовит внутренние переменные к началу проигрывания и не вносит никаких изменений в сам модуль. Но есть плееры у некоторых форматов, в которых данные модуля во время инициализации привязываются к адресу загрузки, и есть даже такие, которые используют область заголовка для своих нужд (и, следовательно, портят её).

Во время инициализации компилированного модуля Sound Tracker Pro осуществляется привязка части смещений к адресу загрузки. Причём внутри файла есть байт-идентификатор, по которому и можно судить, что модуль уже инициализирован.

Расширение STP даётся только тем модулям, которые либо не инициализированы (то есть находятся в том состоянии, в котором их сохранили из редактора), либо с которыми произведена обратная операция отвязки от адреса загрузки.

Ay_Emul во время сохранения найденных модулей (это касается не только STP) проделывает всё необходимое, чтобы вернуть их в состояние "до инициализации".

К сожалению, в последние годы в сети начали появляться модули, которые сохранены без соблюдения этого правила, и даже с некорректно вставленными авторскими строчками (см. далее).

Поэтому в Ay_Emul для некоторых форматов (в том числе и STP) пришлось добавить дополнительные проверки после загрузки для учёта этой особенности текущего момента.

Авторская строка в теле модуля

Первые трекерные форматы на ZX Spectrum мучила одна и та же болезнь. Авторы редакторов либо вообще не предусмотрели в формате место под авторскую строчку (Sound Tracker), либо предусмотрели, но не в формате, а в его плеере. При этом, если в таком редакторе как ASC Sound Master есть намёк, что проигрыватель и данные (модуль) – одно неделимое целое, то в STP прямо в документации упоминается о том, что одним проигрывателем можно играть разные модули (а ведь в таком сценарии использования становится непонятно, к какому именно модулю относится авторская строка).

Мы обсуждали эту проблему с Ильёй Кудрявцевым (Himik's ZXZ), и он предложил немного модифицировать ASC-модули. Я в свою очередь предложил проделать тоже самое с STP. Таким образом, мы договорились о двух новых форматах, главное достоинство которых – полная совместимость с оригиналами. Новые STP и ASC без проблем проигрываются оригинальными плеерами, поскольку те даже не догадываются о наличии дополнительной информации в теле блока данных.

Для вставки авторской строки (длина 53 байта, начинается с "KSA SOFTWARE COMPILATION OF ") из плеера в тело модуля, необходимо:

  1. Область, начинающуюся со смещения +10, перенести на 53 байта вперёд.
  2. В образовавший промежуток вставить авторскую строку.
  3. Увеличить на 53 все смещения в модуле (4 основных в начале модуля, и все, начиная со смещений паттернов, в конце).

Формат компилированного модуля

Далее приведена немного отредактированная выдержка из статьи VfNG в газете Echo № 3.

---------------------------cut here-------------------

В описании могут встречаться отдельные неточности, так что будьте внимательны. Это описание пишется не с целью устранения всех вопросов, а только должно помочь вам разобраться в некоторых вещах при работе с player'ом.

+0Скорость проигрывания;
+1Смещение до TABL1;
+3,4Смещение до TABL2;
+5,6Смещение до TABL3;
+7,8Смещение до TABL4;
+9В этом байте содержится число элементов, к которым надо прибавить реальный адрес +0 в памяти. Это делает секция инициализации. Если этот байт=0, значит инициализация уже проведена. Первый элемент, требующий настройки, находится с адреса TABL2. Каждый элемент – 2 байта (младший, старший байты смещения от +0);
+10Первый паттерн;
TABL1+0длина музыки в позициях;
TABL1+1номер позиции для зацикливания;
TABL1+2по 2 байта/позиция:
+0 6*номер PATTERN;
+1 HEIGHT (отклонения в нотах от обычного звучания PATTERN);
TABL2описатели PATTERN'ов: по 2 байта смещения для каждого канала, значит по 6 байт/PATTERN;
TABL3смещения до орнаментов. 0-й орнамент служит для отключения орнаментов в канале;
ТABL4смещения до сэмплов;

Формат орнамента:

+0точка зацикливания;
+1полная длина;
+2, 1*(+1)отклонения от значения ноты;

Формат сэмпла:

+0точка зацикливания;
+1полная длина;
+2по 4 байта/QUARK:
+0 биты 0-3 амплитуда; бит 4 маска тона; бит 7 маска шума;
+1 бит 0 маска огибающей; биты 1-5 частота шума;
+2,3 байты частотного вибратто;

Каждый описатель PATTERN содержит указатели на описатели каналов. Каналы анализируются следующим образом:

        LD   HL,CHAN_POS
        LD   A,(HL)
        OR   A
        JR   Z,конец PATTERN
        LD   C,#10
LOOP    LD   A,(HL)
        INC  HL
        CP   #C0
        JR   C,L9
        SUB  C
        JR   NC,L1
        SUB  C
        JR   NC,L2
        SUB  C
        JR   NC,L3
        SUB  C
        JR   L4
L9      SUB  #80
        JR   NC,L5
        SUB  C
        JR   NC,L6
        SBC  A,C
        JR   NC,L7
L8      ADD  A,#60

в A – номер ноты. Её установка, выход;

L7

в A – номер сэмпла. LOOP;

L6

в A – номер орнамента. LOOP;

L5

в A – сколько INT'ов не надо анализировать канал. LOOP;

L4

в A – тип огибающей. В следующем байте-период. Установка регистра амплитуды в #1F, LOOP;

L3

выключение канала, выход;

L2

установка величины, полученной в L5, выход;

L1      JR   Z,L0
        DEC  A

в A – число, которое надо отнять от #0F для получения громкости. LOOP;

L0

в следующем байте – glissade. LOOP;

---------------------------cut here-------------------