Gamedev
Andrey Apanasik
1079

Полигоны Another World: Amiga 500

Эта статья часть серии про порты игры Another World. В ней пойдёт речь про хитрости при работе с Amiga 500. Рекомендуется сначала прочитать предыдущую статью.

В закладки
Аудио

История Amiga начинается в середине 1982 года со звонка Ларри Каплана Джею Майнеру. Оба тогда работали в Atari в 70-х. Оба решили покинуть компанию. Каплан из-за отсутствия признания и Майнер из-за запрета руководства на использование крутого, но дорогого процессора Motorola 68000.

Покинув Атари, Каплан основал Activision. После того, как инвесторы обратились к нему с просьбой разработать новую игровую платформу, он связался с самыми блестящими людьми, которых он знал. Майнер взялся за аппаратную часть вопроса в только что образованной компании «Hi-Toro». Система получила кодовое название «Lorraine».

К концу 1983 прототип был собран. Устройство впечатлило посетителей Consumer Electronics Show (CES) в январе 1984 года, благодаря демке Boing Ball, в которой огромные спрайты перемещались с фреймрейтом 60 кадров в секунду. Устройство анонсировали в 1985 году под именем «Amiga from Commodore», позже переименовав в Amiga 1000.

На заметку: Amiga 1000 не могла загрузиться сама по себе, у устройства не было ПЗУ. Загрузчик был на дискете, и лучше бы вам хранить её как зеницу ока!

Серия статей

A500

К 1985 году, после серии ошибок, Commodore оказался в тревожной ситуации на грани банкротства. Томас Раттиган, тогдашний главный операционный директор, провёл радикальные изменения. Помимо амбициозного плана, охватывающего почти все подразделения компании, он разделил Amiga 1000 на два продукта: новая high-end версия, предназначенная для творческого рынка под названием Amiga 2000 и недорогая версия для Commodore 64 под названием Amiga 500.

Amiga 500, также известная как A500, была выпущена в 1987 году. Под капотом Motorola 68000, работало устройство на 7,16 МГц и имело 512 КБ ОЗУ. Устройство стало чрезвычайно успешным, оно снискало популярность среди игроков, программистов, в частности, людей из демо-сцены. Это был самый продаваемый продукт Commodore (было продано примерно 6 миллионов единиц с 1987 по 1991 год).

В A500 был ПЗУ, но памяти было достаточно лишь на размещение загрузчика под названием Kickstart. После инициализации оборудования Kickstart предлагает пользователю вставить дискету, содержащую либо программу, либо ОС Workbench. Дискета должна была оставаться в приводе, пока машина включена. Более поздние модели, такие как A1200 (a.k.a величайшая из когда-либо созданных машин), имели пространство для 2,5-дюймового жёсткого диска и были избавлены от использования дискет.

Архитектура

Поскольку технология изначально создавались с расчётом на гейминг, Amiga не была построена на «железном» процессоре с возможностью аудио и видео, как большинстве компьютеров того времени. 32/16-битная 68000 работает вместе с чипсетом, на котором размещено три мощных чипа: Paula (аудио), Denise (видео) и Agnus (манипулирование данными и синхронизация).

Подобный дизайн с системой памяти, обеспечивающей не только плоскую адресацию, но и общую оперативную память, доступную как для процессора, так и для чипсета, очень способствовал популярности Amiga среди разработчиков. Для сравнения, ни Sega Genesis, ни Nintendo SNES, две мощные системы, выпущенные спустя годы (соответственно, в январе 1989 г. и ноябре 1990 г.), не имели общей памяти.

Шина чипсета имеет сложную систему приоритетов, в которой 68000 не активен на чётных циклах. DMA (прямой доступ к памяти) чипсета пытается использовать только нечётные циклы для постепенного мультиплексирования доступа к шине без влияния на процессор. Но не всегда всё было гладко. Agnus, в частности, вполне справлялся там, где 68000 голодал.

Для решения этой проблемы клиенты могли приобрести расширение «Fast RAM» с выделенной «шиной ЦП» для 68000. С размещением там инструкций 68000 ЦП не голодал, когда канал DMA блиттера был активен. Это удваивало скорость исполнения 68000.

Видеосистема

Видеосистема полностью управляется Denise, предлагая в общей сложности двадцать графических режимов. Самое популярное разрешение было 320x200 с соотношением сторон 1,6, что не соответствовало мониторам того времени (4/3 = 1,3). Соотношение сторон приводит к искажениям, когда кадровый буфер передается на ЭЛТ монитор.

Фреймбуфер хранится не непрерывно, а в отдельных областях памяти, называемых битовыми плоскостями. Может быть выделено до пяти битовых плоскостей по 8 КБ, что даёт 5 бит на пиксель, позволяя получить 32 цветовых индекса. На первый взгляд этот подход выглядит весьма неуклюжим (особенно для разработчика с опытом работы с ПК), но Agnus и особенно его блиттер в целом обеспечивают большую ясность.

