(C) Иван Рощин, Москва, 1998
ART STUDIO
и принцип открытой архитектуры
Есть такая версия графического ре-
дактора ART STUDIO ( v2.01c , corrected
by ROM/SM and FUX/SM ), которая может
проигрывать музыку во время работы. Т.
е. на диске записан сам редактор и сразу
же за ним - файл "artmusic" , содержащий
откомпилированную музыку в формате PRO
TRACKER или SOUND TRACKER PRO . При за-
пуске редактора этот файл загружается в
свободный банк ОЗУ (1 или 6), и в процес-
се работы происходит вызов player 'а по
прерываниям. (Оказалось, что имя этого
файла не имеет значения, лишь бы он был
записан непосредственно за редактором,
т. е. файлом "ART <B>" .)
Раньше я пользовался другими версия-
ми 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