Технический разбор Illusion от X-Trade

Давно хотел попробовать написать новый тип заметки, специально для кодеров. Я хочу попробовать поговорить о внутренних циклах дем, о том, на чём держаться эффекты и об идеях, которые позволяют эти эффекты реализовать. Я не буду лезть в подробности реализации и не дам вам дизассемблер для сборки чего-то выдранного. Только идеи. Только самое интересное.



Ну и поскольку мне нужно с чего-то начать, я хочу начать с Illusion от X-Trade. Мне это демо всегда было симпатично.

Первый эффект в демо, это скроллер натянутый на шар. По сути, этот же самый эффект повторён ближе к концу, там где на шар натянута картинка из робокопа:



Итак, как это делается? У нас в памяти есть чёрно-белая картинка, либо скроллер, либо робокоп, но хранится она в виде байтов (байт на пиксель). Байт = 1 означает «есть пиксель», байт = 0 — «нет пикселя». Это неэкономно по памяти, но позволяет собрать из пикселей новую картинку. В чём идея? Алгоритм рисует сферу горизонтальными полосами вот в таком вот цикле:
DUP 8
add a : add (hl)
    DUP ?
    inc l
    EDUP
EDUP
ld (de),a : inc de ; (4+7+4*x)*8+7+6 = 101+32x тактов на байт (в среднем)

В HL — наша исходная картинка (байт на пиксель), в DE — буфер для результата, а в А накапливаются пиксели. Т.е. мы идём слева направо, умножаем А на 2 и добавляем в А текущий пиксель. Теперь фокус, почему я написал DUP? — потому что следующий пиксель может быть тем же, может быть действительно следующим, через 1, или даже, когда мы рисуем самый верх или самый низ сферы, через несколько пикселей от предыдущего. Т.е. программа генерирует такой код для вывода сферы заранее, и кол-во INC L вообще говоря всё время меняется, во время движения по сфере. Самое большое что я нашёл — пропуск 4 пикселей, но я не могу сказал что искал так уж старательно, где-то могло быть пропущено и 5.

Насколько эффективный это вывод? Можно предположить, что у нас в среднем один пропущенный байт. Размер шарика — 56 х 56 пикселей. Тогда выходит, что сфера занимает 56*56/8=392 байт экранной памяти, и поэтому выведется за 133*392 ~ 52136 тактов. Если бы пропущенных байтов было в среднем два, вышло бы (133+32)*392 ~ 64680 тактов, что с учётом вывода на экран, плейера (4.5 тысячи тактов) и задержек памяти, уже не влезало бы во фрейм на классике. Плюс вывод буфера на экран и т.д. Фреймовый эффект.

Второй заинтересовавший меня эффект — это большой поточечный скроллер с прыгающим по нему мячом:



Мячик это конечно спрайт, физика, конечно, ненастоящая. Меня интересовал сам скроллер. Рисуется он в текстуру в памяти, а потом выводится в экран вот таким образом:
ld a,(bc) : inc c
DUP 8
pop hl : rla : jr nc,0f
set ?,(hl)
0:
EDUP ; 10+4+7+15 = 36t на пиксель

В BC — текстура в памяти. Стек настроен на таблицу адресов в экране, куда нужно будет выводить пиксели. Конкретные биты пикселей не меняются (движение батута строго вверх-вниз, движение получено просто сменой таблицы адресов пикселей). Читаем адрес и проверяем, зажжён ли текущий бит, если да — ставим его в экран.

Время вывода одного пикселя — 36 тактов (или меньше, если пиксель погашен), поэтому экран из 1024 пикселей выводится за 1024*36 ~ 36864 тысяч тактов. Заметили, что батут в нижней трети? Значит у нас есть верхний бордер (64 строки на пентагоне), плюс две трети экрана на рисование (ещё 128 строк), т.о. у нас есть до начала отрисовки батута где-то (64+128)*224 = 43008 тактов. Т.е. эффект спокойно успевает в один экран, могли ещё больше точек нарисовать без проблем :)

Теперь, два «главных» эффекта в демо, moving shit и ротосоник:



Идея реализации в обоих случаях одна и та же, стандартная для ротаторов и вобблеров. Мы опять хотим текстуру с пикселем на байт. В случае этих двух эффектов у нас пиксели 2х2, ну т.е. всё равно храним в байте #03 если пиксель есть или #00 если пиксель пустой. В начале кадра нам нужно сгенерировать процедуру, которая будет идти по экрану строго горизонтально, слева направо, и, одновременно — по текстуре. По текстуре идти придётся под углом (чтобы получилось вращение) или вообще по какой-нибудь кривульке, чтобы вышло moving shit. Такая процедура в Illusion выглядит вот так:
ld a,(hl)
	inc l : dec h ; эти команды меняются в зависимости как наша линия идёт по текстуре
add a : add a : add (hl)
	inc l : dec h
add a : add a : add (hl)
	inc l
add a : add a : add (hl)
	inc l : dec h
