░░░ ░░░ ░▒▒▒░ ░░░ ░░░ ░▒░░ ░░░░░ ░░░ ░░░ ░▒░ ░░░░░░ ░█▓░ ▓█▒ ░▓████░ ▒█▓ ██░ ░███▓ ░████▓ ▓█▒ ░██░ ▒███▒ ░████▒ ░██▒ ▓█▓ ▓██████░ ▒██░ ██▒ ▒████░░████▓ ▓█▓░░██░ ▓███▓ ▒████▒ ░██▓░▓██░░██▓▒▓██▒ ▒██▒ ██▓ ▓█▓█▒ ▒████▒ ▓██░░██▒ ██▓█░ ▓████░ ░███░▓█▒ ▒██░ ░▓█▓ ▒███░██░ ▓█▒░ ██░ ▓██▓░██ ██░░ ░██ ░███▓▓█▒ ▒█▓ ▒█▓ ▒███▒██░ ▒██░ ██▓▓▒ ▓███▒██ ▓█▓░ ░██▓▓░ ░██████▒ ▒█▓░ ▒█▓ ▒██████░ ▒██░ ████▒ ▓██████ ░▓█▓░ ░████░ ░██▓███▒ ▒██▒ ▓█▓ ▒█▓████░ ░██░ ██▓▓░ ▓█▓████ ▒█▓░░██▓▓░ ░██░███▒ ░███▒▒██▒ ▒█▓▒███░ ░▒░██▓ ██░ ▓█▒▓███ ░░░██▒░██ ▓██ ▓██▒ ░▓██████░░██▓░▓██░░▓████▒ █████ ░██▒░███ ░█████░░████▓ ▒██ ░██▒ ░▓████░ ▓█▓ ▒██░░▓████░ ████▓ ░██▒ ▓██ ░████▓░░████▒ ░▒▒ ▒▒░ ░▒▒▒░ ░▒▒ ░▒▒░ ░▒▒▒░ ▒▒▒▒▒ ▒▒░ ░▒▒ ░▒▒▒░ ░▒▒▒▒░ 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) Что!? Давненько не видели столь убогого коду? Погодите, еще не такое напишу! Ведь никто не против? Ну, ладно, все, пухните и пишите че-нить, можете какие-нить статейки к нонсенсу, а то будете читать только мой бред. ──────────────────────────────────────────