Столкнулся с такой проблемой существующих процедур рисования окружности, которые можно, в частности, найти здесь на форуме. Например, алгоритм из "Библии демомейкера" в OVER 1 рисует такую окружность:
Вид для печати
Столкнулся с такой проблемой существующих процедур рисования окружности, которые можно, в частности, найти здесь на форуме. Например, алгоритм из "Библии демомейкера" в OVER 1 рисует такую окружность:
То есть некоторые точки рисуются по два раза. И даже если вообще никто не рисует окружности в режиме OVER 1, то всё равно это - потеря производительности.
Стандартная ПЗУ'шная процедура такой проблемы не имеет.
Хотелось бы найти быструю и корректную в этом смысле процедуру. Что посоветуете?
Есть у меня ещё одна процедура (не помню откуда брал), интересная тем, что радиус можно задавать двухбайтовым числом. И можно рисовать за пределами экрана.
Скрытый текст
Код:void Basic_CIRCLEW_EI (unsigned char cx, unsigned char cy, int radius) __naked {
__asm
LD IY, #0x5C3A
POP DE
POP BC ; BC = YX
POP HL ; HL = radius
PUSH HL
PUSH BC
PUSH DE
LD A, H
OR L
RET Z
BIT 7, H
RET NZ
PUSH IX
DI
LD D, #0
LD E, C
LD C, B
LD B, D
PUSH DE
LD DE, #0
PUSH DE
PUSH BC
PUSH HL
LD IX, #0
ADD IX, SP
PUSH HL
EXX
POP HL
ADD HL, HL
EX DE, HL
LD HL, #3
AND A
SBC HL, DE
EXX
JR ENT1$
CIRCLOOP1$:
AND A
SBC HL, DE
JP M, EXT1$
POP DE
POP HL
ADD HL, DE
EX DE, HL
POP BC
POP HL
ADD HL, BC
LD SP, IX
CALL WRAP1$
POP BC
POP HL
POP DE
ADD HL, DE
EX DE, HL
POP HL
ADD HL, BC
LD SP, IX
CALL WRAP1$
POP DE
POP HL
AND A
SBC HL, DE
EX DE, HL
POP BC
POP HL
AND A
SBC HL, BC
LD SP, IX
CALL WRAP1$
POP BC
POP HL
POP DE
AND A
SBC HL, DE
EX DE, HL
POP HL
AND A
SBC HL, BC
LD SP, IX
CALL WRAP1$
ENT1$:
POP DE
POP HL
ADD HL, DE
EX DE, HL
POP BC
POP HL
AND A
SBC HL, BC
LD SP, IX
CALL WRAP1$
POP BC
POP HL
POP DE
ADD HL, DE
EX DE, HL
POP HL
AND A
SBC HL, BC
LD SP, IX
CALL WRAP1$
POP DE
POP HL
AND A
SBC HL, DE
EX DE, HL
POP BC
POP HL
ADD HL, BC
LD SP, IX
CALL WRAP1$
POP BC
POP HL
POP DE
LD (POSITIV1$+1), DE
AND A
SBC HL, DE
EX DE, HL
POP HL
ADD HL, BC
LD SP, IX
CALL WRAP1$
EXX
EX DE, HL
BIT 7, D
JR Z, POSITIV1$
LD HL, (POSITIV1$+1)
ADD HL, HL
ADD HL, HL
LD BC, #6
JR CALCDONE1$
POSITIV1$:
LD HL, #0
POP BC
DEC BC
PUSH BC
AND A
SBC HL, BC
ADD HL, HL
ADD HL, HL
LD BC, #0xA
CALCDONE1$:
ADD HL, BC
ADD HL, DE
EXX
POP HL
POP DE
POP DE
INC DE
PUSH DE
LD SP, IX
JP CIRCLOOP1$
EXT1$:
LD HL, #8
ADD HL, SP
LD SP, HL
POP IX
EI
RET
WRAP1$:
LD A, D
OR A
RET NZ
LD A, H
OR A
RET NZ
LD A, E
CP #0xB0
RET NC
LD B, E
LD C, L
JP 0x22E5
__endasm;
}
[свернуть]
Но у неё та же проблема:
shurik-ua, спасибо конечно. Но уточню: мне нужна не теория и алгоритм на псевдобейсике, а нормальный отлаженный код на ассемблере Z80. Или совет как пофиксить упомянутые выше процедуры.
Вторую хотелось бы отладить особенно, потому что она редкостная - большинство процедур, которые я здесь встречал, имеют однобайтовые аргументы.
Возможно рисует по две точки как раз из за упрощения/ускорения рисования, просто пожертвовали лишними проверками или точностью алгоритма
Мы хотим получить круто оптимизированный код на ассемблере, чтобы он прямо пиксель в пиксель повторял результат рисования бейсиковского круга? Или можно немножко переставить пикселки в углах, главное чтобы два раза в одном месте не рисовалось, и смотрелось правильно?
Вход определим. X,Y,Z- целые? байт? слово(2 байта) со знаком?
Результат:
На весь экран? (256x192)
Круг частично выходит за экран?
Атрибуты красим? (инк, папер, яркость мигание)
Как опции можно сделать круги с заливкой. Нужно?
В этой процедуре последнюю точку не печатать (если уже была).
Например так (новая подпрограмма печати точки)
Код:WRAP1
LD A, D
OR A
RET NZ
LD A, E
CP #B0
RET NC
LD A, H
OR A
RET NZ
LD B, E
LD C, L
WRAP2 LD HL,0
LD (WRAP2+1),BC
SBC HL,BC
RET Z
JP #22E5
Фикс Destr'а рабочий и, в принципе, меня устраивает. Благодарю!
Думаю, можно.
Сейчас у меня просто стоит задача получить хоть какую-то окружность в OVER 1. Но в общем-то:
1. Для библиотеки Basic (ZXDev) нужна процедура окружности. CIRCLEROM там уже есть. CIRCLE задумана как то же самое, но быстрый вариант (все параметры - беззнаковые байты) и не позволяет рисовать за пределами экрана. CIRCLEW - то же самое, но все параметры - слова со знаком. Такой процедуры я не нашёл, поэтому пока удовольствовался процедурой, где координаты - байты без знака, а радиус - слово со знаком. Она умеет рисовать за пределами экрана не всю окружность, а только её часть.
Можно поспорить с тем, нужна ли CIRCLEW непосредственно в библиотеке Basic, но уже пускай будет - по аналогии с RND (результат - байт) и RNDW (результат - слово).
2. Для библиотеки Gfx, которую я недавно начал формировать, пригодились бы и другие варианты окружности, в т.ч. и залитой. Так что буду благодарен.
Не могу сказать, сколько раз рисуются точки, - это, вообще, странно слышать, что одна точка несколько раз рисуется. Зачем, также, этот кривой ПЗУшный алгоритм? - разве он не через DRAW рисует? - окружности с малыми радиусами получаются КРИВЫЕ (либо у меня другой бейсик зашит?!).
Рекомендую алгоритм Мичнера. Мне его окружности больше глаз радуют. Сам пока использую сишную процедуру, на асме только рисование точек (под TS-Config). Но давненько хотелось целиком на асм переложить. Может, после работы займусь.
Код:/*--------------------------------------------------- V_MIcirc
* Генерирует 1/8 окружности по алгоритму Мичнера
*/
void V_MIcirc (int xc, int yc, int r, int pixel)
{ int x, y, d;
x= 0; y= r; d= 5 - 2*r;
while (x < y) {
Pixel_circle(xc, yc, x, y, pixel,MyVPage);
if (d < 0) d= d + 4*x + 6; else {
d= d + 4*(x-y) + 10; --y;
};
++x;
};
if (x == y) Pixel_circle(xc, yc, x, y, pixel, MyVPage);
} /* V_MIcirc */
void Pixel_circle(int xc, int yc, int x, int y, int pixel, int pg) __naked
{ xc,yc,x,y,pixel,pg;
__asm
di
pop af
pop hl ; xc
ld (5$+1),hl
ex de,hl
pop hl
ld (9$+1),hl ; yc
pop hl
ld (10$+1),hl
ld b,h
ld c,l ; x
pop hl
ld (11$+1),hl ; y
pop hl
ld a,l
ld (7$+1),a
pop hl
ld a,l
ld (6$+1),a
ld hl,#-14
add hl,sp
ld sp,hl
ei
; plot8(xc+x, yc+y);
ex de,hl
add hl,bc
ex de,hl
9$:
ld hl,#0 ; yc val
11$:
ld bc,#0 ; y val
add hl,bc
call 2$
; plot8(xc+y, yc+x);
5$: ld hl,#0 ; xc val
ld bc,(11$+1)
add hl,bc
ex de,hl
ld hl,(9$+1)
10$: ld bc,#0 ; x val
add hl,bc
call 2$
; plot8(xc+y, yc-x);
ld hl,(5$+1)
ld bc,(11$+1)
add hl,bc
ex de,hl
ld hl,(9$+1)
ld bc,(10$+1)
or a,a
sbc hl,bc
call 2$
; plot8(xc+x, yc-y);
ld hl,(5$+1)
ld bc,(10$+1)
add hl,bc
ex de,hl
ld hl,(9$+1)
ld bc,(11$+1)
or a,a
sbc hl,bc
call 2$
; plot8(xc-x, yc-y);
ld hl,(5$+1)
ld bc,(10$+1)
or a,a
sbc hl,bc
ex de,hl
ld hl,(9$+1)
ld bc,(11$+1)
or a,a
sbc hl,bc
call 2$
; plot8(xc-y, yc-x);
ld hl,(5$+1)
ld bc,(11$+1)
or a,a
sbc hl,bc
ex de,hl
ld hl,(9$+1)
ld bc,(10$+1)
or a,a
sbc hl,bc
call 2$
; plot8(xc-y, yc+x);
ld hl,(5$+1)
ld bc,(11$+1)
or a,a
sbc hl,bc
ex de,hl
ld hl,(9$+1)
ld bc,(10$+1)
add hl,bc
call 2$
; plot8(xc-x, yc+y);
ld hl,(5$+1)
ld bc,(10$+1)
or a,a
sbc hl,bc
ex de,hl
ld hl,(9$+1)
ld bc,(11$+1)
add hl,bc
call 2$
ei
ret
2$:
;--- plot routine --- для 0-го окна.
; DE = X
; HL = Y
;--- rom off ---
di
ld a,#0x0E ; // RAM|NoMAP|WE|BASIC-128
ld bc,#0x21af ;_MemConfig
out (c),a
;---------------
add hl,hl
ld a,l
add a,d
and a,#0x3f
ld d,a
add hl,hl
add hl,hl
ld a,h
6$: add a,#0x00 ; сюда при чтении аргументов занести номер видеостраницы.
ld b,#0x10 ; 0-е окно.
out (c),a
7$: ld a,#0x00 ; сюда при чтении аргументов занести значение цвета.
ld (de),a
;--- rom on ---
ld a,#0x04 ; // ROM|MAP|WP|BASIC-128
ld b,#0x21 ; _MemConfig
out (c),a
ld b,#0x10
ld a,#3
out (c),a
ei
;---------------
ret
__endasm;
}
Вот Мичнер в более приятной для Олега паскалевидной форме: ;)
Кстати, воспринимается полегче, чем Си.Код:procedure bres_circle(xc,yc,r:interger):
var x,y,d:integer:
procedure sim(x,y;integer);
begin
putpixel(x+xc,y+yc,White);
putpixel(x+xc,-y+yc,White);
putpixel(-x+xc,-y+yc,White);
putpixel(-x+xc,y+yc,White);
putpixel(y+xc,x+yc,White);
putpixel(y+xc,-x+yc,White);
putpixel(-y+xc,-x+yc,White);
putpixel(-y+xc,x+yc,White);
end;
begin
d:=3-2*y;
x:=0;
y:=r;
while(x <= y) do
begin
sim(x,y);
if d<0 then d:=d+4*x+6
else begin
d:=d+4*(x-y)+10;
dec(y)
end;
inc(x)
end;
end;
Вот-вот, а я-то как удивился. :)
Разве что для полного соответствия ZX-Бейсику или экономии памяти. Ну и реверанс в сторону Ревю и книжек по графике, где окружность предлагалось рисовать только алгоритмом из ПЗУ.
Спасибо! Полезно и для не-ZX. Если будет целиком в машкоде (или адаптированный для Спека) — буду рад увидеть код.
Решил пока воздержаться от изобретания велосипеда, - вот нашёл:
http://icereijo.com/a-circle-algorithm-for-zx-spectrum/
там и исходники, и тапка, и видео даже.
Эврика. Выбранная тобой процедура, используя свойства симметрии, рисует точки по октетам. При одной из координат равной 0, количество вариантов расположения точек вырождается до 4-х: смещения от оси симметрии равны +0/-0. Поэтому точки при этом рисуются на одном и том же месте. Избежать этого можно, если для случаев x=0 / y=0 сделать специальные п/п рисования точек.
а как включить режим OVER 1 для #22Е5 через код?
Пробуйте. Не должно быть повторных точек. Учитывает края экрана.
Расплата: 14 и 20 тактов на точку соответственно.
Код:void circle3(unsigned char cx, unsigned char cy, unsigned char r) __naked
{ cx,cy,r;
__asm
ld hl,#2
add hl,sp
ld b,(hl)
inc hl
ld c,(hl)
inc hl
ld l,(hl)
ld (xcyc+1),bc ; b = x, c = y. , переменная в коде команды.
xor a,a
ld c,l ; y = r;
ld b,a ; x = 0;
ld h,a
add hl,hl
ld de,#5
ex de,hl
or a,a
sbc hl,de
ld (var_d+1),hl ; d = 5 - 2r;
loop:
ld a,b
cp c
jp c,q0
call z,pixels
ret
q0: call pixels
var_d:
ld de,#0 ; _d переменная в коде команды.
bit 7,d
jp z,q1
; d < 0:
ld h,#0
ld l,b
add hl,hl
add hl,hl
add hl,de
ld de,#6
add hl,de
ld (var_d+1),hl
inc b ; ++x
jp loop
q1: ld a,b ; x-y
sub c
ld l,a
sbc a,a
ld h,a ; sign is extended
add hl,hl
add hl,hl
add hl,de
q3: ld de,#10
add hl,de
ld (var_d+1),hl
dec c ; --y
inc b ; ++x
jp loop
pixels:
;xc+x, yc+y
xcyc: ld hl,#0 ;(xcyc)
ld a,b
or a,a
jp z,p1
add a,h
jp c,p1
ld d,a
ld a,c
or a,a
jp z,p1
add a,l
cp a,#192
jp nc,p1
ld e,a
call plote
; xc+x, yc-y
ld hl,(xcyc+1)
p1: ld a,b
or a,a
jp z,p2
add a,h
jp c,p2
ld d,a
ld a,l
sub a,c
jp c,p2
ld e,a
call plote
; xc-x, yc-y
ld hl,(xcyc+1)
p2: ld a,h
sub a,b
jp c,p3
ld d,a
ld a,l
sub a,c
jp c,p3
ld e,a
call plote
; xc-x, yc+y
ld hl,(xcyc+1)
p3: ld a,h
sub a,b
jp c,p4
ld d,a
ld a,l
or a,a
jp z,p4
add a,c
cp #192
jp nc,p4
ld e,a
call plote
; xc+y, yc+x
ld hl,(xcyc+1)
p4: ld a,h
or a,a
jp z,p5
add a,c
jp c,p5
ld d,a
ld a,b
or a,a
jp z,p5
add a,l
cp #192
jp nc,p5
ld e,a
call plote
; xc+y, yc-x
ld hl,(xcyc+1)
p5: ld a,c
or a,a
jp z,p6
add a,h
jr c,p6
ld d,a
ld a,l
sub a,b
jr c,p6
ld e,a
call plote
; xc-y, yc-x
ld hl,(xcyc+1)
p6: ld a,h
sub a,c
jr c,p7
ld d,a
ld a,l
sub a,b
jr c,p7
ld e,a
call plote
; xc-y, yc+x
ld hl,(xcyc+1)
p7: ld a,h
sub a,c
ret c
ld d,a
ld a,b
or a,a
ret z
add a,l
ret c
ld e,a
call plote
ret
plote: ; (C)SATSOFT, Body #07.
push bc
; LD D,10 ;КООРДИНАТА Х
; LD E,11 ;КООРДИНАТА Y
LD A,#0xAF ;РАСЧЕТ АДРЕСА ПО КООРДИНАТАМ
SUB E
jp c,exit
LD E,A
AND A
RRA
SCF
RRA
AND A
RRA
XOR A,E
AND #0xF8
XOR A,E
LD H,A
LD A,D
RLCA
RLCA
RLCA
XOR A,E
AND #0xC7
XOR A,E
RLCA
RLCA
LD L,A
LD A,D ;КООРДИНАТА Х
AND #0x07 ;МАСКИРОВАНИЕ
LD B,A ;ОСТАТОК ОТ ДЕЛЕНИЯ Х НА 8
INC B ;+1
LD A,#0xFE ;ВВЕЛИ БАЙТ 11111110
PLOOP:
RRCA ;ВРАЩЕНИЕ N+1 РАЗ
DJNZ PLOOP
LD B,#0xFF ;ИНВЕРСИЯ,ЧТОБЫ ПЕЧАТЬ ТОЧКИ БЫЛА ЧЕРНЫМ
XOR A,B ;ПО БЕЛОМУ
LD B,A ;ЗАПОМНИЛИ В РЕГИСТРЕ 'B'
LD A,(HL) ;В 'А' ГРУЗИМ ЗНАЧЕНИЕ ИЗ ЭКРАНА
OR A,B ;ВКЛЮЧЕМ ТРЕБУЕМЫЙ БИТ
LD (HL),A ;ГРУЗИМ В ЭКРАН ПОЛУЧЕННЫЙ РЕЗУЛЬТАТ
exit:
pop bc
RET ;ВЫХОД ИЗ ПРОЦЕДУРЫ :)
__endasm;
}
Как всё-таки можно зафиксить "библейский" алгоритм рисования окружности под OVER 1 ? (см. первый пост темы).
Скрытый текст
Код:;--------------------------------------------------
;9. Окружность, на входе в HL,127+87*256 (x=127, y=87)
;--------------------------------------------------
CIRCLE LD HL,127+87*256 ;(x=127, y=87)
LD D,50 ;r=50
LD C,0: LD B,D
LOOP CALL DOT ;sector 1
LD A,B: NEG: LD B,A: CALL DOT ;sector 4
LD A,C: NEG: LD C,A: CALL DOT ;sector 5
LD A,B: NEG: LD B,A: CALL DOT ;sector 8
LD A,C: LD C,B: LD B,A: CALL DOT ;sector 3
LD A,C: NEG: LD C,A: CALL DOT ;sector 6
LD A,B: NEG: LD B,A: CALL DOT ;sector 7
LD A,C: NEG: LD C,A: CALL DOT ;sector 8
LD A,C: LD C,B: LD B,A
INC C
LD A,D: SUB C: LD D,A: JR NC,LOOP
DEC B
LD A,D: ADD A,B: LD D,A
LD A,B: CP C: JR NC,LOOP
RET
DOT PUSH HL: PUSH DE: PUSH BC
LD A,H: ADD A,B: LD B,A
LD A,L: ADD A,C: LD C,A
CALL #22e5
POP bc: POP DE: POP HL
RET
[свернуть]
Я протестировал его с фиксом, предложенным Destr, - запоминать координаты предыдущей точки и если текущие совпадают с ними, то не рисовать.
Не получается. Причина - некоторые (но не все) точки по одним координатам рисуются не подряд.Код:DOT PUSH HL: PUSH DE: PUSH BC
LD A,H: ADD A,B: LD B,A
LD A,L: ADD A,C: LD C,A
WRAP ; fixed for OVER 1 by Destr
LD HL,#ffff: LD (WRAP+1),BC
AND A: SBC HL,BC: CALL NZ,#22e5
POP bc: POP DE: POP HL
RET
Зафиксить бы, братцы, - уж больно процедурка хороша. Компактная такая.
у тебя есть два варианта рисования точек в круге.
1ый когда количество точек четное
2ой когда оно нечетное
в варианте с четным количеством все будет ОК
в варианте с нечетным последняя точка будет рисоваться 2 раза.
Oleg N. Cher, Тупо сделал заплатку.
Код:;--------------------------------------------------
;9. Окружность, на входе в HL,127+87*256 (x=127, y=87)
;--------------------------------------------------
CIRCLE LD HL,127+87*256 ;(x=127, y=87)
LD D,56 ;r=50
LD C,D: LD B,0
CALL DOT
LD A,C: NEG: LD C,A: CALL DOT
LD B,C: LD C,0
CALL DOT
LD A,B: NEG: LD B,A: CALL DOT
jr DLOOP
LOOP CALL DOT ;sector 1
LD A,B: NEG: LD B,A: CALL DOT ;sector 4
LD A,C: NEG: LD C,A: CALL DOT ;sector 5
LD A,B: NEG: LD B,A: CALL DOT ;sector 8
HLOOP
LD A,C: LD C,B: LD B,A: CALL DOT ;sector 3
LD A,C: NEG: LD C,A: CALL DOT ;sector 6
LD A,B: NEG: LD B,A: CALL DOT ;sector 7
LD A,C: NEG: LD C,A: CALL DOT ;sector 8
LD A,C: LD C,B: LD B,A
DLOOP
INC C
LD A,D: SUB C: LD D,A: JR NC,LOOP
DEC B
LD A,D: ADD A,B: LD D,A
LD A,C: CP B: JR C,LOOP
JP Z,HLOOP
RET
DOT PUSH HL: PUSH DE: PUSH BC
LD A,H: ADD A,B: LD B,A
LD A,L: ADD A,C: LD C,A
CALL #22e5
POP bc: POP DE: POP HL
RET
---------- Post added at 23:18 ---------- Previous post was at 23:13 ----------
JP Z,HLOOP можно поменять на JR Z,HLOOP
jr DLOOP можно убрать.( тупо отрисуются лишние 8 точек, зато экономия байтов :) )
Это по вкусу.
Спасибо! Отличное решение, Reobne. И оно оптимальнее исходного по скорости (за счёт отказа от рисования лишних точек). А байтики - то уже такое, процедурка всё равно некрупная. Теперь меня в принципе всё устраивает. Но маленькое отличие кружков в OVER 0 и OVER 1 всё-таки есть. См. самый маленький, как он отличается (справа - OVER 1):
P.S. У месье гурманов есть какие-то претензии к красивости полученных "библейским" способом окружностей?
Ещё заплатки сделал, чтобы R=0 и R=1 были нормальные.
Код:;--------------------------------------------------
;9. Окружность, на входе в HL,127+87*256 (x=127, y=87)
;--------------------------------------------------
CIRCLE LD HL,127+87*256 ;(x=127, y=87)
LD D,1 ;r=50
LD C,D: LD B,0
CALL DOT
LD A,C: NEG: RET Z: LD C,A: CALL DOT
LD B,C: LD C,0
CALL DOT
LD A,B: NEG: LD B,A: CALL DOT
DEC D: RET Z
jr DLOOP
LOOP CALL DOT ;sector 1
LD A,B: NEG: LD B,A: CALL DOT ;sector 4
LD A,C: NEG: LD C,A: CALL DOT ;sector 5
LD A,B: NEG: LD B,A: CALL DOT ;sector 8
HLOOP
LD A,C: LD C,B: LD B,A: CALL DOT ;sector 3
LD A,C: NEG: LD C,A: CALL DOT ;sector 6
LD A,B: NEG: LD B,A: CALL DOT ;sector 7
LD A,C: NEG: LD C,A: CALL DOT ;sector 8
LD A,C: LD C,B: LD B,A
DLOOP
INC C
LD A,D: SUB C: LD D,A: JR NC,LOOP
DEC B
LD A,D: ADD A,B: LD D,A
LD A,C: CP B: JR C,LOOP
JP Z,HLOOP
RET
DOT PUSH HL: PUSH DE: PUSH BC
LD A,H: ADD A,B: LD B,A
LD A,L: ADD A,C: LD C,A
CALL #22e5
POP bc: POP DE: POP HL
RET
Было бы хорошо нам иметь централизованное хранилище таких базовых вещей. Например, вот эта процедура (с правками Reobne конечно) вполне достойна быть включенной туда на правах минималистичной, хотя наверное и не самой идеальной с плане красивости отрисовки окружности. Ну можно и другую процедуру, которая побольше, но красивше рисует. Я просто не знаю такого хранилища, вместо него на просторах инета, на форумах и в прессе туча различных процедур, среди которых довольно много плохо закодированных. И всё это надо разгребать, тестировать, ругаться и т.д.
Но в ZXDev уже вошла. :) Reobne, огромное спасибо тебе.
Я что-то забросил сбор таких важностей
всё велосипеды чудите... :)
хотя бы
ld a,x:neg:ld x,a на xor a:sub x:ld x,a
поменяли...
вот, кстати, тогда - аж заэкранно рисующая процедура, из старинного DEJA VU журнала, с алгоритмом хитро вложенных друг в друга CALL'ов:
http://www.zxpress.ru/article.php?id=7876
для over 1 добавляем:Код:;----------------------------------------;
_NULL EQU 0
;----------------------------------------;
ATTR_P EQU 23693 ;атрибуты экрана
;----------------------------------------;
;биты: 0 - over 0/1, 2 - inverse 0/1
; 4 - ink & paper 9 (прозрачные атр.)
P_FLAG EQU 23697
;----------------------------------------;
;----------------------------------------;
;Algorythm designed by SerzhSoft (c)1996
;рисование окружности
; HL=x, DE=y (-32768..+23767)
; A=радиус (0..255) ;при 0 - точка
CIRCLE
ld (X_CIRC),hl
ld (Y_CIRC),de
ld e,a
ld c,#00
ld b,c
ld d,c
srl a
LPCIR1 ex af,af'
LPCIR2 call PUT8PX
inc c
ex af,af'
sub c
jr nc,LPCIR1
dec e
add a,e
ex af,af'
ld a,e
cp c
jr nc,LPCIR2
ret
;
PUT8PX call PUT4PX
;
PUT4PX ld a,c
ld c,e
ld e,a
ld hl,_NULL
X_CIRC equ $-2
push hl
add hl,bc
call PUT2PX
pop hl
sbc hl,bc
;
PUT2PX inc h
dec h
ret nz
ld a,l
ld (X_NEW),a
ld hl,_NULL
Y_CIRC equ $-2
push hl
add hl,de
call PUT1PX
pop hl
sbc hl,de
;
PUT1PX inc h
dec h
ret nz
ld a,l
cp #C0
ret nc
push de
ld d,a
ld e,_NULL
X_NEW equ $-1
push bc
call PLOT
pop bc
pop de
ret
;----------------------------------------;
;----------------------------------------;
;выч. адреса и проверка состояния точки
POINT
LD B,#07
LD A,D
RRA
SCF
RRA
RRA
AND #5F
LD H,A
XOR E
AND B
XOR E
RRCA
RRCA
RRCA
LD L,A
LD A,D
XOR H
AND B
XOR H
LD H,A
LD A,E
AND B
LD B,A
LD A,#80
JR Z,GO_PNT
LP_PNT RRCA
DJNZ LP_PNT
GO_PNT LD C,A
AND (HL)
RET
;
POINTHL
PUSH HL
CALL POINT
POP HL
RET
;----------------------------------------;
;установка точки
PLOT
CALL POINT
LD A,(P_FLAG)
PUSH HL
LD HL,#A9A9 ;over 1, inv. 1
BIT 0,A
JR NZ,IF_PLT1
LD L,#B1 ;[or c] - over 0
IF_PLT1 BIT 2,A
JR NZ,IF_PLT2
LD H,#00 ;[nop] - inverse 1
IF_PLT2 LD (OVR_PLT),HL
POP HL
LD A,(HL)
OVR_PLT OR C
INV_PLT XOR C
;
TO_PLOT ;вход для пр-ры заливки и др.
LD (HL),A
LD A,(P_FLAG)
BIT 4,A
RET NZ
LD A,H
RRA
RRA
RRA
AND #03
OR #58
LD H,A
LD A,(ATTR_P)
LD (HL),A
RET
;----------------------------------------;
и багфикс для 0 радиуса ( когда E сразу вываливается на 255 и пытается нарисовать к точке еще и окружность ), - заменить srl a:Код:...
PUT8PX call PUT4PX
ld a,c
cp e
ret z
...
call PUT2PX
pop hl
ld a,c
or a
ret z
...
call PUT1PX
pop hl
ld a,e
or a
ret z
or a
jr z,PUT4PX
rra