05 февраля 2003

░░░  ░░░   ░▒▒▒░   ░░░  ░░░  ░▒░░  ░░░░░  ░░░ ░░░   ░▒░  ░░░░░░
░█▓░ ▓█▒  ░▓████░  ▒█▓  ██░ ░███▓ ░████▓  ▓█▒ ░██░ ▒███▒ ░████▒
░██▒ ▓█▓  ▓██████░ ▒██░ ██▒ ▒████░░████▓  ▓█▓░░██░ ▓███▓ ▒████▒
░██▓░▓██░░██▓▒▓██▒ ▒██▒ ██▓ ▓█▓█▒ ▒████▒  ▓██░░██▒ ██▓█░ ▓████░
░███░▓█▒ ▒██░ ░▓█▓ ▒███░██░ ▓█▒░   ██░    ▓██▓░██  ██░░  ░██
░███▓▓█▒ ▒█▓   ▒█▓ ▒███▒██░ ▒██░   ██▓▓▒  ▓███▒██  ▓█▓░  ░██▓▓░
░██████▒ ▒█▓░  ▒█▓ ▒██████░  ▒██░  ████▒  ▓██████  ░▓█▓░ ░████░
░██▓███▒ ▒██▒  ▓█▓ ▒█▓████░   ░██░ ██▓▓░  ▓█▓████    ▒█▓░░██▓▓░
░██░███▒ ░███▒▒██▒ ▒█▓▒███░ ░▒░██▓ ██░    ▓█▒▓███  ░░░██▒░██
▓██ ▓██▒ ░▓██████░░██▓░▓██░░▓████▒ █████ ░██▒░███ ░█████░░████▓
▒██ ░██▒  ░▓████░  ▓█▓ ▒██░░▓████░ ████▓ ░██▒ ▓██ ░████▓░░████▒
░▒▒  ▒▒░   ░▒▒▒░   ░▒▒ ░▒▒░ ░▒▒▒░  ▒▒▒▒▒  ▒▒░ ░▒▒  ░▒▒▒░ ░▒▒▒▒░

                          in basic...

(c) Pix/BrC                         Ижевск
──────────────────────────────────────────
  ┌─┐
  │
  └─┘ вами  в  очередной раз main coder of
Brutal Creators (да простит меня Noviset).
Сегодня я буду глючить на тему  построения
курсора. Я, конечно, не спец в этой облас-
ти, и если вам нужен клёвый и быстрый кур-
сор,  то  это  вам читать противопоказано.
Если  же  вам  побоку  крутость, то читаем
далее.
   Вот, теперь остались  только те, кто не
нашел  статей о курсоре, или те, кто руко-
водствуется  принципом "лишь  бы  пело", а
также  те,  кто  не  очень  крут в кодах и
хочет  понять, как енто оно, блин, работа-
ет. Для последних и написана эта статья.
   Начну  с  проблем, возникающих  у самых
бегинерских  кодеров. Часто  первый собст-
венноручно  написанный  курсор  исчезает в
верхней части скрина или начинает мерцать.
Попытаюсь объяснить причину происходящего.
Для этого  рассмотрим  принцип  построения
изображения  на экране монитора. Как изве-
стно, происходит это замечательное событие
50  раз  в  секунду, сразу  после  прихода
прерывания. Курсор  строится обычно в про-
цедуре обработки прерывания, т.о. курсор и
изображение  строятся одновременно. В про-
цедуре обработки прера происходит примерно
следующее:
   а) восстанавливаем изображение под ста-
рым курсором (стираем его);
   б) сохраняем  изображение в новой пози-
ции;
   в) строим новый курсор;
Т.о. мы  должны  выполнить все 3 пункта до
того  момента, пока видеоконтроллер строит
изображение выше положения курсоров(старо-
го  и  нового). Обычно тормозная процедура
не  успевает  нарисовать  новый  курсор до
того момента, когда место его расположения
начинает  выводится на монитор, поэтому мы
его  и не видим. Отсюда правило: нужно по-
строить  новый  курсор, пока рисуется бор-
дер, а  для этого нужны относительно быст-
рые процедуры. <Примерно то же самое можно
прочитать в ZF#3>.
   Ну, пристипим:
