Hacker VBI, Да - интересно почитать про TS в доступном виде = продолжай ))
Hacker VBI, Да - интересно почитать про TS в доступном виде = продолжай ))
С уважением, Дмитрий.
piroxilin, это хорошо.
в общем, есть ещё один разбор.
MindWarp от DDp
Смотреть бум только первую часть балета - эффект, завязанный на палитре
Что имеем сразу в страницах памяти: сформированное изображение для экрана, сотни килобайт звука для ковокса.
Картинка для экрана - чёрнобелая.
Суть эффекта - в смене палитры для изображения на экране.
изображение палитры - во вложении.
берём в b адрес порта, в а - данные, бросаем в порт:Код:org 0x6200 binclude "mw_pal.bin" ld iyl,3 restart:di ld sp,0x6000 ld hl,mw_int ld (0x67ff),hl ld a,0x67 ld i,a im 2 ; копируем палитру ld hl,0x6200 ld de,0x6000 ld bc,0x0200 ldir ; начинаем заброс данных в порты: ld hl,mwset ld e,(mwset_end-mwset)/2 ld c,0xaf wrrg1: ld b,(hl) inc l ld a,(hl) inc l out (c),a dec e jr nz,wrrg1
0x20,6 - System Config, %10 -ставим частоту 14.0,normal, кеш включен.
0x00,0xc2 - VConfig, включаем макс разрешение 360x288, 256 цветов.
0x01,MW_PIC_PAGE - Video Page, включаем страницу 16 с изображением
0x02,0 - X-offset for graphics, отступы окна просмотра в 0.
0x03,0
0x04,0 - Y-offset for graphics
0x05,0
0x1a,0x00 - DMA Source Address
0x1b,0x20
0x1c,5 - DMASAddrX, страница
0x1d,0 - DMA Destination Address
0x1e,0
0x1f,0 - страница приёмника
0x26,255 - DMA Burst Length, 512 байт за один бурст
0x28,0 - DMANum, колво бурстов - 0 (это 1) штука.
0x27,0x84 - DMACtrl, здесь RAM (Src) is copied to CRAM (Dst)
насколько я понимаю, здесь перебрасывается палитра в память CRAM
что имеем выполняемого?Код:ld hl,0x2000 ; палитра ld de,0x0020 ; сдвиг по палитре ld a,0x84 ; DMACtrl, здесь RAM (Src) is copied to CRAM (Dst) exx ex af,af' ld bc,0x13af ; память со звуком ld de,1 ; инкремент на 1 при воспроизведении ei sloop0: ; здесь происходит вывод звука в ковокс в основном цикле ld a,MW_SND_PAGE jp sloop3 snewpg: ld a,(sndpage) sloop3: out (c),a inc a ld (sndpage),a ld hl,0xc000 sloop1: ld a,(hl) or a jr z,sloop0 out (0xfb),a add hl,de jp c,snewpg ld a,MW_SND_DELAY ; задержка при воспроизведении sdly: dec a jr nz,sdly jp sloop1 ; непосредственно инт, меняющий палитру mw_int: ex af,af' exx add hl,de ; добавили #20 res 1,h ; больше #2200 адрес не увеличится ld b,0x1a ;DMA Source Address младший байт out (c),l ld b,0x1b; DMA Source Address старший байт out (c),h ld b,0x27 ; выполнение DMACtrl out (c),a exx ex af,af' ei ret ; всё, палитра сдвинулась, на экране красота) sndpage:defb 0 mwset: defb 0x20,6 defb 0x00,0xc2 defb 0x01,MW_PIC_PAGE defb 0x02,0 defb 0x03,0 defb 0x04,0 defb 0x05,0 defb 0x1a,0x00 defb 0x1b,0x20 defb 0x1c,5 defb 0x1d,0 defb 0x1e,0 defb 0x1f,0 defb 0x26,255 defb 0x28,0 defb 0x27,0x84 mwset_end:
для эффекта: три аута в порты по прерыванию,
для звука - простой вывод в ковокс:
Просто?Код:ld a,(hl) or a jr z,sloop0 out (0xfb),a add hl,de jp c,snewpg ld a,MW_SND_DELAY ; задержка при воспроизведении sdly: dec a jr nz,sdly
Описание работы эффекта от автора - DDp
Код:Все данные уже подготовлены в нужном формате и загружаются в загрузчиком SPG в заданные страницы памяти. Программу можно разделить на две части: подготовка(инициализация) и собственно эффект. При инициализации устанавливается видео режим, предустанавливается регистры DMA (делается первая пересылка - запись в палитру) и др. Перед запуском эффекта в следующих регистрах установлены значения: DE = 0001 BC = 13AF A'= 84 HL'= 2000 DE'= 0020 C'= AF Основной цикл использует "первый" набор регистров, а обработчик прерывания "второй". Основной цикл программно проигрывает звук на covox. В обработчике прерывания посредством DMA устанавливается новая, циклически сдвинутая, палитра (пересылка "из RAM в ПАЛИТРУ"). ;------------------------------------------------------------------------------ sloop0: ld a,MW_SND_PAGE ;номер начальной страницы памяти со звуком jp sloop3 snewpg: ld a,(sndpage) sloop3: out (c),a ;установка страницы памяти в окне "С000" inc a ld (sndpage),a ;номер следующей страницы сохранить ld hl,0xc000 ;HL - указатель sloop1: ld a,(hl) ;читаем значение семпла из памяти or a ;конец звука? (см. примечания) jr z,sloop0 ; да - играем с начала out (0xfb),a ;вывод семпла звука в порт covox-а add hl,de ;HL+1 - инкремент адреса jp c,snewpg ;конец страницы? да - включить следующую ld a,MW_SND_DELAY ;задержка между семплами sdly: dec a ; (подобрано значение для скорости jr nz,sdly ; примерно 44100 семплов в секунду) jp sloop1 ;------------------------------------------------------------------------------ ;кадровое прерывание mw_int: ex af,af' ;переключаемся на "второй" exx ;набор регистров ;в HL указатель на значения палитры в памяти add hl,de ;HL+32 - коррекция указателя res 1,h ;ограничивает перемещение указателя в пределах 512 байт ld b,0x1a ;"DMA Source Address" - LOW out (c),l ld b,0x1b ;"DMA Source Address" - HIGH out (c),h ld b,0x27 ;"DMA Control / Start" out (c),a ;0x84 - запуск DMA в режиме "из RAM в ПАЛИТРУ" exx ;переключаемся на "первый" ex af,af' ;набор регистров ei ret ;------------------------------------------------------------------------------ Примечание по звуку. Данные звука - PCM unsigned 8bit. Отфильтрованы значения 0x00 и заменены на 0x01. Значение 0x00 используется как флаг "конец звука". Думаю, вполне можно уместить эффект в 256 байт, если картинку и палитру сгенерировать программно. "Гипножаба" работает похожим образом: основной цикл программно проигрывает звук на covox, а в обработчике прерывания посредством DMA обновляется часть экрана размером 112x48 пикселей (пересылка "из RAM в RAM_с_Выравниванием_512"). http://rghost.ru/55036812/image.png
Последний раз редактировалось Hacker VBI; 09.05.2014 в 11:44.
Пример с фреймовыми\строчными интами не хочешь покурить для тренировки?
line-ints.zip
скрин эффекта - внизу
Итак, что имеем в эффекте:
все строки изображения плавно перемещаются в горизонтальной плоскости по синусу.
за прерывание
изображение - 320х200, 16 цветов
некоторые части кода, связанные с синусом я пока не затрагиваю, интересен именно механизм прерываний.
Buyan обьяснит свой прикольный эффект немного позже и гораздо доступней, чем я сейчас
Начнём. Сначала - уже знакомая по этой теме предварительная фаза: установка разрешения/цветности, скорости/кеша, выбор палитры, инициализация позиций окна вывода экрана, указание на место экрана в памяти.
здесь можно отметить две интересные подпрограммы - очистка экрана с помощью дма, и с его-же помощью перемещение графики на экран.
Скрытый текст
Код:device ZXSPECTRUM128 include dev\ts-ports.asm org #8000 start di ld sp,49151 ld a,128 call clear_vpage call gfx_copy call init_gfx call init_zx_pal call init_im2 ei stop jp stop init_gfx ld bc,VConfig ld a,%10000001 out (c),a ld bc,SysConfig ld a,%00000111 out (c),a ld bc,PalSel ld a,%00000000 out (c),a ld hl,0 ld bc,GYOffsL out (c),l ld bc,GYOffsH out (c),h ld bc,GXOffsL out (c),l ld bc,GXOffsH out (c),h ld bc,VPage ld a,128 out (c),a ret[свернуть]
итак, инициализация прерывания.
читаем мануал:
"...В TS-Conf можно запрограммировать несколько источников маскируемого прерывания. Среди них:
- кадровый (frame, индекс 0),
- строчный (line, индекс 1),
- окончание DMA транзакции (dma, индекс 2).
Источник frame срабатывает, когда значение счетчиков растра совпадает с регистрами HSINT и VSINT. Источник line срабатывает в каждой строке, когда горизонтальный счетчик растра равен 0. Источник dma срабатывает после окончания любой транзакции DMA.
Каждый источник прерывания формирует сигнал ~INT и выставляет собственный байт D[7:0] на ШД в цикле ~IORQ || ~M1.
- $FF - кадровый,
- $FD - строчный,
- $FB - DMA."
здесь можно отметить установку горизонтального HSINT и вертикального VSINT прерывания (INT) в ноль - начало отрисовки экрана. замечаем, что адрес обработчика прерывания записывается в адрес #beff, что говорит о фреймовом вызове. ну типа каждый кадр. как обычно, в общем
после разрешения, и как начинаем отрисовывать экран с абсолютного 0,0 - происходит прерывание im_blank.
Скрытый текст
Код:init_im2 ld a,#be ld i,a ld hl,im_blank ld (#beff),hl ld bc,HSINT ld a,0 out (c),a ld hl,0 ld bc,VSINTL out (c),l ld bc,VSINTH out (c),h im 2 ret init_zx_pal ld a,%00010000 ; маппинг на #0000 ; 0 - ZX palette ld bc,FMAddr out (c),a ld hl,zx_palette ld de,0 ld bc,32 ldir xor a ld bc,FMAddr out (c),a ret zx_palette include "dev\zx_palette.asm" im_blank di push af ex af,af push af push hl push de push bc push ix push iy exx push hl push bc push de ld hl,30+24 ld bc,VSINTL out (c),l ld bc,VSINTH out (c),h ld hl,im_blank_off ld (#beff),hl ld de,(roll_beg) ld (roll),de inc de ld a,d and %00000001 ld d,a ld (roll_beg),de pop de pop bc pop hl exx pop iy pop ix pop bc pop de pop hl pop af ex af,af pop af ei ret frame_counter defw 0 flag defb 0 roll_beg defw 0[свернуть]
по приходу im_blank в строчный регистр интов VSINT устанавливаются значения нового обработчика фреймовых прерываний,
которые будут вызваны по началу отрисовки строки 30+24 (54).
другими словами, пропуск отрисовки линий, ибо пока малюется бордюр.
следующий инт приходит на 54 строке экрана, и попадает в im_blank_off
Скрытый текст
Код:im_blank_off di push af push hl push de push bc ld hl,31+24+240 ld bc,VSINTL out (c),l ld bc,VSINTH out (c),h ld hl,im_blank_on ld (#beff),hl ld bc,INTMask ld a,%00000011 out (c),a ld hl,line_proc ld (#befd),hl pop bc pop de pop hl pop af ei ret[свернуть]
указываем, что следующее прерывание должно возникнуть на строке 31+24+240 - а это у нас конец экрана и начало бордюра, и вызывать im_blank_on для фреймового int.
Разрешаем строчный инт - по строкам будет приходить прерывание на line_proc. Отмечаем, что строчный инт у нас пишется по #befd
RTFM: "Регистр конфигурации INTMask содержит биты разрешения индивидуального источника маскируемого прерывания, 0 - запрещен / 1 - разрешен.
бит 0, FRAME - разрешение источника frame,
бит 1, LINE - разрешение источника line,
бит 2, DMA - разрешение источника dma,
биты 3-7 - не используются, записывать 0."
Скрытый текст
Код:im_blank_on di push af push hl push de push bc ld hl,0 ld bc,VSINTL out (c),l ld bc,VSINTH out (c),h ld hl,im_blank ld (#beff),hl ld bc,INTMask ld a,%00000001 out (c),a pop bc pop de pop hl pop af ei ret[свернуть]
следующее прерывание пришло на im_blank_on. указываем приход нового фреймового с позиции 0 (новый кадр), вырубаем строчные инты - пропуск бордюра. и опять по кругу.
что же делают здесь строчные инты? КАЧАЮТ девочек
line_proc отрабатывает с позиции VSINT от 54 до 295 (область экрана) и бросает в порт GXOffs ("X-offset for graphics") сдвиг по х для текущей строки, взятой из текущего положения переменной roll, + sines_tab (которая указывают на таблицу синусов):
Скрытый текст
Код:line_proc di push af push hl push de push bc ld de,(roll) sin_tb ld hl,sines_tab add hl,de inc de ld a,d and %00000001 ld d,a ld (roll),de ld a,(hl) ld bc,GXOffsL out (c),a pop bc pop de pop hl pop af ei ret roll defw 0 sines_tab include "\dev\sineline.asm"[свернуть]
дма очистка и ldir на экран:
Скрытый текст
Код:clear_vpage push af ld bc,Page0 ld a,33 out (c),a ld hl,0 ld (0),hl ld bc,DMASAddrX ld a,33 out (c),a ld hl,0 ld bc,DMASAddrH out (c),h ld bc,DMASAddrL out (c),l ld bc,DMADAddrX pop af out (c),a ld hl,0 ld bc,DMADAddrH out (c),h ld bc,DMADAddrL out (c),l ld bc,DMALen ld a,255 out (c),a ld bc,DMANum ld a,255 out (c),a ld bc,DMACtrl ld a,%00000100 out (c),a ld bc,DMAStatus c1rl1 in a,(c) or a jr nz,c1rl1 retКод:gfx_copy ld bc,DMASAddrX ld a,100 out (c),a ld hl,0 ld bc,DMASAddrH out (c),h ld bc,DMASAddrL out (c),l ld bc,DMADAddrX ld a,128 out (c),a ld hl,0 ld bc,DMADAddrH out (c),h ld bc,DMADAddrL out (c),l ld bc,DMALen ld a,160/2-1 out (c),a ld bc,DMANum ld a,240-1 out (c),a ld bc,DMACtrl ld a,%00010001 out (c),a ld bc,DMAStatus s1cp1rl in a,(c) or a jr nz,s1cp1rl ret endcode nop SAVEBIN "1-spg\line-ints.bin",start, endcode-start[свернуть]
Другими словами, за один отрисованный экран было вызвано 3 фреймовых и -надцать строчных прерывания.
аминь
А вот слова автора эффекта, господина Buyan, который любезно предоставил исходники для разбора, ознакомления и изучения принципа работы системы прерываний:
"Такс.. Для начала по растру - у нас в кадре 320 строк. Это размеры видеосигнала с учетом всех бланков, синхр и тд, а не видимой части изображения. Видимых из них соответственно 288 (при максимальном разрешении). Т.е. строки 0-31 на экране мы не видим никогда. Остальные отображаются. Но как они отображаются (т.е. что там отображается - бордер или графика уже зависит от включенного разрешения. Т.е. при 360х288 все строки отображают графику, при 320х240 соответственно 240 строк графику, а остаточные строки сверху и снизу уйдут на бордер.
Теперь по интам: тут у нас есть фреймовый и строчный. Фреймовый инт приходит 1 раз в кадре (при условии что мы по ходу кадра его не перепрограммируем на другую позицию по ходу луча. Строчные же инты после включения будут срабатывать в начале каждой строки, т.е. до 320 раз за фрейм. Отсюда и пляшем:
В данном случае т.к. разрешение выбрано 320х240 нам нужно обработать соответственно 240 строк, ибо качать строки которые на экране не отображаются смысла нет. Для этого и используется несколько обработчиков инта последовательно:
Изначально у нас фреймовый инт настроен на 0 строку. Поехали:
im_blank - пришло прерывание в начале кадра. Тут проинитили синусоиду для качения, ну и как обычно на спеке музычку можно проиграть и т.д. Далее чтобы проц не дергать и невидимые строки не дрюкать переставляем фреймовый инт на im_blank_off - на 30 (неотображаемых) + 24 (бордер) т.е. попадем за 2 строки до начала отображаемых.
im_blank_off - вот мы уже на 30+24 строке и нам пора начать обрабатывать видимые 240 строк строчным интом. Но как нам оганичиться 240 строками если строчные инты долбят по всему диапазону строк? Просто: переставляем фреймовый инт на конец отображения наших 240 строк, т.е. на im_blank_on, который придет в 32(невидимые)+24(бордер)+240 наших качаемых строк и вырубит строчные инты. Переставили. Включаем строчные инты (line_proc)
line_proc вызывается в каждой следующей строке и изменяет ее смещение. Проходит 240 строк и тут срабатывает опять фреймовый инт, который мы перенастроили перед этим:
im_blank_on отрубаем строчный инт и перенастраиваем фреймовый на первый обработчик и начало следующего кадра. Зе енд."
Все экземпляры Евы (вопреки тому, что трындит рупор), при условии прошивания сабжа в оные.
Медленно но верно портируется на Реверс U8, медленно потому что не в лоб, а допиливается, а процесс этот небыстрый. Потом портируем на U16, возможно на другие клоны. Например, она могла бы работать с некоторыми ограничениями v6z80p, если найдется смельчак, чтоб перетащить ее на Xilinx.
в пост MindWarp от DDp добавил описание работы эффекта от автора.
Спасибо ему
Есть такой прием, который называется "дрочка инта".
А как будет рендериться экран, если меняется вертикальное или горизонтальное положение тайлов?
denpopov, ты на сеге игры видел?
так же и будет
там каждую линию данные берутся
С уважением,
Jerri / Red Triangle.
denpopov, как будет рендериться экран, если меняется вертикальное или горизонтальное положение тайлов ты можешь увидеть в инвитре, там такого море.
в моей части с синими шарами меняется положение тайлов на экране по синусу, всех сразу - и норм
насчёт "дрочка инта" в сонике за фрейм вызывается два инта, соответственно два хальта стоит) один инт - начало экрана, красный бордюр, второй инт - средина, белый.
всё
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)