Universal PT2 and PT3 Turbo Sound player for ZX Spectrum Release 0
(c)2004-2007 S.V.Bulba <vorobey@mail.khstu.ru>
http://bulba.untergrund.net/ (http://bulba.at.kz/)
Дата выпуска: 29 апреля 2007 года

Общие замечания
---------------

За основу данного плеера взят PTxPlay Release 0. Таким образом, когда-то
подсказанная мне Иваном Рощиным и Андреем Богдановичем идея объединения PT2 и
PT3 плееров и навеянная перепиской с Дмитрием Быстровым идея создания плеера
для Turbo Sound дали довольно неожиданный результат: на ваш суд представляется
универсальный и компактный проигрыватель PT2 и PT3 модулей всех известных на
сегодняшний день версий с возможностью вывода как на стандартный звуковой
сопроцессор ZX Spectrum (далее AY), так и на устройство Turbo Sound (далее TS).

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

Возможности
-----------

- Проигрываются PT2-модули всех версий, включая PT v2.4PhF.
- Модули PT v2.4PhF можно располагать по адресу, отличному от адреса компиляции.
- По версии PT3-модулей генерируются правильные тоновые и громкостные таблицы.
- Для PT3-модулей версий 3.6 и старше используется другой алгоритм портаменто.
- Для PT3-модулей версий 3.7 и старше разрешены спецкоманды 1.xx и 2.xx.
- Модули с новым заголовком Vortex Tracker II играются как модули PT 3.6.
- Два модуля PT2 можно проиграть одновременно через TS.
- Аналогично через TS можно проиграть два модуля PT3.
- Модули PT 3.7, сохраненные в режиме TS, также можно проиграть через TS.
- Плеер сигнализирует о переходах на цикл по каждому проигрываемому модулю.
- Можно запретить зацикливание проигрывания.
- Можно по ходу проигрывания менять стереораскладку каналов.
- Возможно использование плеера из бэйсика ZX Spectrum.
- Возможно отслеживание номера текущей позиции по каждому проигрываемому модулю.
- Плеер компилируется по любому удобному адресу.
- Почти все переменные вынесены за пределы кодового блока по выбранному адресу.

Компиляция
----------

Данный плеер с помощью условного ассемблирования может быть скомпилирован со
следующими дополнительными функциями:

1) счетчик позиций каждого из двух модулей по адресу (VARS1+0) и (VARS2+0);
2) возможность менять раскладку каналов "налету";
3) отслеживание перехода на цикл с возможностью запрета;
4) запрет официального идентификатора;
5) корректный возврат при вызове из бэйсика.

Для ассемблирования использовался ассемблер под Win32:

SjASM Z80 Assembler v0.39f
Copyright 2005 Sjoerd Mastijn

Минимальная конфигурация занимает 2312 байт под коды и 703 байта под переменные.

Файлы
-----

PTxPlay.asm - исходный текст для ассемблера Z80.
PTxPlay.txt - тот же текст, адаптированный под ZX Asm 3.10.
PTxPlay.h - тот же текст, адаптированный под Alasm (удалены все комментарии).
PTxPlay - ассемблированный блок в минимальной конфигурации для ZX Spectrum с
идентификатором для загрузки по адресу #C000, нули в конце можно отрезать.

Точки входа
-----------

Плеер стандартен, то есть сперва нужно вызвать START (адрес загрузки), а потом
каждое прерывание - START+5. Для сброса AY после окончания проигрывания можно
вызвать START опять, либо START+8, которая просто глушит звук AY (это можно
использовать в режиме паузы, чтобы в последствии продолжить проигрывание с того
же места).

Перед вызовом START по адресу SETUP (START+10) нужно соответствующим образом
установить бит 1, который отвечает за тип модуля: 0 для PT3 и 1 для PT2, а также
биты 4 и 5, которые указывают плееру, какой режим проигрывания инициализировать:
%00 - один модуль для стандартного AY; %01 - 2 модуля для TS-режима; %10 -
только один PT3-модуль (TS режим включается автоматически, если модуль сохранен
из PT v3.7+ в режиме TS). Остальные биты можно устанавливать или тестировать в
любой момент (если соответствующие функции не были отключены во время
ассемблирования), подробности ниже. Тип модуля можно определить с помощью
UniSearch Андрея Богдановича.

Плеер не перемещаемый, используйте другой ORG перед ассемблированием,
если вам нужен адрес, отличный от 49152, при этом область VARS можно поместить
в любое другое удобное место.