BEGXP   EQU     184  ;начальные координаты
BEGYP   EQU     0    ;у=184 x=0
XY_KOOR DB      BEGXP,BEGYP ;текущие коор.
   Процедуры  наши  должны  быть быстрыми,
посему  все  сложные  (тормозные)  расчеты
сделаем один раз. Например, печатать спри-
та  с точностью до пиксела можно только по
y-ку, а по x шаг дискретный (8pix). Но нам
нужно печатать как по y, так и по x с оди-
наковой точностью,равной 1 pixel. Для это-
го нужно двигать спрайт на кол-во пикселей
равное  остатку от деления на 8. т.е. если
х=10, то  p=x%8=2, значит, нужно  сдвинуть
спрайт на 2 пискела вправо,а затем напеча-
тать  его  в  позицию x/8(char), y(pixel).
Делать это можно в процессе печати, но это
будет  медленно, посему  сделаем  к нашему
исходному спрайту еще 7 образовнных из не-
го  путем сдвига. Их-то мы и будем исполь-
зовать  в процессе вывода. Всей этой муте-
нью будет заниматься процедура инициализа-
ции:
INIT_CUR        ;собственно процедура инициализации курсора.
        LD      A,BEGXP
        LD      (XY_KOOR),A
        LD      A,BEGYP
        LD      (XY_KOOR+1),A
   Создадим таблицу адресов экрана для бы-
строй печати по Y. Для этого переберем все
строки от 0 до 192 и запишем адреса их на-
чал в Tabl_adr.
INT_TAB LD      DE,#4000      ; начало экранной области
        LD      HL,TABL_ADR   ; HL = адрес таблицы
        LD      B,192         ; кол-во строк
INT_TB1 LD      (HL),D        ; заносим адрес строки, который
        INC     HL            ; находится в DE.
        LD      (HL),E        ; ..
        INC     HL            ; ..
        CALL    DOWN_DE       ; Вычислим адрес следующей строки
        DJNZ    INT_TB1       ; переберем все строки.
 Теперь создадим спрайты, о  которых гово-
рилось  выше.  Одновременно  смешаем его с
маской.
        LD      HL,SUR_CUR    ; исходный спрайт
        LD      DE,CURSPR     ; там и будем смещать.
        LD      BC,32         ; длина одного спрайта с маской
        LDIR                  ; первый - смещение #00
INT_SPR LD      B,8           ; вроде кол-во новых спритов.
        LD      DE,NEW_SPR    ; новый спрайт написано.
INT_SPO PUSH    BC            ; для циклу :)
        LD      HL,CURSPR     ; начало сприта
        LD      IX,CURSPR+16  ; начало маски
        LD      B,16          ; длина сприта или маски
INT_SP1 LD      A,(IX)        ; берем маску
        LD      (DE),A        ; кладем, куда надо
        INC     DE            ; след. элем.
        LD      A,(HL)        ; берем сприт
        LD      (DE),A        ; калдем.
        INC     DE            ; след.
        INC     HL            ; след.спр.
        INC     IX            ; нехт.маск.
        DJNZ     INT_SP1      ; ну, цикл, вроде.
   Вот, смешали  маску со спрайтом, теперь
имеем  сприт  с  маской  в  формате маска,
сприт, маска, сприт...со смещением #00.Te-
перь будем двигать.
        LD      HL,CURSPR     ; исход для смещений.
        LD      B,8           ; высота, вроде
INT_SP2 LD      A,(HL)        ; берем
        OR      A             ; cy=0
        RRA                   ;  ->
        LD      (HL),A        ; ложим на место
        INC     HL            ; след.
        LD      A,(HL)        ; берем 2-ой байт сприта
        RRA                   ;  ->
        LD      (HL),A        ; кладем
        INC     HL            ; далее
        DJNZ    INT_SP2       ; ну и так далее...
        LD      HL,CURMASK    ;
        LD      B,8           ;
