░░░ ░░░ ░▒▒▒░ ░░░ ░░░ ░▒░░ ░░░░░ ░░░ ░░░ ░▒░ ░░░░░░
░█▓░ ▓█▒ ░▓████░ ▒█▓ ██░ ░███▓ ░████▓ ▓█▒ ░██░ ▒███▒ ░████▒
░██▒ ▓█▓ ▓██████░ ▒██░ ██▒ ▒████░░████▓ ▓█▓░░██░ ▓███▓ ▒████▒
░██▓░▓██░░██▓▒▓██▒ ▒██▒ ██▓ ▓█▓█▒ ▒████▒ ▓██░░██▒ ██▓█░ ▓████░
░███░▓█▒ ▒██░ ░▓█▓ ▒███░██░ ▓█▒░ ██░ ▓██▓░██ ██░░ ░██
░███▓▓█▒ ▒█▓ ▒█▓ ▒███▒██░ ▒██░ ██▓▓▒ ▓███▒██ ▓█▓░ ░██▓▓░
░██████▒ ▒█▓░ ▒█▓ ▒██████░ ▒██░ ████▒ ▓██████ ░▓█▓░ ░████░
░██▓███▒ ▒██▒ ▓█▓ ▒█▓████░ ░██░ ██▓▓░ ▓█▓████ ▒█▓░░██▓▓░
░██░███▒ ░███▒▒██▒ ▒█▓▒███░ ░▒░██▓ ██░ ▓█▒▓███ ░░░██▒░██
▓██ ▓██▒ ░▓██████░░██▓░▓██░░▓████▒ █████ ░██▒░███ ░█████░░████▓
▒██ ░██▒ ░▓████░ ▓█▓ ▒██░░▓████░ ████▓ ░██▒ ▓██ ░████▓░░████▒
░▒▒ ▒▒░ ░▒▒▒░ ░▒▒ ░▒▒░ ░▒▒▒░ ▒▒▒▒▒ ▒▒░ ░▒▒ ░▒▒▒░ ░▒▒▒▒░
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: