Page 1 of 1

SYNCHRONIZATION - Cyrcles Text Mode

PostPosted: Tue, 24.07.2018 21:19:54
by robus
Привет всем.

На последнем собрании true zx'еров, мы все много общались. Ваня Пирог и Вал просили меня объяснить, как же был сделан эффект "XOR-CYRCLES" в SYNCHRONIZATION. Но я как не шуршал мозгами замаринованные в коньяке, так и не смог вспомнить.
Речь идёт вот про этот эффект https://youtu.be/e4gy3lJ3ZU4?t=382

Итак, как же оно работает ... Всё очень просто, но нужно вчитаться ... Итак есть текстовый режим и прерывания на каждую строчку, начиная с минус один от первой отображаемой линии.
1. Вначале прерывание, которое происходит 240 раз. Оно нужно, что бы в первую очередь, задать новую отображаемую линию для текстового режима, и во вторую очередь выпендриться и покрасить бордюр в новый цвет. Но главная фишка именно в обновлении отображение новой линии. У меня есть зарезервированные страницы с какого-то там места, выделенного автоматически под именем VTX_PAGE. В VTX_PAGE лежит экранная область отображаемая TSLDac'ом, но линейно. То есть вначале отобразятся первый 64 символа, потом вторые, ну и так 240 раз ... В итоге у нас получается некая видео-область размером в 240*64, что является 8-ми tslстраниц. Нужно помнить, что у Вала каждая новая строчка пересчитывается с учётом смещения по Y, в итоге каждое прерывание обновляет новое смещение по Y и высчитывает новый адрес страницы для VideoPage. Выглядит это так:
Code: Select all
INPEx2  LD HL,0
        LD BC,8
        ADD HL,BC
        LD (INPEx2+1),HL
        LD BC,TSL.GYOffsL
        OUT (C),L
        INC B
        OUT (C),H
        LD B,HIGH(TSL.Vpage)
        LD A,H
        AND 00000110B
        ADD A,VTX_PAGE
        OUT (C),A

2. Далее подготовка графики для текста. В предыдущем пункте решена проблема с отображением, теперь когда у нас есть линейное отображение памяти в пикселях, можно заниматься магией. Итак, у нас высвечивается 480 по 8 пикселей, код текста с адреса VTX_PAGE+64*LINE. Реальных, а точнее привычных нам пикселей не 8 а 4, по скольку текст в двое плотнее стандартного графического режима. Теперь перед всем этим эффектом, один раз заполняем графику текста, так что бы код буквы соответствовал XORу верхней и нижней тетрады кода символа.. То есть например код отображаемого символа в бинари такой "10010011" это значит что я хочу сделать "1001" XOR "0011" = "1010". Отлично, теперь символ с кодом "10010011", заполняем графикой восемь раз "11001100", что равно "1010". Однако, сделаем эффект более интересный, где пиксели будут преобладать над пустотой, тогда появится "жирность". Так что сегенируем табличку ITEG_TBL из 16-ти значений утолщённых пикселей. Графика текста складывается в страницу (VTX_PAGE+1). Генератор графики получается таким:
Code: Select all
InitTextGFX:
        LD A,VTX_PAGE+1
        CALL IORQTS.RAMPage3
        LD HL,49152
        LD BC,0000H
        LD D,HIGH(ITEG_TBL)
ITEGx1  LD A,C
        RRCA
        RRCA
        RRCA
        RRCA
        XOR C
        AND 00001111B
        ADD A,LOW(ITEG_TBL)
        LD E,A
        LD A,(DE)
        .8
         LD (HL),A
         INC L
        ..
        ORG $-1
        INC HL
        INC C
        DJNZ ITEGx1
        RET
        ALIGN 16
ITEG_TBL  ;   0 0 0 0
          DB 00000000B
          DB 00000011B
          DB 00001110B
          DB 00001111B
          DB 00111000B
          DB 00111111B
          DB 00111110B
          DB 00111111B
          DB 11100000B
          DB 11110111B
          DB 11101110B
          DB 11101111B
          DB 11111000B
          DB 11111011B
          DB 11111110B
          DB 11111111B


3. Далее подготовка кругов. Я не буду расписывать сам генератор, но смысл прост, на нужно сгенерировать 8-мь гигантских экранов размером 128х512 байт, где графика будет хранить в верхней тетраде, и ещё 8-мь экранов точно таких же, где графика будет в нижней тетраде. Получится что нужно 128*512*8*2 = 1 мегабайт памяти. Его и заполняем графикой кругов. Вот пока вылетает череп с шариками вместо глаз, это и происходит на заднем плане ...

