Code: Select all
#include <vcl.h>
#include <math.h>
#pragma hdrstop
#include "nedodefs.h"
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
#define FLOAT int
#define SQRTFIXK 256L
#define FIXK (SQRTFIXK*SQRTFIXK)
#define spheres 2
FLOAT cx[spheres] = {
(FLOAT)(-30*FIXK/100), (FLOAT)(90*FIXK/100)
};
FLOAT cy[spheres] = {
(FLOAT)(-80*FIXK/100), (FLOAT)(-110*FIXK/100)
};
FLOAT cz[spheres] = {
(FLOAT)(300*FIXK/100), (FLOAT)(200*FIXK/100)
};
FLOAT r[spheres] = {(FLOAT)(60*FIXK/100), (FLOAT)(20*FIXK/100)};
FLOAT q[spheres];
FLOAT projx[spheres];
FLOAT projy[spheres];
FLOAT projr[spheres];
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
FLOAT umul(FLOAT a,FLOAT b)
{
RETURN ((a>>8) * (b>>8));
}
FLOAT mul(FLOAT a,FLOAT b)
{
FLOAT res;
FLOAT ia;
FLOAT ib;
ia = a;
ib = b;
IF (ia < 0 /*>= 0x80000000L*/) {ia = -ia;};
IF (ib < 0 /*>= 0x80000000L*/) {ib = -ib;};
res = umul(ia, ib);
IF ((a^b) < 0 /*>= 0x80000000L*/) {res = -res;};
RETURN res;
}
FLOAT udiv(FLOAT a,FLOAT b)
{
FLOAT ib;
ib = b>>8;///SQRTFIXK;
if (ib == 0L) {
ib = 1L;
};
RETURN ((a / ib)<<8/**SQRTFIXK*/);
}
FLOAT idiv(FLOAT a,FLOAT b)
{
FLOAT res;
FLOAT ia;
FLOAT ib;
ia = a;
ib = b;
IF (ia < 0 /*>= 0x80000000L*/) {ia = -ia;};
IF (ib < 0 /*>= 0x80000000L*/) {ib = -ib;};
res = udiv(ia, ib);
IF ((a^b) < 0 /*>= 0x80000000L*/) {res = -res;};
RETURN res;
}
FLOAT add(FLOAT a,FLOAT b)
{
RETURN (a + b);
}
FLOAT mul2(FLOAT a)
{
RETURN add(a,a);
}
FLOAT sub(FLOAT a,FLOAT b)
{
RETURN (a - b);
}
FLOAT neg(FLOAT a)
{
RETURN (-a);
}
UINT lsqrt(FLOAT arg)
{
BYTE count=0x10;
UINT res=0;
UINT tmp=0;
IF (arg!=0L) {
/* IF (!(arg&0xFF000000L)) {
arg = arg<<8;
count-=4;
};*/
res = 1;
WHILE ((tmp<1)&&(count!=0x00)){
DEC count;
IF (arg&0x80000000L) {tmp|=2;};
IF (arg&0x40000000L) {tmp|=1;};
arg = arg << 2L;
};//поиск первой 1-ы
DEC tmp;
WHILE (count!=0x00) {
tmp = tmp << 2;
res = res + res; //res << 1;
DEC count;
IF (arg&0x80000000L) {tmp = tmp | 2;};
IF (arg&0x40000000L) {tmp = tmp | 1;};
arg = arg << 2L;
IF (tmp >= ((res<<1)|1)) {
tmp = tmp - ((res<<1)|1);
res = res | 1;
};
};
};
RETURN res;
}
FLOAT root(FLOAT a)
{
RETURN ((FLOAT)lsqrt(a)*SQRTFIXK);
}
FLOAT fract(FLOAT a)
{
RETURN ( a & (FIXK/2) /*!= 0L*/ );
}
BOOL positive(FLOAT a)
{
RETURN (a >= 0 /*< 0x80000000L*/);
}
BOOL less(FLOAT a, FLOAT b)
{
RETURN ((unsigned int)a < (unsigned int)b);
}
void TForm1::prhex(AnsiString name, int a)
{
AnsiString s = "";
AnsiString sc = " ";
char c;
for (int i = 0; i < 8; i++) {
c = (a & 0x0f) + '0';
if (c>=('0'+10)) c = c+'a'-('0'+10);
sc[1] = c;
s = sc + s;
a = a >> 4;
};
Memo1->Lines->Add(name+s);
}
PROC TForm1::tracepixel(int i,int j)
{
BYTE n;
BYTE k;
FLOAT s;
FLOAT px;
FLOAT py;
FLOAT pz;
FLOAT sc;
FLOAT aa;
FLOAT bb;
FLOAT pp;
FLOAT nx;
FLOAT ny;
FLOAT nz;
FLOAT nn;
FLOAT u;
FLOAT v;
FLOAT l;
FLOAT x;
FLOAT y;
FLOAT z;
FLOAT dx;
FLOAT dy;
FLOAT dz;
FLOAT dd;
#define GROUND 0xfe
#define SKY 0xff
#define EYEX (FLOAT)(30*FIXK/100)
#define EYEY (FLOAT)(-50*FIXK/100)
#define EYEZ (FLOAT)(0*FIXK/100)
x = EYEX;
y = EYEY;
z = EYEZ;
#define KVECTOR 64L
// dx = (FLOAT)((FLOAT)(j-128)*FIXK/KVECTOR);
// dy = (FLOAT)((FLOAT)(88-i)*FIXK/KVECTOR);
// dz = (FLOAT)((FLOAT)(300)*FIXK/KVECTOR);
#define MULVECTOR 0x0400L
dx = mul(((FLOAT)(j)-(FLOAT)(128))*FIXK, MULVECTOR);
dy = mul(((FLOAT)(88)-(FLOAT)(i))*FIXK, MULVECTOR);
dz = mul((FLOAT)(256)*FIXK, MULVECTOR);
//prhex("dx=",dx);
//prhex("dy=",dy);
//prhex("dz=",dz);
dd = add(mul(dx,dx),add(mul(dy,dy),mul(dz,dz))); //dx*dx+dy*dy+dz*dz;
//prhex("dx*dx=",mul(dx,dx));
//prhex("dy*dy=",mul(dy,dy));
//prhex("dz*dz=",mul(dz,dz));
//prhex("dd=",dd);
L100:
IF (positive(y) || !positive(dy)) {
n = SKY;
s = 0x7fffffffL;
}ELSE {
n = GROUND;
s = neg(idiv(y, dy)); //-y/dy; //???
};
//prhex("s=",s);
k = 0x00;
REPEAT { //ищем сферу, на которую смотрим (если есть)
px = sub(cx[k], x); //c[k][0]-x;
//prhex("px=",px);
py = sub(cy[k], y); //c[k][1]-y;
//prhex("py=",py);
pz = sub(cz[k], z); //c[k][2]-z;
//prhex("pz=",pz);
#define FIXX 256
#define SCRX (((FLOAT)(j)-(FLOAT)(128))*FIXX)
#define SCRY (((FLOAT)(88)-(FLOAT)(i))*FIXX)
IF (!(
(SCRX >= sub(projx[k],projr[k]))
&&(SCRX < add(projx[k],projr[k]))
&&(SCRY >= sub(projy[k],projr[k]))
&&(SCRY < add(projy[k],projr[k]))
// &&((i^j)&1)
)) {
//Image1->Canvas->Pixels[j][175-i] = 0xff7fff;
goto L200; //не та сфера
//goto RETURNME;
};
pp = add(mul(px,px),add(mul(py,py),mul(pz,pz))); //px*px+py*py+pz*pz;
//prhex("px*px=",mul(px,px));
//prhex("py*py=",mul(py,py));
//prhex("pz*pz=",mul(pz,pz));
//prhex("pp=",pp);
sc = add(mul(px,dx),add(mul(py,dy),mul(pz,dz))); //px*dx+py*dy+pz*dz;
//prhex("sc=",sc);
IF (!positive(sc)) {
goto L200; //не та сфера
};
bb = idiv(mul(sc,sc),dd); //sc*sc/dd;
//prhex("bb=",bb);
aa = q[k]-pp+bb; //add(sub(q[k],pp),bb); //q[k]-pp+bb;
//prhex("aa=",aa);
IF (!positive(aa)) {
goto L200; //не та сфера
};
sc = idiv(sub(root(bb),root(aa)),root(dd)); //(sqrt(bb)-sqrt(aa))/sqrt(dd);
//prhex("scp=",sub(root(bb),root(aa)));
//prhex("scq=",root(dd));
//prhex("sc=",sc);
// IF (less(sc,s) /*|| (n >= 0x80)*/) { //нашли сферу
n = k;
s = sc;
goto LFOUND;
// };
L200:
INC k;
}UNTIL (k == spheres);
IF (n == SKY) {goto RETURNME;}; //небо
LFOUND:
// Image1->Canvas->Pixels[j][175-i] = 0x007fff;
// goto RETURNME;
dx = mul(dx,s); //dx*s;
dy = mul(dy,s); //dy*s;
dz = mul(dz,s); //dz*s;
//prhex("dx=",dx);
//prhex("dy=",dy);
//prhex("dz=",dz);
dd = mul(dd,mul(s,s)); //dd*s*s;
//prhex("dd=",dd);
x = add(x,dx); //x+dx;
y = add(y,dy); //y+dy;
z = add(z,dz); //z+dz;
IF (n == GROUND) {goto L300;}; //земля
nx = sub(x,cx[n]); //x-c[n][0];
ny = sub(y,cy[n]); //y-c[n][1];
nz = sub(z,cz[n]); //z-c[n][2];
nn = add(mul(nx,nx),add(mul(ny,ny),mul(nz,nz))); //nx*nx+ny*ny+nz*nz;
//prhex("nn=",nn);
l = idiv(mul2(add(mul(dx,nx),add(mul(dy,ny),mul(dz,nz)))),nn); //2*(dx*nx+dy*ny+dz*nz)/nn;
//prhex("l=",l);
dx = sub(dx,mul(nx,l)); //dx-nx*l;
dy = sub(dy,mul(ny,l)); //dy-ny*l;
dz = sub(dz,mul(nz,l)); //dz-nz*l;
//prhex("dx=",dx);
//prhex("dy=",dy);
//prhex("dz=",dz);
goto L100; //отражение
L300: //земля
k = 0x00;
REPEAT {
u = sub(cx[k],x); //c[k][0]-x;
v = sub(cz[k],z); //c[k][2]-z;
IF (add(mul(u,u),mul(v,v)) <= q[k]) {goto RETURNME;}; //(u*u+v*v)
INC k;
}UNTIL (k == spheres);
IF (fract(x) != fract(z)) {Image1->Canvas->Pixels[j][175-i] = 0xffffff;}; //((x+100)-(int)(x+100)) //(z-(int)(z))
RETURNME:
}
void __fastcall TForm1::FormCreate(TObject *Sender)
{
BYTE i;
BYTE j;
BYTE k;
k = 0x00;
REPEAT {
q[k] = mul(r[k],r[k]); //r[k]*r[k];
INC k;
}UNTIL (k == spheres);
k = 0x00;
REPEAT {
projx[k] = idiv(sub(cx[k],EYEX), sub(cz[k],EYEZ));
projy[k] = idiv(sub(cy[k],EYEY), sub(cz[k],EYEZ));
projr[k] = idiv(r[k]*17/16, sub(cz[k],EYEZ)); //больше, потому что "бок" сферы торчит за проекцию
prhex("projx=",projx[k]);
prhex("projy=",projy[k]);
prhex("projr=",projr[k]);
INC k;
}UNTIL (k == spheres);
i = 0x00;
REPEAT {
j = 0x00;
REPEAT {
Image1->Canvas->Pixels[j][175-i] = 0x000000;
tracepixel(i,j);
INC j;
}UNTIL (j == (BYTE)255);
INC i;
}UNTIL (i == (BYTE)175);
cx[0] = cx[0]+(FLOAT)(10*FIXK/100);
cz[1] = cz[1]+(FLOAT)(30*FIXK/100);
Memo1->Lines->Add(IntToStr(0x100000000000000 >> 16));
}
In 2018, I tried to made the same scene in 1K and under 1 minute (Daniel Nagy had over 5 minutes with his short floats - I lost his web page with the code), but ended at 72 seconds (in 16 bit arithmetics): http://alonecoder.nedopc.com/zx/raytrace1k.zip
The engine must remain universal for future applications. So, no hard-wired masking for "unused" screen zones. My final speedup was realtime calculated 2D masks for every object on the scene. I also tried simple animation, but the final version doesn't fit in 1K with both animation and masking.
Code: Select all
device pentagon1024 ;don't trust this, it's for 48K :)
GO=0x6001;0x8001
SQUAREMUL=1
SQUARESQR=1
showtime=1
fastest=1
original_coords=1
IMVEC=0x7d00;0xae00;0xbe00
IMER=(IMVEC/256+1)*257
SQRTFIXK=256
FIXK=(SQRTFIXK*SQRTFIXK)
FIXKDIV2=(FIXK/2)
spheres=0x02
cx0=-(30*FIXK/100>>8) ;-30
cy0=-(80*FIXK/100>>8) ;-80
cz0=(300*FIXK/100>>8) ;300
r0=(60*FIXK/100>>8) ;60
if original_coords
cx1=(83*FIXK/100>>8) ;90 ;88
cy1=-(120*FIXK/100>>8) ;-110 ;-114
cz1=(200*FIXK/100>>8)
r1=(20*FIXK/100>>8)
else
cx1=(87*FIXK/100>>8) ;90
cy1=-(100*FIXK/100>>8) ;-110 (100 оптимизируется MegaLZ)
cz1=(200*FIXK/100>>8) ;200 (200 оптимизируется MegaLZ)
r1=(20*FIXK/100>>8) ;20
endif
q0=(r0*r0>>8)
q1=(r1*r1>>8)
GROUND=0x3e;0x7f ;код команды ld a,N
SKY=0xff
EYEX=(30*FIXK/100)
EYEY=-(50*FIXK/100)
EYEZ=(0*FIXK/100)
KVECTOR=64
;EYEDZ=(300*FIXK/KVECTOR)
EYEDZ=(256*FIXK/KVECTOR)
EYEDZDIVFIXK=(EYEDZ/SQRTFIXK)
SQEYEDZ=(EYEDZDIVFIXK*EYEDZDIVFIXK)
macro SQDELOOP
;+de*+de
ld hl,0
ld d,l;0
;полное умножение требует 16(15) проходов, а мы сделаем по частям в 8(7) проходов
;0de0 * 0de0 = de0*d + de*e = (d*d<<16) + (d*e<<9) + (e*e)
;(d*e<<9) -> hl0
rlca ;"d"
jr nc,$+4
ld l,e ;"0e"
add hl,hl
dup 6
rlca ;"d"
jr nc,$+3
add hl,de ;"0e"
add hl,hl
edup
;hl0 = (d*e<<9)
if 1==0 ;don't use bc (невыгодно по сравнению с sqde:ld iy,de:...:sqde:add iy,de:...:sqde:add iy,de
ex de,hl
ld h,tsqr/256+1
ld h,(hl) ;(e*e)
ld l,a
ld a,h
ld h,tsqr/256
ld h,(hl) ;(d*d<<16)
ld l,a
add hl,de
ex de,hl
else
ld c,a
ld d,tsqr/256+1
ld a,(de) ;(e*e)
add a,l
ld e,a
ld b,tsqr/256
ld a,(bc) ;(d*d<<16)
adc a,h
ld d,a
endif
;out: 0de0
endm
macro SQDE
ld a,d
rlca
jr nc,$+2+3+3
xor a
sub e
ld e,a
sbc a,d
sub e
rlca ;"d"
if SQUARESQR
scf
rra
ld d,a
res 0,e
ex de,hl
ld e,(hl)
inc l
ld d,(hl)
ld a,l
cp 8 ;костыль для младшего бита
rl e;sla e
rl d
;ld a,(hl)
;inc l
;ld h,(hl)
;ld l,a
;add hl,hl ;выигрыш 1 байт по сравнению с оптимизированным
;ex de,hl
else
SQDELOOP
endif
endm
macro SQHL
ld a,h
rlca
jr nc,$+2+3+3
xor a
sub l
ld l,a
sbc a,h
sub l
rlca ;"h"
if SQUARESQR
scf
rra
ld h,a
res 0,l
;ex de,hl
ld e,(hl)
inc l
ld d,(hl)
;ld a,l
;cp 8 ;костыль для младшего бита
rl e;sla e
rl d
;ld a,(hl)
;inc l
;ld h,(hl)
;ld l,a
;add hl,hl ;выигрыш 1 байт по сравнению с оптимизированным
;ex de,hl
else
ex de,hl
SQDE
endif
endm
macro DIVLOOP
;(keep bc)
;hla = "0de"
;a = hla/bc0
;do 7 bits
;shift left hla, try sub, keep carry (inverted bit of result)
rla;add a,a
adc hl,hl ;no carry ;rl l нельзя
sbc hl,bc
jr nc,$+3
add hl,bc
rla
dup 7
adc hl,hl ;no carry
sbc hl,bc
jr nc,$+3
add hl,bc
rla
edup
cpl
ld d,a ;"res_l"
;hl = "de"
;a = hla/bc0
;do 7 bits
;shift left hla, try sub, keep carry (inverted bit of result)
dup 7
add hl,hl ;no carry
sbc hl,bc
jr nc,$+3
add hl,bc
rla
edup
add hl,hl ;no carry
sbc hl,bc
;jr nc,$+3
;add hl,bc
rla
cpl
ld e,a
;out: de
endm
macro DIVDEBC_POSITIVE
;(keep bc)
ld h,0
ld l,d
ld a,e
;hla = "0de"
DIVLOOP
;out: de
endm
macro DIVDEBC_AXSIGN_NONEGBC
;(keep bc)
ld a,d
rla
jr nc,$+2+6;idivnonegde
xor a
sub e
ld e,a
sbc a,d
sub e
ld d,a
;idivnonegde
;out: de
;idiv_0de0_00bc
DIVDEBC_POSITIVE
ex af,af' ;M=разные знаки
jp p,$+3+6;ret p
xor a
sub e
ld e,a
sbc a,d
sub e
ld d,a
;ret
endm
macro DIVDEBC_ASIGN
ex af,af' ;M=разные знаки
ld a,b
rla
jr nc,$+2+6;idivnonegbc
xor a
sub c
ld c,a
sbc a,b
sub c
ld b,a
;idivnonegbc
DIVDEBC_AXSIGN_NONEGBC
endm
macro ROOTHL
if 1==1
xor a
ld b,a
ld e,l
ld l,h
ld h,a
sla l;add hl,hl
sla l;add hl,hl
;cp h
;jr nc,$+5
;dec h
;ld a,4
add hl,hl
add hl,hl
ld c,a
sub h
jr nc,$+6
cpl
ld h,a
inc c
inc c
ld a,c
add hl,hl
add hl,hl
add a,a
ld c,a
sub h
jr nc,$+6
cpl
ld h,a
inc c
inc c
ld a,c
add hl,hl
add hl,hl
add a,a
ld c,a
sub h
jr nc,$+6
cpl
ld h,a
inc c
inc c
ld a,c
ld l,e
add hl,hl
add hl,hl
add a,a
ld c,a
sub h
jr nc,$+6
cpl
ld h,a
inc c
inc c
ld a,c
add hl,hl
add hl,hl
add a,a
ld c,a
sub h
jr nc,$+6
cpl
ld h,a
inc c
inc c
ld a,c
add a,a
ld c,a
add hl,hl
add hl,hl
jr nc,$+6
sub h
jp $+6
sub h
jr nc,$+6
inc c
inc c
cpl
ld h,a
ld e,1
ld a,l
ld l,h
add a,a
ld h,a
adc hl,hl
adc hl,hl
sll c
rl b
sbc hl,bc
jr nc,$+3
add hl,bc
sbc a,a
;add a,a
;inc a
or e;1
add a,c
ld c,a
;iteration 9
add hl,hl
add hl,hl
sll c
rl b
sbc hl,bc
jr nc,$+3
add hl,bc
sbc a,a
;add a,a
;inc a
or e;1
add a,c
ld c,a
add hl,hl
add hl,hl
sll c
rl b
sbc hl,bc
jr nc,$+3
add hl,bc
sbc a,a
;add a,a
;inc a
or e;1
add a,c
ld c,a
add hl,hl
add hl,hl
sll c
rl b
sbc hl,bc
jr nc,$+3
add hl,bc
sbc a,a ;0/-1
;add a,a ;0/-2
;inc a ;+1/-1
or e;1
add a,c
;ld c,a
;add hl,hl
;add hl,hl
;sll c
;rl b
;sbc hl,bc
;jr nc,$+3
;add hl,bc
;sbc a,a
;add a,a
;inc a
;add a,c
;ld c,a
;12th iteration completed
; output in BC
;srl b
;rr c
ld h,b
ld l,a;c
else
;root0hl0
or a ;NC
ld bc,64 ;c=64 (const), eb будет результат
ld a,l
ld l,h
ld h,b;0
ld e,b;0
;0hla=00NN
dup 4
sbc hl,bc
jr nc,$+3
add hl,bc
ccf
rl b
rla
adc hl,hl
rla
adc hl,hl
edup
;ahl0=0??0
sbc hl,bc
jr nc,$+3
add hl,bc
ccf
rl b
rl e
add hl,hl
rla
add hl,hl
rla
dup 3
sbc hl,bc
sbc a,e
jr nc,$+4
add hl,bc
adc a,e
ccf
rl b
rl e
add hl,hl
rla
add hl,hl
rla
edup
;ahl0=???0
dup 3
sbc hl,bc
sbc a,e
jr nc,$+4
add hl,bc
adc a,e
ccf
rl b
rl e
add hl,hl
rla
add hl,hl
rla
edup
sbc hl,bc
sbc a,e
jr nc,$+4
add hl,bc
adc a,e
ccf
;rl b
;rl e
;eb=результат q=[sqrt N]
ld l,b
ld h,e
adc hl,hl
;out: hl ;NC
endif
endm
macro MULDEBCLOOP
;0de * 0bc = (de * b)<<8 + (de * c) => ah
;a=b<<1
;keep de! (можно портить биты 0,15)
if SQUAREMUL
;d.e * b.c = 0.5*(d.e+b.c)^2 - 0.5*d.e^2 - 0.5*b.c^2
rra
ld b,a
res 0,c
;set 7,d
;res 0,e
;адрес в таблице: %1hhhhhhh.lllllll0
if 1==1
ld h,d
ld l,e
add hl,bc ;d.e+b.c
;ld ($+4),hl
;ld hl,(0)
;set 7,b
;ld ($+6),bc
;ld bc,(0)
;sbc hl,bc
;ld ($+6),de
;ld bc,(0)
;sbc hl,bc
set 7,b
ex de,hl
ld a,(bc)
inc c
add a,(hl)
inc l
ld lx,a
ld a,(bc)
adc a,(hl)
ld b,a ;0.5*d.e^2 + 0.5*b.c^2
ex de,hl
ld a,(hl) ;0.5*(d.e+b.c)^2
sub lx
inc l
ld c,a
ld a,(hl)
sbc a,b
;ld h,c
;add hl,hl ;11t = 1 s
;out: ah = 0.5*(d.e+b.c)^2 - 0.5*d.e^2 - 0.5*b.c^2
else
ld h,d
ld l,e
add hl,bc ;d.e+b.c
ex de,hl
ld a,(de) ;0.5*(d.e+b.c)^2
inc e
sub (hl) ;0.5*d.e^2
inc l
ld lx,a
ld a,(de)
sbc a,(hl)
ld hx,a
ex de,hl
;ix = 0.5*(d.e+b.c)^2 - 0.5*d.e^2
ld h,b
ld l,c
set 7,h
ld a,lx
sub (hl)
inc l
ld c,a
ld a,hx
sbc a,(hl)
;ld h,c
;out: ac = 0.5*(d.e+b.c)^2 - 0.5*d.e^2 - 0.5*b.c^2
endif
else
;hl=0
add a,a
add a,a
add a,a
jr nc,$+5;4
ld h,d
ld l,e
add hl,hl
add a,a
jr nc,$+3
add hl,de
dup 3;4
add hl,hl
add a,a
jr nc,$+3
add hl,de
edup
ld b,h ;b = hsb(de * b)
ld h,a;0 ;l = lsb(de * b)
;c*de => ahl
ld a,c
ld c,h;0
dup 7
add hl,hl
rla
jr nc,$+4
add hl,de
adc a,c;0
edup
add hl,hl
rla
jr nc,$+3;4
add hl,de
;adc a,c;0
;ahl = (de * c) + lsb(de * b)<<8
adc a,b ;b = hsb(de * b)
endif
;out: ah
endm
macro MULDEBC_SIGNED
;+de0 * +bc0 -> .de.
ld a,d
xor b
ex af,af' ;M=разные знаки '
ld a,d
rla
jr nc,$+2+6;mul_noneghld0
xor a
sub e
ld e,a
sbc a,d
sub e
ld d,a
;mul_noneghld0
ld a,b
add a,a
jr nc,$+2+6;mul_nonegbcx0
xor a
sub c
ld c,a
sbc a,b
sub c
;ld b,a
add a,a
;mul_nonegbcx0
if SQUAREMUL
set 7,d
res 0,e
else
ld hl,0
endif
;0de * 0bc = (de * b)<<8 + (de * c) => de
;a=b<<1
;ld a,b
;add a,a
MULDEBCLOOP
if SQUAREMUL
ld e,c
else
ld e,h
endif
ld d,a
;out: de
ex af,af' ;M=разные знаки '
jp p,$+3+6;ret p
xor a
sub e
ld e,a
sbc a,d
sub e
ld d,a
endm
macro MULDEBC
if fastest
MULDEBC_SIGNED
else
call muldebc
endif
endm
macro MULDEBC_TOIY
if 1==0
MULDEBC
ld hy,d
ld ly,e
else
;+de0 * +bc0 -> .iy.
ld a,d
xor b
ex af,af' ;M=разные знаки '
ld a,d
rla
jr nc,$+2+6;mul_noneghld0
xor a
sub e
ld e,a
sbc a,d
sub e
ld d,a
;mul_noneghld0
ld a,b
add a,a
jr nc,$+2+6;mul_nonegbcx0
xor a
sub c
ld c,a
sbc a,b
sub c
;ld b,a
add a,a
;mul_nonegbcx0
if SQUAREMUL
set 7,d
res 0,e
else
ld hl,0
endif
;0de * 0bc = (de * b)<<8 + (de * c)
;b*de => hl
;ld a,b
;add a,a
MULDEBCLOOP
if SQUAREMUL
ld b,a;hy,a
;out: iy
ex af,af' ;M=разные знаки '
jp p,$+3+6;8;ret p
xor a
sub c
ld c,a
sbc a,b;hy
sub c
ld b,a;hy,a
ld hy,b
ld ly,c
else
ld e,h
ld hy,a
;out: iy
ex af,af' ;M=разные знаки '
jp p,$+3+8;ret p
xor a
sub e
ld e,a
sbc a,hy
sub e
ld hy,a
ld ly,e
endif
endif
endm
macro MULDEBC_POSITIVE
if SQUAREMUL
set 7,d
res 0,e
else
ld hl,0
endif
;0de * 0bc = (de * b)<<8 + (de * c)
;b*de => hl
ld a,b
add a,a
MULDEBCLOOP
if SQUAREMUL
ld e,c
else
ld e,h
endif
ld d,a
;out: de
endm
macro MULDEBC_TOHL_POSITIVE
if SQUAREMUL
set 7,d
res 0,e
else
ld hl,0
endif
;0de * 0bc = (de * b)<<8 + (de * c)
;b*de => hl
ld a,b
add a,a
MULDEBCLOOP
if SQUAREMUL
ld l,c
else
ld l,h
endif
ld h,a
;out: hl
endm
macro MULDEBC_TOHL_DEPOSITIVE
if SQUAREMUL
set 7,d
res 0,e
endif
;+de0 * +bc0 -> .hl. (keeps de)
xor a
if !SQUAREMUL
ld l,a
ld h,a
endif
xor b
ex af,af' ;M=разные знаки '
ld a,b
add a,a
jr nc,$+2+6;mul_nonegbcx0
xor a
sub c
ld c,a
sbc a,b
sub c
;ld b,a
add a,a
;mul_nonegbcx0
;0de * 0bc = (de * b)<<8 + (de * c)
;b*de => hl
;ld a,b
;add a,a
MULDEBCLOOP
if SQUAREMUL
ld l,c
else
ld l,h
endif
ld h,a
;out: HL
ex af,af' ;M=разные знаки '
jp p,$+3+6;ret p
xor a
sub l
ld l,a
sbc a,h
sub l
ld h,a
endm
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
org GO
begin
;xor a
;out (0xfe),a
;ld de,0x5801
;ld h,d
;ld l,a
;ld bc,767
;ld (hl),7
;ldir
if SQUAREMUL
;d.e * b.c = 0.5*(d.e+b.c)^2 - 0.5*d.e^2 - 0.5*b.c^2
;адрес в таблице: %1hhhhhhh.lllllll0
;максимум = 127^2/2 = #1f80
;ex de,hl ;hl=0 after dehrum
ld de,#8000
;ld sp,hl
xor a ;сумма мл
;ld d,a
;ld e,a
;ld b,a
;ld c,a
;ld de,0 ;сумма
ld bc,0 ;счётчик
ld lx,a ;счётчик мл
mksquare
ex de,hl
ld (hl),e
inc l
ld (hl),d
inc lx
inc lx
inc lx
inc lx
jr nz,$+3
inc bc
add a,lx
ex de,hl ;тут лучше
adc hl,bc
;ex de,hl
;inc hl
;inc h
;dec h
inc de
inc d
dec d
jr nz,mksquare
endif
if !SQUARESQR
ld bc,1
ld de,tsqr
;ld hl,0 ;выгоднее на MegaLZ и Hrum (после dehrum уже hl=0, de=rnd, bc=#1010)
mksqr0
ex de,hl
ld (hl),e
inc h
ld (hl),d
dec h
ex de,hl
add hl,bc
inc bc
inc bc
inc e
jr nz,mksqr0
;e=0
;hl=0
;bc=0x201
endif
if showtime
ld de,IMVEC;0xbe00 ;выгоднее на MegaLZ
ld a,d
ld i,a
inc a
;ld a,IMER/256
ld (de),a
inc e
jr nz,$-2
inc d
ld (de),a
ld e,d
ld hl,on_int.
ld b,1
ldir
im 2
ei
else
;di
raytrace_begin
;ld a,0xaf
endif
if 1==1
ld l,2*(spheres-1)+1
mkbounding0
push hl
dec l
ld h,cz/256
ld c,(hl)
inc l
ld b,(hl)
;de=cz
;ld hl,-EYEZ ;0
;add hl,de
;ld b,h
;ld c,l
;bc=sub(cz[k],EYEZ) >= 0
;pop hl
;push hl
inc h ;ld h,rad/256
ld d,(hl)
dec l
ld e,(hl)
ld a,d
or a
ex af,af'
DIVDEBC_AXSIGN_NONEGBC ;(keep bc)
pop hl
ld h,projr/256
push hl
ld (hl),e
ld h,cx/256
ld d,(hl)
dec l
ld e,(hl)
ld hl,-((EYEX>>8)&0xffff)&0xffff
add hl,de
ex de,hl
ld a,d
or a
ex af,af'
DIVDEBC_AXSIGN_NONEGBC ;(keep bc)
pop hl
inc h
push hl
;ld h,projx/256
ld (hl),e
ld h,cy/256
ld d,(hl)
dec l
ld e,(hl)
ld hl,-((EYEY>>8)&0xffff)&0xffff
add hl,de
ex de,hl
ld a,d
or a
ex af,af'
DIVDEBC_AXSIGN_NONEGBC ;(keep bc)
pop hl
;inc h
;ld h,projy/256
dec l
ld (hl),e
dec l
jp p,mkbounding0
endif
; i = 0x00;
; REPEAT {
; //eyedy = ((FLOAT)(88)-(FLOAT)(i))<<10L;
; //eyedy = mul(((FLOAT)(88)-(FLOAT)(i))*FIXK, MULVECTOR);
; //sqeyedy = sq(eyedy);
; count_eyedy();
; j = 0x00;
; REPEAT {
; tracepixel(i,j);
; INC j;
; }UNTIL (j == 0x00);
; INC i;
; }UNTIL (i == 0xb0);
ld a,0xaf
raytrace_lines0
;//eyedy = ((FLOAT)(88)-(FLOAT)(i))<<10L;
;//eyedy = mul(((FLOAT)(88)-(FLOAT)(i))*FIXK, MULVECTOR);
ld (tracepixel.i),a
sub 88
ld (scryHSB),a
ld l,a
SBC A,a
ld h,a
add hl,hl
add hl,hl
LD [eyedyUINT],hl
SQHL
LD hl,+(SQEYEDZ>>8)&0xffff
add hl,de
LD [sqeyedyUINT],HL
ld a,(tracepixel.i)
ld c,0
call 8880
raytrace_pixels0
push af
push hl
call tracepixel
pop hl
rl (hl)
pop af
inc a
push af
and 7
jr nz,nonextbyte
inc l
nonextbyte
pop af
jr nz,raytrace_pixels0
tracepixel.i=$+1
ld a,0
dec a;sub 1
jp nz,raytrace_lines0
if showtime
ld iy,23610
ld hl,10072
exx
im 1
_TIMER=$+1
ld bc,0
sla c
rl b
ld sp,0x5fe8
;ret
on_int.
push hl
;_TIMER=$+1+IMER-on_int.
ld hl,(_TIMER);0
inc hl
ld (_TIMER),hl
pop hl
ei
ret
else
if 1==1
halt
else
;ld hl,cz
;ld a,(hl)
;sub 5
;ld (hl),a
;ld hl,cz+2
;ld a,(hl)
;add a,5
;ld (hl),a
ld hl,cy
inc (hl)
;inc hl
;inc hl
;dec (hl)
jp raytrace_begin
endif
endif
tracepixel
;//x = EYEX;
;//y = EYEY;
;//z = EYEZ;
;//dx = ((FLOAT)(j)-(FLOAT)(128))<<10L; //dx = mul(((FLOAT)(j)-(FLOAT)(128))*FIX
;//dy = eyedy;
;//dz = EYEDZ; //mul((FLOAT)(300)*FIXK, MULVECTOR);
;//dd = sq(dx) + sqeyedy + SQEYEDZ; //sq(dz); //dx*dx+dy*dy+dz*dz;
;a = j
eyedyUINT=$+1
LD hl,0 ;+(EYEDZ>>8)&0xffff и т.п. невыгодно
LD [tracepixel.dyUINT],HL
LD HL,+(EYEDZ>>8)&0xffff
LD [tracepixel.dzUINT],HL
LD hl,+(EYEX>>8)&0xffff
LD [tracepixel.xUINT],hl
LD hl,+(EYEZ>>8)&0xffff ;ld l,h проигрывает 2 байта в MegaLZ, 1 байт в Hrum
LD [tracepixel.zUINT],hl
LD hl,+(EYEY>>8)&0xffff
LD [tracepixel.yUINT],hl
sub l;128
ld (scrxHSB),a
ld l,a
SBC A,a
ld h,a
add hl,hl
add hl,hl
ld (tracepixel.dxUINT),hl
SQHL ;out: de
sqeyedyUINT=$+1
LD hl,+(SQEYEDZ>>8)&0xffff;0
add hl,de
LD [tracepixel.ddUINT],HL
tracepixel.L100
;//IF (positive(y) || negative(dy)) { n = SKY; s = 0x7fffffffL; }ELSE { n = GROUND; s = neg(idiv(y, dy)); };
LD BC,[tracepixel.dyUINT] ;лучшая перестановка
ld hl,[tracepixel.yUINT]
ld a,h
cpl
or b
LD [tracepixel.sUINT+1],a
JP M,skyorground_count_s.q
;P
ex de,hl ;de=y
DIVDEBC_ASIGN ;de / bc
LD [tracepixel.sUINT],de
LD A,GROUND
skyorground_count_s.q
LD [tracepixel.n],A
ld l,2*(spheres-1)+1
checkbounding0
ld h,projr/256
ld e,(hl) ;projr
inc h;ld h,projx/256
scrxHSB=$+1
ld a,GROUND;0
sub (hl) ;a = SCRX - projx
dec l
add a,e ;a = SCRX - (projx-projr)
jp m,tracepixel.NOTFOUNDb
srl a
cp e
jp nc,tracepixel.NOTFOUNDb
;inc h;ld h,projy/256
scryHSB=$+1
ld a,GROUND;0
sub (hl) ;a = SCRY - projy
add a,e ;a = SCRY - (projy-projr)
jp m,tracepixel.NOTFOUNDb
srl a
cp e
;jr nc,tracepixel.NOTFOUNDb
jr c,checkspheres
;ld a,(scrxHSB)
;ld hl,scryHSB
;xor (hl)
;rra
;ret c
tracepixel.NOTFOUNDb
dec l
jp p,checkbounding0
jp checkspheresq
checkspheres
;jp tracepixel.NOTFOUND
ld a,2*(spheres-1)
tracepixel.checkspheres0
LD [tracepixel.k],A
;//ищем сферу, на которую смотрим (если есть)
;//px = cx[k] - x;
;//py = cy[k] - y;
;//pz = cz[k] - z;
;//pp = sq(px) + sq(py) + sq(pz);
;//sc = mul(px,dx) + mul(py,dy) + mul(pz,dz);
ld (count_pxpypzppsc_cxaddr),a
ld (count_pxpypzppsc_cyaddr),a
ld (count_pxpypzppsc_czaddr),a
;центр проекции сферы: cx[k]/pz, cy[k]/pz
;радиус проекции сферы: r[k]/pz
; IF (!(
; (SCRX >= sub(projx[k],projr[k]))
; &&(SCRX < add(projx[k],projr[k]))
; &&(SCRY >= sub(projy[k],projr[k]))
; &&(SCRY < add(projy[k],projr[k]))
; )) {
; goto L200; //не та сфера
; };
count_pxpypzppsc_czaddr=$+1
ld hl,(cz)
tracepixel.zUINT=$+1
LD bc,0;x0101
;or a
SBC HL,bc
push hl ;pz=cz[k]-z
SQHL ;out: de
ld hy,d
ld ly,e ;sq(pz)
count_pxpypzppsc_cyaddr=$+1
ld hl,(cy)
tracepixel.yUINT=$+1
LD bc,0;x0101
;or a
SBC HL,bc
push hl ;py=cy[k]-y
SQHL ;out: de
add iy,de ;sq(pz) + sq(py)
count_pxpypzppsc_cxaddr=$+1
ld hl,(cx)
tracepixel.xUINT=$+1
LD bc,0;x0101
SBC HL,bc
push hl ;px=cx[k]-x
SQHL ;out: de
add iy,de
LD [tracepixel.ppUINT],iy ;pp = sq(px) + sq(py) + sq(pz)
pop bc ;px=cx[k]-x
tracepixel.dxUINT=$+1
LD de,0;x1111
MULDEBC_TOIY
pop bc ;py=cy[k]-y
tracepixel.dyUINT=$+1
LD de,0;x1111
MULDEBC
add iy,de
pop bc ;pz=cz[k]-z
tracepixel.dzUINT=$+1
LD de,0;x1111
MULDEBC
add iy,de ;sc = mul(px,dx) + mul(py,dy) + mul(pz,dz)
;//IF (negative(sc)) { goto L200; }; //не та сфера
;//bb = idiv(sq(sc),dd); //sc*sc/dd;
;//aa = q[k]-pp+bb; //add(sub(q[k],pp),bb); //q[k]-pp+bb;
;//IF (negative(aa)) { goto L200; }; //не та сфера
;//s = idiv(root(bb)-root(aa), root(dd)); //(sqrt(bb)-sqrt(aa))/sqrt(dd);
;//n = k;
;//goto LFOUND;
;//L200:
ld d,hy
ld e,ly ;de = sc = mul(px,dx) + mul(py,dy) + mul(pz,dz) ;ниже невыгодно в MegaLZ (2 байта)
LD a,d
or a;rla
JP M,tracepixel.NOTFOUND ;выгоднее в MegaLZ
if SQUARESQR
set 7,d
res 0,e
ex de,hl
ld e,(hl)
inc l
ld d,(hl)
;ld a,l
;cp 8 ;костыль для младшего бита
rl e;sla e
rl d
else
SQDE
endif
tracepixel.ddUINT=$+1
LD bc,0
DIVDEBC_POSITIVE ;de = bb
ld hl,(q)
tracepixel.k=$-2
checksphereradius_qaddr=$-2
add hl,de ;q[k]+bb ;CY=0, т.к. q[k] (>=0) + bb (>=0)
tracepixel.ppUINT=$+1
LD bc,0;x0101
;or a
sbc hl,bc ;q[k]+bb-pp
JP M,tracepixel.NOTFOUND
push de ;bb
ROOTHL
ex (sp),hl ;push sqrt(aa), pop bb
ROOTHL;call root0hl0
pop bc ;sqrt(aa)
;or a
SBC HL,bc ;hl = sqrt(bb)-sqrt(aa)
push hl
LD hl,[tracepixel.ddUINT]
ROOTHL
ld b,h
ld c,l ;bc = sqrt(dd)
pop de ;de = sqrt(bb)-sqrt(aa)
DIVDEBC_POSITIVE ;sqrt(bb)-sqrt(aa) >= 0
LD [tracepixel.sUINT],de ;s = (sqrt(bb)-sqrt(aa))/sqrt(dd)
LD A,(tracepixel.k);0x3e
LD [tracepixel.n],A
;de = s
jr tracepixel.FOUND
tracepixel.NOTFOUND ;не та сфера
ld a,(tracepixel.k)
sub 2
JP nc,tracepixel.checkspheres0
checkspheresq
LD A,[tracepixel.n]
or a ;SUB 0x80
ret M ;nc ;//небо
tracepixel.sUINT=$+1
LD de,0
tracepixel.FOUND
;de = s
;//dx = mul(dx,s); //dx*s;
;//dy = mul(dy,s); //dy*s;
;//dz = mul(dz,s); //dz*s;
;//dd = mul(sq(s),dd); //dd*s*s;
;//x = x + dx; //x+dx;
;//y = y + dy; //y+dy;
;//z = z + dz; //z+dz;
if SQUAREMUL
set 7,d
res 0,e
endif
LD bc,(tracepixel.dxUINT)
MULDEBC_TOHL_DEPOSITIVE
if SQUAREMUL
dec e
endif
LD [tracepixel.dxUINT],hl ;dx = dx*s
LD bc,[tracepixel.xUINT]
add hl,bc
LD [tracepixel.xUINT],hl ;x = x+dx
LD bc,[tracepixel.dyUINT]
MULDEBC_TOHL_DEPOSITIVE
if SQUAREMUL
dec e
endif
LD [tracepixel.dyUINT],hl ;dy = dy*s
LD bc,[tracepixel.yUINT]
add hl,bc
LD [tracepixel.yUINT],hl ;y = y+dy
LD bc,[tracepixel.dzUINT]
MULDEBC_TOHL_DEPOSITIVE
if SQUARESQR&SQUAREMUL
dec e ;выигрыш 1 байт по сравнению с dec l
endif
LD [tracepixel.dzUINT],hl ;dz = dz*s
LD bc,[tracepixel.zUINT]
add hl,bc
LD [tracepixel.zUINT],hl ;z = z+dz
if SQUARESQR&SQUAREMUL
ex de,hl
ld e,(hl)
inc l
ld d,(hl)
ld a,l
cp 8 ;костыль для младшего бита
rl e;sla e
rl d
else
LD HL,[tracepixel.sUINT]
SQHL ;out: de
endif
LD bc,[tracepixel.ddUINT]
MULDEBC_TOHL_POSITIVE
LD [tracepixel.ddUINT],hl ;dd = dd*s*s
tracepixel.n=$+1
LD A,0x3e
cp GROUND
JP z,tracepixel.ground ;//земля
;//nx = x - cx[n];
;//ny = y - cy[n];
;//nz = z - cz[n];
;//l = idiv(mul2( mul(dx,nx) + mul(dy,ny) + mul(dz,nz)), /**nn*/sq(nx) + sq(ny)
;//dx = dx - mul(nx,l); //dx-nx*l;
;//dy = dy - mul(ny,l); //dy-ny*l;
;//dz = dz - mul(nz,l); //dz-nz*l;
ld (count_reflection_cxaddr),a
ld (count_reflection_cyaddr),a
ld l,a
LD h,cz/256
ld c,(hl)
inc l
ld b,(hl)
LD HL,[tracepixel.zUINT]
SBC HL,BC
LD [tracepixel.nz],HL ;z-cz[n]
SQHL ;out: de
ld hy,d
ld ly,e
count_reflection_cyaddr=$+2
LD bc,(cy)
LD HL,[tracepixel.yUINT]
SBC HL,BC
LD [tracepixel.ny],HL ;y-cy[n]
SQHL ;out: de
add iy,de
count_reflection_cxaddr=$+2
LD bc,(cx)
LD HL,[tracepixel.xUINT]
SBC HL,BC
LD [tracepixel.nx],HL ;x-cx[n]
SQHL ;out: de
add iy,de
push iy ;делитель = sq(nx)+sq(ny)+sq(nz)
tracepixel.nx=$+1
LD bc,0;x0101
LD de,[tracepixel.dxUINT]
MULDEBC_TOIY
tracepixel.ny=$+1
LD bc,0;x0101
LD de,[tracepixel.dyUINT]
MULDEBC
add iy,de
tracepixel.nz=$+1
LD bc,0;x0101
LD de,[tracepixel.dzUINT]
MULDEBC
add iy,de
ld d,hy
ld e,ly
rl e
rl d ;for sign ;de = делимое = 2*(dx*nx+dy*ny+dz*nz)
pop bc ;bc = делитель = sq(nx)+sq(ny)+sq(nz)
;ld a,d
;xor b
ex af,af'
DIVDEBC_AXSIGN_NONEGBC ;de / bc
push de ;tracepixel.l = 2*(dx*nx+dy*ny+dz*nz)/(sq(nx)+sq(ny)+sq(nz)) ;со знаком
LD bc,[tracepixel.nx] ;со знаком
MULDEBC
ld hl,(tracepixel.dxUINT)
;or a
sbc hl,de;bc
ld (tracepixel.dxUINT),hl ;dx-nx*l
pop de
push de ;tracepixel.l
LD bc,[tracepixel.ny] ;со знаком
MULDEBC
ld hl,(tracepixel.dyUINT)
;or a
sbc hl,de;bc
ld (tracepixel.dyUINT),hl ;dy-ny*l
pop de ;tracepixel.l
LD bc,[tracepixel.nz] ;со знаком
MULDEBC
ld hl,(tracepixel.dzUINT)
;or a
sbc hl,de;bc
ld (tracepixel.dzUINT),hl ;dz-nz*l
JP tracepixel.L100 ;//отражение
tracepixel.ground
;//земля
;//k = 0x00;
;//REPEAT {
;// IF (less((sq(/**u*/cx[k]-x) + sq(/**v*/cz[k]-z)), q[k])) {goto RETURNME;};
;// INC k;
;//}UNTIL (k == spheres);
;//IF (fract(x) != fract(z)) {
;// invpix(j,i)
;//}; //((x+100)-(int)(x+100)) //(z-(int)(z))
ld a,2*(spheres-1)
drawground_findshadow0
LD [tracepixel.k],A
ld (drawground_findshadow_qaddr),a
ld (drawground_findshadow_cxaddr),a
LD l,A
LD h,cz/256
LD E,[HL]
INC L
LD D,[HL]
LD hl,[tracepixel.zUINT]
sbc hl,de
SQHL ;out: de
ld hy,d
ld ly,e
drawground_findshadow_cxaddr=$+2
ld de,(cx)
LD HL,[tracepixel.xUINT]
sbc hl,de
SQHL ;out: de
add iy,de
ld d,hy
ld e,ly
drawground_findshadow_qaddr=$+1
ld hl,(q)
sbc hl,de
ret nc
LD a,[tracepixel.k]
sub 2
JP nc,drawground_findshadow0
ld a,(tracepixel.xUINT) ;дробная часть
ld hl,tracepixel.zUINT
xor (hl)
rla
ret
if !fastest
muldebc
;+de0 * +bc0 -> .de.
ld a,d
xor b
ex af,af' ;M=разные знаки '
ld a,d
rla
jr nc,mul_noneghld0
xor a
sub e
ld e,a
sbc a,d
sub e
ld d,a
mul_noneghld0
ld a,b
rla
jr nc,mul_nonegbcx0
xor a
sub c
ld c,a
sbc a,b
sub c
ld b,a
mul_nonegbcx0
if SQUAREMUL
set 7,d
res 0,e
endif
MULDEBC_POSITIVE
ex af,af' ;M=разные знаки '
ret p
xor a
sub e
ld e,a
sbc a,d
sub e
ld d,a
ret
endif
if !SQUARESQR
;ds (-$)&255
tsqr=0x7b00;0x7a00 ;код команды ld a,d (не помогает)
;ds 512 ;incbin "tsqr"
endif
align 256
q ;такой порядок выгоднее в MegaLZ
DW q1
DW q0
align 256
cx
DW cx1
DW cx0
align 256
cy
DW cy1
DW cy0
align 256
cz
DW cz1
DW cz0
align 256 ;сразу после cz
rad
DW r1*17/16 ; //больше, потому что бок сферы торчит за проекцию
DW r0*17/16
end
align 256
projr
dw 0 ;используется только старший байт
dw 0
align 256 ;projx и projy сразу после rad
projx
dw 0 ;используется только старший байт
dw 0
; align 256
;projy
; dw 0 ;используется только младший байт
; dw 0
;end
display "End=",end
display "Free after end=",/d,#c000-end
display "Size ",/d,end-begin," bytes"
savebin "code.c",begin,end-begin
LABELSLIST "..\us\user.l"