rotatebegin=$
;было в среднем 750t на вершину, включая матрицу
;(без матрицы 652t, включая вход =125/8=16t, т.е. без входа 636t/вершина)
;(матрица=1702t по трём осям, 404 по двум осям)
;(но надо учитывать построение засечек 6156t - сделать 15 засечек вместо 31 и пропустить одну таблицу из 9?)
;(230t процедура деления, включая call-ret(27), jr(12), shift(32), add(7) =78t)
;(голое деление ~152t)
;т.е. всё, кроме процедуры деления, составляет около 176t
;[-3t за счёт add a,d вместо константы (возвращено назад для засечек)]
;-35t за счёт rangeshift одним джампом
;-17t за счёт squash только в range0
;-24t за счёт MATRIXDIV2 (весь сдвиг засунуть в матрицу невыгодно - слишком часто считать матрицу даже при отсортированных объектах)
;DIVBYTAB примерно 450t (431..474) на вершину (ROTVERTEX2), не считая матрицу

XADD=xbase;#c0
YADD=ybase;#80;#c0

;_reg=0 ;0=A, 1=B, 2=C, 3=D, 4=E, 5=H, 6=L

	macro LDREG value
	if _isx
_=#ff&(value+XADD)
	else
_=#ff&(value+YADD)
	endif
	if _reg==0
	ld a,_
	endif
	if _reg==1
	ld b,_
	endif
	if _reg==2
	ld c,_
	endif
	if _reg==3
	ld d,_
	endif
	if _reg==4
	ld e,_
	endif
	if _reg==5
	ld h,_
	endif
	if _reg==6
	ld l,_
	endif
	endm

	macro LDREGA
	if _reg==0
	;ld a,a
	endif
	if _reg==1
	ld b,a
	endif
	if _reg==2
	ld c,a
	endif
	if _reg==3
	ld d,a
	endif
	if _reg==4
	ld e,a
	endif
	if _reg==5
	ld h,a
	endif
	if _reg==6
	ld l,a
	endif
	endm

	macro DECREG
	if _k==-1
	INCREG
	else
	if _reg==0
	dec a
	endif
	if _reg==1
	dec b
	endif
	if _reg==2
	dec c
	endif
	if _reg==3
	dec d
	endif
	if _reg==4
	dec e
	endif
	if _reg==5
	dec h
	endif
	if _reg==6
	dec l
	endif
	endif
	endm

	macro INCREG
	if _k==1
	DECREG
	else
	if _reg==0
	inc a
	endif
	if _reg==1
	inc b
	endif
	if _reg==2
	inc c
	endif
	if _reg==3
	inc d
	endif
	if _reg==4
	inc e
	endif
	if _reg==5
	inc h
	endif
	if _reg==6
	inc l
	endif
	endif
	endm


;a/e->a = a*d
	macro DODIVBYTAB
	 if _isx
	;inc h;ld h,t1divz/256
	ld l,e ;e
	ld d,(hl) ;1/z, потом используется в ~_isx
	inc h
	sub d
	ld l,a ;a-d
	add a,d
	add a,d
	ld c,a ;a+d
;a-d = -#6b..#70 (или ..#7f??? точно бывает #88)
	ld a,(hl) ;-sqrsigned (bit9=1, bit8=1, bit7=1)
	ld l,c ;a+d

	else ;~_isx

	dec h
	sub d ;1/z заранее посчитано в _isx
	ld l,a ;a-d
	add a,d ;1/z заранее посчитано в _isx
	add a,d ;1/z заранее посчитано в _isx
	ld d,a ;a+d
;a-d = -#6b..#70
	ld a,(hl) ;-sqrsigned (bit9=1, bit8=1)
	ld l,d ;a+d
	 endif ;~_isx
	inc h
