Making of Hara Mamba,Scene!

hmslogo
Привет народ!

Недавно мы выпустили нашу новую демку под названием Hara Mamba, Scene! которая заняла аж 3-е место на CAFeDemoparty 2019. И я решил немного рассказать про то как там всё сделано и как оно вообще делалось. Возможно кому-то будет интересно! Погнали!

CODING PART DISCLAMER:

Я абсолютно не претендую на крутость кода и почти уверен что можно сделать лучше и красивее. Зачастую я использую тактику кучи дупов вместо цикла, брутфорса, быстрокода и суперсекретный метод под названием «пофикси Артёмка». Поэтому не трачу времени на оптимизации если ясно что всё и так работает и хорошо пакуется!



HIDDEN ROTATOR




Это самый старый из эффектов, который давно лежал в загашнике со времён OverRelaxed, а часть кода не менялась ещё со времён Relaxed. По сути у нас тут простая бордерная анимация размером в 16 кб по 256 байтов на кадр. Анимацию я генерировал в небольшой тулзе, написанной специально для растер эффектов в OverRelaxed. Ну т.е. все эти ротаторы и прочие штуки честно сделаны кодом, а потом экспортированы в анимацию. По-простому у нас в 16кб влезет 64 кадра, но я уплотнил всё в два раза засунув в папер ещё один кадр. Таким образом получается, что первый кадр в инке, второй кадр в папере и.т.д. В верхнем бордюре мы патчим наш код который формирует растербары на экране нужным значением. В случае же двухслойный эффектов как в этой деме, нам приходится в папер пихать кадры второй анимации. Таким образом просто стирая пиксели мы «вскрываем» вторую анимацию. Абсолютно также сделаны «горбатые ротаторы» в OverRelaxed, только там в папере лежит та же анимация что и в инке но отстающая на один кадр, а форма ротатора сделана пиксельной подложкой в виде столбиков.

Конкретно для эффекта из HaraMamaba код выглядит так:


bufStart: ld hl,49152	
        
N=0
        dup 192
        ld a,(hl)                ;Берём значение из анимации
        ld (rastaCode+1+N),a     ;Патчим код ниже
        ld (rastaCode+2+N),a     ;Патчим код ниже
        and 7                    ;Отгрызаем папер чтобы не шумел бипер
        ld (rastaCode+15+N),a    ;Патчим код ниже в части вывода на бордер
        inc l		         ;Следующее значение
N=N+29
        edup

N=0
        ;Рисуем растеры
	ld (stk+1),sp     ;сохраняем стек
ADDR = 22528              ;Адрес в атрибутах куда начнём рисовать
rastaCode:
	dup 24            ;24 знакоместа по 8 линий
;=================================
	dup 8
;rastaCode+1+2
      	ld de,00000        ;Тут у нас уже значения подставленные кодом выше
        ld sp,ADDR + 16      ;Cтавим стек на середину строки экрана, луч её только что пролетел на линию выше

            dup 8
            push de;             ;Кладём 16 атрибутов
            edup

;rastacode+15
	ld a,0               ;Цвет бордюра, значение уже подставлено кодом выше
	out (254),a          ;Меняем цвет бордюра 
        ld sp,ADDR+32        ;Ставим стек в конец строки экрана

            dup 8
            push de          ;Бежим навстречу лучу в надежде что он нас не встретит по дороге
            edup
                             ;Ура, мы всё успели и уложились ровно в 224 такта!
	edup
;=================================
ADDR=ADDR+32                 ;Положили восемь строк, нужно перейти на следующий адрес в атрибутах
        edup

stk:	ld sp,00000    ;Восстанавливаем стек


KPACKU SCROLL + GRTZ TO DIVER




Многие критикуют SibKrew за повторы чужих эффектов, не понимая, что у нас такая концепция. В своё оправдание хочется сказать что мы не просто копируем, мы обязательно что-нибудь да добавляем своё. Так же получилось и со скроллом из Kpacku Deluxe. Это достаточно интересный и зрелищный эффект, состоящий из двух задач. Нам необходимо вывести 768*2 атрибутов в разные экраны до того, как луч приступит ко второй задаче и будет выводить пушами пиксельный экран попутно переключая экраны каждую строчку.

Итак сначала сам скролл атрибутов, в моей реализации он основан на том что в у нас в текущем знакоместе в инке хранится текущий цвет, а в папере цвет следующего знакоместа. Таким образом плавно стирая знакоместо справо налево мы получим плавный скрол квадратиков 8х8. Потом нужно только сдвинуть буфер атрибутов когда мы полностью «проявим папер» и повторить процедуру. Чтобы вернуть нам кучу красивых цветов необходимо во время заполнения пиксельного экрана нужной нам «маской-патерном» знакомест ещё и переключать экраны каждую строчку. Также надо рисовать патерн в экран который будет виден на следующей линии, т.е. мы как-бы отстаём от луча на одну линию.

Задача осложнялась ещё и тем что в отличии от ребят из Красок нам нужно было уложится в 16 кб, а сама картинка, которую мы будем скроллить занимает достаточно много места, а именно 256*24*2 = 12288 байт. Поэтому пришлось всё усложнять чтобы уложится в 224 такта на линию и воспользоваться такими штуками как jp (iy) и jp (hl).

Выглядит это примерно так:


        ; переброс патерна экрана   
	ld (stack+1),sp ;сохраняем стек
        
    ld      a, 11111111b    ;Маска-патерн экрана
inkPattern  equ     $-1     ;Видно что тут уже похозяйничал Артёмка, я пишу по олдскульнее
    
        ld d,a : ld e,a     ;Сохраняем патерн в DE

	ld iy,jpiy          ;Подгатавливаем к прыжкам через jp (iy)
                            
                            ;Очень грубая реализация интерлейс
                            ;патчим байтики в b1 b2 снаружи чтобы менять порядок линий интерлейса

b1:	ld a,16+7           ;Показывать первый экран и изменять второй
        exa                 
b2:     ld a,16+5+8         ;Показывать второй экран и изменять первый
        exa
    
globalLine = 0              ;Номер пиксельной линии экрана, да я использую прям переменные, без макросов :)
	dup 193
XX = 0
line = globalLine % 8
YY = globalLine / 8
a1 = ( YY / 8 ) * 2048
a2 = ( YY % 8) * 32
addr  =  49152 + a1 + a2 +line*256+XX	 ;Вычисляем адрес нужной нам линии экрана

	ld sp,addr+32                    ;Ставим стек в конец линии экрана
	exa                              ;Он же ex af,af, опять рука Артёма
	out (c),a                        ;Включаем нужную нам комбинацию экрана и страницы
	ld hl,$+5                        ;Адрес возврата в HL
	jp (iy)                          ;Рисуем одну линию патернов в DE c возвратов по jp (hl)
globalLine=globalLine+1
	edup

stack:  ld sp,00000


Процедура которая выводит одну линию очень простая:


jpiy:
	dup 16 : push de : edup    ;Кладём байты в экран
	jp (hl)                    ;Возвращаемся обратно по адресу в HL


Теперь о том как скопировать все атрибуты в оба экрана, это делается простой связкой pop hl: ld (addr),hl с одним нюансом. В верхнем бордере это всё не успеть сделать, поэтому часть атрибутов начинает кидаться сразу после того как луч нарисовал картинку, а оставшаяся уже после halt.

Саму картинку я рисовал в самописном редакторе который я сделал для финала в OverRelaxed. Для гритцов я добавил в него запись событии, откат на событие назад и параллельный скролл, чтобы полностью имитировать то что будет в деме. Событие это просто адрес в буфере и атрибут. Скролл иногда обгонял картинку, поэтому приходилось делать всякие художественные завитки. В итоге повторив процесс дважды я получил массивы событий для двух «кистей» которые всё рисуют, получилось меньше 3кб.

МУЗЫКА


Чтобы немного отдохнуть от кода дадим слово нашему музыканту n1k-o

Значит, трек из харымабыру делался легко и непринужденно, ремикс же, что там делать-то!



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



nq-haramamburook-1.pt3

А затем просто заполняем пустое пространство – мелодия же есть, бас тоже: прописываем ударные, чуть правим под них же басы и трельки, потом даблтрекуем и отдельный момент на сбивках, плюс — не забываем о том, что в деме нужно последовательное наращивание, чтобы не сразу в лицо всеми орудиями, оставляем кое-какие элементы на финал трека. Трек готов! Приправить по необходимости фиксом, обязательно по вкусу мигнуть и потрясти.

nq-haramamburook.pt3

VASYLIEV SKROLL



Идею сгенерировал Daniel на форуме zxdemos.ru. Он предложил сделать классическую атриубтную бегучку которую можно плющить с помощью мультиколора. В процессе написания эффектов я вспомнил про эту идею и решил сделать! Для начала я выдрал шрифт из рандомной интрухи Антона Васильева и сгенерировал на его основе большой атрибутный шрифт с тенью, распарсив каждую букву оригинального. Примерно таким кодом:


        ld a,(de)               ;берём байт из оригинального шрифта
	dup 8
	rla			;сдвигаем
	jr nc,1f		;если нет битика то пропускаем
	ld (ix),7+7*8+64	;точка есть – кладём байт цвета буквы		
	ld (ix+7),0 		;тень
