Vortex Tracker II v1.0 PT3 player for ZX Spectrum Release 7
(c)2004,2007 S.V.Bulba <vorobey@mail.khstu.ru>
http://bulba.untergrund.net/ (http://bulba.at.kz/)
Дата выпуска: 30 апреля 2007 года
Версия для MSX: 9 января 2005 года (Release 6)
Адаптация к XAS 9.06: 11 января 2005 года (Release 6)


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

Поскольку на ZX Spectrum существует проблема совместимости плееров PT3 разных
версий, а также наличие нескольких тоновых табличек, которые частично изменялись
в некоторых версиях (включая табличку громкости), поскольку все стандартные
плееры содержат ряд ошибок (неправильное воспроизведение портаменто в некоторых
случаях) и ограничений (например, Tempo не менее 2, или даже 3 в некоторых
старых версиях), я решил написать новый плеер PT3 для Speccy, который теперь и
будет использоваться в Vortex Tracker II при импорте на ZX.

Данный плеер во время инициализации определяет номер версии модуля и генерирует
необходимые таблицы громкости и нот. Также во время проигрывания работает один
из двух алгоритмов портаменто (старый для версии 3.5 и ниже, и новый для 3.6+ и
Vortex Tracker II). Начиная с этого выпуска (Release 7) для модулей версий 3.7 и
выше отрабатываются команды 1.xx и 2.xx.

Несмотря на то, что данный плеер в пике почти в два раза медленней стандартных,
имеется ряд бонусов:

1) нет необходимости держать в вашем софте несколько разных версий плееров и
   табличек нот и громкости;
2) плеер занимает меньше места (всего 1,6 кб) без ущерба правильности
   воспроизведения;
3) плеер может быть ассемблирован по любому адресу, не нужно никакого круглого
   адреса как в стандартных плеерах;
4) правильно воспроизводит любое портаменто (звук в точности соответствует
   звучанию в редакторе), чем не может похвастаться не один другой ныне
   существующий PT3-плеер;
5) переменные могут быть расположены где угодно в памяти и могут быть отрезаны
   без всякого ущерба целостности плеера.

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

SjASM Z80 Assembler v0.39f
Copyright 2005 Sjoerd Mastijn

Файлы
-----

VTII10bG.asm - исходный текст для ассемблера Z80.
ZX_Asms\VTII10bG.h - тот же текст, адаптированный под Alasm.
ZX_Asms\VTII10bG.txt - тот же текст, адаптированный под ZX Asm 3.10.
ZX_Asms\Jocker\PT3_VORT.!a - адаптация старого выпуска (Release 6) к ассемблеру
XAS 9.06 в формате Hobeta (выполнил Jocker/OHG/CMS).
VTII10bG - ассемблированный блок для загрузки по адресу #C000, нули в конце
можно отрезать.
Файлы в папке MSX - адаптация старого выпуска (Release 6) для компьютеров MSX
(выполнил Alfonso D.C. a.k.a. Dioniso).
Файлы в папке ROM - адаптация плеера с возможностью запуска из ROM (весь
самомодифицирующийся код перемещен в область переменных).

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

Плеер стандартен, то есть сперва нужно вызвать START (адрес загрузки), а потом
каждое прерывание - START+5. Для сброса AY после окончания проигрывания можно
вызвать START опять, либо START+8, которая просто глушит звук AY (это можно
использовать в режиме паузы, чтобы в последствии продолжить проигрывание с того
же места). Плеер не перемещаемый, используйте другой ORG перед ассемблированием,
если вам нужен адрес, отличный от 49152, при этом область VARS можно поместить
в любое другое удобное место. По адресу START+10 находится байт настройки и
статусных флагов. Установкой бита 0 вы можете запретить плееру переходить на
цикл (по окончанию проигрывания вместо перехода на цикл звук будет просто
отключен). Бит 0 можно устанавливать и сбрасывать в любой момент - и до
проигрывания, и во время проигрывания, так как он анализируется плеером только
при переходе на цикл. Бит 7 устанавливается каждый раз после того, как плеер
доиграет последнюю позицию. При этом, если зацикливание не запрещено,
осуществляется переход на позицию цикла. Если бит 0 сброшен, то одновременно с
установкой бита 7 на AY отправляются первые данные из позиции цикла, то есть
происходит обычное зацикливание. Если необходимо, чтобы бит 7 устанавливался
только при запрете зацикливания, переместите команду SET 7,(HL) после RET Z (см.
подпрограмму CHECKLP).

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

	LD HL,PT3ModuleAddress
	CALL START+3

Один из самых простых способов приклеить плеер к своему модулю - экспортировать
его из редактора Vortex Tracker II, в котором можно задать не только адрес
компиляции, но и байт настройки. С чужими модулями так поступать нельзя, так
как при перекомпиляции модуля в не родной версии теряются некоторые нюансы,
зачастую влияющие и на звук.

Организаторы разных party! Прекратите, наконец, перекомпилировать модули!
Почему вы думаете, что приклеить плеер к модулю можно только с помощью
редактора? Я понимаю, что у вас много других проблем с организацией мероприятия,
но это нисколько не оправдывает вашу некомпетентность в этом вопросе.

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

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

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

;1 первый вариант заглушки звука (возможно возобновление с того же места):
	CALL #C008 ;глушим звук AY

;2 второй вариант заглушки звука (возможно проигрывание только с начала):
;2	CALL #C000 ;повторный вызов init

	RET

По адресу START+11 находится двухбайтовый указатель на текущую позицию в модуле.
Чтобы узнать текущий номер позиции во время проигрывания (например, для
визуализации), выполните следующий код:

	LD HL,(START+11)
	LD DE,-PT3ModuleAddress-201
	ADD HL,DE

Номер позиции будет в регистре HL (в нормальном модуле H всегда будет 0).

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

	LD A,1
	LD (START+10),A
	CALL START
	EI
LOOP	HALT
	CALL START+5
	LD A,(START+10)
	RLA
	JR NC,LOOP
	RET

Проигрывание с трехкратным зацикливанием:

	CALL START
	LD A,3
	EI
LOOP	PUSH AF
	HALT
	CALL START+5
	POP AF
	LD HL,START+10
	SLA (HL)
	JR NC,LOOP
	DEC A
	JR NZ,LOOP
	CALL START+8
	RET

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

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

Несмотря на то, что данный плеер прошел ряд объективных тестов на правильность
воспроизведения, автор допускает, что возможны некоторые ошибки. Если вы найдете
таковые, или вы считаете нужным внести свой вклад в оптимизацию кода или просто
имеете свои предложения по дальнейшему развитию плеера, пишите мне по адресу
vorobey@mail.khstu.ru.

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

Spectre за помощь в отладке, советы по усовершенствованию и адаптацию
исходных текстов под ассемблеры ZX.
Ивану Рощину за советы по оптимизации, алгоритмы генерации таблиц тона и
громкости и тематические статьи.
Alfonso D.C. aka Dioniso за адаптацию под компьютеры MSX.
Alone Coder за дискуссию, которая и сподвигла меня на написание плеера, а также
за советы по оптимизации.
Jocker/OHG/Critical Mass за адаптацию к ассемблеру XAS 9.06.
Himik's ZxZ за моральную поддержку с перспективой использования в Pusher.

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

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