ld (de),a : inc e ; 7+4+4 + 4+4+7+4+4 + 4+4+7+4+4 + 4+4+7+4+4 + 7+4 = 95t на 4 чанка (один байт)

В HL адрес в текстуре. Чанк 2х2 добавляется в А, а потом мы сдвигаемся по текстуре inc l — влево, dec h — вверх. Конкретные команды пересчитываются каждый фрейм. В DE — адрес буфера в памяти, куда осуществляется вывод. Когда буфер целиком собран, кадр выводится на экран используя стандартный код:
pop hl : ld (),hl : ld (),hl ; 10+16+16=42t на 4 экранных байта

Считаем скорость вывода. Размер экрана в Moving Shit — 128 x 96 чанков, которые обсчитываются за 95*(128*96/4) = 291840 тактов. С учётом времени на вывод из буфера и музыки, это 4-5 фреймов на каждый кадр. У соника вывод на весь экран, поэтому скорость на треть медленнее, 5-6 фреймов на кадр.

Один эффект я что-то не понял — zoomscroller в конце. Там несколько кусков кода, который выглядит не так понятно как примеры выше. Если кто-то может рассказать, как он устроен, буду очень благодарен. На этом всё на сегодня, счастливо и попутного кода :)

116 комментариев

avatar
Круто! Очнеь круто. Правда я ждал другой концовки. Типа «а теперь возьмем ручки и запишем домашнее задание». Шутка.
avatar
Хочешь домашку? :) Вот объясни мне на пальцах, как устроен у тебя blur букв в приветах в приглашении на мультиматограф. Можно даже без внутренних циклов.
avatar
я тоже хочу домашку!
avatar
Твою домашку сам знаешь. Популярное объяснение bump-mapping :)
avatar
/me спрятался в уголке
avatar
Между прочим, тебе благодарность: твои метаболсы на тс-конфе заставили меня задуматься как их делать на дохлых платформах (типа нашей).
avatar
Ты про это?

avatar
Да!
avatar
Тяжело разбираться исходниках трех с половиной летней давности. Тем более, код не полностью мой. За основу взята интра newart'a для DonNews #18.

Всё просто. Каждая горизонтальная линия может отрисовываться одним из двух вариантов: или по OR с текущим содержимым экрана, или то же самое, но с накладыванием маски по AND. Хитрость в чередовании линий и масок.

Всего декранчится четыре процедуры скролла, в которых меняется порядок отрисовки линий. Неизменным остается только их соотношение: 144 линии по OR, оставшиеся 48 отрисовываются по AND + XOR.

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

После того, как текст останавливается, процедуры какое-то время продолжают вызываться. Но уже с совпадающими данными источника и назначения. Тем самым, за счет накладывания маски, экран постепенно очищается от «мусора».
avatar
Общую идею понял, спасибо!
avatar
Очень крутой пост, особенно для начинающих кодеров. Спасибо!
avatar
Спасибо, многое почерпнул. Такие разборы принципов работы эффектов — лучшая помощь начинающим вроде меня.
avatar
Спасибо! Эта дема в моем личном топ 10 с 97 года.
Есть в ней что-то человечное, не сюжет конечно, но что-то большее чем набор эффектов.
Что позволяло ее показывать случайнам людям, друзьям, родственникам. )
Однако осталось не понятным, возможно ли перечисленные эффекты ускорить/улучшить/решить иначе?
Ну и интересно твое мнение на счет этой демы как демы, в контексте тех лет конечно.
Еще про музыку вопрос, там обычный pt2 плеер жрущий 2-3к тактов?
avatar
Я решил для себя, что не буду обсуждать улучшения эффектов по двум причинам. Во-первых, это может показаться людям обидным, что мне меньше всего бы хотелось (см. треды такого типа Алон-кодера на zx-pk.ru). Во-вторых, лично меня очень вдохновляет даже просто посмотреть на эти решения, просто как способ думать немного по-другому. В третьих, с моей точки зрения, если есть мысли как улучшить, нужно делать об этом демо, а не писать об этом на Hype :)

А вообще — «Illusion» — одна из немногих дем 1990х, которая нравилась мне тогда и нравится сейчас. Она быстрая, без передержанных сцен, с мелодичным треком, с чувством самоиронии и без типичных для того времени понтов. Впечатляющая не смотря на это всё. Подытоживая, я не думаю, что когда-нибудь сделаю дему похожую на «Illusion», но отношение у меня к ней очень тёплое.

Плейер я даже не посмотрел, — там в бегущей строке под робокопом авторы сами написали что у них плейер 4500 тысячи тактов.
avatar
Удивительно: мне всегда казалось, что трек в этой деме — какой-то кавер. С того самого момента, как я её увидел в первый раз, вот уже двадцать лет меня не покидает совершенно определённое ощущение, что я слышал этот трек где-то ещё. Я уверен в этом. Но никакой инфы об этом нет.
Ни у кого больше нет такого ощущения?
  • sq
  • +1