4. Далее DMA копирование, которое будет формировать изображение. Тут всё просто ... Вначале нужно скопировать с помощью DMA, с флагом RAM_RAM, из первой области гигантского экрана в VTX_PAGE видео-области. Следующим шагом скопировать в то же самое место VTX_PAGE видео-области из второй области гигантского экрана но с флагом BLT_RAM. Получается что вы скрестите верхние и нижние тетрады двух гигантских экранов с кругами в видео-области. И по-скольку графика каждого кода символа уже раскранчена XOR'ом, у вас получается аппарат, который сам за вас XOR'ит. Ваша задача только задавать DMA аппарату, что, куда и откуда копировать, ну и процессором ничего не делать. Вот выдержка процедур, которые копируют и ждут:
Code: Select all
        CALL INTDMA0
        CALL IORQTS.DMA_WAIT
        CALL INTDMA4
        CALL ShowBallA
        CALL IORQTS.DMA_WAIT
        CALL INTDMA1
        CALL ShowBallB
        CALL IORQTS.DMA_WAIT
        CALL INTDMA5
        CALL IORQTS.DMA_WAIT
        CALL INTDMA2
        CALL IORQTS.DMA_WAIT
        CALL INTDMA6
        CALL MUSIC.PLAYSTEP
        CALL IORQTS.DMA_WAIT
        CALL INTDMA3
        CALL IORQTS.DMA_WAIT
        CALL INTDMA7
        RET

Если присмотритесь, то пока DMA что там копирует я не сильно парясь обновляю координаты шариков - "ShowBallA" и "ShowBallB", где-то в конце ещё и музыку играю "MUSIC.PLAYSTEP".


А теперь похвастаюсь своим MASONом. Сверху виден пример, что в середине прерывания я вызываю "MUSIC.PLAYSTEP". Может показаться, что в каждом эффекте нужно вызывать руками эту процедуру? Это не так! В этом и прелесть этого плеера. Каждое прерывание происходит вот такое:
Code: Select all
        CALL MUSIC.OUT
        CALL SUPER_PUPER_EFFECT
        LD A,MUSIC.PAGE
        CALL IORQ.MUSIC_PAGE_SWITCH_A
        CALL Mas_LOA
        CALL Z,MUSIC.PLAY

Это стандартный аппарат который крутит всю дему или игру. Процедура SUPER_PUPER_EFFECT это ваши действия, где вы показываете графику или что-то ещё. В этой процедуре можно вызвать процедуру "MUSIC.PLAYSTEP", которая за вас переключит страницу, проиграет музыку, и вернёт страницу назад. Далее, выйдя из процедуры вашего эффекта, исполнится процедура "Mas_LOA", которая сама подготовит буфер для отправки на AY и проверит нужно-ли плееру новые данные на следующее прерывание выставляя флаг ZF, что даёт сигнал для вот этой команды "CALL Z,MUSIC.PLAY". Таким образом вы в прерывании можете вызвать 10-ть раз процедуру "MUSIC.PLAYSTEP", и автоматически на 10-ть прерываний вперёд сохранятся данные для AY'ка. Догадайтесь сами какие возможности у вас появляются. Кстати, можно вызвать процедуру "MUSIC.PLAY0", и тогда в буфер упадёт только данные канала "А", ну а если вызвать "MUSIC.PLAY1", то данные канала "В"! Можете делать это в любой момент, когда вам это удобно и главное, все эти вызовы стабильны в прерывании. То есть всегда будут занимать одно и то же количество тактов, при любых данных музыки.



Я не знал в какую рубрику отнести этот топик, поэтому если это больше подходить для, например, "демо", то прошу перебросить его "туды", или ещё "куды".

Re: SYNCHRONIZATION - Cyrcles Text Mode

PostPosted: Tue, 24.07.2018 22:35:39
by VBI
хитрость со ксором - отличная, просто отличная!

Re: SYNCHRONIZATION - Cyrcles Text Mode

PostPosted: Thu, 26.07.2018 07:48:46
by TS-Labs
robus wrote:Я не знал в какую рубрику отнести этот топик, поэтому если это больше подходить для, например, "демо", то прошу перебросить его "туды", или ещё "куды".

Правильная рубрика ) Может еще закинь на хайп?

Re: SYNCHRONIZATION - Cyrcles Text Mode

PostPosted: Thu, 26.07.2018 17:10:00
by robus
Если на HYPE, тогда Вока и Вал, предлагаю расписать все эффекты со всей демки. И тогда надо ещё и графику с музыкой затронуть. Как вы думаете стоит такое делать? Я бы хотел написать эти статьи. Думаю Вовка про свои эффекты распишет. И с большим удовольствием почитал бы про эффект Вовки на фоне робота, этот эффект пример как из рандома делают последовательность, и в итоге получается конфетка. =)

