Из журнала ZX Format #6, Санкт-Петербург, 30.07.1997 Руководство по программированию General Sound. Версия 1.03. Stinger _________________________________________ 1. Краткие технические характеристики GS Процессор : Z80, 12MHz, no wait states ROM : 32k, 27256 RAM : static ram 128k total, 112k for modules and samples in base version INT : 37. 5 KHz Channels : 4 Independent 8 bit channels, each with 6 bit Volume Cntrl 2. Краткое описание GS GS - музыкальная карточка, предназначен- ная для проигрывания музыкальных модулей и отдельных сэмплов (эффектов). Модули для GS - это стандартные Амижные и PCшные 4-х канальные MOD файлы, а сэмп- лы - как Амижные signed sample, так и PCшные unsigned sample. Проигрыватель MOD файлов в GS является практически полным аналогом ProTracker'а на Амиге и создавался при интенсивном ис- пользовании исходников ProTracker'a. MOD Player поддерживает все команды Pro Tracker'а, за исключением двух : Е01 Filter On Амига-специфичная коман- да,включает фильтр высо- ких частот, в котором GS не нуждается. EFX Invert Loop Я еще не видел плейера, который бы эту команду поддерживал бы.Возможно, она поддерживается на каких-то старых плейе- рах. GS представляет из себя, по-сути, мик- ропроцессорный комплекс со своим процес- сором, ПЗУ, ОЗУ и портами, и абсолютно не зависит от главного процессора Спектрума, что позволяет, например, загрузить свой любимый модуль, сбросить Спектрум, загру- зить ассемблер и творить под любимую му- зыку. Soft внутри GS полностью берет на себя задачи проигрывания звука, интерпре- тации модуля и т. д., и программирование GS'а сводится к передаче байт за байтом модуля и/или сэмплов, а затем требуется только подавать команды типа: запустить модуль, установить глобальную громкость проигрывания модуля, запустить сэмпл #09 в канале #02 и т. д. Если предполагается загрузить модуль вместе с сэмплами, то ОБЯЗАТЕЛЬНО требу- ется загружать вначале модуль, а затем сэмплы. При загрузке модуля очень рекомендуется оставить свободными 2к памяти, т.е. заг- ружать модули длиной максимум 110к. Это условие не является необходимым, но его исполнение очень желательно в целях сов- местимости с поседующими версиями. Аналогично очень рекомендуется оставлять по 80 байт для каждого сэмпла, например если требуется загрузить 63-х килобайтный модуль и 18 сэмплов, то имеем: Total_Sample_Length=112*1024-63*1024-2*1024-18*80=46688 байт - суммарная длина сэмплов. Если, например, требуется вычислить, сколько поместится в память GS'а 2-х ки- лобайтных сэмплов, то это вычисляется следующим образом: N=112*1024/(2048+80)=53 сэмпла. В GS'е имеются 4 физических канала, ко- торые и проигрывают звук. Каналы 0 и 1 - левые, а 2 и 3 - правые. 3. Интерфейс со Спектрумом На мир GS смотрит при помощи 4 регистров: 1. Command register - регистр команд, доступный для записи порт по адресу 187 В этот регистр записываются команды. 2. Status register - регистр состояния, доступный для чтения порт по адресу 187 Биты регистра: 7 - Data bit, флаг данных 6 - Неопределен 5 - Неопределен 4 - Неопределен 3 - Неопределен 2 - Неопределен 1 - Неопределен 0 - Command bit, флаг команд Этот регистр позволяет определить состо- яние GS, в частности можно ли прочитать или записать очередной байт данных, или подать очередную команду, и т. п. 3. Data register - регистр данных, дос- тупный для записи порт по адресу 179 В этот регистр Спектрум записывает дан- ные, например это могут быть аргумен- ты команд. 4. Output register - регистр вывода,дос- тупный для чтения порт по адресу 179 Из этого регистра Спектрум читает данные, идущие от GS. Command bit в регистре состояний уста- навливается аппаратно после записи коман- ды в регистр команд. Сбрасываться в 0 он может только из GS, что сигнализирует об определенном этапе исполнения команды. Data bit в регистре состояний может быть установлен или сброшен как по желанию Спектрума, так и по желанию GS: При записи Спектрумом в регистр данных он аппаратно устанавливается в 1, а после чтения GS'ом из этого регистра сбрасыва- ется в 0. При записи GS в регистр вывода он (все тот же Data bit) аппаратно устанавливает- ся в 1, а после чтения из этого порта Спектрумом сбрасывается аппаратно в 0. Несмотря на то, что регистр данных и ре- гистр вывода расположены в пространстве адресов портов по одному и тому же адре- су, и воздействуют на один и тот же бит данных, они являются двумя независимыми регистрами. Значение, один раз записанное в один из этих регистров, остается неиз- менным в нем до новой записи. Состояние бита данных очень часто неопре- делено, и если в спецификации команд не определены значения этого бита на опре- денных этапах исполнения команды, недо- пустимо делать какие-либо предположения относительно значения этого бита. 4. Система команд GS Вначале позволю себе небольшое отступле- ние от собственно системы команд. GS, как известно, предназначен в основном для проигрывания модулей и сэмплов. В данной версии (1. 03) GS ROM допукается загрузка одного модуля и/или до 32 сэмплов. Каждый сэмпл при загрузке его в память получает свой уникальный идентификатор, который однозначно определяет обращение к данному сэмплу в командах, которые требу- ют номер сэмпла. Самый первый загруженный сэмпл получает номер (handle) = 1, следу- ющий - номер 2, и т. д. То же самое применимо и к модулям, и этот единственный загруженный модуль бу- дет иметь handle=1 после загрузки. Особенностью данной версии является так- же то, что вначале требуется загружать модуль, а затем уже сэмплы. Особенности описания команд: Команды описываются следующим образом: 1. Hex код команды 2. Название команды 3. Десятичный код команды 4. Выполняемые действия при исполнении команды 5. Формат команды 6. Комментарии к команде Формат команды описывается следующим образом: GSCOM EQU 187 GSDAT EQU 179 SC #NN : Послать код команды в регистр команд LD A, #NN OUT (GSCOM), A WC : Ожидание сброса Command bit WCLP IN A, (GSCOM) RRCA JR C, WCLP SD Data : Послать данные в регистр данных LD A, Data OUT (GSDAT), A WD : Ожидание сброса Data bit, по сути, ожидание, пока GS не примет посланные ему данные WDLP IN A, (GSCOM) RLCA JR C, WDLP GD Data : Принять данные из регистра данных IN A, (GSDAT) WN : Ожидание установки Data bit, по сути, ожидание очередных данных от GS WNLP IN A, (GSCOM) RLCA JR NC, WNLP Команды GS: #00 Reset flags ( 0) Сбрасывает флаги Data bit и Command bit. SC #00 WC (Data bit=0, Command bit=0) #0E Go in Covox mode ( 14) Переходит в режим Ковокс, напрямую копирует регистр данных в ЦАПы двух (правого и левого) каналов. Выход из этого режима- запись #00 в регистр команд. SC #0E WC SD \ SD \ .. / Это вывод в ЦАПы SD / SC #00 WC #F3 Warm restart (243) Сбрасывает полностью GS,но пропускает этапы определения количества страниц памяти и их провеки, что очень сильно ускоряет процесс инициализации. SC #F3 WC #F4 Cold restart (244) Полный перезапуск GS со всеми провер- ками. По сути, JP #0 SC #F4 WC #F5 Busy on (245) Устанавливает флаг занятости в #FF SC #F5 WC #F6 Busy off (246) Устанавливает флаг занятости в #00 SC #F6 WC Изначально Busy=#00. Исполнение всех команд в GS выполня- ется в главном цикле командного ин- терпретатора. Этот цикл в условном виде можно представить так: 1. if Command bit=0 then goto 1 2. Execute Command 3. if Command bit=1 then goto 2 4. if Playing=0 then go to 1 5. if Busy=#ff then go to 1 6. Process Sound 7. go to 1 Используя команды Busy можно, например инициировать проигрывание сэмплов во всех каналах, потом, скажем, изменить парамет- ры проигрывания в каналах, а потом запус- тить это все одновременно. Если же их не использовать, то возможна такая ситуация: инициируется первый сэмпл, станет проигрываться, а только по- том инициируется второй сэмпл, и т.д. #20 Get total RAM ( 32) Получить общий объем доступной памяти на GS. ( В базовой версии это 112к) SC #20 WC GD RAM. L(Младшая часть) WN GD RAM. M(Средняя часть) WN GD RAM. H(Старшая часть) Total RAM=65536*RAM. H+256*RAM. M+RAM. L #21 Get free RAM ( 33) Получить общий объем свободной памяти на GS. SC #20 WC GD RAM. L(Младшая часть) WN GD RAM. M(Средняя часть) WN GD RAM. H(Старшая часть) Free RAM=65536*RAM. H+256*RAM. M+RAM. L #23 Get number of RAM Pages ( 35) Получить число страниц на GS. SC #23 WC GD Number_RAM_Pages В базовой версии 3 страницы. #2A Set Module Master Volume Установить громкость проигрывания модулей. SD Module_Master_Volume [#00.. #40] SC #2A WC [GD Old_Master_Volume] - Старая громк. #2B Set FX Master Volume Установить громкость проигрывания эффектов. SD FX_Master_Volume [#00.. #40] SC #2B WC [GD Old_FX_Volume] - Старая громкость #2E Set Current FX Установить текущий эффект. Просто присваивает переменной CURFX это зна- чение. Если какая-либо команда требу- ет номер сэмпла (sample handle), то можно вместо этого номера подать ей #00 и интерпретатор подставит вместо этого нуля значение переменной CURFX. SD Cur_FX SC #2E WC #30 Load Module Загрузка модуля в память. SC #30 WC [GD Module_Handle]-номер модуля (Command bit=0, Data bit=0) SC #D1 (Open Stream-открыть поток) WC SD \ WD \ . Байты модуля SD / WD / SC #D2 (Close Stream-закрыть поток) WC #31 Play module Проигрывание модуля. SD Module_Handle - номер модуля SC #31 WC #32 Stop module Остановить проигрывание модуля. SC #32 WC #33 Continue module Продолжить проигрывание модуля после остановки. SC #33 WC #35 Set module Global Volume Установить глобальную громкость моду- ля. SD Module_Global_Volume [#00.. #40] SC #35 WC [GD Old_Global_Volume] - Старая громк. #38 Load FX Загрузка сэмпла эффекта в память. Загружает беззнаковые сэмплы (PC type) SC #38 WC [GD FX_Handle]-номер сэмпла (Command bit=0, Data bit=0) SC #D1 (Open Stream-открыть поток) WC SD \ WD \ .. Байты сэмпла SD / WD / SC #D2 (Close Stream-закрыть поток) WC При загрузке каждого сэмпла, в памяти GS создается для этого сэмпла заго- ловок,в котором описываются различные параметры сэмпла. После загрузки эти параметры устанавливаются в опреде- ленные значения, как то: Note=60, Volume=#40, FineTune=0, SeekFirst=#0F, SeekLast=#0F, Priority=#80, No Loop и внутренняя переменная CurFX уста- навливается равной FX_Handle. Затем командами #40,#41,#42,#45,#46 и #47 можно эти значения по умолчанию сменить на свои. Это требуется пото- му что команда #39 для инициации проигрывания сэмпла использует зна- чения параметров из заголовка сэмпла. #39 Play FX Проигрывание эффекта. SD FX_Handle - номер сэмпла SC #39 WC При исполнении этой команды происхо- дит следующее: смотрятся каналы, ука- занные в SeekFirst параметре нашего сэмпла, и если хотя-бы один из них свободен, в нем и проигрывается сэмпл, в противном случае смотрятся каналы, указанные в SeekLast и если один из них свободен, в нем и играет- ся сэмпл, если свободных нет, то просматриваются все каналы, указанные SeekLast, из них выбирается канал с наименьшим приоритетом и сравнивается с приоритетом нашего сэмпла, (имеется в виду сэмпл, который мы хотим проиг- рать) если у этого сэмпла будет боль- ший приоритет, чем у сэмпла, уже иг- рающего в канале, то играющий в кана- ле сэмпл будет остановлен, а наш сэмпл будет запущен в этом канале вместо старого сэмпла. Вот такая вот приоритетная схема. Когда сэмпл запускается в канале, то его нота, громкость и т. п. параметры записываются в область данных канала из заголовка сэмпла. В общем случае, что-бы проиграть сэмпл с нужными параметрами, вы може- те установить эти параметры после загрузки сэмпла и смело использовать команду #39. Если же параметры должны меняться, то можно поступать следующим образом: командой #2E сделать текущим требуе- мый сэмпл, командами #4x изменить его параметры, а затем уже запускать его командой #39. Альтернативный метод запуска сэмплов предоставляют команды #80.. #9F, при исполнении этих команд вы прямо в ко- де команды указываете, в каком канале требуется запустить сэмпл, и кроме этого, вы можете также указать с ка- кой нотой и/или громкостью требуется запустить сэмпл. #3A Stop FX in channels oстановка проигрывания эффектов в за- данных каналах, которые указываются в маске каналов (Channel Mask). В ней единица в n-ном бите указывает на то, что эффект в n-ном канале тре- буется остановить SD Channel_Mask SC #3A WC #3D Set FX Global Volume Установить глобальную громкость эффе- ктов. SD FX_Global_Volume [#00.. #40] SC #3d WC [GD Old_Global_Volume] - Старая громк. #3E Load FX (Extended version) Загрузка сэмпла эффекта в память. Позволяет загружать сэмплы со знаком. (Amiga type) SD #01 (Signed sample) SC #3E WC [GD FX_Handle]-номер сэмпла (Command bit=0, Data bit=0) SC #D1 (Open Stream-открыть поток) WC SD \ WD \ .. Байты сэмпла SD / WD / SC #D2 (Close Stream-закрыть поток) WC #40 Set FX Sample Playing Note Установка ноты по умолчанию для текущего эффекта. SD Note [0.. 95] SC #40 WC Note: 0 C-0 1 C#0 12 C-1 24 C-2 36 C-3 (C-1 в Амиге) 48 C-4 (C-2 в Амиге) 60 C-5 (C-3 в Амиге) 72 C-6 84 C-7 В данной версии Sound Generators Wave 2, 3 могут воспроизвести октавы 3, 4 и 5, поэтому допустимым значением параметра Note является диапазон от 36 до 71. #41 Set FX Sample Volume Установка громкости по умолчанию для текущего эффекта. SD FX_Volume [#00.. #40] SC #41 WC #42 Set FX Sample Finetune Установка Finetune для текущего эффекта. SD FX_Finetune [#00.. #40] SC #42 WC #45 Set FX Sample Priority Установка приоритета для текущего эффекта. SD FX_Priority [#01.. #fe] SC #45 WC #46 Set FX Sample Seek First parameter Установка параметра Seek First для текущего эффекта. SD FX_SeekFirst SC #46 WC #47 Set FX Sample Seek Last parameter Установка параметра Seek Last для текущего эффекта. SD FX_SeekLast SC #47 WC #60 Get Song Position Получение значения переменной Song_Position в текущем модуле. SC #60 WC GD Song_Position [#00.. #FF] Можно интерпретировать как количество проигранных паттернов модуля. После старта модуля принимает значение 0 и увеличивается на единицу после проиг- рывания очередного паттерна. Эта переменная может использоваться для синхронизирования процессов в Спектруме с проигрыванием модуля. Для этого можно, например, в начале про- цедуры обработки прерывания сделать SC #60, затем выполнить процедуры различных операций с экраном, скрул- линга строчек и т.п. (т.е. чтобы была достаточная для выполнения команды задержка), а затем прочитать значение порта 179 ( GD Song_Position), и сравнить его с требуемым и, в случае равенства, перейти на следующую часть демы, т.е. if (Song_Position==My_Po- sition) then goto Next_Part_Of_Demo #61 Get Pattern Position Получение значения переменной Pattern_Position в текущем модуле. SC #61 WC GD Pattern_Position [#00.. #3F] Получить значение смещения в паттерне ( текущий ROW ), использование анало- гично предыдущей команде, однако тре- буется заметить, что эта величина из- меняется довольно быстро, и поэтому if (Pattern_Position>=My_Position) then goto Next_Part_Of_Demo #62 Get Mixed Position Получить значение Pattern_Position, немного смешанной с Song_Position. SC #62 WC GD Mixed_Position Mixed_Position: (по битам) 7 - Song_Position. 1 6 - Song_Position. 0 5 - Pattern_Position. 5 4 - Pattern_Position. 4 3 - Pattern_Position. 3 2 - Pattern_Position. 2 1 - Pattern_Position. 1 0 - Pattern_Position. 0 т.е. если получить Mixed_Position и сделать с ним AND #3F то получится вылитый Pattern_Position, а если пос- ле получения его немного RLCA, RLCA, AND #02 - то это будут младшие два бита Song_Position. См. примечания к командам #60 и #61. #63 Get Channel Notes Получить ноты всех каналов модуля. SC #63 WC GD Note_of_channel_0 WN GD Note_of_channel_1 WN GD Note_of_channel_2 WN GD Note_of_channel_3 Если в каком-либо канале значение но- ты изменилось с последнего исполнения команды #63 то бит 7 полученного за- начения Note_of_channel_N будет в ну- ле, если же это значение то же самое, что и было раньше, то этот бит будет в единице. Младшие семь битов и есть собственно нота от 0 до 95; если это значение равно 127, то это означает, что никакие сэмплы в канале не игра- ют. Данная команда предназначена в основ- ном для построения на ее основе раз- личных анализаторов. #64 Get Channel Volumes Получить громкости всех каналов модуля. SC #64 WC GD Volume_of_channel_0 WN GD Volume_of_channel_1 WN GD Volume_of_channel_2 WN GD Volume_of_channel_3 См. описание команды #63 #80 Direct Play FX Sample (#80.. #83) Проигрывание сэмпла в заданном кана- ле. SD Sample_Number SC #80.. #83 (Младшие биты определяют непосредственно номер канала, в котором требу ется играть сэмпл) WC #88 Direct Play FX Sample (#88.. #8B) Проигрывание сэмпла в заданном кана- ле с заданной нотой. SD Sample_Number SC #88.. #8B (Младшие биты определяют непосредственно номер канала, в котором требу ется играть сэмпл) WC SD Note [0.. 95] WD #90 Direct Play FX Sample (#90.. #93) Проигрывание сэмпла в заданном кана- ле с заданной громкостью. SD Sample_Number SC #90.. #93 (Младшие биты определяют непосредственно номер канала, в котором требу ется играть сэмпл) WC SD Volume [#00.. #40] WD #98 Direct Play FX Sample (#98.. #9B) Проигрывание сэмпла в заданном кана- ле с заданной нотой и громкостью. SD Sample_Number SC #88.. #8B (Младшие биты определяют непосредственно номер канала, в котором требу- ется играть сэмпл) WC SD Note [0.. 95] WD SD Volume [#00.. #40] WD 5. Немного лирики. Авторы GS : ( 2 штуки ;) - Слава Dangerous - (X-Trade) Ему принадлежит идея создания GS'a, ап- паратная реализация оного, некоторые по- желания относительно Soft'а GS'а, а также Amiga 1200, на которой мною производились всяческие эксперименты. Он- единстенный и неповторимый производитель General So- und'а и именно он заведует производством и продажей GS. - Stinger - Это я, автор сего опуса и по-совмести- тельству душа и сердце General Sound'а. Я являюсь разработчиком всего встроенного Soft'a в GS'е и предполагаю и дальше за- ниматься сим действом. (Да, я также явля- юсь автором некоторых хитрых наворотов в аппаратной части GS'а, и был бы автором еще многих, если бы не был все время сдерживаем Славой, постоянно озабоченным проблемами понижения цены. ) Написав около 20 кб кода за пол-года, призанаться, я немного устал, но имею до- вольно большие планы относительно следую- щих версий GS'a, как-то: - Wave 4 Sound Generators воспроизводя- щих все октавы. - Ускорение за счет оных процентов на 30-40 генерации звука. - Очень хотелось бы проигрывание STM'ов от PC. - Развитая система команд. - Различные спецэффекты над сэмплами - Хранение паттернов в закомпрессован- ном виде ( остается около 15% от из- начального обьема). - И многое другое Все программное обеспечение должно рабо- тать и на последующих версиях прошивки, если оно написано в соответствии с моими вышеизложенными пожеланиями и требования- ми. Кроме описанных команд в GS'e сущест- вует еще большое количество команд, кото- рые не документированы, и я оставляю за собой право изменять их каким-угодно об- разом и только относительно документиро- ваных команд приемлю законные претензии типа: "В документации написано так, а в прошивке это работает по другому. " Я планирую значительное расширение сис- темы команд, и буду рад конструктивным (желательно конкретным) предложениям. Так что, если вы озвучиваете игрушку или пишете музыкальный редактор для GS и об- наруживаете, что вам очень не хватает ка- кой-либо команды, то звоните мне и выска- зывайте предложения. (Телефон, я думаю, особого труда узнать не составит ;) Sanx 4 moral support: Дима (X-Trade) SParker (XLD) _________________________________________