Введение

Язык программирования GRASS (GRAphics Symbiosis System) — это язык программирования, созданный для создания скриптов 2D векторной графической анимации. Синтаксис GRASS был схож с BASIC, но он включал множество инструкций для задания анимации 2D-объектов, в том числе масштабирование, перемещение и вращение во времени. Эти функции напрямую поддерживались графическим терминалом Vector General 3D, для которого и был разработан GRASS. Он быстро завоевал популярность в художественном сообществе, экспериментировавшем с новым средством компьютерной графики, и наиболее известен тем, что Ларри Куба использовал его для создания оригинальной анимации "атака на Звезду Смерти будет нелегкой" в фильме "Звёздные войны" (1977). В рамках последующего сотрудничества с Midway Games язык был портирован на Z Box от Midway, основанный на процессоре Z80. Эта машина использовала растровую графику и спрайты, что потребовало значительных изменений для поддержки, а также анимации изменения цвета. Эта версия получила название ZGRASS.

ТРАС

Оригинальная версия GRASS была разработана Томом ДеФанти для его докторской диссертации в 1974 году в Университете штата Огайо. Она была разработана на PDP 11/45, управляющем дисплеем Vector General 3DR. Как следует из названия, это была чисто векторная графическая машина. GRASS включал в себя ряд команд векторного рисования и мог организовывать их коллекции в иерархию, применяя различные эффекты анимации к целым "деревьям" изображения сразу (хранящиеся в массивах). После окончания университета ДеФанти переехал в Университет Иллинойса в Чикаго. Там он присоединился к Дэну Сандину, и вместе они создали Circle Graphics Habitat (сегодня известную как Лаборатория электронной визуализации, или EVL). Сандин присоединился к университету в 1971 году и создал Sandin Image Processor, или IP. IP был аналоговым компьютером, который принимал два видеовхода, смешивал их, раскрашивал результаты и затем воссоздавал ТВ-выход. Он описал его как видеоверсию синтезатора Moog. ДеФанти подключил существующую систему GRASS в качестве входных данных для IP, создав GRASS/Image Processor, который использовался на протяжении середины 1970-х годов. Чтобы сделать систему более полезной, ДеФанти и Сандин добавили всевозможные "разовые" команды к существующей системе GRASS, но эти изменения также сделали язык значительно более своеобразным. В 1977 году другой член Habitat, Нола Донато, переработал многие контрольные структуры GRASS, приведя их к более общим формам, в результате чего появился значительно более чистый GRASS3. Работа Ларри Кубы над фильмом "Звездные войны" основана на полуавтоматизированной съемке системы GRASS, работающей на 3D-терминале Vector General. VG3D имел внутреннее аппаратное обеспечение, которое выполняло базовые преобразования – масштабирование, вращение и т.д. – в реальном времени, не взаимодействуя с компьютером. Только во время представления новых сцен происходит гораздо более медленная связь с языком GRASS. Это можно увидеть в последовательности: в начальных сценах фильма Звезда Смерти вращается и масштабируется очень быстро, в то время как в более поздних сценах, имитирующих полет вниз по траншее, требуется загружать новые сцены из "деревьев" GRASS. Их можно увидеть появляющимися группами.

ZGRASS и UV-1

В 1977 году ДеФанти познакомился с Джеффом Фредериксеном, разработчиком микросхем, работавшим в Dave Nutting Associates. Nutting получил контракт от Midway, игрового подразделения Bally, на создание стандартизированной микросхемы графического драйвера. Они планировали использовать её в большинстве своих будущих аркадных игр, а также в разрабатываемой ими видеоигровой консоли, которая впоследствии стала Astrocade. Midway проявляла большой интерес к запуску языка GRASS на своей системе и заключила с ДеФанти контракт на его портирование на эту платформу. Над проектом, который они называли Z Box, работали несколько сотрудников Habitat, а также специалисты из Nutting. GRASS3, работающий на Z Box, получил название ZGRASS. Z Box представлял собой растровую графическую машину, в отличие от оригинальных систем GRASS, поэтому, хотя в ZGRASS был сохранен основной стиль GRASS3, в него были добавлены команды, предназначенные для работы с растровыми изображениями. Среди них был обширный набор команд передачи блоками бит для имитации спрайтов, которых не было в аппаратной части. Midway так и не выпустила эту разработку, но Circle использовала её в качестве основы для создания машин Datamax UV 1.

