	device pentagon1024
;todo:
;иногда на 1 кадр гасится экран
;всё ещё есть крайне редкое выпадение (явно стека должно хватать) (даже без смены координат - рандомно)
;большие полигоны на полу исчезали из-за 8-битного visibility (сделан костыль логического сплющивания на правом краю экрана),
;но и при 16-битном visibility из-за отрисовщика нельзя использовать большие полигоны, надо половинки)

STACK=#6000;#be00;#5fe0;#be00
drawsp=#5f00

main=#8000;#6400
progtable=#4000
makers=#4100

SMALLLINES=0;1 ;большой набор процедур коротких линий
LINEEX=0 ;чередовать начало-конец линии

TWOAXES=1
xbase=#80;#c0 ;todo #80 (только при scrbuf=#d000+: scf:rr h:sra h)
ybase=#80;#c0 ;#80 удобнее сравнивать (по CY - можно высоты >128) ;при #80+(scrhgt/2) проблема с переполнением в большую сторону - линии не туда
;todo 0? (сравнения по PE)

scrhgt=96
scrwid=32
	if SMALLLINES&&(xbase != #80)
scrbuf=#d000+ybase-(scrhgt/2) ;#e080+#10
	else
scrbuf=#e000+ybase-(scrhgt/2) ;#e080+#10
	endif
scrbrim=(32-scrwid)/2
scrtop=#4000
;scrbottomend=#5800-scrbrim
scrbufmid=(scrbuf&#ff00)+#1000

endfree=scrbuf&#ff00;#e000;#df00;#ce00

	if SMALLLINES
;только для xbase=#c0!!! и уже глючит
endfree=endfree-#100 ;из-за выскакивающих по X линий (max 8 pix)
;linemaxhgt=31 ;63 segments
;jumptable=#a000
linemaxhgt=7 ;15 segments
jumptable=endfree-(256*(linemaxhgt*2+1)) ;=#d000
jumptable_center=jumptable+(linemaxhgt*256)
;сейчас линии занимают #9409..#a93e
;todo не генерировать линии вверх, делать jp на линии вниз (будет неточно?)
endfree=jumptable
	endif

NOISECLS=0 ;0=очистка, 1=шум, 2=пропуск байтов

DIVCHECKOVERFLOW=1 ;1=проверка переполнения за двойной экран (если не проверять, то рандомный результат вне экрана (нас устраивает), но при делении через квадраты вообще рандомный результат (нас не устраивает)) ;2=урезание делимого до DIVMAX
;DIVMAX=#49;#40 заметно; #50 еле заметно; #70 незаметно ;#a0 надо по теории для 7.5/6.5
rangeshiftmax=4
MATRIXDIV2=1
MINZ=#1e ;#16..#18 (редкие пропадания на половинных гранях) ;#1e (нет пропаданий на половинных гранях) ;#30 (в теории для кубика с единичными гранями)
SORTLEVELS=128 ;256 (разница 8000t только за счёт количества и 3000t ещё за счёт терминатора)
FASTROTOBJ=1 ;быстрое вращение объекта с инлайновым умножением через патчи

VISIBILITY16=0

sz=5;31;70 ;NU для куба, рассматривается просто как положительное значение

basetime=0

_tables=endfree
	macro BEGIN256 size
_codes=$
	org _tables-size
	.ALIGN 256
_tables=$
	endm
	macro END256
	org _codes
	endm

	org #6100

begin
	xor a
	;ld a,1
	out (#fe),a
	ld hl,#4000
	ld de,#4001
	ld bc,#17ff
	ld (hl),l
	ldir
	ld hl,#5800
	ld de,#5801
	ld bc,#2ff
	ld (hl),7
	ldir

	ld hl,ON_INT
	ld de,IMER
	ld bc,szON_INT
	ldir
	
	ld hl,wasmakers
	ld de,makers
	ld bc,szmakers
	ldir
	
	ld hl,scrbuf
	ld de,scrbuf+1
	ld bc,#2000-1
	ld (hl),0
	ldir ;clear scrbuf
	
	;ld (#5d10),a
	;ld (iy+1),#cc
	ld sp,STACK

	call GENLOG2
	call GEN2X
	if SMALLLINES
	call mklines
	endif
	ld hl,#4000
	ld de,#4001
	ld bc,#17ff
	ld (hl),l
	ldir

	 ld bc,#fbdf
	 in a,(c)
	 ld (oldfbdf),a
	 ld bc,#ffdf
	 in a,(c)
	 ld (oldffdf),a

	ei
	;halt
	ld hl,IMVEC&#ff00
	ld a,h
	ld i,a
	;if ((IMVEC+256)&#ff00)==(IMER&#ff00)
	inc a
	;else
	;ld a,IMER/256
	;endif
	ld (hl),a
	inc l
	jr nz,$-2
	inc h
	ld (hl),a
	im 2
	ld hl,(timer)
	ld (oldtimer),hl
	jp waithalt
	;ld (scriptsp),sp
	
	jp maingo



;=====================================
	ds main-$
	org main
maingo

;********************************************************************
mainloop
	ld hl,end
	ld (sortobjtabend),hl
	ld (sortobjinitsp),sp
	ld sp,tsortobjend
	if SORTLEVELS==256
	ld hl,#ffff ;NULL
	ld b,255/51
sortobjinit0
	dup 51
	push hl
	edup
	djnz sortobjinit0
	else
	ld bc,256*(128/32)
	push bc ;произвольное чётное число-терминатор
	ld hl,#ffff ;NULL
	jr $+2+2
sortobjinit0
	dup 32
	push hl
	edup
	djnz sortobjinit0
	endif
	ld (tsortobj),hl
sortobjinitsp=$+1
	ld sp,0
	
	ld a,-1 ;невозможное значение рыскания объекта?
	ld (oldyaw),a ;чтобы первый раз не совпало
	;xor a
	;ld (linesdrawn),a
mcamx=$+1
	ld hl,0
	ld (frame_mcamx),hl
mcamy=$+1
	ld hl,500
	ld (frame_mcamy),hl
mcamz=$+1
	ld hl,+#020
	ld (frame_mcamz),hl
	;xor a
	;ld (alpha),a ;крен
	ld a,(tangage)
	ld (frame_tangage),a ;тангаж
	ld (cosZYpatch),a
	if FASTROTOBJ==0
	ld (cosZYpatch2),a
	endif
	cpl
	add a,#40+1
	ld (sinZYpatch),a
	add a,#80
	ld (sinZYpatchneg),a
	ld a,(azimuth)
	ld (frame_azimuth),a ;рыскание
	;xor #80 ;чтобы первый раз не совпало
	;ld (oldyaw),a
	;xor #80
	;ld a,(frame_azimuth) ;azimuth (yaw, рыскание)
	ld (cosZXpatch),a
	if FASTROTOBJ==0
	ld (cosZXpatch2),a
	endif
	cpl
	add a,#40+1
	ld (sinZXpatch),a
	add a,#80
	ld (sinZXpatchneg),a

	if FASTROTOBJ
cosZYpatch=$+1
	ld a,(tcos)
	;cpl
	;and   %11111100
	;add a,%00000010 ;чтобы без ошибок прибавить или вычесть +-#3ff
	;ld (cosZYpatchN),a
	ld e,a
	push af
sinZYpatch=$+1
	ld a,(tcos)
	;cpl
	;and   %11111100
	;add a,%00000010 ;чтобы без ошибок прибавить или вычесть +-#3ff
	;ld (sinZYpatchN),a
	ld hl,mulYX1-5
	call mkmul2fast_h
sinZYpatchneg=$+1
	ld a,(tcos)
	;cpl
	;and   %11111100
	;add a,%00000010 ;чтобы без ошибок прибавить или вычесть +-#3ff
	;ld (sinZYpatchnegN),a
	ld e,a
	pop af
	;ld (cosZYpatchN2),a
	ld hl,mulYX2-5
	call mkmul2fast_h
	
cosZXpatch=$+1
	ld a,(tcos)
	;cpl
	;and   %11111100
	;add a,%00000010 ;чтобы без ошибок прибавить или вычесть +-#3ff
	;ld (cosZXpatchN),a
	ld e,a
	push af
sinZXpatch=$+1
	ld a,(tcos)
	;cpl
	;and   %11111100
	;add a,%00000010 ;чтобы без ошибок прибавить или вычесть +-#3ff
	;ld (sinZXpatchN),a
	ld hl,mulZX1-5
	call mkmul2fast_h
sinZXpatchneg=$+1
	ld a,(tcos)
	;cpl
	;and   %11111100
	;add a,%00000010 ;чтобы без ошибок прибавить или вычесть +-#3ff
	;ld (sinZXpatchnegN),a
	ld e,a
	pop af
	;ld (cosZXpatchN2),a
	ld hl,mulZX2-5
	call mkmul2fast_h
	endif

;кнопка нажата, когда 0 И было 1 (т.е. keyinv&keyold)
floorkeyold=$+1
	ld c,8
	ld a,#fd
	in a,(#fe)
	ld (floorkeyold),a
	cpl
	and c
	and 8 ;'f'
	jr z,nofloorkey ;key not pressed
	ld a,(flooron)
	cpl
	ld (flooron),a
nofloorkey
flooron=$+1
	ld a,0
	or a
	call z,DOFLOOR

	ld bc,-#80 ;bc=Y (будет =Z')
	ld hl,-#30 ;hl=X (будет =X')
	ld de,-#020 ;de=Z (будет =Y')
	ld a,#20
	add a,-3
	 inc a
	 jr z,$+3 ;-1 = невозможное значение рыскания объекта?
	 dec a
	ld ($-2-1-4),a
	LD ix,vertwascube
	call DOOBJ ;вращающийся кубик справа внизу

	ld bc,#80;#100 ;bc=Y (будет =Z')
	ld hl,-#60 ;hl=X (будет =X')
	ld de,-#020 ;de=Z (будет =Y')
	;ld a,0
	LD ix,vertwas;cube
	call DOOBJNROT ;кубик слева внизу
	
	if 1==1
	;ld bc,-#10;#40 ;bc=Y (будет =Z')
	;ld hl,#20 ;hl=X (будет =X')
	;ld de,-(sz/2) ;de=Z (будет =Y')
	;ld a,#80;#40
	;add a,5
	 ;inc a
	 ;jr z,$+3 ;-1 = невозможное значение рыскания объекта?
	 ;dec a
	;ld ($-2-1-4),a
	;LD ix,vertwascurve
	;call DOOBJNROT
	ld bc,0 ;bc=Y (будет =Z')
	ld hl,#60 ;hl=X (будет =X')
	ld de,#02-#05c;0 ;de=Z (будет =Y') ;стена вверху
	;ld a,0;#20
	LD ix,vertwaswall
	call DOOBJNROT
	ld bc,0 ;bc=Y (будет =Z')
	ld hl,#60 ;hl=X (будет =X')
	ld de,#40-#05c ;de=Z (будет =Y') ;стена внизу
	;ld a,0;#20
	LD ix,vertwaswall
	call DOOBJNROT
	ld bc,-#80 ;bc=Y (будет =Z')
	ld hl,-#30 ;hl=X (будет =X')
	ld de,-#40-#060 ;de=Z (будет =Y')
	;ld a,0
	LD ix,vertwaspyramid
	call DOOBJNROT ;пирамида справа вверху
	endif
	
_blz=0
	if 1==0
_=0
	dup 2
	ld bc,-#180 ;bc=Y (будет =Z')
	ld hl,-#100+_ ;hl=X (будет =X')
	ld de,_blz;#80-#060 ;de=Z (будет =Y')
	;ld a,0
	LD ix,vertwashalfcube
	call DOOBJNROT ;кубик справа
	ld bc,-#140 ;bc=Y (будет =Z')
	ld hl,-#140+_ ;hl=X (будет =X')
	ld de,_blz;#80-#060 ;de=Z (будет =Y')
	;ld a,0
	LD ix,vertwashalfcube
	call DOOBJNROT ;кубик справа
	ld bc,-#100 ;bc=Y (будет =Z')
	ld hl,-#100+_ ;hl=X (будет =X')
	ld de,_blz;#80-#060 ;de=Z (будет =Y')
	;ld a,0
	LD ix,vertwashalfcube
	call DOOBJNROT ;кубик справа
	ld bc,-#0c0 ;bc=Y (будет =Z')
	ld hl,-#140+_ ;hl=X (будет =X')
	ld de,_blz;#80-#060 ;de=Z (будет =Y')
	;ld a,0
	LD ix,vertwashalfcube
	call DOOBJNROT ;кубик справа
	ld bc,-#080 ;bc=Y (будет =Z')
	ld hl,-#100+_ ;hl=X (будет =X')
	ld de,_blz;#80-#060 ;de=Z (будет =Y')
	;ld a,0
	LD ix,vertwashalfcube
	call DOOBJNROT ;кубик справа
	ld bc,-#040 ;bc=Y (будет =Z')
	ld hl,-#140+_ ;hl=X (будет =X')
	ld de,_blz;#80-#060 ;de=Z (будет =Y')
	;ld a,0
	LD ix,vertwashalfcube
	call DOOBJNROT ;кубик справа
_=_+#80
	edup
	endif

	if 1==1
_=0
	ld bc,-#120;#40 ;bc=Y (будет =Z')
	ld hl,-#100+_ ;hl=X (будет =X')
	ld de,-(sz/2) ;de=Z (будет =Y')
	LD ix,vertwascurve
	call DOOBJNROT

	ld bc,-#140;#40 ;bc=Y (будет =Z')
	ld hl,-#0c0+_ ;hl=X (будет =X')
	ld de,-(sz/2) ;de=Z (будет =Y')
	LD ix,vertwascurve
	call DOOBJNROT

	dup 3
	;ld a,(col1a)
	;or a
	;jp z,1f
__=-#180
	dup 3
	ld bc,__ ;bc=Y (будет =Z')
	ld hl,-#100+_ ;hl=X (будет =X')
	ld de,_blz;#80-#060 ;de=Z (будет =Y')
	;ld a,0
	LD ix,vertwascell
	call DOOBJNROT
	ld bc,#20+__ ;bc=Y (будет =Z')
	ld hl,-#120+_ ;hl=X (будет =X')
	ld de,_blz;#80-#060 ;de=Z (будет =Y')
	;ld a,0
	LD ix,vertwascell
	call DOOBJNROT
__=__+#40
	edup
1
_=_+#40
	edup
	endif

	call sortobjpop

	ld hl,coltab+1
	ld a,(hl)
	xor #55
	ld (hl),a
	inc l
	ld a,(hl)
	cpl
	ld (hl),a
	inc l
	ld a,(hl)
	xor #aa
	ld (hl),a
	inc l
	ld a,(hl)
	xor #55
	ld (hl),a
	inc l
	ld a,(hl)
	cpl
	ld (hl),a

	;ld hl,#8080 ;xy1
	;ld de,#909f ;xy2
	;call line
	;halt
	call copyscreen ;92053(77525)t чересстрочно весь экран с полной очисткой
	ld hl,framesdrawn
	inc (hl)
paws
	ld a,#ef
	in a,(#fe)
	rra
	jr nc,paws
	if LINEEX
	ld a,(line_opcode)
	xor #eb ;ex de,hl
	ld (line_opcode),a
	endif
	;call drawedges ;test
	;call copyscreen
	;jp $
waithalt
	ld hl,(timer)
oldtimer=$+1
	ld de,0
	ld (oldtimer),hl
	or a
	sbc hl,de
	jp z,waithalt;mainloop
	ld b,l
timeraction0
	push bc
	;call scripting
curmove=$+1
	call movecube
	pop bc
	djnz timeraction0
	ld de,basetime+(192*9)-18;15
	ld hl,(timer)
	or a
	sbc hl,de
	jp c,mainloop
quit
	jp mainloop


	
	include "script.asm"

	include "3dmodel.asm"

	include "rotobj.asm"
	include "rotmatrix.asm"
	include "rotate.asm"
	include "rotmodel.asm"
	include "visibility.asm"
	include "floor.asm"

	include "drawedges.asm"
	include "drawfaces.asm"
	include "display.asm"
	
	include "sortobj.asm"

;сейчас начальная сцена с 5 фигурами в среднем 205000t = 200xxxt...209xxxt (203000 = 197xxx...207xxx)
; 77525t copyscreen чересстрочно весь экран с полной очисткой - очистка заменится на бокс
; 11340t ROTATE_OBJECT (5*2268, т.к. все видимы) - невидимые 633t --- fixed будет 5000t
; 30000t? (inline) ROTATE_VERTICES
; 12870t (восьмибитное) checkvisibility (5*2574)
; 54000(53000)t drawfaces (без них 151000 (150000)) - у цикла переброски 30 проходов по 501t = 15000! плюс от DRWPOLY до DRS1_ = 1533..1548..1576..1660t (15 таких проходов)
;---- сумма = 185xxx(184xxx)
; 20xxx(19xxx)t накладные расходы (сортировка 16000t) --- fixed теперь сортировка 5000t

;надо ускорить выпуклые объекты через инлайн, но с возможностью подключения невыпуклых (с собственной сортировкой)

;если залить весь экран двумя полигонами, то только обвязка займёт 200*200=40000t
;и ещё заливка 11*3000=33000t

;со всеми 25 объектами, полом и потолком при scrhgt=64:
;438000:
;103687 floor+ceiling
; 47263 obj
;232000 sortpop, из них:
     ;2000t сам цикл прохода сортировки
     ;6525t (25*261) чтение объектов, переход на объекты, стек, возврат и вход в цикл снова
     ;18900t (3*6300 ровно) вход и построение матрицы с засечками (вызывается 3 раза)
     ;остаток=204575:
     ;50000? (?*????) вращение: ROTWALL=4549, ROTCELL=1768, ROTCURVE=7814, ROTPYRAMID=2532
     ;50000? (?*????) visibility: WALL=1974, CELL=0, CURVE=6219, PYRAMID=2450
     ;100000? (?*????) draw: WALL=11478, CELL=829, CURVE=4010, PYRAMID=7428
; 52011 display
;  3000 накладные расходы

	;.ALIGN 256
	BEGIN256 256
tcos
	INCBIN "cos.$c!" ;не с 0, а с 2*pi*(1/512)??? (для ROTATE_OBJECT)
	END256

	BEGIN256 256
tsindiv2
	INCBIN "sindiv2" ;с 0 (для ROTATE_MATRIX)
	END256

showfps
	ld a,(framesdrawn)
	push de
	ld de,#4000
	ld bc,10-256
	inc b
	sub c
	jr nc,$-2
	add a,c
	ld c,a
	ld a,b
	call showdig
	ld a,c
	call showdig
	pop de
	xor a
	ld (framesdrawn),a
	ret
showdig	
	add a,"0"
	push de
	add a,a
	ld h,15
	ld l,a
	add hl,hl
	add hl,hl
	ld b,8
showdig0
	ld a,(hl)
	ld (de),a
	inc l
	inc d
	djnz showdig0
	pop de
	inc e
	ret
framesdrawn
	db 0

	BEGIN256 512
IMVEC=$+#ff
IMER=(($/#100)+1)*#101
IMERSP=IMER
	ds #101,#ff&IMER
	END256
;IMER=#cfcf
;IMERSP=IMER
;IMVEC=#ceff;#3bff
;endfree=endfree-#200

prog

	;if IMVEC!=#3bff
ON_INT
;по прерыванию в стек пишется de
	disp IMER
	 ex de,hl
	ex (sp),hl ;hl запомнили, вспомнили адрес возврата
	ld (IMERjp),hl
	pop hl ;вспомнили hl
	 ex de,hl
	ld (IMERwassp),sp
	;push de ;пишем de
	ld sp,IMERSP
	push af,bc,hl
	ld hl,(timer)
	inc hl
	ld (timer),hl
timersec=$+1
	ld a,1
	dec a
	jr nz,timernsec
	call showfps
	ld a,50
timernsec
	ld (timersec),a
	;push de
	;push ix,iy
	;ld a,(curpg)
	;push af
	;ld a,pgmuz
	;call OUTA
	;;call muz+5
	;pop af
	;call OUTA
	;pop iy,ix
	;pop de
	pop hl,bc,af
IMERwassp=$+1
	ld sp,0
	ei
IMERjp=$+1
	jp 0
timer
	dw 0
	ent
szON_INT=$-ON_INT
	;endif

wasmakers
	disp makers
;GEN TABLE Y.B=2^(X/256)-1 ,X=(0;1)
GEN2X
        LD IX,TB2X
        LD HL,0
GN2X    LD A,H;ROUNDING
        BIT 7,L
        JR Z,$+3
        INC A
        LD (IX),A
        XOR A
        EXX 
        LD L,A
	ld H,A
	ld E,A
        LD BC,#00B2;(2^1/256)*#10000
        EXX 
        LD BC,#1801
GN2X1   RR C
	rr H
	rr L
        EXX 
        JR NC,GN2X2
        ADD HL,BC
        ADC A,1
GN2X2   RRA 
        RR H
	rr L
        EXX 
        DJNZ GN2X1
        LD A,C
        RRA 
        EXX 
        LD H,L
	ld L,A
        INC LX
        JR NZ,GN2X
        RET 

;GEN TABLE Y.W=LOG2(X) ,X=(1,255)
GENLOG2
        LD HL,TBLOG2
        XOR A
        LD E,A
	ld D,A
        LD (HL),A
        INC H
        LD (HL),#F0
        DEC H
        INC L
GNLG1   LD (HL),D
        INC H
        LD (HL),A
        DEC H
        EXA 
        PUSH HL,DE
        LD DE,#7440
        LD C,L
        SRL C
        RR D
        XOR A
        LD HL,#B8AA
        EXX 
        LD H,A
	ld L,A
        LD B,#10
GNLG2   EXX 
        ADD HL,HL
        ADC A,A
        SBC HL,DE
        SBC A,C
        JR NC,GNLG3
        ADD HL,DE
        ADC A,C
GNLG3   EXX 
        CCF 
        adc hl,hl
        ;rl l
        ;rl h
        DJNZ GNLG2
        POP DE
        EXA 
        ADD HL,DE
        ADC A,B
        EX DE,HL
        POP HL
        INC L
        JR NZ,GNLG1
        RET 

	if SMALLLINES
mklines
	ld hl,prog
	ld ix,progtable
;generate progs for all angles
	ld b,64;32 ;angles
mklines_angles0
	push bc
	ld a,64;32
	sub b ;0..63;31 (todo optimize)
	;find dx,dy for given angle
	push hl
	;add a,a ;angle*2 (there are 64 angles in the table)
	add a,a
	ld hl,tsines
	add a,l
	ld l,a
	adc a,h
	sub l
	ld h,a
	ld e,(hl) ;dx
	inc hl
	ld d,(hl) ;dy
	xor a
	sub e
	ld e,a
	xor a
	sub d
	ld d,a
	ld (mklinedraw_dxdy),de
	pop hl
	call mkline
	ld (ix+0),e
	ld (ix+1),d ;entry (todo optimize)
	inc ix
	inc ix
	;ld de,(mklinedraw_dxdy)
	;sra d
	;sra e
	;ld (mklinedraw_dxdy),de
	;call mkline
	;ld (ix+0),e
	;ld (ix+1),d ;entry (todo optimize)
	;inc ix
	;inc ix
	pop bc
	djnz mklines_angles0

;generate jumptable
	ld d,-32 ;dy
	ld b,64
mklines_dy0
	push bc
	ld e,-linemaxhgt;-31 ;dx
	ld b,linemaxhgt*2+1;63
mklines_dx0
	push bc
	push de
	push hl
	ld a,e ;dx
	add a,jumptable_center/256 ;#a0xx..#dfxx - таблица джампов
	ld hx,a
	ld a,d ;dy
	add a,a
	add a,a
	ld lx,a
	;find angle from dx,dy (signed)
	call atan2
	;de=%000yyyyy 000xxxxx (abs)
	;a=angle=0..255
	;find prog for given angle
	bit 4,d
	jr nz,mklines_long
	bit 4,e
	jr nz,mklines_long
mklines_short
	add a,4 ;правильное округление до 2 ("0"=-4..+3, "2"=+4..+11...)
	rra
	rra
	and #3e ;только короткие линии
	ld l,a
	ld a,d
	cp 3
	jr nc,mklines_longq
	ld a,e
	cp 3
	jr nc,mklines_longq
	ld a,#c9
	jp mklines_wrjp ;too short
mklines_long
	add a,2 ;правильное округление до 1 ("0"=-2..+1, "1"=+2..+5, "2"=+6..+9...)
	rra
	rra
	and #3f ;чередуем длинные/короткие линии в зависимости от угла
	ld l,a
mklines_longq
	ld h,0
	add hl,hl
	ld de,progtable
	add hl,de
	ld e,(hl)
	inc hl
	ld d,(hl)
	;ld a,#c3
mklines_wrjp
	pop hl
	ld (ix+0),#c3
	ld (ix+1),line_slow_dy&#ff
	ld (ix+2),line_slow_dy/256
	 ld a,l
	 cp -4*8
	 jp m,mklines_wrjpq
	 cp +4*8
	 jp p,mklines_wrjpq
	ld (ix+1),e
	ld (ix+2),d ;entry
mklines_wrjpq
	pop de
	inc e ;dx++
	pop bc
	djnz mklines_dx0
	inc d ;dy++
	pop bc
	djnz mklines_dy0
	;ld a,#c9 ;ret
	;ld (#c000),a ;dx=dy=0
	ret

mkline
	ld c,l ;00 entry
	ld a,%00000000
	call mklinedraw ;00
	ld b,l ;0x entry
	ld (hl),#cb
	inc hl
	ld (hl),#2c ;sra h
	inc hl
	ld (hl),#30 ;jr nc
	inc hl
	ld a,c
	sub l
	dec a
	ld (hl),a ;disp to 00
	inc hl
	ld a,%01000000
	call mklinedraw ;01
	ld c,l ;10 entry
	ld a,%10000000
	call mklinedraw ;10
	push hl ;entry
	ld (hl),#eb ;ex de,hl
	inc hl
	;ld (hl),#cb
	;inc hl
	;ld (hl),#2c ;sra h
	;inc hl
	ld (hl),#30 ;jr bc
	inc hl
	ld a,b
	sub l
	dec a
	ld (hl),a ;disp to 0x
	inc hl
	ld (hl),#cb
	inc hl
	ld (hl),#2c ;sra h
	inc hl
	ld (hl),#30 ;jr nc
	inc hl
	ld a,c
	sub l
	dec a
	ld (hl),a ;disp to 10
	inc hl
	ld a,%11000000
	call mklinedraw ;11
	pop de ;entry
	ret

	;set n,(hl)
	;;inc l
	;;inc h
mklinedraw
	push bc
mklinedraw_dxdy=$+1
	ld de,0
;e=dx=-31..+31
;d=dy=-31..+31
;a=%xx000000
	ld c,a
	push hl
	bit 7,e ;dx
	ld hl,mkline_incx
	jr z,mklinedraw_dxpos
	xor a
	sub e
	ld e,a ;dx=0..31
	ld hl,mkline_decx
mklinedraw_dxpos
	ld (mkline_incdecx_jp),hl
	pop hl
	bit 7,d ;dy
	ld a,#2c ;inc l
	jr z,mklinedraw_dypos
	xor a
	sub d
	ld d,a ;dy=0..31
	ld a,#2d ;dec l
mklinedraw_dypos
	ld (mkline_incdecy_opcode),a
	LD A,d ;dy
	CP e ;dx
	JR NC,HORNV ;dy>=dx, dx<=dy
HORNH ;
	LD A,e
	LD B,e ;dx
	INC B ;dx+1 pixels
	CPL 
	;SCF ;уже CY=1 
	RRA ;mym:=256-(dx div 2)
HORNH0
	call mkline_pixel
	call mkline_incdecx
	ADD A,d ;mym:=mym+dy
	JR NC,HORNHQ
	SUB e ;mym:=mym-dx
	call mkline_incdecy
HORNHQ	DJNZ HORNH0
	JP HORNQ
HORNV ;
	LD B,d ;dy
	INC B ;dy+1 pixels
	CPL
	SCF ;CY=1
	RRA ;xm:=256-(dy div 2)
HORNV0	call mkline_pixel
	ADD A,e ;xm:=xm+dx
	JR NC,HORNVQ
	SUB d ;xm:=xm-dy {dy<>0!!!}
	call mkline_incdecx
HORNVQ	call mkline_incdecy
	DJNZ HORNV0 
HORNQ
	call mkline_finishpixel
mkline_pixelend=$+1
	ld hl,0
	pop bc
	ld (hl),#c9
	inc hl
	ret

mkline_incdecy
	call mkline_finishpixel
mkline_incdecy_opcode=$+1
	ld (hl),#2c ;inc l
	;ld (hl),#2d ;dec l
	inc hl
	ret

mkline_finishpixel
	push af
mkline_npixels=$+1
	ld a,0
	cp 2
	jr c,mkline_finishpixelq
mkline_pixelbeg=$+1
	ld hl,0
	ld (hl),#36 ;ld (hl),n
	inc hl
	ld (hl),#ff
mkline_pixelsmask=$+1
	ld a,0
	cp (hl)
	jr z,mkline_finishpixelqff
	dec hl
	ld (hl),#7e ;ld a,(hl)
	inc hl	
	ld (hl),#f6 ;or n
	inc hl	
	ld (hl),a
	inc hl	
	ld (hl),#77 ;ld (hl),a
mkline_finishpixelqff
	inc hl	
	ld (mkline_pixelend),hl
mkline_finishpixelq
	xor a
	ld (mkline_npixels),a
	ld (mkline_pixelsmask),a
	pop af
	ret

mkline_incdecx
	push af
	ld a,c ;%xxx00000
mkline_incdecx_jp=$+1
	jp mkline_incx
mkline_incx
	add a,%00100000
	ld c,a
	jr nc,mkline_incxq
	call mkline_finishpixel
	ld (hl),#24 ;inc h
	inc hl
mkline_incxq
	pop af
	ret
mkline_decx
	sub %00100000
	ld c,a
	jr nc,mkline_decxq
	call mkline_finishpixel
	ld (hl),#25 ;dec h
	inc hl
mkline_decxq
	pop af
	ret

mkline_pixel
	push af
	ld a,(mkline_npixels)
	or a
	jr nz,$+2+3
	 ld (mkline_pixelbeg),hl
	ld a,c ;%xxx00000
	rrca
	rrca ;%00xxx000
	xor #fe ;todo optimize
	 ld (hl),#34 ;inc (hl) ;НЕТОЧНАЯ ЗАМЕНА!!!
	 cp #c6
	 jr z,mkline_pixel_0
	ld (hl),#cb
	inc hl
	ld (hl),a ;#c6/#ce...#fe ;set n,(hl)
mkline_pixel_0
	inc hl
	ld (mkline_pixelend),hl
	 inc a
	 ld (mkline_pixel_setopcode),a ;set n,a
	 ld a,(mkline_pixelsmask)
mkline_pixel_setopcode=$+1
	 set 0,a
	 ld (mkline_pixelsmask),a
	ld a,(mkline_npixels)
	inc a
	ld (mkline_npixels),a
	pop af
	ret

atan2
;e=dx=-31..+31
;d=dy=-31..+31
            ;192
;128;-dx,-dy ;+dx,-dy
    ;-dx,+dy ;+dx,+dy ;0
            ;64
	xor a
	bit 7,d
	jr z,atan2_dypos
;atan2_dyneg
	sub d
	ld d,a
	xor a
	bit 7,e
	jr z,atan2_dyneg_dxpos
;atan2_dyneg_dxneg
	sub e
	ld e,a
	ld a,128
atan2_dypos_dxpos
	call atan2_index
	add a,(hl) ;0..64
	ret
atan2_dypos
	bit 7,e
	jr z,atan2_dypos_dxpos
;atan2_dypos_dxneg
	sub e
	ld e,a
	ld a,128
atan2_dyneg_dxpos
	call atan2_index
	sub (hl) ;0..64
	ret

atan2_index
	push de
	;%000yyyyy 000xxxxx
	sla e
	sla e
	sla e
	;%000yyyyy xxxxx000
	srl d
	rr e
	srl d
	rr e
	srl d
	rr e
	;%000000yy yyyxxxxx
	ld hl,tatan2
	add hl,de ;+%yy yyyxxxxx
	pop de
	ret

	;align 256
tatan2
	;incbin "atan2" ;#YX ;0..64 = 0..pi/2
	incbin "atan2_32" ;+%yy yyyxxxxx ;0..64 = 0..pi/2
tsines
	;incbin "sines" ;dx,dy (64 angles)
	incbin "sineeven" ;dx,dy (64 angles: short,long,short...)
	endif ;SMALLLINES
	
	ent
szmakers=$-wasmakers

	display "beginfree=",prog
	display "_tables=",_tables
	display "endfree=",endfree
end=_tables
	ds _tables-$


	;display "Size ",/d,end-begin," bytes"
	display "Size ",/d,endfree-begin," bytes"
	
	;savebin "code.c",begin,end-begin
	savebin "code.c",begin,endfree-begin
	
	LABELSLIST "..\us\user.l"