avatar
Хе-хе. Есть не только ощущение но и прототип трека…
avatar
Ну вот, наконец-то понятные и интересные объяснения :) Спасибо!
avatar
Отличное начинание! Полностью поддерживаю.
Почерпнул для себя некоторые идеи
Мое личное пожелание:
Вообще циклы выводящие текстуру, лично мне и так понятны, равно как и ухищрения со стеком и т.п.
А вот мне как раз интересно, как это оно «идет по кривуле», как эту «кривулю» посчитать. И считают ли они
ее в теле демы, или тупо загружают координаты? В каком виде удобно хранить именно эти данные?
avatar
Прямо на скриншоте, посмотри на верхнюю кромку слова SHIT и сравни её с нижней кромкой. Ничего не напоминает?
А теперь посмотри на линию между H и I, и сравни её с правой кромкой буквы T.
Думаю, это отвечает на твой вопрос :)
avatar
Синус?
avatar
Да, он, родимый.
avatar
«синус — наше всё!» :)
avatar
То что в данном случае это синус это понятно. Но это, во-первых, лишь малая часть моего вопроса.
Интересно как авторы в каждом случае устраивают матрицы этих кривуль, как их лучше хранить
для каждого кадра (при прекалькуляции), или где-то выгодно считать на лету по таблицам того же исходного синуса — тогда
какие используются алгоритмы для быстрых вычислений.
во вторых, часто дело синусом не ограничивается, и идет в ход матан пожощще. А вот авторы
статей про демо эффекты, почему-то стараются всегда этот вопрос обходить стороной.
avatar
Ты с кем сейчас разговариваешь, поясни пожалуйста. Если понятно что синус, зачем спрашиваешь. Если тебе интересно, как люди, вообще, считают и хранят разные, вообще, математические функции? ну, по-разному, и считают, и хранят. Как можно ответить на такой широкий вопрос? Только так же широко. Учи математику. Придумывай, как все остальные придумывают. Но какое отношение это всё имеет к демо «Illusion»?

Какие-то авторы статей про демо-эффекты тебя не удовлетворяют…
Ну вот скажу тебе симметрично, что комментаторы у статей про демо-эффекты тоже бывают весьма замысловатые.
avatar
Ладно, давай проще.

«В HL — наша исходная картинка (байт на пиксель), в DE — буфер для результата, а в А накапливаются пиксели. Т.е. мы идём слева направо, умножаем А на 2 и добавляем в А текущий пиксель. Теперь фокус, почему я написал DUP? — потому что следующий пиксель может быть тем же, может быть действительно следующим, через 1, или даже, когда мы рисуем самый верх или самый низ сферы, через несколько пикселей от предыдущего. Т.е. программа генерирует такой код для вывода сферы заранее, и кол-во INC L вообще говоря всё время меняется, во время движения по сфере.»

Лично мне интересно, как сформировали этот развернутый цикл. Например в разбираемой деме ILLUSION. чтобы в DUB стоял не знак вопроса а описание формулы и ее реализация, поскольку ЛИЧНО ДЛЯ МЕНЯ, это наиболее интересная часть эффекта. Конечно, твое личное дело как автора писать это или нет, а мое как комментатора — написать свое пожелание. Возможно в будущих статьях кто-то учтет мое пожелание и расскажет об этом. Иначе зачем вообще тогда комментарии? достаточно кнопки +
avatar
Вот в этом твоём «кто-то учтёт моё пожелание» и заключается причина моего раздражения. Ты пишешь вопрос под моей статьёй, но адресуешь свои призывы «кому-то». Этот неведомый «кто-то» должен по-твоему написать эту же самую статью по-другому. Влезть в код и что-то там рассмотреть не так как я, а так, как хотелось бы тебе. Или что-то ещё в том же роде.

И меня это злит. Потому что этот «кто-то» — это ведь подразумеваюсь я, но задать мне прямой вопрос тебе видимо не позволила гордость или х.з. даже что. В итоге сначала я должен тянуть из тебя клещами информацию о том, чего же тебе собственно хочется (ну, за пределами очевидного понтования о том, как тебе всё это кажется тривиальным). И после всего этого я же и оказываюсь виноватым, потому что ты, якобы, меня покритиковал, а я, якобы, адекватно воспринимаю только плюсики. Твой комментарий — это типичнейшее в стиле zx-pk.ru потребительство, где ты полон мыслей, что всё нужно делать не так, а лучше, но сам явно ничего делать не собираешься; тебе оказалось лень сформулировать даже прямой вопрос.

Генератор развёрнутого кода начинается с адреса #6133. Данные о пропусках хранятся в таблице с адреса #6944.
Формат таблицы такой:
6944:	db	0c ; ширина в пикселях этой строки сферы (+1 или +2, это какой-то подгон под кодогенератор)
6945:	db	0c,06,04,04,04,03,04,04,04,06,0c ; 11 пропусков для пикселей первой строки
и т.д.