Re: SYNCHRONIZATION - Cyrcles Text Mode

PostPosted: Thu, 26.07.2018 19:15:53
by TS-Labs
Да даже один этот эффект стоит отдельной статьи. По крайней мере несколько человек уже пыталось его разгадать.

Re: SYNCHRONIZATION - Cyrcles Text Mode

PostPosted: Thu, 26.07.2018 21:16:40
by WBC
"вот оно что..." :)
Как-то мы с introspec'ом тоже пытались расколоть этот эффект и пришли к немного другой идее: заполнить знакогенератор таким образом, чтобы графика символа соответствовала его коду, как в случае монохромного 6144 (то есть например символ с кодом 0xAA дает нам на экране #_#_#_#_). Если на строчных прерываниях сдвигать экран каждые 8 строк вниз (и попутно не забывая переключать страницы при переходе через 63-ю строку), то на выходе получим своего рода ~720x288 8x1 multicolor :)
Далее вооружаемся Z80, настраиваем стек и рисуем на этом экране, но здесь уже возникает другая проблема - сделать подобный эффект "в лоб" процом в один фрейм не получится (даже на 14мгц вот такой иннерлуп:
Code: Select all
здесь SP и HL - графика кругов, DE - указатель на экран

POP BC
LD A, [HL] : INC HL
XOR C
LD [DE], A : INC DE
LD A, [HL] : INC HL
XOR B
LD [DE], A : INC DE
; 62t на пару байт
хотя можно и подускорить

для экрана (720/8)*288 = 25920 символов будет выполняться ооочень долгие 803520 такта (на самом деле больше из-за тормозов памяти, пусть даже с кэшем), что в one-frame никак не уложится. Блиттер тут тоже не поможет - битовым операциям он не научен, максимум - BLT копирование с прозрачностью для 0-го пиксела в 16/256c, для BLT2 - еще и сложение с насыщением до 15\255, но оно тут тоже не помощник.

Вариант два - использовать как фреймбуфер непосредственно знакогенератор, заполнив буфер символов последовательно кодами 0..255, тогда для режима 80x30 одним шрифтом можем гарантированно заполнить 3 строки текстмода = 24 строки графики, соответственно надо переключать каждые 24 строки шрифт, и при таком случае получим уже экранку ближе к классическому 6912 со всеми его ограничениями :)

Вариант три Робуса, конечно, жжот, до него мы не догадались :) а вообще получилось очень классно, респект!

Re: SYNCHRONIZATION - Cyrcles Text Mode

PostPosted: Thu, 26.07.2018 22:31:11
by robus
Кстати ... Кэш это "апупезная" штука !!! На кэше можно творить чудеса. Теперь появилась проблема пришедшая с момента, когда появилось много пикселей, например в АТМ. Процессор просто не способен справиться с таким количеством пикселей. Но есть супер "НО". Есть кэш, который ещё недооценен. Да, не получится сделать процессором xor или например ротатор, но можно придумать подобный эффект ротаторам. Вот я года три тому недосделал игру JIMMY, которую показывал и Валу и Вовке, где именно на кэше сделал анализ карты 128х128 элементов. JIMMY это аналог BOULDER DASH или EARTH SHAKER, точнее эта игра поглотила обе этих игры, плюс ещё куча фишек. И вся анимация всё в ней попиксельное, с учётом того что ONE-FRAME обрабатывается карта 128х128 элементов. Что бы вы понимали, каждый элемент влияет на другой, с учётом направления гравитации. Вот это вообще не возможно, однако за счёт кэша, я расчитал так что бы куски кода не перекрещивались с гранулярностью по 512 байт, и сделал так, что бы редко-встречаемые объекты по памяти исполнения кода передвигались в область не требующую кэширования. Если попытаться проанализировать код, то кажется что это жуткий набор каких-то кусочков. Игру я так и не доделал, хотя есть полный автомат для сбора графики уровней и упаковывания этого всего в релиз. Ещё на кэше у меня есть семь эффектов, один из них в текстовом режиме, и он 3D, конечно же. как всегда, фокусы.
Вообщем кэш это круть, он даёт возможность пока копируется что-то DMAшкой шуршать процессором. В синхронизации принципиально не использовалась такая возможность, по скольку идея была в том, что бы показать именно аппаратные фокусы.

Re: SYNCHRONIZATION - Cyrcles Text Mode

PostPosted: Thu, 26.07.2018 22:46:25
by robus
Так, сейчас на HYPE переброшу эту статью ... Наверное дам название что-то типа "SYNCHRONIZATION Secrets ... XXX", где XXX это название(порнуха) эффекта ... =)