Пример с фреймовыми\строчными интами не хочешь покурить для тренировки?
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 отрубаем строчный инт и перенастраиваем фреймовый на первый обработчик и начало следующего кадра. Зе енд."
![]()








Ответить с цитированием