Мне было лень сейчас разбираться, как там согласовано то, что ширина хранится не точно, а +1 или +2. Непосредственно число в начале строки преобразовывается в число пикселей на половину рисунка, потом пересчитывается в сдвиг в байтах (для вывода на экран) и там возня не интересная, приспособленная к конкретному коду.
avatar
Ну, во-первых мне искренне жаль, что своим безобидным вопросом, с просьбой раскрыть для меня некоторые интересующие меня, но не раскрытые в статье аспекты я вызывал твое раздражение, мне правда стыдно.В оправдание, хотелось бы пояснить: Если я что-то спрашиваю, то я спрашиваю именно то что я спрашиваю, без скрытых смыслов и двойного дна. Если я обращаюсь не конкретно к тебе, а ко многим, или пространному «кому-то», то это значит лишь то, что я прочитал много статей на хайпе по программированию, и, по моему скромному разумению, чуть более во всех из них вышеописанные аспекты игнорируются. А коммент, именно под твоей статьей я написал, так как доселе я считал, что именно ты можешь адекватно воспринять вопрос, и, возможно, если не лень ответить. Я прекрасно отдавал себе отчет, что достопочтенный Интроспек не будет переписывать ради меня эту статью, но, т.к., эта статья заявляется как первой в цикле подобных – то, возможно, если будет желание, в какой-то из следующих статей, он учтет и мое пожелание, а также, возможно, его учтет и КТО-ТО ДРУГОЙ. На твоем месте, я бы был удовлетворен, так как подобные вопросы (в отличие от бездумного тыкания плюсиков) свидетельствуют как минимум о том, что статью прочитали, заинтересовались, т.е. работа проделана не зря. Задавая эти вопросы, я ожидал услышать ответы по существу, или на худой конец, что-то вроде: «Извиняй чувак, мне было в лом в этом разбираться, да и вообще я хотел написать о другом». Вместо этого я в очередной раз, вижу, как у автора, говоря современным слэнгом, начинает «подгорать», причем буквально с «пол-оборота». Причем ладно бы я сказал статья Г. и автор М., так нет, в целом выразил благодарность за поднятую интересную тему, просто попросил раскрыть тему еще полнее. Насчет «клешней»: адекватная реакция на вопрос, который не понятен – просьба разъяснить точнее, что имелось ввиду, а не злость.
Насчет понтований: тут понтов никаких, я действительно знал эти методы, и видел синус в мувинг шите, я спрашивал не про него. Но их реализации в конкретной деме, тем не менее, интересны, ибо всегда полезно иметь ввиду чужой успешный опыт, ибо свои представления могут быть ошибчно и неэффективны.
avatar
В дополнение к вышесказанному:
Сейчас мы конечно же можем на писюке посчитать матрицу и вогнать ее на спек, более того, можно на писюке сгенерить
сразу ассемблерный код развернутого цикла. Но тогда ведь считали все прямо на спеке? или я не прав?
avatar
Не скажу за illusion, но некоторые прекалькуляции таблиц делали на бейсике на этапе разработки.
avatar
Было и такое. Вообще, в частности по сферам была такая история:
Один мой товарищ Joker делал вращающуюся сферу размером в пол экрана. в районе 8 фаз анимации.
Так вот, сначала он считал сферу (естественно по формуле сферы) вызовами пзу-шного калькулятора. И считалось все это дело добрых 15 минут.
Потом он переделал на собственные процедуры арифметических операций и табличный синус — и о чудо, 30 секунд. Что вполне нормально.
Конечно можно было заранее сгенерить массив координат в текстуре, заархивировать его, и подсасывать с диска при загрузке интры. Но вы все сами понимаете, что следующий шаг — запилятор (который в некоторых случаях может оказаться даже эффективнее предыдущего метода).
avatar
не может эффективнее — он статичен
avatar
Ну смотри, 4 фазы анимации маленького шарика 2 на 2 знакоместа, проще эффективнее загрузить прямо спрайтами, чем пытаться их как-то генерить на месте
avatar
похоже мы по разному воспринимаем термин запилятор.
ибо ты говоришь о спрайте «4 фазы анимации маленького шарика 2 на 2 знакоместа», а я о экранном выводе заданного гифа, в котором уже заданы кадры и координаты вывода.
avatar
Общим термином «запилятор» я обычно нарекаю любую растровую анимацию)
avatar
Мне, кстати, кажется, что твоя точка зрения про таблицы весьма экстремальна. Мне прекалк в 30 секунд не кажется нормальным, а уж особенно в середине трекмо. Ты напомнил мне, как кодер ротозумера в Batman Forever на амстраде вместо традиционного расчета вектора для шагания по текстуре сделал просто таблицу готовых векторов для каждого нужного ему угла и его обвиняли его в том, что у него не ротозумер, а анимация.