INT_SPЗ LD      A,(HL)        ; Тожа самое для маски
        SCF                   ; cy=1
        RRA                   ;  ->
        LD      (HL),A        ;
        INC     HL            ;
        LD      A,(HL)        ;
        RRA                   ;
        LD      (HL),A        ;
        INC     HL            ;
        DJNZ    INT_SPЗ       ; с масками все...

        POP     BC            ;
        DJNZ    INT_SPO       ; след. смещение, след. сприт
        LD      A,#37         ;
        LD      (CUR_PR),A    ; кое-какие предустановки
        JP      PR_CUR_       ; ну и все,инсталл закончен, появ-
                              ; ляем первый куроср.

DOWN_DE INC     D          ; проца вычисления адреса след строки
        LD      A,D        ; из адреса предыдущей. Стандартная.
        AND     7
        RET     NZ
        LD      A,E
        ADD     A,#20
        LD      E,A
        RET     C
        LD      A,D
        SUB     8
        LD      D,A
        RET

  Теперь  процедуры  печати  курсора. Тут,
вроде,все просто: немного математики, оче-
нь  немного.  Никакого  стекового  вывода.
Скорость  достигается  отсутствием  сдвига
спритов.Здесь же процы восстановления зна-
комест под старым курсором. Думаю,разбере-
тесь сами, мне уже лень... :)

PR_CUR  LD      A,0
        LD      B,0
        LD      C,A
        SLA     C
        RL      B
        LD      HL,TABL_ADR
        ADD     HL,BC
        LD      D,(HL)
        INC     HL
        LD      E,(HL)
PR_CURO LD      A,0
        SRL     A
        SRL     A
        SRL     A
        ADD     A,E
        LD      E,A
        JR      NC,PRCO
        INC     D
PRCO    LD      HL,SPR_BUF
        LD      B,8
PRC__   LD      A,(HL)
        INC     HL
        LD      (DE),A
        INC     DE
        LD      A,(HL)
        LD      (DE),A
        DEC     DE
        INC     HL
        CALL    DOWN_DE
        DJNZ    PRC__
WOST_PR OR      A
        RET     C
PR_CUR_ LD      A,(XY_KOOR)
        LD      (PR_CUR+1),A
        LD      B,0
        LD      C,A
        SLA     C
        RL      B
        LD      HL,TABL_ADR
        ADD     HL,BC
        LD      D,(HL)
        INC     HL
        LD      E,(HL)
        LD      A,(XY_KOOR+1)
        LD      (PR_CURO+1),A
        SRL     A
        SRL     A
        SRL     A
        ADD     A,E
        LD      E,A
        JR      NC,PRCO
        INC     D
PRCO    LD      A,(XY_KOOR+1)
        AND     7
        LD      BC,NEW_SPR
        LD      H,0
        LD      L,A
        ADD     HL,HL
        ADD     HL,HL
        ADD     HL,HL
        ADD     HL,HL
        ADD     HL,HL
        ADD     HL,BC
        LD      IX,SPR_BUF
        LD      B,8
PRC1    LD      A,(DE)
        LD      (IX),A
        INC     IX
        AND     (HL);MASK
        INC     HL
        XOR     (HL);CUR
        INC     HL
        LD      (DE),A
        INC     DE
        LD      A,(DE)
        LD      (IX),A
        INC     IX
        AND     (HL);MASK
        INC     HL
        OR      (HL);CUR
        INC     HL
        LD      (DE),A
        DEC     DE
        CALL    DOWN_DE
        DJNZ    PRC1
        RET

   Ну и загрузим спритик курсора и маски.

SUR_CUR LCODE   "CurSpr22.C";fixed line noatr (smS.11)

   Что!? Давненько не видели столь убогого
коду? Погодите, еще  не такое напишу! Ведь
никто не против? Ну, ладно, все, пухните и
пишите че-нить, можете какие-нить статейки
к нонсенсу, а то будете  читать только мой
бред.
──────────────────────────────────────────



Other articles:


Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Similar articles:
B.B.S. News - The work BBS'ok.

В этот день...   21 November