По адресу START+10 находится байт настройки и статусных флагов. Установкой бита
0 вы можете запретить плееру переходить на цикл (по окончанию проигрывания
вместо перехода на цикл звук будет просто отключен). Бит 0 можно устанавливать и
сбрасывать в любой момент - и до проигрывания, и во время проигрывания, так как
он анализируется плеером только при переходе на цикл. Бит 1 описан выше. Биты
2-3 можно менять в любой момент для управления раскладкой каналов. Из четырех
комбинаций битов разрешены только первые три: 0 - ABC, 1 - ACB, 2 - BAC.
Раскладка ABC выводит звук "как есть", ACB меняет местами каналы B и C, а BAC -
A и B. Таким образом, в случае стерео в центр можно поставить любой из трех
каналов, то есть охвачены все стандартные раскладки: ABC - большинство наших
клонов ZX, ACB - Восточная Европа, BAC - ZS Scorpion 256K. Для получения еще,
трех комбинаций стерео, поменяйте колонки местами. Биты 4-5 описаны выше. Биты 6
и 7 устанавливается каждый раз после того, как плеер доиграет последнюю позицию
второго (бит 6) и первого (или единственного, бит 7) модулей. При этом, если
зацикливание не запрещено, осуществляется переход на позицию цикла. Если бит 0
сброшен, то одновременно с установкой бита 6 или 7 на AY отправляются первые
данные из позиции цикла, то есть происходит обычное зацикливание. Если
необходимо, чтобы биты 6 и 7 устанавливались только при запрете зацикливания,
переместите блок команд c SET x,(HL) после RET Z (см. подпрограмму CHECKLP).

В данной сборке первый модуль нужно загружать сразу же после переменных плеера.
Конечно, вы можете изменить это в исходнике или прямо в коде. Также можно
загружать адреса модулей в HL и DE и вызывать START+3 вместо START:

	LD HL,PT3Module1
	LD DE,PT3Module2
	LD A,16 ;2xPT3
	LD (START+10),A
	CALL START+3

Вызывая START, вы тем самым вызываете процедуру INIT, которая анализирует
бит типа модулей и готовит соответствующие ветки плеера, по версии первого
PT3-модуля готовит соответствующие таблицы громкости и нот, инициализирует
проигрывание модулей, а также сбрасывает AY. Вызов PLAY без предварительного
вызова INIT может привести к полному краху, тоже будет, если модуль не загружен
по указанному в INIT адресу. MUTE лучше тоже не вызывать до INIT, так как флажок
режима TS до INIT находится в неопределенном положении.

Для проигрывания вызывайте START+5 каждые 1/50 секунды (прерывание). Во время
работы процедуры проигрывания не должно быть никаких прерываний - это приведет
к сбою. За этим должны следить вы сами. Например, следующий пример абсолютно
корректен:

	CALL #C000 ;вызов init
	EI ;разрешение прерываний
_LP	HALT ;ждем очередного прерывания
	CALL #C005 ;вызываем play
	XOR A ;опрос клавиатуры
	IN A,(#FE)
	CPL
	AND 15
	JR Z,_LP
	CALL #C008 ;глушим звук AY (возможно возобновление с того же места)
	RET

Если плеер ассемблирован со включенной функцией счетчика позиций, то по адресу
VARS1+0 (VARS2+0 для второго модуля) находится байт с номером текущей позиции в
модуле. Общее число позиций можно взять непосредственно из заголовка модуля или
с помощью вышеупомянутой процедуры UniSearch.

Модули в режиме TS играются асинхронно, поэтому и значения счетчиков позиций, и
моменты перехода на цикл в общем случае разные. Исключение составляет TS-модуль
от PT v3.7+, в котором, благодаря структуре модуля, все происходит синхронно (в
противном случае модуль придется подкорректировать в редакторе).

Пример проигрывания без перехода на цикл:

	LD A,1
	LD (START+10),A
	CALL START
	EI
LOOP	HALT
	CALL START+5
	LD A,(START+10)
	RLA ;здесь для простоты следим только за первым модулем
	JR NC,LOOP
	RET

Читайте также комментарии в исходнике.

Помощь
------

Плеер оброс множеством новых функций и поэтому тестирование его автоматически
(как это делалось раньше) методом брутфорса уже крайне затруднительно. Если вы
найдете ошибки (общие или в одном из режимов или вариантов сборки), или вы
считаете нужным внести свой вклад в оптимизацию кода или просто имеете свои
предложения по дальнейшему развитию плеера, пишите мне по адресу
vorobey@mail.khstu.ru или в форум http://dlcorp.ucoz.ru/forum/

Благодарности
-------------

Ивану Рощину за алгоритмы генерации таблиц тона и громкости и за идею доработки
PT3-плеера для проигрывания PT2-модулей.
Андрею Богдановичу aka Spectre за идею объединения возможностей PT2Play и Vortex
Tracker II v1.0 PT3 player, за помощь в отладке, советы по усовершенствованию,
адаптацию исходных текстов под ассемблеры ZX и процедуру UniSearch.
Дмитрию Быстрову за идею расширения возможностей моих плееров для использования
с TS, за консультации, а также за публикацию проекта в своем журнале.

Сергей Бульба

19 сентября 2004 года - 29 апреля 2007 года