С моей точки зрения, это какие-то бессмысленные ограничения, которые портят впечатление с т.зр. зрителя. Т.к. я стараюсь делать демы для зрителей, я не считаю принципиальным кто и где считал таблицы и, даже больше, я уже неоднократно задействовал кодогенераторы написанные на PC. Это позволяет при прочих равных условиях повысить качество сгенерированного кода (качество в плане объёма и/или скорости), даёт сопоставимую скорость распаковки, а так же в разы упрощает отладку.
avatar
Тут надо разделять понятие демы и интры. Понятно что в деме такой ход неприменим. А вот интра она на то и интра, чтобы все генерить «в себе», с минимальным объемом загружаемого исходного кода, в этом и состоит ее прелесть.
avatar
Но вы все сами понимаете, что следующий шаг — запилятор

Долго смеялся :) Самое главное демы не забывайте делать, а то в теории то все крутые и принципиальные!
avatar
Денис, тот факт что у меня нет времени на написание полноценных дем, не отменяет того факта, что тема программирования демоэффектов мне крайне интересна. Но мне больше в демах интересны не «флоу», а программистские этюды. Как свободный человек, я имею право выбирать чем мне интересоваться.
avatar
Неа, тема то про то что таблицы посчитанные на PC это почти запилятор, а таблицы посчитанные ПЗУшным калькулятором или хитрым монстрокодом это тру :) Вот это позабавило. Ну а так, каждому нравиться своё, кому-то этюды с сильным кодом, кому-то всё подряд, кому-то эмузвин :)
avatar
вот мне уже самому хочется этот эмузвин попробовать после такого всеобщего вокруг него ажиотажа)
avatar
bfox даже не думай про эмузвин, у тебя и так всё отлично выходит! Это просто меня посоны с ним троллят постоянно, никакого ажиотажа :)
avatar
если бы spke объяснил…
надо покопаться по старым запасам, где-то у меня валялся sphere texture mapping.
avatar
kotsoft, удивительно, что тебе понятны иннерлупы, но непонятен синус :) Это как вообще)
avatar
Поверь, мне понятны как работают эти эффекты целиком и полностью. Вопрос мой гипотетический. и используемый «матан» часто сложнее и интереснее стандартного алгоритма меппинга текстуры.
avatar
1. «Кривуля» чаще всего функция sin. Таблицы — это всё.
2. Храни sin в таблице 256 байт, рассчитай заранее.
3. Загрузи старшую половину регистровой пары чтобы получить адрес таблицы, пусть это будет H
4. Тогда L — будет произвольный аргумент функции.
5. Крути L как угодно — будешь ходить по функции туда-сюда.
6. Читай значения sin как LD reg,(HL)
7. cos это то же самое что sin, но сдвинутый на четверть периода. И наоборот. Четверть периода это регистр L +- 64
8. Удобно вместо значений sin/cos сразу прошить таблицу адресами.
9. Значения таблиц sin можно подготовить на старте.
avatar
А где последняя, десятая заповедь? Не желай кода ближнего твоего, и не желай эффекта ближнего твоего, ни алгоритма, ни музыки, ни графики.
avatar
все дружно ложим или кладем свои исподники в опенсорс
avatar
Не, мои исходники в обозримом будущем в опенсорс не пойдут.
avatar
не сочувствуете детям германии?
avatar
Я больше себе любимому сочувствую, какие уж там дети Германии…
avatar
Напомнило попытки Быстрова выглядеть самым умным и объяснить как работают демоэффекты. Его фраза про столбики для вокселя просто должна попасть в анналы.
Этот топик мне вряд ли что объяснит, например, неясно, как строится табличка для Robocop.

с Moving Shit ясно итак: я попытался повторить похожий эффект в Reality, помог разобраться с работой исходник от пейсишной bbstro:

Нарисуйте спрайт, где колеблется синусная линия. Затем добавьте смешение по горизонтали, смещение определяется как sin(A)+sin(B).
avatar
Ну вот а мне такой способ объяснения понятнее, чем лоскуты неперевареного кода, которые любишь выкладывать ты.

Твой Moving Shit, насколько я помню, и был причиной я влез в Illusion, потому что у тебя было душераздирающе медленно (в 4 раза медленнее, насколко я помню). Если бы ты научился думать о внутренних циклах описанным мной образом, м.б. и у тебя вышло бы пошустрее.
avatar
Давно я так не смеялся. шути ещё)
avatar
introspec, и правда. Как сделать табличку искажений битмап->шар?
Я помню для Chaos Reconstruction мне помогал Alex Rider, но… на шар оно так и не было похоже.
avatar
Нет однозначного ответа на этот вопрос. Картографы бьются уже который век в спорах, как правильнее натягивать карту на глобус.
Вот таблица из Википедии: en.wikipedia.org/wiki/List_of_map_projections#Cylindrical

Авторы Illusion приложили только таблицу, поэтому можно потратить несколько дней исследуя, какую именно из проекций они применили. Я этим заниматься не буду. Наиболее вероятные кандидаты — Equirectangular, Mercator, Gall stereographic, Miller, Lambert cylindrical equal-area, Gall–Peters, т.е. различные «старые» проекции.