Палитра основана на 4-битном RGB цветовом пространстве на канал. 12-бит на цвет позволяет определить до 4096 различных цветов, что было намного больше, чем обычно на компьютерах той же эпохи.

Многие трюки позволили отобразить больше цветов. Как Copper, позволяющий изменить палитру на HSYNC.

Следующие два изображения представляют две противоположные стороны цветового пространства RGB. С чёрным в координатах (0x0, 0x0, 0x0), красным в (0xF, 0x0, 0x0), зелёным в (0x0, 0xF, 0x0) синим в (0x0, 0x0, 0xF) и белым в (0xF, 0xF) 0xF). Эти красочные изображения хорошо иллюстрируют творческую свободу, предоставленную разработчикам графики.

Another World на Amiga

Another World на Amiga, собственно говоря, не является портом. Поскольку A500 использовался для разработки, это оригинальная версия, созданная в период с 1989 по 1991 год 21-летним Эриком Шайи, работавшим в одиночку в своей спальне.

Две причины сделали Amiga идеальной машиной для разработки. Во-первых, GenLock позволил сделать ротоскопирование. Во-вторых, и что наиболее важно, Amiga Agnus чрезвычайно облегчил рендеринг полигонов.

Блиттер

Идея создать игру, основанную исключительно на полигонах, возникла из-за неправильного предположения о том, что «Dragon's Lair, Escape from Singe's Castle» на Амиге использовала их. Эрику нужно было как-то это реализовать с разумной частотой кадров. Именно на этом этапе исследований и разработок блиттер Амиги сыграл ключевую роль.

Отрисовка полигонов

В документации к блиттеру упоминается функция под названием «Area Fill Mode». Мы не говорим о причудливой трехмёрной проекции или текстурировании. Блиттер работает в экранном пространстве на битовых строках с возможностью «fill the blank». Работа базируется на сканированию слева направо. Пока блиттер видит 0, ничего не происходит. Как только первая 1 пройдена, блиттер заполнит строку единицами до следующей 1. Рисунок из документации хорошо иллюстрирует работу. Обратите внимание, что даже вогнутый многоугольник может быть правильно отображён с помощью этого метода.

Подобное решение приводит ко второй проблеме — как нарисовать «границы» многоугольника. Если вы внимательно посмотрите на рисунок выше, вы увидите, что это нестандартный алгоритм Брезенхэма, поскольку горизонтальные линии должны быть пропущены. К счастью, дизайнер Амиги подарил блиттеру режим «line draw».

Мы ещё не закончили. Есть ещё проблемы. Во-первых, «рисование линий и затем заполнение области» должно быть выполнено четыре раза (один раз для каждой битовой плоскости), что кажется очень дорогостоящим. Во-вторых, движок должен рендерить сотни полигонов. Блиттер нуждается в чистом буфере, полном нулей и хороших границ из единиц для работы. После нескольких полигонов фрейм-буфер наверняка будет похож на суп из битов. Наконец, блиттер выводит только 1-цы, но нам нужна возможность выводить 0 в некоторых из четырёх битовых плоскостей, чтобы генерировать правильный 4-битный цвет.

Решением этих проблем является настройка входов A, B и C блиттера. Этот процесс лучше объяснил Blogger Scali в своём блоге.

… есть решение этой проблемы, и это даже не так сложно. Блиттер может рендерить где угодно в chipmem, поэтому легко установить временный чистый буфер, «scratchpad», и отрисовать в нём многоугольник. Затем вы копируете его в фактическую область экрана, используя бит блит по маске[16]. Часто эту операцию ещё называют «cookie cut». Это, в сущности, та же самая операция, которую вы использовали бы с 2D-изображениями, когда вы записываете пиксели, только когда они установлены в исходном изображении, и оставляете целевые пиксели нетронутыми в противном случае (логическая операция ИЛИ). Это правильно объединит полигоны на экране.

На самом деле, возможно, сейчас самое время объяснить блиттер более подробно. Блиттер имеет 3 входа и 1 выход. Все они обрабатываются DMA, поэтому он может работать полностью независимо от ЦП после настройки. 3 входа могут быть объединены с помощью логических операций. Результат затем записывается в выходной канал. В случае блита по маске вы, в общем-то, выполняете такую операцию:

выход = (маска И растровое изображение) ИЛИ (НЕ маска И вывод)

Scali’s OpenBlog™

С учётом входных данных блиттера, у нас теперь есть полная картина того, что требуется для рендеринга каждого полигона.

  • Выделить кусок буфера.
  • Очистите нулями с помощью блиттера.
  • Отрисовать границы многоугольника единицами в режиме «draw line».
  • Заполнить область буфера единицами в режиме «area fill».
  • Блитнуть кусок буфера четыре раза (один раз для каждой битовой плоскости).