1:
	inc ix			;следующая точка
	edup


Про то как сделать писксельную сетку я даже не буду описывать, просто пушим байтик и скролим его. Затем мы покрываем нашу сетку обычным мультиколором 8х2, но с возможностью менять источник каждой линии мультиколора:



	exx
	ld bc,#7ffd : ld de,16+7+(24+5)*256 ;для попеременно подключения основного экрана и теневого в банку и обратно
	exx

N=6
MCLOOP:
	dup 12
	dup 2
addr = 49152+6144+32*N
	ld sp,00000             ;строчка мультиколорного буфера с которого рисуем, будем изменять её чтобы искажать картинку
	exx: out (c),d : exx    ;показываем теневой экран и подключаем в банку основной
	dup 16
	pop hl: ld (addr),hl   ; спокойно пишем байтики в невидимый экран не переживая по поводу луча
addr=addr+2
	edup	

addr = 49152+6144+32*N
	ld sp,00000            ;строчка мультиколорного буфера с которого рисуем, будем изменять её чтобы искажать картинку
	exx: out (c),e : exx   ;показываем основной экран и подключаем в банку теневой
	dup 16
	pop hl: ld (addr),hl   ; спокойно пишем байтики в невидимый экран не переживая по поводу луча
addr=addr+2
	edup

	nop                    ;Добавляем 4 такта задержки так как мы сделали всё чуть быстрее чем 224*2 такта

	edup
N=N+1
	edup



Теперь изменением значений в ld sp, ххххх, мы можем искажать наш отображаемый буфер в который мы рисуем бегучку. У делаю это на основе «шаблонов искажений» с помощью стека всё тем же стандартным pop ld, вот так:


    
        ld sp,scaleTemplate ;стек на шаблон

        ;path
ADDR=MCLOOP+1
	dup 24
	pop hl            ;берём адрес
	ld (ADDR),hl      ;патчим мультиколор
	pop hl            ;берём адрес
	ld (ADDR+71),hl   ;патчим мультиколор
ADDR=ADDR+259-116
	edup


Сами шаблоны представляют собой просто список адресов мультиколорного буфера в нужной нам последовательности.

SETKA V KLETKU




Очень простой чисто атрибутный эффект в ловресе который лежал со времён Qumi Demo. Достаточно взглянуть на пиксельную подложку чтобы понять как оно сделано. Все движения получаются с дискретностью в 4 пикселя, если координата полосочки чётная то выводим одну комбинацию ink,paaper если нечётная то другую. Всё успевает отрисоваться до интерлейса, так что большую часть фрейма просто переключаются линии экрана.



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

ГРАФИКА И ЗАТУЛИНСКИЙ ТУННЕЛЬ


Давайте ещё раз отвлечёмся от моего повествования и послушаем парней.

r0bat Пришел Денис, накидал референсов, сказал, СЛЫШЬ РИСОВАТЬ, ну я и нарисовал. Потом еще неделю в голове харамамбуру играла без остановки!



wbcbz7 БЗЗ, БЗЗ, ЗАТУЛИНКА, ДОСОВАНИЕ, Я ПОБЕЖАЛ, БЗЗ, БЗЗ! если вкратце, то таблички шас спокойно можно на луе считать… на самом деле это обычный табличный туннель, просто в табличке подряд идут смещения для четной и нечетной строки в столбце, потому что 8x4 а иллюзия многослойности достигается просто хитрой текстурой :) соответственно 4 верхних строки знакомета — инк, 4 нижних — папер далее в иннерлупе читаем два тексела из текстурок и накладываем :)

REALTIME MORPHING CAT




Искажающийся кот на 90% сделан на основе того, что я уже описывал в статьях про свои мультиколорные скроллерные игры. Также 25fps, пиксели вокруг луча и мультиколор 8х1. Искажения сделаны тем же способом что и в мультиколорном атрибутном скролле Васильева. Такой же патчинг адресов в ld sp,xxxxx. Только шаблон искажения содержит дельты, на которые мы шагаем. Двигаясь по шаблону, мы получаем волны пикселей и цветов безо всякого клэшинга. Миракл!

Патчинг и шаблоны искажений:


bcSin:	ld bc,sinDist     ;Указатель на шаблон искажений, выровненый на 256 байт для зацикливания
	inc c : inc c     ;Шагаем по нему
	ld (bcSin+1),bc   ;Сохраняем новое значение

patch:
N=0
	ld d,0
	ld hl,picAddr     ;Адрес атрибутов картинки в формате 8х1

	dup 136             ;136 линий в высоту
	ld a,(bc)           ;Берём дельту
	ld e,a:add hl,de    ;Прибавляем к текущему адресу
	ld (testBuf+N*2),hl ;Патчим мультиколор по фиксированным адресам
	inc c