Собственно, это одна из причин почему мне кажется бессмысленным давать рецепты такого рода. kotsoft прав, что самые интересные секреты — это вычисления в этом роде. Но какой смысл научить сейчас всех, допустим, Ламберту, чтобы потом все как попугаи шпарили шары с одними и теми же искажениями?
avatar
А было такое в истории спектрума? Что вот в каком-то журнале что-то разжовывалось и приводило к всплеску однообразных эффектов?
avatar
ОК, например, линия Dark^X-Trade, прекрасная статья, никаких вопросов вообще. Но много ты знаешь реально быстрых линий, спроектированных иначе чем у него?
avatar
Ну вот и ответ на мой вопрос — оказывается там прекалькулированная заранее, и тупо загруженная таблица смещений. Понятно что методы ее вычисления — это скорее, тема отдельной статьи. а насчет методов — думаю авторы иллюзион слыхом не слыхивали ни об одном из перечисленных. Посчитали по формуле сферы с проекцией на ортогональную плоскость да и все, тупо из бейсика, поками.
Рискну предположить, что непосредственно в теле демы по этой таблице генерится статичный развернутый цикл.
avatar
Ничего тупого в таблицах я не вижу, тупо делать что-то сложное, когда есть простой способ решения задачи.

То, что авторы не слышали ни об одном из описанных методов, тем не менее, совсем не означает, что они не задействовали одну из описанных по моей ссылке формул. Я собственно уверен на 99% что одну из них они и сделали.
avatar
в данном контексте слово тупо употребляется не в значении «плохо». А в значении «прямо, без лишних хитростей»
avatar
У нас с тобой как с Nuts_, язык вроде один, а понимания не происходит.
avatar
Да ладно, вроде все выяснили, и даже не посрались))) так что все норм)
avatar
Ммм, а ещё возможно, что они и по-честному посчитали, с учётом перспективы.
Вот тут есть пример выкладок: www.javaworld.com/article/2076696/learn-java/draw-textured-spheres.html
avatar
Вот за эту ссылку отдельное спасибо
avatar
Скажу за себя: лично мне куда интереснее писать свой код, основываясь на хорошо объяснённых алгоритмах, чем копипастить чужой код и пытаться в нём разобраться. Но я ни на чём не настаиваю.
avatar
Ошибочка. Дима не пытается выглядеть умней всех, Дима делиться своими соображениями основанными на его опытах и задает реальные вопросы. Тоже самое в статье сделал и Introspec. Другое дело что уровень начальной подготовки читателя и/или язык повествования могут сказаться негативным образом на понимании. Но никто же не мешает задавать вопросы касающиеся подробностей.
avatar
Не, все верно, чо: нашел кусок кода, посчитал такты, поделился открытием.
avatar
Давай уже пиши статью как сделал линии в Break Space, от момента возникновения идеи, попыток раскраски знакомест и понимания закономерностей до конечной модели их поведения и внутреннего устройства кода :) Распарсить код и понять алгоритмы можно, а вот процесс зарождения идеи и путей его реализации — думаю это самое интересное, в готовой реализации всего этого нету)
  • TmK
  • +1
avatar
Я бы рассказал с удовольствием, если бы у меня не было чёткого ощущения, что должен быть какой-то способ лучше чем то, что я наделал в запарке. Итоговый эффект вышел в 3 фрейма на пентагоне; но концовка самую малость тормозит на классике, т.е. слегка вылезает из 3х фреймов. Исходно подразумевался рендер в 3 прохода (1. линии -> чанки 2х2, 2. чанки 2х2 -> чанки 1х1, 3. вывод чанков 1х1), но в первом проходе я накосячил и времени переделать его ещё раз не оставалось, поэтому сделан второй проход, который чинит недостатки первого, потом третий проход, который частично красит кадр и переводит всё в чанки 8х8 и только потом 4й проход с выводом чанков.

Первые 2 прохода, невзирая на недостатки того, как я их сделал, довольно эффективны. Третий проход писался последним и на него не было времени, он фактически не оптимизирован…

Короче, ты прав, может и нужно написать ужастик, хоть кодеры поржут.
avatar
В коде каждого из нас зарыт злостный гоблин… :)
Я про то, что какой бы ужастик в коде не был, интересен путь, а также проблемы и нюансы решаемые и возникающие в процессе.
avatar
ага, наел более внятное объяснение:
www.petesqbsite.com/sections/express/issue25/index.html
avatar
Вот их профессура ГОТОВА! ©

Отличный анализ, отличный разбор, читал и другим рекомендую.
avatar
www.wothke.ch/spectreZX/ примерно 5й музон — музыка похожа на тему из демы.
avatar
speccy alive in our hearts вобщем называется 4й по счету.
avatar
Вот тут получается, что этот трек написан Davos в 1999 году, т.е. скорее он по мотивам Illusion чем наоборот: zxart.ee/eng/authors/d/davos/speccy2/
avatar
Zoom Scroll очень интересен. Не так давно Titus выложил исходник свего интро к Dizzy 7.
avatar
Где выложил? :)
avatar
Значит у нас есть верхний бордер (64 строки на пентагоне), плюс две трети экрана на рисование (ещё 128 строк)
хотелось бы в подробностях/понять/напомнить, что за «64 строки» и «две трети экрана»… если не затруднит)
avatar
Представь отрисовку кадра на экране. Есть собственно экран спектрума в центре (192 строки по 256 пикселов) и есть бордер, который шире, который тоже рисуется на телеэкране. Всего на кадре сформированном на пентагоне 320 строк. 64 из них рисуются до начала отрисовки экрана 256х192, потом рисуется экран, потом рисуются оставшиеся 48 строк.