;a+d = #11..#ec (или ..#7f??? точно бывает #88)
;(при DIVMAX=#49) #11..#b5
	add a,(hl) ;sqrpos = 0..0xff
	srl a ;лишний бит точности
	endm

;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$


	macro DIV8NEG div8posaddr,div8_128addr
_k=-1
;a/e->a
	; or a
	;jp p,div8pos
	if DIVCHECKOVERFLOW
	if DIVCHECKOVERFLOW==2
	;урезание делимого до DIVMAX
	cp #ff&(-DIVMAX)
	jr nc,$+4
	ld a,#ff&(-DIVMAX)
	else
	;отработка переполнения для отрицательных
	add a,e
	jr c,$+2+1+2 +1 ;+2 ;CY: |a|<e
	add a,e
	jr nc,div8_128addr ;CY: |a|<2*e
	 ;jr z,div8_128addr ;|a|=2*e
	sub e
	sub e
	endif
	endif

	neg
	DODIVBYTAB ;a/e->a
	if _isx
	cpl;neg
	add a,XADD+1
	else
       if !INTERLACE
       add a,a
       jp m,div8_128addr
       endif
	cpl;neg
	add a,YADD+1
	endif
	LDREGA
	endm ;DIV8NEG


	macro DIV8POS div8posaddr,div8_127addr
_k=1
	if DIVCHECKOVERFLOW
	if DIVCHECKOVERFLOW==2 ;урезание делимого до DIVMAX
	cp DIVMAX
	jr c,$+4
	ld a,DIVMAX
	else ;отработка переполнения для положительных
	sub e
	jr c,$+2+1+2 ;CY: a<e
	cp e
	jr nc,div8_127addr ;CY: a<2*e
	add a,e
	endif
	endif
	
	DODIVBYTAB
	if _isx
	add a,XADD
	else
       if !INTERLACE
       add a,a
       jp m,div8_127addr
       endif
	add a,YADD
	endif
	LDREGA
	endm ;DIV8POS

;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&77

;----------- X
_isx=1
_reg=2 ;C ;0=A, 1=B, 2=C, 3=D, 4=E, 5=H, 6=L
div8xinch
	inc h ;for DIVBYTAB
;a=-127..+127
div8x
rangeshiftpatch=$+1
	jr $+2
;rangeshiftrange0
	if MATRIXDIV2==0
	 sra a ;объект половинного размера
	 sra c
	 sra b;e
	endif
;a=-63..+63
zspaceshift=$+1
	add a,#40;d
	ld e,a;b,a
;squash range0 only
rotatesquashcp=$+1
	 cp MINZ;#30 ;#30 для range0 ;#10 или лучше не надо для range1 (#28(minZ)-#18(maxz)=#10)
	 jp p,div8xnosquash
	 ld e,MINZ;b,MINZ;#30 ;сплющивание по Z+z
	 jp div8xnosquash
rangeshiftjrbase=$-(rangeshiftpatch+1)
	dup rangeshiftmax
	sra a ;z
	sra c ;x
	sra b;e ;y
	edup
	if MATRIXDIV2==0
	 sra a ;объект половинного размера
	 sra c
	 sra b;e
	endif
;a=-63..+63
zspaceshift2=$+1
	add a,#40;d
	ld e,a;b,a
;squash range0 only
;rotatesquashcp=$+1
;	 cp MINZ;#30 ;#30 для range0 ;#10 или лучше не надо для range1 (#28(minZ)-#18(maxz)=#10)
;	 jp p,div8xnosquash
;	 ld e,MINZ;b,MINZ;#30 ;сплющивание по Z+z
div8xnosquash
	 ld a,c ;x
xspaceshift=$+1
	add a,0
;a/b => a
;f=флаги после сложения двух знаковых
;+-8/+7 => +-1.6 (т.е. можно перспективу в удвоенном створе экрана, но реально зависит от делителя - при b=255 будет только один створ экрана)
;для правильного деления надо a < 2*b (иначе надо формировать переполнение)
	jp po,div8xposjp ;pe=переполнение
;S=9-й бит результата инверсный
	jp m,div8xpos
div8xneg
	DIV8NEG div8xpos,div8x_128
	jp div8y
div8x_128
	;inc h;ld h,t1divz/256
	ld l,e;b ;z
	ld d,(hl) ;1/z, потом используется в ~_isx
	ld h,trotsqrpos/256
	LDREG 128 ;ld a,128
	jp div8y
div8x_127
	;inc h;ld h,t1divz/256
	ld l,e;b ;z
	ld d,(hl) ;1/z, потом используется в ~_isx
	ld h,trotsqrpos/256
	LDREG 127 ;ld a,127
	jp div8y
div8xposjp
;S=9-й бит результата
	jp m,div8xneg
div8xpos
	DIV8POS div8xpos,div8x_127
	jp div8y

;---------- Y
_isx=0
_reg=1 ;B
;a=-127..+127
div8y
	ld a,b;e ;y
yspaceshift=$+1
	add a,0
;a/b => a
;f=флаги после сложения двух знаковых
;+-8/+7 => +-1.6 (т.е. можно перспективу в удвоенном створе экрана, но реально зависит от делителя - при b=255 будет только один створ экрана)
;для правильного деления надо a < 2*b (иначе надо формировать переполнение)
	jp po,div8yposjp ;pe=переполнение
;S=9-й бит результата инверсный
	jp m,div8ypos
div8yneg
	DIV8NEG div8ypos,div8y_128
	ret
div8y_128
	LDREG 128 ;ld a,128
	ret
div8y_127
	LDREG 127 ;ld a,127
	ret
div8yposjp
;S=9-й бит результата
	jp m,div8yneg
div8ypos
	DIV8POS div8ypos,div8y_127
	ret ;bc=yx на экране


;######################################################

	macro CALLDIVX val
	ld h,t1divz/256
;a=x=-127..+127
	call div8x
	endm

	MACRO ASDECreg reg
	if reg==0
	dec b
	endif
	if reg==1
	dec d
	endif
	if reg==2
	dec e
	endif
	endm

	MACRO ASINCreg reg
	if reg==0
	inc b
	endif
	if reg==1
	inc d
	endif
	if reg==2
	inc e
	endif
	endm

	MACRO AS reg
;-sz/0/+sz
	ASDECreg reg
	jp m,$+4
	add a,(hl)
	ASINCreg reg
	jp p,$+4
	sub (hl)
	INC L
	ENDM 
;по идее тут надо умножать, но для куба хватит взять +-значение повёрнутой оси

	macro ROTATEBEGIN
	ld (sortobjnexthl),sp
	ld sp,vertbufend
	endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;
;вращаем вершины
;hl=vert
ROTVB
	ROTATEBEGIN

ROTVB1 ;
	ld a,(hl)
	inc hl
	exx
	ld d,a ;x
	exx
	ld a,(hl)
	inc hl
	exx
	ld b,a ;z
	exx
	ld a,(hl)
	inc hl
	exx
	ld e,a ;y
	LD HL,MATRIX

	xor a
	if TWOAXES==0
        AS 0;Xoz,B ;(=0 без крена)
	endif
        AS 1;Xox,D
        AS 2;Xoy,E
	ld c,a ;x
	xor a
        AS 0;Yoz,B
        AS 1;Yox,D
        AS 2;Yoy,E
        ;AS 0;Zoz,B ;тут ld b,a ;y
	inc b
	dec b
	ld b,a
	ld a,(hl)
	jr nz,$+2+1
	xor a
	jp p,$+3+1+1
	xor a
	sub (hl)
	inc l
        AS 1;Zox,D
        AS 2;Zoy,E
	org $-1
;a=z=-127..+127
	;c=x
	;b=y
	;a=z
	CALLDIVX 0
	push bc

	exx
	if TWOAXES;(($+2-(ROTVB1+#81))&#8000)==0
	djnz ROTVB1
	else
	dec b
	jp nz,ROTVB1
	endif

	push de ;edge
	push hl ;poly
	call checkvisibility ;11600t (4600t восьмибитное)
	pop hl ;poly
	call drawfaces ;на 5 кубиках 131000t (остальное=296000t)
	pop hl ;edge
	call drawedges ;27800t ;на 5 кубиках 62000t (остальное=365000t)
	jp sortobjnext

;-----------------------------

	display "rotate size=",$-rotatebegin
