Files
TeslaRel410/sda4/DPL3/VRENDER/AS860/TRISTRAP.SS
T
CydandClaude Fable 5 db7745fcd0 sda4: commit the Glaze developer hard-drive dump
Un-ignored: the dev drive is the ground truth the restoration and
emulator work constantly reference (DPL3/LIBDPL + VRENDER i860 renderer
source, BT/RP live+dev game trees, VGL_LABS pod boot, scene/audio
content). Kept in-repo for the pod-owner community.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 19:41:15 -05:00

1012 lines
27 KiB
Scheme

//
//
// this is the fully working tristrip.ss from before
// trapezoom
//
// Phil 14 April 1992
//
//
//
//
//
// void tristrip ( void (*init)(int,int,int,int),
// void (*scan)(int*,int*,int,int,int,int,int,int,int,int,int),
// int *framebuffer,
// int *zbuffer,
// triangle *head,
// int n_tris,
// int processor_shift,
// int processor_id,
// int stride,
// int pxlsize )
//{{{ register allocation
#define param1 r16
#define param2 r17
#define param3 r18
#define param4 r19
#define param5 r20
#define param6 r21
#define param7 r22
#define param8 r23
#define param9 r24
#define param10 r25
#define param11 r26
#define param12 r27
#define at r3
#define y r4
#define fbl r5
#define zbl r6
#define x r7
#define xr r8
#define dyx r9
#define dyxr r10
#define dyr r11
#define dyg r12
#define dyb r13
#define dyz r14
#define pmask r15
#define pid r28
// overload the processor id register with the y hop value
#define yhop r28
#define r r18
#define g r19
#define b r20
#define z r21
#define dx r22
#define dxr r23
#define dxg r24
#define dxb r25
#define dxz r26
#define rscan r29
#define rstride r30
//}}}
//{{{ structure offsets
//{{{ vertex offsets
// typedef struct s_vert {
// struct s_vert *next;
// POINT position;
// POINT planeEqn;
// float snorm [3];
// float gnorm [3];
// float colour [3];
// } VERTEX;
// from start of structure
#define position_offs 4
#define vert_x_offs 4
#define vert_y_offs 8
#define vert_z_offs 12
#define plane_offs 20
#define snorm_offs 36
#define gnorm_offs 48
#define colour_offs 60
#define vert_r_offs 60
#define vert_g_offs 64
#define vert_b_offs 68
//}}}
//{{{ triangle offsets (plane equation etc.)
// typedef struct s_triangle {
// struct s_triangle *next;
// edge *edgy;
// edge *ziggy;
// int dr_by_dx;
// int dg_by_dx;
// int db_by_dx;
// int dz_by_dx;
// } triangle;
#define next_offs 0
#define edgy_offs 4
#define ziggy_offs 8
#define dr_by_dx_offs 12
#define dg_by_dx_offs 16
#define db_by_dx_offs 20
#define dz_by_dx_offs 24
//}}}
//{{{ edge offsets
// typedef struct struct_edge {
// VERTEX *v0, *v1, *vmin, *vmax;
// int dx_by_dy;
// int dr_by_dy;
// int dg_by_dy;
// int db_by_dy;
// int dz_by_dy;
// } edge;
#define v0_offs 0
#define v1_offs 4
#define vmin_offs 8
#define vmax_offs 12
#define dx_by_dy_offs 16
#define dr_by_dy_offs 20
#define dg_by_dy_offs 24
#define db_by_dy_offs 28
#define dz_by_dy_offs 32
//}}}
//}}}
//{{{ stack frame layout
#define nlocals -160
#define locals 160
#define fpoffs 156
#define retoffs 152
#define r1offs 148
#define roffs 144
#define goffs 140
#define boffs 136
#define zoffs 132
#define strideoffs 128
#define trioffs 124
#define ledgeoffs 120
#define redgeoffs 116
#define aedgeoffs 112
#define headoffs 108
#define ntrisoffs 104
#define pshiftoffs 100
#define initoffs 96
#define r4offs 92
#define r5offs 88
#define r6offs 84
#define r7offs 80
#define r8offs 76
#define r9offs 72
#define r10offs 68
#define r11offs 64
#define r12offs 60
#define r13offs 56
#define r14offs 52
#define r15offs 48
#define fboffs 44
#define f2offs 40
#define f4offs 32
#define f6offs 24
#define zboffs 16
//}}}
//{{{ temporary registers
// head aliases b
#define head param5
// n aliases z
#define n param6
// e_ab aliases dx
#define e_ab param7
// e_bc aliases dxr
#define e_bc param8
// e_ac aliases dxg
#define e_ac param9
// va aliases dxb
#define va param10
// vb aliases dxz
#define vb param11
// vc safe
#define vc param12
// ledge aliases dyx
#define ledge r9
// redge aliases dyxr
#define redge r10
// aedge aliases dyr
#define aedge r11
//}}}
//{{{ bacon,lettuce,tomato
#define bge(a,b,label)\
subs r0,b,r31;\
adds r31,a,r0;\
bnc label
//}}}
.align 8
.text
//{{{ _reg_dump
.globl _reg_dump
.align 8
_reg_dump::
//{{{ proc entry - save r1 r2 r3
addu -256, sp, sp
st.l r1,0(sp)
adds 256,sp,r1
st.l r1,4(sp)
st.l fp,8(sp)
//}}}
//{{{ save r4..r31
st.l r4, 12(sp)
st.l r5, 16(sp)
st.l r6, 20(sp)
st.l r7, 24(sp)
st.l r8, 28(sp)
st.l r9, 32(sp)
st.l r10, 36(sp)
st.l r11, 40(sp)
st.l r12, 44(sp)
st.l r13, 48(sp)
st.l r14, 52(sp)
st.l r15, 56(sp)
st.l r16, 60(sp)
st.l r17, 64(sp)
st.l r18, 68(sp)
st.l r19, 72(sp)
st.l r20, 76(sp)
st.l r21, 80(sp)
st.l r22, 84(sp)
st.l r23, 88(sp)
st.l r24, 92(sp)
st.l r25, 96(sp)
st.l r26, 100(sp)
st.l r27, 104(sp)
st.l r28, 108(sp)
st.l r29, 112(sp)
st.l r30, 116(sp)
st.l r31, 120(sp)
//}}}
call _trace_regs
mov sp, r16
//{{{ save r4..r31
ld.l 12(sp) , r4
ld.l 16(sp) , r5
ld.l 20(sp) , r6
ld.l 24(sp) , r7
ld.l 28(sp) , r8
ld.l 32(sp) , r9
ld.l 36(sp) , r10
ld.l 40(sp) , r11
ld.l 44(sp) , r12
ld.l 48(sp) , r13
ld.l 52(sp) , r14
ld.l 56(sp) , r15
ld.l 60(sp) , r16
ld.l 64(sp) , r17
ld.l 68(sp) , r18
ld.l 72(sp) , r19
ld.l 76(sp) , r20
ld.l 80(sp) , r21
ld.l 84(sp) , r22
ld.l 88(sp) , r23
ld.l 92(sp) , r24
ld.l 96(sp) , r25
ld.l 100(sp) , r26
ld.l 104(sp) , r27
ld.l 108(sp) , r28
ld.l 112(sp) , r29
ld.l 116(sp) , r30
ld.l 120(sp) , r31
//}}}
//{{{ proc exit
ld.l 0(sp),r1
ld.l 8(sp),fp
bri r1
addu 256, sp, sp
//}}}
//}}}
//{{{
call _reg_dump
nop
//}}}
//{{{ _trapezoid that works ish
// this coding vaguely works ...
// .align 8
// // WORST CASE 28 ticks per line, NO MEMORY HITS!
// // subs y,at,r0 <-- now folded into main body code
// _trapezoid::
// bnc .do_not_collect_200_pounds
// ixfr r1,f4 // NOTE f2..f7 unused in inner loops at present !
// and y,pmask,r31
// xor r31,pid,r0 // r31 == y&pmask - if y&pmask!=pid, DONT call
// shra 16,xr,dx
// .trap_loop:
// bnc .skip_call // normally we DO skip the call
//
// shra 16,x,r31 // r31 = xl
// subs dx,r31,dx // dx = xr - xl
// subs 0,r31,r0 // carry clear if dx>0
// shl 2,r31,r31 // doesnt affect carry, avoids freeze condition
// bnc .skip_call
// // prepare to call fn
// adds fbl,r31,param1
// adds zbl,r31,param2
// // save volatile registers
// ixfr r,f2
// calli rscan // GO MAN GO
// ixfr g,f3
//
// fxfr f3,g
// fxfr f2,r
//
// .skip_call:
// adds 1, y, y
// adds x, dyx, x
// adds xr,dyxr,xr
// adds g, dyg, g
// adds r, dyr, r
// adds b, dyb, b
// adds z,dyz,z
// and y, pmask, r31
// bnc .skip_bmp // skip the bump if y&pmask!=0
// // bump fbl, zbl
// adds fbl,rstride,fbl
// adds zbl,rstride,zbl
//
// .skip_bmp:
// subs y,at,r0 // now folded into main body code
// shra 16,xr,dx // doenst affect carry flag, avoid bc.t freeze
// bc.t .trap_loop // this exits on y>at
// xor r31,pid,r0 // r31 == y&pmask - if y&pmask!=pid, DONT call
// fxfr f4,r1
// .do_not_collect_200_pounds:
// bri r1
// nop
//}}}
//{{{ _trapezoid
//{{{ C coding of trapezoid (from tristrip.c)
//
// while (y<at) {
// if ((y&pmask) == pid) {
// r31=x>>16;
// dx =(xr>>16)-r31;
//
// if (dx > 0) {
// /* save rgbz */
// (*rscan)(fbl+r31, zbl+r31, r,g,b,z, dx, dxr,dxg,dxb,dxz);
// /* restore rgbz */
// }
// }
//
// x+=dyx; xr+=dyxr; r+=dyr; g+=dyg; b+=dyb; z+=dyz;
//
// y++;
//
// if ((y&pmask) == 0) {
// fbl+=rstride;
// zbl+=rstride;
// }
// }
//}}}
.align 8
// WORST CASE 28 ticks per line, NO MEMORY HITS!
// subs y,at,r0 <-- now folded into main body code
_trapezoid::
bnc .do_not_collect_200_pounds
//
// OK - we have some crapoid code here - all the processors walk up
// all the scanlines, and check to see if this is their scanline
//
// so we need to modify this to - firstly get the real rgbzx by
// walking up until (y&pmask)==pid
// now we shift all the slopes up by pshift.
// now we walk up n scanlines at a time, doing each line UNTIL (y>=at)
// now we shift all the slopes back down, and carry on adding until
// y==at. Then we exit. Slopes are as they were before the shift, we
// are on the same scanline we would have been on. All should be well.
//
//
ixfr r1,f4 // NOTE f2..f7 unused in inner loops at present !
//
// while ((y&pmask) != pid) {
// y++;
// x+=dx;
// xr+=dxr;
// r+=dr;
// g+=dg;
// b+=db;
// z+=dz;
// if ((y&pmask)==0) {
// zbl+=rstride;
// fbl+=rstride;
// }
// }
// dx<<=2;
// dxr<<=2;
// dr<<=2;
// dg<<=2;
// db<<=2;
// dz<<=2;
//
// while (y<at) {
// scanline();
// x+=dx;
// xr+=dxr;
// r+=dr;
// g+=dg;
// b+=db;
// z+=dz;
// zbl+=rstride;
// fbl+=rstride;
// y+=hop;
// }
//
// dx>>=2;
// dxr>>=2;
// dr>>=2;
// dg>>=2;
// db>>=2;
// dz>>=2;
//
// while (y>at) {
// x-=dx;
// xr-=dxr;
// r-=dr;
// g-=dg;
// b-=db;
// z-=dz;
// }
//
//
and y,pmask,r31
xor r31,pid,r0 // r31 == y&pmask - if y&pmask!=pid, DONT call
shra 16,xr,dx
.trap_loop:
bnc.t .skip_call1 // normally we DO skip the call
adds 1, y, y
shra 16,x,r31 // r31 = xl
subs dx,r31,dx // dx = xr - xl
subs 0,dx,r0 // carry clear if dx>0
shl 2,r31,r31 // doesnt affect carry, avoids freeze condition
bnc.t .skip_call1
adds 1, y, y
// prepare to call fn
adds fbl,r31,param1
adds zbl,r31,param2
// save volatile registers
ixfr r,f2
calli rscan // GO MAN GO
ixfr g,f3
fxfr f3,g
fxfr f2,r
.skip_call0:
adds 1, y, y
.skip_call1:
adds xr,dyxr,xr
adds g, dyg, g
adds r, dyr, r
adds b, dyb, b
adds z, dyz,z
adds x, dyx, x
and y, pmask, r31
bnc.t .skip_bmp1 // skip the bump if y&pmask!=0
subs y,at,r0 // now folded into main body code
// bump fbl, zbl
adds fbl,rstride,fbl
adds zbl,rstride,zbl
.skip_bmp:
subs y,at,r0 // now folded into main body code
.skip_bmp1:
shra 16,xr,dx // doenst affect carry flag, avoid bc.t freeze
bc.t .trap_loop // this exits on y>at
xor r31,pid,r0 // r31 == y&pmask - if y&pmask!=pid, DONT call
fxfr f4,r1
.do_not_collect_200_pounds:
bri r1
nop
//}}}
//{{{ _trapezoom
.align 8
// seems to be 24 ticks per line, no memory hits
// subs y,at,r0 <-- now folded into main body code
//
//
// this is the zippywippy trapezoid which understands that it
// has been given slopes shifted up by processor_shift
// its only difference in behaviour is to add 'hop' to y rather
// than 1. When y > at we exit, DOING NOTHING - the calling
// code can then do smart things dependent on l/r ness of the
// replace edge etc.
//
// so our trapezoom algorithm is simply
//
// while (y<at) {
// scanline();
// x+=dx;
// xr+=dxr;
// r+=dr;
// g+=dg;
// b+=db;
// z+=dz;
// zbl+=rstride;
// fbl+=rstride;
// y+=hop;
// }
// return (y-at);
//
_trapezoom::
bnc .exit_zoom
//
ixfr r1,f4 // NOTE f2..f7 unused in inner loops at present !
//
shra 16,xr,dx
.trapzoom_loop:
shra 16,x,r31 // r31 = xl
subs dx,r31,dx // dx = xr - xl
subs 0,dx,r0 // carry clear if dx>0
shl 2,r31,r31 // doesnt affect carry, avoids freeze condition
bnc.t .skip_zoomcall
adds yhop, y, y
// prepare to call fn
adds fbl,r31,param1
adds zbl,r31,param2
// save volatile registers
ixfr r,f2
calli rscan // GO MAN GO
ixfr g,f3
fxfr f3,g
fxfr f2,r
.skip_zoomcall:
adds xr,dyxr,xr
adds g, dyg, g
adds r, dyr, r
adds b, dyb, b
adds z, dyz,z
adds x, dyx, x
adds fbl,rstride,fbl
adds zbl,rstride,zbl
subs y,at,r31 // now folded into main body code
bc.t .trapzoom_loop // this exits on y>at
shra 16,xr,dx // doesnt affect carry flag, avoid bc.t freeze
// 24 ticks per scanline rendered..
fxfr f4,r1 // exit with r31 == y - at
.exit_zoom:
bri r1
nop
//}}}
//{{{ _setv
// #define setv(yptr, atptr, l,r,act) \
// y =yptr[Y]; \
// ledge=l; redge=r; activate_edge=act; \
// at =atptr[Y]
// below are ordered to try and minimize freezes
#define _setv(yp,lp,rp,ap)\
ld.l vmin_offs(ap), r31;\
mov lp,ledge;\
ld.l vert_y_offs(yp), y;\
mov rp,redge;\
ld.l vert_y_offs(r31), at;\
br .l_and_r_decision;\
mov ap,aedge
//}}}
//{{{ _swap(p1,p2)
#define _swap(p1,p2)\
mov p1,r31;\
mov p2,p1;\
mov r31,p2
// xor ledge,redge,ledge;
// xor ledge,redge,redge;
// xor ledge,redge,ledge
//}}}
//{{{ _astristrip
.globl _astristrip
.align 8
_astristrip::
//{{{ check for n > 0
subs r0, param6, r0
bc .procentry
bri r1
nop
//}}}
//{{{ proc entry
.procentry:
addu nlocals, sp, sp
st.l fp,fpoffs(sp)
st.l r1,retoffs(sp)
//}}}
//{{{ save r4..r15
st.l r4, r4offs(sp)
st.l r5, r5offs(sp)
st.l r6, r6offs(sp)
st.l r7, r7offs(sp)
st.l r8, r8offs(sp)
st.l r9, r9offs(sp)
st.l r10, r10offs(sp)
st.l r11, r11offs(sp)
st.l r12, r12offs(sp)
st.l r13, r13offs(sp)
st.l r14, r14offs(sp)
st.l r15, r15offs(sp)
//}}}
//{{{ save f2..f7
fst.d f2, f2offs(sp)
fst.d f4, f4offs(sp)
fst.d f6, f6offs(sp)
//}}}
//{{{ save and reorder params
st.l param1, initoffs(sp)
mov param2, rscan
st.l param3, fboffs(sp)
st.l param4, zboffs(sp)
st.l param5, headoffs(sp)
st.l param6, ntrisoffs(sp)
st.l param7, pshiftoffs(sp)
mov param8, pid
shl 2,param9, rstride // fix stride for byte addressing
or 1,r0,r31
shl param7,r31,pmask // 1 << param7
adds -1,pmask,pmask // pmask = (1<<processor_shift) - 1
//}}}
//{{{ call setpixelsize()
call _setpixelsize
mov param10,param1
//}}}
.for_i_ntris:
//{{{ order edges (sort triangle on minimum y)
// {
// triangle *n=head->next;
// edge *ab,*bc,*ac;
//
// ab=head->ziggy; ac=head->edgy;
// bc=n->ziggy;
ld.l headoffs(sp), head
ld.l next_offs(head), n
st.l n, headoffs(sp) // pre-walk triangle pointer
ld.l ziggy_offs(head), e_ab
ld.l edgy_offs(head), e_ac
ld.l ziggy_offs(n), e_bc
// /* there are only 3 cases - a lowest, b lowest, c lowest */
// {
// int *a, *b, *c, *atp;
//
//
// a=(int *) (&ab->v0->position);
// b=(int *) (&ab->v1->position);
// c=(int *) (&ac->v1->position);
//
ld.l v0_offs(e_ab), va
ld.l v1_offs(e_ab), vb
ld.l v1_offs(e_ac), vc
// if (a[Y] < b[Y]) {
ld.l vert_y_offs(va), param1
ld.l vert_y_offs(vb), param2
bge(param1,param2,.check_bc)
// if (c[Y] < a[Y]) {
ld.l vert_y_offs(vc), param2
bge(param2,param1,.a_lowest)
// atp=(int *) (&ab->vmin->position);
// setv(c,atp,ac,bc,ab);
// }
.c_lowest:
_setv(vc,e_ac,e_bc,e_ab)
.a_lowest:
// else {
// atp=(int *) (&bc->vmin->position);
// setv(a,atp,ac,ab,bc);
// }
// }
_setv(va,e_ac,e_ab,e_bc)
.check_bc:
// else {
// if (b[Y] < c[Y]) {
ld.l vert_y_offs(vc), param1 // since b still in param2
bge(param2,param1,.c_lowest)
// atp=(int *) (&ac->vmin->position);
// setv(b,atp,bc,ab,ac);
// }
_setv(vb,e_bc,e_ab,e_ac)
// else {
// atp=(int *) (&ab->vmin->position);
// setv(c,atp,ac,bc,ab);
// }
// }
// }
// _setv(vc,e_ac,e_bc,e_ab)
//}}}
.l_and_r_decision:
//{{{ now determine ABSOLUTELY SECURELY which edge is l and which is r
// remember, we have not yet stored ledge/redge/aedge into memory
// if (ledge->dx_by_dy == MINT) {
ld.l dx_by_dy_offs(ledge),param1 // param1 = ledge->dx_by_dy
ld.l dx_by_dy_offs(redge),param2 // param2 = redge->dx_by_dy
xorh 0x8000,param1,r0
bnc.t .check_r_horiz
xorh 0x8000,param2,r0 // most edges are NOT horizontal, so we TAKE this
// if (ledge->vmin == redge->vmin) {
ld.l vmin_offs(ledge),param1
ld.l vmin_offs(redge),param2
xor param1,param2,r0
bnc .lmin_not_rmin // branch taken if not the same
// swap (ledge,redge, edge* );
_swap(ledge,redge)
// activate_edge = (edge *) (1|(int) activate_edge);
or 1,aedge,aedge
// x = ((int *)(ledge->vmin->position))[X];
// }
ld.l vmin_offs(ledge), r31
br .extract_plane_eqn
ld.l vert_x_offs(r31),x
.lmin_not_rmin:
// else {
// x = ((int *)(redge->vmin->position))[X];
// }
// }
ld.l vmin_offs(redge), r31
br .extract_plane_eqn
ld.l vert_x_offs(r31),x
.check_r_horiz:
// else if (redge->dx_by_dy == MINT) {
// xorh 0x8000,param2,r0 <--- this is now executed above in a delayed branch
bnc.t .none_horiz
subs r0,param1,r31 // again, this is most frequent case
// first instruction of .none_horiz
// if (redge->vmax == ledge->vmin) {
ld.l vmax_offs(redge),param1
ld.l vmin_offs(ledge),param2
xor param1,param2,r0
bnc .rmax_not_lmin
// swap ( ledge,redge, edge* );
_swap(ledge,redge)
// x = ((int *)(redge->vmin->position))[X];
// }
ld.l vmin_offs(redge), r31
br .extract_plane_eqn
ld.l vert_x_offs(r31),x
.rmax_not_lmin:
// else {
// activate_edge = (edge *) (1|(int) activate_edge);
or 1,aedge,aedge
// x = ((int *)(ledge->vmin->position))[X];
// }
// }
//
ld.l vmin_offs(ledge), r31
br .extract_plane_eqn
ld.l vert_x_offs(r31),x
.none_horiz:
// else {
// if (redge->dx_by_dy < ledge->dx_by_dy) {
// this was
adds r31,param2,r0 // r31 holds -ledge->dx_by_dy
bnc .dont_swap
// swap(ledge,redge, edge* );
_swap(ledge,redge)
// }
//
.dont_swap:
// x = ((int *)(ledge->vmin->position))[X];
ld.l vmin_offs(ledge), r31
ld.l vert_x_offs(r31),x
//
// if (((int *)(ledge->vmax->position))[Y] >
// ((int *)(redge->vmax->position))[Y])
// {
// activate_edge = (edge *) (1|(int) activate_edge);
ld.l vmax_offs(ledge), param1
ld.l vmax_offs(redge), param2
ld.l vert_y_offs(param1),param1
ld.l vert_y_offs(param2),param2
subs param2,param1,r0
bc.t .extract_plane_eqn
or 1,aedge,aedge
//}}}
.extract_plane_eqn:
// tidy up after previous stuff
// st.l ledge, ledgeoffs(sp)
// st.l redge, redgeoffs(sp)
st.l aedge, aedgeoffs(sp)
mov x,xr // since xr==x at start of triangle
//{{{ extract plane eqn DONE
// remember, head is still in param5
mov head,r31
ld.l dr_by_dx_offs(r31), dxr
ld.l dg_by_dx_offs(r31), dxg
ld.l db_by_dx_offs(r31), dxb
ld.l dz_by_dx_offs(r31), dxz
//}}}
//{{{ set up initial values for {xyzrgb} DONE
//
mov ledge,r31
ld.l dx_by_dy_offs(redge), dyxr
ld.l vmin_offs(r31), param1 // param1 = ledge->vmin
ld.l vert_x_offs(param1), x
ld.l vert_y_offs(param1), y
ld.l vert_z_offs(param1), z
ld.l vert_r_offs(param1), r
ld.l vert_g_offs(param1), g
ld.l vert_b_offs(param1), b
ld.l dx_by_dy_offs(r31), dyx
ld.l dr_by_dy_offs(r31), dyr
ld.l dg_by_dy_offs(r31), dyg
ld.l db_by_dy_offs(r31), dyb
ld.l dz_by_dy_offs(r31), dyz
//}}}
// /* GO ! */
//{{{ compute start values of fbl,zbl DONE
ld.l pshiftoffs(sp), r31
shr r31, y, r31
ixfr r31, f2
ixfr rstride, f4
fmlow.dd f2,f4,f2
ld.l fboffs(sp), fbl
ld.l zboffs(sp), zbl
fxfr f2,r31
adds fbl,r31,fbl
adds zbl,r31,zbl
//}}}
//{{{ set up slopes for subsequent scans DONE
// (*init)(dxr,dxg,dxb,dxz);
// this can be optimised by passing hods-o-bogus parameters to init
ld.l initoffs(sp), r31
calli r31
nop
//}}}
// ideally we call trapezoom here, passing it
// 4x slopes .. we need to do the trap stuff, skipping,
// until we are aligned with this processor. then we do the
// trapzoom, hopping 2 (4,8) lines at a time. trapzoom exits
// with y-at in r31, so IF ITS A LEFT HAND EDGE, de-click all
// incrementers until aligned - this costs way less on a right
// edge. Now extract stuff out of the new edge, walking up
// until at (from the new edge) == y (from the exit of last trap)
// then call trapzoom again
//
//{{{ trapezoid DONE
call _trapezoid
subs y,at,r0
//}}}
//{{{ replace worn-out edge DONE
ld.l aedgeoffs(sp), r31
and 1,r31,r0
bnc .activate_right
// now activate left edge
//{{{ activate left edge - happens every other triangle
// ledge=activate_edge;
ld.l vmin_offs(r31), param1
// param1 = aedge->vmin
ld.l dx_by_dy_offs(r31), dyx
ld.l dr_by_dy_offs(r31), dyr
ld.l dg_by_dy_offs(r31), dyg
ld.l db_by_dy_offs(r31), dyb
ld.l dz_by_dy_offs(r31), dyz
ld.l vert_x_offs(param1), x
ld.l vert_z_offs(param1), z
ld.l vert_r_offs(param1), r
ld.l vert_g_offs(param1), g
br .set_at
ld.l vert_b_offs(param1), b
//}}}
.activate_right:
// here activate right edge
//{{{ easy case, right edge
// redge = (edge *) (1 ^ (int) activate_edge);
// xr =((int *)(&redge->vmin->position))[X];
// dyxr =redge->dx_by_dy;
xor 1,r31,r31
ld.l vmin_offs(r31), param1 // r16 = redge->vmin
ld.l dx_by_dy_offs(r31), dyxr
ld.l position_offs(param1), xr
//}}}
// at=((int *) (&redge->vmax->position))[Y];
.set_at:
// ld.l redgeoffs(sp), r31
ld.l vmax_offs(r31), r31 // since r31 holds aedge !
ld.l vert_y_offs(r31), at
//}}}
//{{{ trapezoid DONE
call _trapezoid
subs y,at,r0
//}}}
//{{{ head=n; ntris--; } DONE /* i.e end loop */
ld.l ntrisoffs(sp), param1
adds -1, param1, param1
or r0,param1,r0
bnc.t .for_i_ntris
st.l param1, ntrisoffs(sp)
//}}}
.restore:
//{{{ restore f2..f7
fld.d f2offs(sp), f2
fld.d f4offs(sp), f4
fld.d f6offs(sp), f6
//}}}
//{{{ restore r4..r15
ld.l r4offs(sp), r4
ld.l r5offs(sp), r5
ld.l r6offs(sp), r6
ld.l r7offs(sp), r7
ld.l r8offs(sp), r8
ld.l r9offs(sp), r9
ld.l r10offs(sp), r10
ld.l r11offs(sp), r11
ld.l r12offs(sp), r12
ld.l r13offs(sp), r13
ld.l r14offs(sp), r14
ld.l r15offs(sp), r15
//}}}
//{{{ proc exit
ld.l fpoffs(sp),fp
ld.l retoffs(sp),r1
bri r1
addu locals, sp, sp
//}}}
//{{{ E S C A P E ! ! ! ! !
br .restore
nop
//}}}
//}}}