ГРАСС RT/1

Последняя версия GRASS была RT/1 – это порт GRASS на другие платформы, который отделил язык программирования от модели отображения и обеспечил возможность переноса на другие платформы. Версии существовали для MS DOS, Microsoft Windows, платформы SGI с использованием OpenGL, HP UX, AIX, Macintosh и Amiga. Язык остался схожим с более ранними версиями, поэтому причина смены названия остаётся неясной.

Описание

Это описание основано на оригинальных руководствах Bally, а также на описании ACM. Zgrass был основан на стандартном наборе команд BASIC и использовал большую часть его синтаксиса. Отличием Zgrass от BASIC было то, что все команды фактически были функциями и возвращали значения, подобно языку программирования C. Если явного возвращаемого значения не было, ожидалось, что функция вернет 1 в случае успеха и 0 в случае неудачи. Например, команда PRINT PRINT 10 была бы недопустима в BASIC, но в Zgrass она вывела бы 10 1, где 1 – это значение, возвращенное второй командой PRINT, означающее "Я успешно вывела строку '10'". Программы в Zgrass назывались "макросами" и хранились в виде строк. Обе эти особенности были намеренными, поскольку Zgrass позволял любой строке стать программой. Например, MYBOX="BOX 0,0,100,100,2" определяет строку (не требуется символ $ у переменной, как в Microsoft BASIC), содержащую фрагмент кода Zgrass. Просто набрав ее, можно было запустить команды внутри. Эта функция может использоваться вместо более традиционной команды GOSUB из BASIC, но имеет дополнительное преимущество в виде четко определенного имени, в отличие от непрозрачного номера строки. Кроме того, команда остается в форме строки в памяти и может быть обработана во время выполнения стандартными строковыми операциями. Большинство интерпретаторов BASIC того времени преобразовывали входной текст в токенизированную версию, в которой каждая команда заменялась одним числом (обычно длиной в один байт). Это ускоряло выполнение программы, поскольку не требовалось постоянно декодировать команды из строк. Использование строковых макросов в Zgrass затрудняло это, поэтому токенизация не применялась. Вместо этого был включен компилятор, который можно было использовать для любого конкретного макроса, значительно ускоряя его выполнение. Программы часто состояли из смеси скомпилированных и нескомпилированных макросов. Номера строк в Zgrass были необязательными и обычно появлялись только на строках, являющихся целью команды GOTO. Большинство интерпретаторов BASIC требовали номера строк для каждой строки кода, что было связано с их использованием в "редакторе строк" – если нужно было отредактировать определенную строку, ссылаться на нее можно было только по номеру. Zgrass использовал более продвинутый полноэкранный редактор, устраняющий эту необходимость. Zgrass позволял любой строке выступать в качестве "номера строки", и оба варианта были допустимы. Zgrass также включал безымянные переходы, используя инструкцию, которая перемещала выполнение вперед или назад на заданное количество строк. Это важно в Zgrass, поскольку номера строк были необязательными, и разные макросы могли использовать одни и те же метки. Например, некоторые вариации, вероятно, будут найдены во многих фрагментах кода, что может привести к конфликту имен. Использование избежало этой возможности. В соответствии с первоначальным назначением как графического языка, Zgrass включал многочисленные команды для простого рисования. Система координат Zgrass имела одну точку для каждого пикселя в режиме высокого разрешения графического чипа Nutting, что давало сетку 320×202. Astrocade, по замыслу, мог использовать только режим низкого разрешения этого чипа, дисплей 160×101. Чтобы избежать потенциальных проблем с отображением, нулевая точка координатного пространства была помещена в центр экрана. −160 до 160 были допустимыми значениями X, а −101 до 101 – допустимыми значениями Y. Для использования на Astrocade использовались только положительные значения, в то время как на UV 1 было доступно все пространство. Zgrass добавил довольно полный набор функций для работы с массивами, поскольку массивы широко используются в графике. Это включало возможность "захвата" частей дисплея в массив в виде растрового изображения, с которым можно было манипулировать как с любым другим графическим элементом. Это позволило Zgrass включить в язык функциональность, подобную спрайтам, что аппаратное обеспечение Nutting не поддерживало напрямую. Еще одной особенностью, отсутствовавшей в Astrocade, была возможность обрабатывать массивы с разумной скоростью, поэтому UV 1 включал FPU, поставляемый Zilog, для повышения производительности. Zgrass включал три уровня приоритета (называемые "уровнями"), которые позволяли запускать макросы в обычном режиме или на уровнях "переднего плана" или "заднего плана". Это добавило простую форму многозадачности, которая была чрезвычайно полезна в языке, ориентированном на анимацию. Авторы игр могли помещать подпрограммы чтения джойстика в макрос, настроенный на выполнение на заднем плане, и тогда джойстик считывался бы автоматически после завершения текущего макроса рисования. Функции, помещенные на передний план, выполнялись раньше, и часто использовались для таймеров и других задач, требующих "низкой задержки". Zgrass включал функцию, которая вызывала макросы через заданные промежутки времени, что упрощало реализацию таймеров. Zgrass также включал серию команд, которые "перекрывали" CP/M, что позволяло получать доступ к диску без выхода в командную строку. Можно было легко сохранить макросы в именованные файлы и загрузить их тем же способом, что позволяло создавать программы путем загрузки различных макросов с диска в одну большую программу. Команды также автоматически создавали резервную копию каждого сохранения. Аналогичные функции поддерживались для хранения на компакт-кассете, но, странно, синтаксис не был параллельным: команды для диска начинались с D, например, , а команды для кассеты не начинались с T, например, , а скорее с TAPE, например, .
С программами, построенными из случайно выбранных модулей, Zgrass нуждался в лучшем контроле над своими переменными, чем BASIC. В BASIC все переменные "глобальные", поэтому, если два подпрограммы используют одну и ту же переменную, которая часто используется в качестве переменной-счетчика цикла, они могут изменять значения друг друга, что приводит к трудноустранимым проблемам. В Zgrass программист, загружающий два модуля, мог легко обнаружить, что оба используют в качестве счетчика цикла, что могло вызвать проблемы. Для решения этой проблемы Zgrass считал переменные, названные строчными буквами, локальными только для этого макроса, поэтому и были разными переменными, глобальной и локальной соответственно. Странно, но примеры, поставляемые с языком, не широко используют эту функцию, что может сбить с толку новых программистов, которые могут не знать о ее существовании.