N=N+1
	edup


sinDist:
	dup 16
	db 16*1,16*1,16*0,16*1,16*1,16*1,16*1,16*1,16*1,16*2,16*2,16*1,16*1,16*1,16*1,16*1,16*0
	db 16*1,16*1,16*1,16*1,16*0,16*1,16*1,16*1,16*1,16*1,16*2,16*1,16*1,16*1,16*1,16*0,16*2
	edup


На этом всё, ребяты! Пишите демосцены, делитесь опытом и трюками!

Всем добра!

Ссылки на саму дему и видео:

POUET

YOUTUBE:

LIVE:

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

avatar
Круто, спасибо! Скролл Васильева очень доставил.
avatar
Очень хочется прокомментировать статью, но пока не знаю, что написать!
Потому что я так и не понял, как всё это работает. Но Денис, ты мега молодец! И Артёмка тоже! И Олежа!
  • sq
  • +2
avatar
А я не молодец значит? :(
avatar
Ты не просто молодец! Ты охренеть какой вообще супер мега молодец!!!
avatar
avatar
Это строго Пентагон в итоге?
avatar
В таком виде, да. Для классики нескольких эффектам пришлось бы ширины подрезать в пару знакомест, а то и передизайнить :)
avatar
наши европейские партнеры не одобрят конечно такой подход к исконным ценностям
avatar
Я провёл специальное исследование и выяснил что ютуб смотрят 90%,9% смотрят в эмулях и умеют включать пентагон, и 1% пытается запустить на своих divmmc. А если серьёзно то я третьего дня объяснял уже что я раньше делал тапки и фиксил под классику, но никакой разницы не заметил, как не смотрели наши европейские партнёры так и не смотрят. А вот в играх другое дело, смотрят, играют, донатят и фидбэчат так что спектрум демы на поуте просто тихо краснеют в дальнем углу спектрумизма.
avatar
Да вы исследователь почище британских ученых! :-)

На самом деле и .TAP и поддержка оригинального железа это вопрос религиозный. В момент, когда мы его откидываем, начинается noflic, gigascreen, а там и до ATM2+ недалеко…
avatar
Считайте меня атеистом!
avatar
Плюсанул бы дважды, если бы мог ) Спасибо за дему и за статью! Kpacku Scroll великолепен.
avatar
Нужно еще больше Thumbs на Pouet!

Плюсуй по славу Великого Секущего Луча! https://www.pouet.net/prod.php?which=83540
avatar
Поступило важное дополнение про туннель от wbc которое полностью объясняет как он сделан, приведу его полностью:

на самом деле это обычный табличный туннель, просто в табличке подряд идут смещения для четной и нечетной строки в столбце, потому что 8x4

а иллюзия многослойности достигается просто хитрой текстурой :)

соответственно 4 верхних строки знакомета — инк, 4 нижних — папер

далее в иннерлупе читаем два тексела из текстурок и накладываем :)
avatar
Денис, отличная работа и очень прикольный write-up. Воббл с котом меня зацепил в деме больше всего, хотя мне показалось, что ты его недодержал. Очень хороший туннель, и как обычно с нетривиальной палитрой. А вот васильевский скролл я просмотрел, причём дважды, видимо увидел «старьё» и выключился, а дальнейший его расколбас пропустил мимо ушей.

Если честно, насколько мне понравилось всё визуально и технически, настолько же мне было тяжело принять общий посыл работы. Наверное, для меня это было самое негативное из твоих демо. No grtz to diver меня меньше расстроила. Ты иногда шутишь больше, иногда меньше, но тут я просто не засмеялся, наверное, не разу за всю дему. Внешние атрибуты юмора соблюдены — Харамумбура, мультяшные физиономии, но текст чёрный и я не знаю что с этим делать. Наверное, я какая-то антицелевая аудитория для тебя.
avatar
\o/

Судя по тому что полуживая аудитория на пати среагировала на все панчи и даже на некоторые не очевидные, то я думаю что не промазал с юмором :) У тебя да, своё чувство юмора и действително я в него не целился. Шутки же на поверку абсолютно не злые, просто они максимально утрируют те посыли и стериотипы которыми шедро награждают спектрумистов.

С другой стороны все эти шутки я написал как временные, но ближе к нашему локальному дедлайну 14 октября оказалось что менять их уже некогда. Из-за этих же сроков не удалось сделать микрофиксов всяких и пришлось оставить самый простой вариант которые я сделал по рыбе Олежи.
avatar
Спасибо, что написали! Интересно посмотреть, как DUP и увеличение переменной могут быть использованы для получения крутых эффектов!
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.