Каждая строка пентагона рисуется за 224 такта процессора. У меня было написано: «Заметили, что батут в нижней трети? Значит у нас есть верхний бордер (64 строки на пентагоне), плюс две трети экрана на рисование (ещё 128 строк), т.о. у нас есть до начала отрисовки батута где-то (64+128)*224 = 43008 тактов.» Экран спектрума хранится в памяти кусками по 2кб, таких кусков три, поэтому многие эффекты, не только в этом демо, организованы так, чтобы воспользоваться такой организацией памяти. Поэтому идёт речь о третях экрана.
avatar
Спасибо! Стало заметнее понятнее (лет 25 как хотелось понять))
Но до сих пор не понятно, как же строятся всякого рода бегущие строки… ведь у бордера «нету своей видеопамяти»..?
Кто бы в деталях разжевал, так сказать, для окончательного понимания построения подобных эффектов…

Еще раз и Много-много раз — Спасибо!
avatar
знаешь как строится изображение на экране? луч бежит по строкам экрана с левого верхнего угла к нижнему правому. ну и остается только в нужный момент менять его цвет путем изменения цвета бордера.
avatar
Цвет на экране телевизора/монитора появляется не весь одновременно, а «попиксельно», слева направо и сверху вниз. Это относится не только к видеопамяти, но и к бордюру. Отрисовка каждого «пикселя» берет некоторое время, поэтому можно на практике поменять на лету цвет бордюра, и всё, что отрисовано до этой замены (выше по кадру на картинке) останется старого цвета, а всё, что ниже — будет уже нового. А если успевать менять цвет бордюра достаточно часто, то можно добиваться целых узоров разного цвета.
avatar
а так как на одну команду у процессора уходит минимум 4 такта, то за каждый такт мы получим точку ранее заданного цвета на бордюре.
учитывая то, что вывод в порт — out (#fe),a / out (c),a — занимают 11/12 тактов, то это минимальный размер бордюрного пикселя…
avatar
стоит добавить, что за один такт выводится 2 пикселя. в итоге получаем линию размером 22/24 пикселя
avatar
[28.07.2017 13:47:29 Way Be: TSL, 128ой каждый такт лучом ставит точки на экране?
[28.07.2017 17:44:04] TSL: каждые полтакта
[28.07.2017 17:44:17] TSL: пиксель имеет длительность = периоду частоты 7мгц
avatar
покажите мне на примере линию на бордюре в 22 пикселя \11 тактов.
А лучше несколько, друг за другом. Желательно код.
Видимо мы в разных вселенных существуем, но меньше чем 12 тактов\24 пикселя мне не удается. ЧЯНТД?
avatar
а, наверное понял, одну то линию 11 тактовую можно, но не больше, ибо на вторую надо перегружать аккумулятор. Итого остается в сухом остатке те же 12 тактов, а с 11-ю ничего не сделать путного.
avatar
щука, сам с собой беседую. Клиника. Нет, низя. Или пример в студию. Одиночную линию в в любом месте бордюра длиной 11 тактов. Можно красную на черном бордюре.
avatar
Извини, нарисовалась почему-то белая.
avatar
ld bc,#FE : ld a,7 : out (c),b : out (#FE),a : out (c),b ; линия, одна шт.
Несколько подряд не получится, но неправ всё же ты.
avatar
а если подряд несколько разноцветных линий по 11 тактов нельзя, то смысла нет от слова совсем. Я всегда не прав, специфика… Для себя уясняю.
avatar
:)

Я возмутился вот этому в первую очередь: «покажите мне на примере линию на бордюре в 22 пикселя \11 тактов». Показал. А потом было столько уточнений и поправок, что сам чёрт не разберёт уже.
avatar
я же согласился, что не прав. Уточнил, что практического применения не имеет, но как нибудь все же попробую.
avatar
s2.micp.ru/oc25z.jpg
ну и в подтверждение своей неправоты :((((
ЧЯА5ДНТ? Или «не верь глазам своим! ©»?
avatar
Смотря что именно эмулирует твой эмулятор. Дело в том что на классических спектрумах (и скорпионах) цвет бордера выровнен до границ знакомест (именно поэтому мой бордерный формат хранит данные с точностью до знакомест). Чтобы увидеть 22 пикселя, тебе нужен не только правильный код, но ещё и пентагон, или пентагон-совместимый комп.
avatar
ага-ага. я не только не прав но еще и дурак, свои под(д)елки не знаю для чего пишу и в чем тестировать и как выравнивается на классике…
В четырех эмулях (уточняйю — под ПЕНТАГОН!) — полоски равны между собой и равны 24 пикселя. У вас же у всех есть реальные Пентево-гоны, код выше, правильный) Вот и проверьте. Теорию — практикой.
avatar
Ты свою задачу выполнил — я задумался :)
avatar
вот и поделишься по итогам думками. Я для себя уже все решил:
out (#fe),a — не совсем 11-ти тактовая команда :) я бы сказал это что то типа «12-1», что вовсе не равнозначно одиннадцати :))))))))
подождем объяснений более вумных людей.
avatar
хм… подтверждаю…
я раньше не проверял, ибо надобности не было — эти 11 тактов не пришей туда рукав. но чисто теоретически ожидал адекватную реакцию в 22 пиксела)
верхняя линия 12 тактов, нижняя — 11.
отсюда вопрос — какого хрена так происходит?
avatar
я уже два таких теста нарисовал :) Ну как самый неправый тут, объясняю со своей колокольни)
Возможно OUT (port) и 11 тактовая, во всех остальных случаях, кроме бордюра, на бордюре она ведет себя странно, прикидывается 12-тактовой, НО!!! отжирает один такт от ПРЕДЫДУЩЕЙ! команды,
в сумме то как бы и правильно, только наеборот все, предыдущая перед ней команда укорачивается на такт, это видно по раскраске пикселя, а сама она становится 12 тактов, ну и общая сумма не меняется. вот потому я ее и назвал «12-1». Зато я не прав, что радует )
avatar