Это было не так весело, но работа сделана. Усилие стоило того, так как программа могла обрабатывать до 50 полигонов (в зависимости от их размера) со скоростью 20 кадров в секунду. Что приводит нас ко второй проблеме.

Копирование фреймбуфера

Как бы быстро блиттер не мог отрисовать полигоны, он всё ещё был недостаточно быстр. Каждый кадр состоит из тысяч полигонов. Некоторые полигоны настолько малы (1x1, называемые пиксигонами), что не оправдывают накладные расходы. Один из первых фонов в игре (когда Лестер выходит из воды) состоит из 981 полигонов.

Решением было кэшировать фон в специальный BKGD буфер с простым копированием. Это было специальным заданием для блиттера.

Блиттер — один из двух сопроцессоров в Amiga. Являясь частью чипа Agnus, он используется для копирования прямоугольных блоков памяти и отрисовки линий. При копировании памяти он примерно в два раза быстрее 68000 и способен перемещать почти четыре мегабайта в секунду. Он может рисовать линии со скоростью почти миллион пикселей в секунду.

Amiga Developer CD v2.1 (OS 3.5)

Со скоростью 4000 байтов в миллисекунды, блиттинг BKGD-буфера в начале каждого нового кадра требует «всего» 8 мс.

На заметку: несмотря на то, что Another World была отполированной игрой, некоторые края остались «шероховатыми». Если игрок попытается проявить смекалку во время викторины по защите от копирования и нажмёт «c», чтобы ввести код для перехода к игровому процессу, экран становится зеленым, и Amiga зависает. Единственный выход – рестарт игры.

Заполнение фреймбуфера

Несмотря на то, что процессор 68000 может записывать 16 бит за раз, очистка фреймбуфера также, вероятно, была выполнена с помощью блиттера. Документация Amiga содержит пример кода «clearmem», который использует блиттер для очистки 128 КБ ОЗУ.

Материал опубликован пользователем.
Нажмите кнопку «Написать», чтобы поделиться мнением или рассказать о своём проекте.

Написать
{ "author_name": "Andrey Apanasik", "author_type": "self", "tags": ["\u0440\u0435\u0432\u0435\u0440\u0441\u0438\u043d\u0436\u0438\u043d\u0438\u0440\u0438\u043d\u0433","\u043f\u0430\u043b\u0438\u0442\u0440\u0430","outofthisworld","anotherworld","amiga500","amiga"], "comments": 21, "likes": 44, "favorites": 74, "is_advertisement": false, "subsite_label": "gamedev", "id": 91795, "is_wide": false, "is_ugc": true, "date": "Wed, 08 Jan 2020 01:50:50 +0300", "is_special": false }
0
{ "id": 91795, "author_id": 1922, "diff_limit": 1000, "urls": {"diff":"\/comments\/91795\/get","add":"\/comments\/91795\/add","edit":"\/comments\/edit","remove":"\/admin\/comments\/remove","pin":"\/admin\/comments\/pin","get4edit":"\/comments\/get4edit","complain":"\/comments\/complain","load_more":"\/comments\/loading\/91795"}, "attach_limit": 2, "max_comment_text_length": 5000, "subsite_id": 64954, "last_count_and_date": null }
21 комментарий
Популярные
По порядку
Написать комментарий...
5

сверхнизкоуровневая статья, приятная для чтения разве только для asm-программистов, но круто по-любому, автор, переводи еще, интересно знакомиться с созданием ключевых игр индустрии (помню рассказы про нее своих друзей, а потом и опыт игры, это незабываемо, отпечаток в памяти на всю жизнь)

Ответить
3

Что-то очень много времени перевод подобных статей отнимают, учитывая, что я на таком низком уровне с аппаратурой не особо много работал. А девятого уже на работу в офис.

Так что следующую статью из этой серии смогу не раньше выходных начать переводить (。•́︿•̀。)

Ответить
1

Ничего, мы подождем, главное запили)

Ответить
3

Эх, ностальжи... в годы юеости, в 92м, стал счастливым обладателем А600 с последующим апгрейдом до А1200 + Фастрам + хардварный сэмплер для 4-хканального трекера OctaMed.

Но тогда я, в основном, игрался в Cannon Fodder, Flashback, Walker, Settlers и Elite Frontier и попиксельно рисовал мышкой фан-арт. :)

Ответить
0

Бро, ты случайно не в Соединенном Королевстве жил с «таким» Амига®™️ набором) Не припомню, что бы на «Пост-Советском» пространстве такое было)  

