Из журнала Adventurer #8, Рыбинск, 20.08.98  Иван Рощин, Москва, 1998 ART STUDIO и принцип открытой архитектуры Есть такая версия графического ре- дактора ART STUDIO ( v2.01c , corrected by ROM/SM and FUX/SM ), которая может проигрывать музыку во время работы. Т. е. на диске записан сам редактор и сразу же за ним - файл "artmusic" , содержащий откомпилированную музыку в формате PRO TRACKER или SOUND TRACKER PRO . При за- пуске редактора этот файл загружается в свободный банк ОЗУ (1 или 6), и в процес- се работы происходит вызов player 'а по прерываниям. (Оказалось, что имя этого файла не имеет значения, лишь бы он был записан непосредственно за редактором, т. е. файлом "ART " .) Раньше я пользовался другими версия- ми ART STUDIO , у которых были свои не- достатки: то стрелка исчезнет непонятно куда, то на экране появятся цветные поло- сы и все зависнет... Так что с появлением новой версии я перешел на нее. Но и тут меня поджидали неприятные особенности (в общем-то, известные всем пользователям ART STUDIO ) - включение белого border 'а в режимах Magnify , Font editor и Scrapbook . Надо было что-то с этим де- лать, и я решил немного изменить player в файле с музыкой. Редактор устанавливал белый border , а вызываемый по прерыва- ниям player , помимо основной своей задачи, устанавливал нужный мне цвет. Довольно долго я работал с такой версией ART STUDIO , пока не возникла другая проблема: нужно было нарисовать некоторое изображение по известным коор- динатам его точек. Как, например, отме- тить на рисунке точку с координатами X=45, Y=83? Вот если бы на экране пос- тоянно отображались текущие координаты курсора... И тут я подумал: а что если написать модуль с таким же стартовым адресом (#C000), такими же точками входа (INIT = #C000, PLAY = #C006), как и у откомпили- рованной музыки, а потом "подсунуть" его редактору, записав вместо файла "artmusic" . А этот модуль, в свою оче- редь, каждый раз, когда к нему произво- дится обращение, будет выводить на экран координаты курсора. Модуль (известный под именем art_xy) был написан и успешно выводил координа- ты (а кроме того, следил за border 'ом и устанавливал нужные мне начальные значе- ния атрибутов). В конце этой статьи при- веден исходный текст его главной части, который пригодится вам при разработке собственных модулей. Что же мы видим? Оказывается, любую отсутствующую в ART STUDIO возможность нетрудно реализовать самому, написав для этого специальный модуль. А если написано несколько модулей, то можно загружать их по очереди, не выходя из редактора (для этого, естественно, в каждом модуле долж- на быть предусмотрена команда - загрузить другой модуль и передать ему управле- ние). +================+ +================+ -+ ОЗУ |- | ###### ДИСК = | -++--------------+|- | ###### ====== ++ -+| ||- | +--------+ ++ -+| ART STUDIO ||- | |модуль 1| | -+| ||- | +--------+ | -+| +----------+ ||- | ... | -+| |+--------+| ||- | +--------+ | -+| ||модуль 1|| ||- | |модуль n| | -++-++--------++-+|- | +--------+ | +================+ +================+ Создать свой модуль, без сомнения, намного легче, чем написать новый графи- ческий редактор "с нуля". Различные моду- ли могут быть написаны разными людьми, независимо друг от друга. А в этом и зак- лючается принцип ОТКРЫТОЙ АРХИТЕКТУРЫ. Наверняка James Hutchby , автор ART STUDIO , и не предполагал о таких возмож- ностях своего редактора. Какие функции могут содержаться в дополнительном модуле? Например, быстрый просмотр записанных на диске картинок без загрузки их в редактор, сохранение и восстановление конфигурации, использова- ние дополнительной памяти (>128K) в ка- честве RAM - диска, выполнение различных преобразований над отмеченным окном, ну и конечно, музыка и screen saver . Все это вполне уместится в 16 килобайт. В "ZX-FORMAT #7" можно прочесть о проекте "STATE OF THE ART" группы "AVALON" . Как там написано, это новый графический редактор с необыкновенными возможностями, сочетающий достоинства лучших редакторов на SPECTRUM , PC и AMIGA . Хотелось бы, чтобы и там исполь- зовался модульный принцип построения, с подробным описанием интерфейса между мо- дулем и редактором, чтобы каждый пользо- ватель мог сам реализовать нужную ему функцию. Это дает практически неограни- ченное расширение возможностей редакто- ра. -------------- Теперь я более подробно расскажу о том, как написать собственный модуль для ART STUDIO . Начну с известных мне адре- сов, по которым находятся переменные ре- дактора: INK - 52186 (0-7, 8-transp.) PAPER - 52187 (0-7, 8-transp.) BORDER - 52188 (0-7) BRIGHT - 52189 (0-off, 1-on, 2-transp.) FLASH - 52190 (0-off, 1-on, 2-transp.) Абсолютные координаты курсора (X - 56035, Y - 56036) дублируются по адресам 64977 и 64978 соответственно. Начало координат расположено в левом верхнем уг- лу экрана. Так как эти переменные находятся в 0 банке памяти, а модуль загружается в 1 или 6 банк, доступ к ним осуществляется с помощью специальных функций - см. лис- тинг. Во время первых 50 обращений к моду- лю (т. е. 1 секунда реального времени после запуска редактора) происходит рас- паковка редактора и инициализация пере- менных. Если в модуле предусмотрено изме- нение задаваемых по умолчанию атрибутов ( INK , PAPER , BORDER ) на другие - эти атрибуты нужно устанавливать заново при каждом из первых 50 обращений. Объяснение тут такое: очевидно, при запуске редакто- ра выполняются команды следующего вида: LD A,0 LD (52186),A ;INK LD A,7 LD (52187),A ;PAPER LD A,7 LD (52188),A ;BORDER ... ;происходит прерывание, вызывает- ;с модуль, который устанавливает ;нужные INK , PAPER , BORDER CALL CLS ;очистка экрана ;в соотв. с атрибутами Видно, что установка нужных атрибу- тов должна произойти после того, как ре- дактор установит их значения, но до того, как редактор выполнит очистку экрана. А так как неизвестно, какое по счету преры- вание будет соответствовать этому момен- ту, приходитря выполнять установку атри- бутов 50 раз. Кстати, если при запуске редактора нужно изменить заданные по умолчанию зна- чения атрибутов на "transparent" , это лучше сделать после первых 50 вызовов мо- дуля - иначе во время очистки экрана ат- рибуты знакомест установятся случайным образом. Исходный текст главной части модуля "art_xy" ----------------------------- ORG #C000 JP INIT ;#C000 - INIT DS 3 JP PLAY ;#C006 - PLAY RET ;#C009 - STOP ;Значения INK,PAPER,BORDER: COLORS DB 7,0,0 ;--------------------------------------- ;Процедура INIT - выполняется перед ;началом работы редактора. INIT DI ;Сохраняем память под резидентом: CALL SAVE_M ;Переносим резидент N3 и запускаем его. ;В ячейке BANK получаем номер банка, ;куда загружен art_xy: LD HL,RES3_B CALL LOAD_R CALL #6000 ;Восстанавливаем ранее сохраненный ;участок памяти под резидентом: CALL LOAD_M ;Вывод сообщения "загружен модуль... " ;и ожидание нажатия клавиши: CALL #D000 INIT1 XOR A IN A,(254) CPL AND 31 JR Z,INIT1 EI RET ;--------------------------------------- ;Процедура PLAY - выполняется каждые ;1/50 секунды. PLAY DI CALL SAVE_M ... CALL LOAD_M EI RET ;--------------------------------------- ;Процедура LOAD_M сохраняет в буфере ;участок памяти под резидентом ;(адрес начала - #6000, длина участка - ;длина самого длинного резидента, в ;данном модуле это резидент N3). LOAD_M LD HL,RES_BUF LOAD_R LD DE,#6000 LD BC,RES3_E-RES3_B LDIR RET ;--------------------------------------- ;Процедура SAVE_M восстанавливает ранее ;запомненный (с помощью LOAD_M) участок ;памяти. SAVE_M LD HL,#6000 LD DE,RES_BUF LD BC,RES3_E-RES3_B LDIR RET ;--------------------------------------- ;Процедура GET_MEM - аналог команды ;LD A,(DE). Нужна для доступа к 0 банку ;памяти. GET_MEM PUSH HL PUSH BC PUSH DE LD HL,RES1_B CALL LOAD_R POP DE CALL #6000 POP BC POP HL RET ;--------------------------------------- ;Процедура TO_MEM - аналог команды ;LD (DE),A. Нужна для доступа к 0 банку ;памяти. TO_MEM PUSH HL PUSH BC PUSH DE LD HL,RES2_B CALL LOAD_R POP DE CALL #6000 POP BC POP HL RET ;--------------------------------------- ;Резидент N1 - LD A,(DE): RES1_B LD BC,#7FFD LD HL,(BANK) OUT (C),H LD A,(DE) OUT (C),L RET RES1_E ;--------------------------------------- ;Резидент N2 - LD (DE),A: RES2_B LD BC,#7FFD LD HL,(BANK) OUT (C),H LD (DE),A OUT (C),L RET RES2_E ;-------------------------------------- ;Резидент N3 определяет, в какой банк ;(1 или 6) загружен модуль art_xy. ;Запоминает это значение в переменной ;BANK. RES3_B LD BC,#7FFD LD A,#11 OUT (C),A LD A,(PRIZN) CP "+" LD A,#11 JR Z,RES3_1 LD A,#16 RES3_1 OUT (C),A LD (BANK),A RET RES3_E ;--------------------------------------- ;Буфер дл запоминания участка памяти ;под резидентом: RES_BUF DS RES3_E-RES3_B PRIZN DB "+" BANK DW #1000