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>
1012 lines
27 KiB
Scheme
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
|
|
//}}}
|
|
|
|
//}}}
|
|
|