А что за семплер такой аппаратный? Это что то типа «внешней звуковухи»? Не думаю, что это какой нить профессиональный классический семплер тех лет, типа AKAI S3000, подключённый к Амиге через MIDI адаптер? Такое только ведь с Atari ST было возможно (вся современная музыкальная «софтвара» ведь оттуда)! 

Ответить
0

У нас был атари такой, ещё наверное с 80-х, до переезда в РФ жили в Германии (восточной). Видимо туда как-то протекали западные вещи.

Ответить
2

Самое популярное разрешение было 320x200 с соотношением сторон 1,6, что не соответствовало мониторам того времени (4/3 = 1,3).

На самом деле на PC была та же фигня, так что - норм. :)

Ответить
0

Удивительно, учитывая, что PC тоже использовали "мониторы того времени".

Ответить
0

И как это связано? NES выводила картинку на такие же 4:3 телевизоры, но внутреннее разрешение имела 256:240 (PAL) или 256:224 (NTSC).

Ответить
0

Как связаны PC и мониторы? Обычно, кабелем.

Ответить
0

Пойдука я. Это уже какая-то недостижимая гениальность уровня Кодзимы. Не меньше.

Ответить
1

Ой спасибо , напомнили эти игры

Ответить
0

Статья из разряда "Ничего не понял, но очень интересно". А кто-то может объяснить не разбирающемуся человеку, почему на скринах я вижу 2D-графику, но в самой статье речь о полигонах?

Ответить
2

Игра рисует изображение не на основе спрайтов, пиксельных картинок, а на основе многоугольников описанных вершинами которые залиты цветом - каждый персонаж, камень или земля это набор таких многоугольников - полигонов. В первой статье вроде описано это.

Ответить
0

Все мы в этом мире лишь полигоны.

Ответить
1

Мы скорее воксели 🧐

Ответить
0

Как картинки делали из кусочков цветной бумаги, каждый кусочек это полигон:

Ответить
0

Полигон - многоугольник.

Ответить
0

Благодарю, теперь дошло

Ответить

Прямой эфир

[ { "id": 1, "label": "100%×150_Branding_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox_method": "createAdaptive", "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "ezfl" } } }, { "id": 2, "label": "1200х400", "provider": "adfox", "adaptive": [ "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "ezfn" } } }, { "id": 3, "label": "240х200 _ТГБ_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fizc" } } }, { "id": 4, "label": "Article Branding", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "p1": "cfovz", "p2": "glug" } } }, { "id": 5, "label": "300x500_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "ezfk" } } }, { "id": 6, "label": "1180х250_Interpool_баннер над комментариями_Desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "h", "ps": "clmf", "p2": "ffyh" } } }, { "id": 7, "label": "Article Footer 100%_desktop_mobile", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fjxb" } } }, { "id": 8, "label": "Fullscreen Desktop", "provider": "adfox", "adaptive": [ "desktop", "tablet" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fjoh" } } }, { "id": 9, "label": "Fullscreen Mobile", "provider": "adfox", "adaptive": [ "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fjog" } } }, { "id": 10, "disable": true, "label": "Native Partner Desktop", "provider": "adfox", "adaptive": [ "desktop", "tablet" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fmyb" } } }, { "id": 11, "disable": true, "label": "Native Partner Mobile", "provider": "adfox", "adaptive": [ "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fmyc" } } }, { "id": 12, "label": "Кнопка в шапке", "provider": "adfox", "adaptive": [ "desktop", "tablet" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fdhx" } } }, { "id": 13, "label": "DM InPage Video PartnerCode", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox_method": "createAdaptive", "adfox": { "ownerId": 228129, "params": { "pp": "h", "ps": "clmf", "p2": "flvn" } } }, { "id": 14, "label": "Yandex context video banner", "provider": "yandex", "yandex": { "block_id": "VI-250597-0", "render_to": "inpage_VI-250597-0-1134314964", "adfox_url": "//ads.adfox.ru/228129/getCode?pp=h&ps=clmf&p2=fpjw&puid1=&puid2=&puid3=&puid4=&puid8=&puid9=&puid10=&puid21=&puid22=&puid31=&puid32=&puid33=&fmt=1&dl={REFERER}&pr=" } }, { "id": 15, "label": "Баннер в ленте на главной", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "p1": "byudo", "p2": "ftjf" } } }, { "id": 16, "label": "Кнопка в шапке мобайл", "provider": "adfox", "adaptive": [ "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "p1": "chvjx", "p2": "ftwx" } } }, { "id": 17, "label": "Stratum Desktop", "provider": "adfox", "adaptive": [ "desktop" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fzvb" } } }, { "id": 18, "label": "Stratum Mobile", "provider": "adfox", "adaptive": [ "tablet", "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fzvc" } } }, { "id": 20, "label": "Кнопка в сайдбаре", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "p1": "chfbl", "p2": "gnwc" } } } ]