www.dropbox.com/s/selbdtzr5b37n7h/out11.sna?dl=0

azesmbog, ты забыл, что собственно запись в порт происходит совсем не обязательно на последнем такте команды. Тот пример, что я написал из головы, очевидно, записал ровно 12 тактов, хотя между 12-тактовыми командами сидела 11-тактовая.
avatar
чего-то я совсем запутался… а какого хрена в двух случаях получалось 24 пикселя, а у тебя 22?
avatar
я же говорю, визуально на два пикселя уменьшается предыдущая команда, а сама оут=порт визуально рисуется 24 пикселя
zx-pk.ru/attachment.php?attachmentid=61855&d=1501537431
надо бы на реале проверить
avatar
Цвет меняется не в конце команды ассемблера, а где-то внутри. Если лепить out (254),a: out (254),a: out (254),a… то от записи до записи, понятно 11 тактов. Если лепить out (c),b: out (c),b: out (c),b… то от записи до записи будет 12 тактов. А если команды чередовать, то будет от записи внутри одной команды, до записи внутри другой команды. Как показывают ваши тесты, для комбинации out (c),b: out (#FE),a: out (c),b выходит чёрточка в 12 тактов. Ну ок, тогда я написал чёрточку ниже out (#FE),a: out (c),b: out (#FE),a и получил другую длину.
avatar
ага, кажется ничинаю понимать)
avatar
Нас поправляют радиослушатели, точнее, нас поправляет Blade. Запись происходит всё же на последнем такте.
Думаем по шагам
out (c),b ; настроили чёрный бордер
out (#FE),a ; включили в самом конце команды другой цвет
out (c),b ; другой цвет держался ровно 12 тактов, как и положено для out (c),b

Если написать наоборот, будет
out (254),а ; настроили чёрный бордер
out (c),b ; включили в самом конце команды другой цвет
out (254),a ; другой цвет держался ровно 11 тактов, как и положено для out (254),a


Т.е. если бы я подумал чуть-чуть мозгом перед тем как писать самый первый пример кода, ничего бы этого не случилось. Так что, извиняйте :)
avatar
вот теперь все понятно)
avatar
вы будете смеяться, но в эмузвине всё чотко :) Синяя 22 пикселя красная 24.
Шах и мат, товарищи :))))

avatar
Ну вот и разобрались :) У меня как раз так было:

out (254),a
out (c),l
out (254),a
out (c),l
out (c),h
avatar
avatar
вот когда будут фото с реала, тогда и разберемся, а пока так —
рисуем команду
out (c),l за ней out (254),a
в l — 1 (синий) в а — 2 ( красный)
синяя полоска нарисуется 22 пикселя, красная — 24
avatar
Запусти пожалуйста мой .sna на своём реале. У меня реала нет.
avatar
у меня куча таких же sna, реал подключать оч проблематично, телек сгорел)
такие полоски я и сам нарисую, я говорю как оно последовательно выходит.
Осталось разобраться, только в эмулях так, или на железном проце то жи
avatar
Эмули сейчас очень хорошие. Реально. Я не сомневаюсь что всё будет ОК.
avatar
Т.е., есть некоторые вещи, которым я не вполне доверяю в эмуляторах.
Но это не одна из таких вещей.
avatar
хотя если верить радиослушателям, что запись цвета происходит на последнем шаге команды, и идет как бы с запозданием — тогда логично ((
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.