Пример

Этот текст создает новый макрос под названием SINCURVE, который можно вызвать, просто введя SINCURVE в командную строку или из других макросов или программ. SINCURVE использует две локальные переменные, x и angle, а также глобальную переменную OFFSET. PROMPT/INPUT является модификацией оригинального BASIC INPUT, который не будет запрашивать ввод, если пользователь введет его в командную строку при вызове макроса. В этом случае ввод SINCURVE приведет к появлению запроса и ожиданию ввода, тогда как ввод SINCURVE 30 пропустит запрос, и OFFSET будет автоматически присвоено значение 30. Это позволяет использовать один и тот же макрос как интерактивно, так и внутри программы в качестве функции. POINT – пример одной из многих графических команд, включенных в язык Zgrass. POINT требует указания координат X и Y, а также цвета. В этом примере пользователь задает OFFSET, который смещает x-позицию кривой на экране, а Y-позиция вычисляется тригонометрической функцией, соответствующим образом увеличенной для отображения (в данном случае, в 80 раз). Цвет задается последним значением, и в этом случае это 3. UV 1 использовал цветовые регистры, поэтому 3 не определял конкретный цвет, а цвет, выбранный из текущей палитры. IF также заслуживает внимания. Он помещает инкремент (x=x+1) перед условием, что обычно недоступно в BASIC. В этом случае IF предписывает вызвать SKIP 2, если условие истинно, что переместит курсор назад на две строки и может быть использовано вместо GOTO, поскольку отсутствует целевой номер строки.