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>
632 lines
13 KiB
Scheme
632 lines
13 KiB
Scheme
//{{{ on higher-level fns
|
|
//
|
|
// Under old 8-bit shader, we called scanline from scansegment
|
|
//
|
|
// scansegment is called twice per triangle, so it pays to
|
|
// make the entry to scansegment as cheap as possible
|
|
//
|
|
// so i suggest that triangle() is fully assembly-coded.
|
|
//
|
|
// we can pre-compute the floats dr dg db dz into dbl floating
|
|
// registers for the duration of a whole triangle
|
|
// then only ir ig ib iz need setting up, according to alignment
|
|
// of start segment
|
|
//
|
|
// we can organise that scansegment is called with all the right
|
|
// register parameters to pass on to scanline
|
|
//
|
|
// we are trying to optimise 100 pixel triangles - i.e 16 pixels
|
|
// wide by 16 pixels high (128)
|
|
//
|
|
// so we will call scansegment twice per triangle, scanline 16 times
|
|
// and will fill 8 lines > 8, 4 > 4, 4 < 4
|
|
// giving rates of 16 / (8/2.6 + 4/2 + 4) = 1.76 Mpix
|
|
// so a 128 pixel triangle will fill in 72 uS, giving a triangle rate of
|
|
// 13.8 k - however, we will have a rate of 26k 64 pixel triangles
|
|
//
|
|
// this is crap
|
|
//
|
|
//
|
|
//}}}
|
|
//
|
|
// 32-bit gouraud shaded z-buffered entrypoint
|
|
//
|
|
|
|
.globl _zbufferline
|
|
.align 8
|
|
//{{{ do the funky gibbon
|
|
|
|
//{{{ define registers
|
|
//
|
|
// r1 return address
|
|
// r2 sp
|
|
// r3 frameP
|
|
// r4 .. r15 I should strive to conserve
|
|
// r16 .. r30 I can trash away
|
|
// r31 reserved as an addressing temporary - but available
|
|
//
|
|
// scanline ( int *fbuffer, int *zbuffer,
|
|
// int ir, int ig, int ib, int iz,
|
|
// int idr, int idg, int idb, int idz, int dx )
|
|
//
|
|
//
|
|
//
|
|
//
|
|
// FUNCTION PARAMETERS
|
|
//
|
|
|
|
#define paddr r16
|
|
#define zaddr r17
|
|
#define ir r18
|
|
#define ig r19
|
|
#define ib r20
|
|
#define iz r21
|
|
#define idr r22
|
|
#define idg r23
|
|
#define idb r24
|
|
#define idz r25
|
|
#define dx r26
|
|
|
|
|
|
//
|
|
// LOCALS
|
|
//
|
|
//
|
|
// interpolant values
|
|
// we should save these first !
|
|
#define oddz f6
|
|
#define ddz f4
|
|
#define ddz_lo f4
|
|
#define ddz_hi f5
|
|
|
|
#define r_lo f8
|
|
#define r_hi f9
|
|
#define r r_lo
|
|
|
|
#define g_lo f10
|
|
#define g_hi f11
|
|
#define g g_lo
|
|
|
|
#define b_lo f12
|
|
#define b_hi f13
|
|
#define b b_lo
|
|
|
|
#define z_lo f14
|
|
#define z_hi f15
|
|
#define z z_lo
|
|
|
|
// interpolant delta values
|
|
|
|
#define dr_lo f16
|
|
#define dr_hi f17
|
|
#define dr dr_lo
|
|
|
|
#define dg_lo f18
|
|
#define dg_hi f19
|
|
#define dg dg_lo
|
|
|
|
#define db_lo f20
|
|
#define db_hi f21
|
|
#define db db_lo
|
|
|
|
#define dz_lo f22
|
|
#define dz_hi f23
|
|
#define dz dz_lo
|
|
|
|
// double-length float temporaries
|
|
#define oldz_lo f24
|
|
#define oldz_hi f25
|
|
#define oldz oldz_lo
|
|
|
|
#define nuz f26
|
|
#define col f28
|
|
|
|
#define dbltmp f30
|
|
|
|
// integer temporaries
|
|
#define itemp1 r27
|
|
#define itemp2 r28
|
|
#define itemp3 r29
|
|
#define itemp4 r30
|
|
|
|
#define minus1 itemp1
|
|
|
|
//}}}
|
|
_zbufferline:
|
|
adds -5,dx,r0
|
|
bnc .zb_optimise // if dx >= 17, GOTO optimise (i.e at least 2 runs)
|
|
|
|
//{{{ short-run setup
|
|
|
|
ixfr ib, b_lo
|
|
ixfr ig, g_lo
|
|
|
|
br .tidy_up
|
|
ixfr ir, r_lo
|
|
|
|
//}}}
|
|
.zb_optimise:
|
|
//{{{ fast z-buffer loop
|
|
// construct floating-point 2dr 2dg 2db 2dz
|
|
//{{{
|
|
|
|
addu idr,idr,itemp1
|
|
ixfr itemp1, dr_lo
|
|
|
|
addu idg,idg,itemp1
|
|
ixfr itemp1, dg_lo
|
|
|
|
addu idb,idb,itemp1
|
|
ixfr itemp1, db_lo
|
|
|
|
addu idz,idz,itemp1
|
|
ixfr itemp1, dz_lo
|
|
|
|
addu itemp1,itemp1,itemp1
|
|
ixfr itemp1, ddz_lo
|
|
|
|
fmov.ss dr_lo,dr_hi
|
|
fmov.ss dg_lo,dg_hi
|
|
fmov.ss db_lo,db_hi
|
|
fmov.ss dz_lo,dz_hi
|
|
fmov.ss ddz_lo,ddz_hi
|
|
|
|
and 4,paddr,r0 // if paddr&7 == 0, cc set
|
|
bc .aligned // so we jump if paddr&7==0, i.e aligned
|
|
//}}}
|
|
|
|
// on entering inner loop, we need a col and an oldz, and we need
|
|
// paddr and zaddr down-ticked
|
|
|
|
// unaligned branch
|
|
//{{{
|
|
// ir corresponds to high word of 64-bit pair, so we down tick to
|
|
// get ir_lo etc.
|
|
//
|
|
//
|
|
ixfr ir, r_hi
|
|
ixfr ig, g_hi
|
|
ixfr ib, b_hi
|
|
ixfr iz, z_hi
|
|
|
|
// construct lo word of rgbz by subtraction
|
|
|
|
subs ir, idr, ir
|
|
subs ig, idg, ig
|
|
subs ib, idb, ib
|
|
subs iz, idz, iz
|
|
|
|
ixfr ir, r_lo
|
|
ixfr ig, g_lo
|
|
ixfr ib, b_lo
|
|
|
|
adds -1,r0,minus1
|
|
ixfr minus1, z_lo // important - zlo MUST be invisible for fchkz
|
|
|
|
// align to double boundary
|
|
|
|
adds -12, zaddr, zaddr
|
|
adds -4, paddr, paddr // the branch destination adds -8!
|
|
|
|
fld.d 8(zaddr), oldz // load zbuffer value (from &z0-4)
|
|
|
|
adds 1,dx,dx // tick count
|
|
|
|
fzchkl oldz,z,nuz // z-check with frigged z
|
|
and 3,dx,itemp3 // itemp3 = extras on rhs
|
|
br .aligned_path
|
|
ixfr iz, z_lo // correct z
|
|
//}}}
|
|
.aligned:
|
|
//{{{
|
|
//
|
|
// write iz into dbl z lo, iz+dz into dbl z hi etc
|
|
//
|
|
ixfr ir, r_lo
|
|
ixfr ig, g_lo
|
|
ixfr ib, b_lo
|
|
ixfr iz, z_lo
|
|
|
|
adds ib, idb, ib
|
|
adds ig, idg, ig
|
|
adds ir, idr, ir
|
|
adds iz, idz, iz
|
|
|
|
fld.d r0(zaddr), oldz // load zbuffer value
|
|
|
|
ixfr ib, b_hi
|
|
ixfr ig, g_hi
|
|
ixfr ir, r_hi
|
|
ixfr iz, z_hi
|
|
|
|
adds -1,r0,minus1
|
|
adds -8, zaddr, zaddr
|
|
and 3,dx,itemp3 // itemp3 = extras on rhs
|
|
|
|
.dual
|
|
fzchkl oldz,z,nuz // z-check with unfrigged z
|
|
nop
|
|
.aligned_path:
|
|
faddp b,f0,f0
|
|
shr 2,dx,dx
|
|
faddp g,f0,f0
|
|
adds -1,dx,dx // fix dx for by 8 inner loop
|
|
faddp r,f0,f0
|
|
bla minus1, dx, .inner_loop
|
|
form f0,col
|
|
adds -8, paddr, paddr
|
|
//}}}
|
|
// THIS IS THE INNER LOOP
|
|
|
|
//{{{ 32-bit z, 32-bit pixel inner loop
|
|
.inner_loop:
|
|
faddz z,dz,oddz
|
|
fst.d nuz, 8(zaddr)++
|
|
faddz z,ddz,z
|
|
nop
|
|
fzchkl oldz,oddz,nuz
|
|
fld.d 16(zaddr), oldz
|
|
fzchks f0,f0,f0
|
|
nop
|
|
faddp b,db,b
|
|
fst.d nuz, 8(zaddr)++
|
|
faddp g,dg,g
|
|
pst.d col, 8(paddr)++
|
|
faddp r,dr,r
|
|
nop
|
|
form f0,col
|
|
nop
|
|
faddp b,db,b
|
|
nop
|
|
faddp g,dg,g
|
|
pst.d col, 8(paddr)++
|
|
faddp r,dr,r
|
|
nop
|
|
form f0,col
|
|
bla minus1,dx,.inner_loop
|
|
fzchkl oldz,z,nuz
|
|
fld.d 16(zaddr), oldz
|
|
//}}}
|
|
|
|
// on exit, we have yet to do itemp3 loops
|
|
// not only that but zaddr and paddr are pointing 8 ahead
|
|
// we have a formed colour and have read oldz
|
|
// however, we just HAVE to read oldz again,
|
|
// but we can fix the pointers
|
|
.enddual
|
|
fmov.ss f0, f0
|
|
or r0,itemp3,dx
|
|
fnop
|
|
bc .slow_exit
|
|
|
|
adds 8,zaddr,zaddr
|
|
adds 8,paddr,paddr
|
|
|
|
fxfr z_lo, iz
|
|
//}}}
|
|
// this is the entrypoint for short runs -
|
|
.tidy_up:
|
|
//{{{ short runs, deltas hold single click, dx holds pixels_left-1
|
|
// loop doing simple z-buffer
|
|
//
|
|
ixfr idr, dr_lo
|
|
ixfr idg, dg_lo
|
|
ixfr idb, db_lo
|
|
|
|
.dual
|
|
faddp b,f0,f0
|
|
adds -1, r0, minus1 // set up decrementing counter
|
|
faddp g,f0,f0
|
|
adds minus1, dx, dx // correct for bla
|
|
faddp r,f0,f0
|
|
bla minus1,dx,.longhand_loop // SET UP LCC ! ! ! required by bla
|
|
form f0,col
|
|
adds -4, paddr, paddr
|
|
|
|
.longhand_loop:
|
|
faddp b,db,b
|
|
ld.l r0(zaddr), itemp3
|
|
fnop
|
|
subu iz,itemp3,r0
|
|
fnop
|
|
bnc.t .do_replace
|
|
faddp g,dg,g
|
|
fst.l col, 4(paddr)++
|
|
|
|
.no_replace:
|
|
// walk pointers to pixel + colour
|
|
fnop
|
|
addu 4,zaddr,zaddr
|
|
fnop
|
|
addu 4,paddr,paddr
|
|
faddp r,dr,r
|
|
bla minus1, dx, .longhand_loop
|
|
form f0,col
|
|
adds iz,idz,iz
|
|
fnop
|
|
br .slow_exit
|
|
fnop
|
|
nop
|
|
.do_replace:
|
|
// replace pixel / zixel
|
|
faddp r,dr,r
|
|
addu 4,zaddr,zaddr
|
|
fnop
|
|
st.l iz, -4(zaddr)
|
|
form f0,col
|
|
bla minus1, dx, .longhand_loop
|
|
fnop
|
|
adds iz,idz,iz
|
|
// right, weve done
|
|
.slow_exit:
|
|
.enddual
|
|
fmov.ss f0,f0
|
|
bri r1
|
|
fnop
|
|
nop
|
|
|
|
//}}}
|
|
//{{{ undefine registers
|
|
|
|
#undef paddr
|
|
#undef zaddr
|
|
#undef ir
|
|
#undef ig
|
|
#undef ib
|
|
#undef iz
|
|
#undef idr
|
|
#undef idg
|
|
#undef idb
|
|
#undef idz
|
|
#undef dx
|
|
|
|
|
|
//
|
|
// LOCALS
|
|
//
|
|
//
|
|
// interpolant values
|
|
|
|
#undef r_lo
|
|
#undef r_hi
|
|
#undef r
|
|
|
|
#undef g_lo
|
|
#undef g_hi
|
|
#undef g
|
|
|
|
#undef b_lo
|
|
#undef b_hi
|
|
#undef b
|
|
|
|
#undef z_lo
|
|
#undef z_hi
|
|
#undef z
|
|
|
|
// interpolant delta values
|
|
|
|
#undef dr_lo
|
|
#undef dr_hi
|
|
#undef dr
|
|
|
|
#undef dg_lo
|
|
#undef dg_hi
|
|
#undef dg
|
|
|
|
#undef db_lo
|
|
#undef db_hi
|
|
#undef db
|
|
|
|
#undef dz_lo
|
|
#undef dz_hi
|
|
#undef dz
|
|
|
|
// double-length float temporaries
|
|
#undef oldz_lo
|
|
#undef oldz_hi
|
|
#undef oldz
|
|
|
|
#undef nuz
|
|
#undef col
|
|
|
|
// integer temporaries
|
|
#undef itemp1
|
|
#undef itemp2
|
|
#undef itemp3
|
|
#undef itemp4
|
|
#undef minus1
|
|
|
|
//}}}
|
|
//}}}
|
|
|
|
|
|
//
|
|
// simple 1 pixel at a time texturing
|
|
//
|
|
.globl _textureline
|
|
.align 8
|
|
//{{{ texture (YEAH!)
|
|
//{{{ define registers
|
|
//
|
|
// texline ( int *fbuffer, int *zbuffer,
|
|
// int iu, int iv, int iz,
|
|
// int idu, int idv, int idz, int texbase )
|
|
//
|
|
// FUNCTION PARAMETERS
|
|
//
|
|
|
|
#define paddr r16
|
|
#define zaddr r17
|
|
#define ir r18
|
|
#define ig r19
|
|
#define iz r20
|
|
#define idr r21
|
|
#define idg r22
|
|
#define idz r23
|
|
#define tex_base r24
|
|
#define dx r25
|
|
|
|
|
|
//
|
|
// LOCALS
|
|
//
|
|
//
|
|
// interpolant values
|
|
|
|
#define r_lo f8
|
|
#define r_hi f9
|
|
#define r r_lo
|
|
|
|
#define g_lo f10
|
|
#define g_hi f11
|
|
#define g g_lo
|
|
|
|
#define dblspare f12
|
|
|
|
#define z_lo f14
|
|
#define z_hi f15
|
|
#define z z_lo
|
|
|
|
// interpolant delta values
|
|
|
|
#define dr_lo f16
|
|
#define dr_hi f17
|
|
#define dr dr_lo
|
|
|
|
#define dg_lo f18
|
|
#define dg_hi f19
|
|
#define dg dg_lo
|
|
|
|
#define tex_val1 f20
|
|
#define tex_val2 f21
|
|
|
|
#define dz_lo f22
|
|
#define dz_hi f23
|
|
#define dz dz_lo
|
|
|
|
// double-length float temporaries
|
|
#define oldz_lo f24
|
|
#define oldz_hi f25
|
|
#define oldz oldz_lo
|
|
|
|
#define nuz f26
|
|
#define col_lo f28
|
|
#define col_hi f29
|
|
#define col col_lo
|
|
|
|
#define dbltmp f30
|
|
|
|
// integer temporaries
|
|
#define itemp1 r27
|
|
#define itemp2 r28
|
|
#define itemp3 r29
|
|
#define itemp4 r30
|
|
|
|
#define minus1 itemp1
|
|
|
|
//}}}
|
|
|
|
_textureline:
|
|
//{{{ setup
|
|
|
|
.tx_slow:
|
|
//
|
|
// build floating-point dr dg db registers
|
|
// NB replace on new <= old
|
|
//
|
|
// or r1,r0, itemp2
|
|
// or r16,r0,itemp1
|
|
//
|
|
// call _setpixelsize
|
|
// or 1,r0,r16 // set pixel size to 16 bits
|
|
//
|
|
// or itemp2,r0,r1
|
|
// or itemp1,r0,r16
|
|
|
|
// fmov.dd f0, g
|
|
// fmov.dd f0, dg
|
|
// fmov.dd f0, r
|
|
// fmov.dd f0, dr
|
|
|
|
and 0xffff, idg, itemp1
|
|
ixfr itemp1, dg_lo // these are 16 bit deltas !!!!
|
|
and 0xffff, idr, itemp1
|
|
ixfr itemp1, dr_lo
|
|
|
|
and 0xffff, ig, itemp1
|
|
ixfr itemp1, g_lo
|
|
and 0xffff, ir, itemp1
|
|
ixfr itemp1, r_lo
|
|
|
|
//}}}
|
|
//{{{ short runs, deltas hold single click, dx holds pixels_left-1
|
|
//
|
|
// loop doing simple textured (!) z-buffer
|
|
//
|
|
// possible optimisation is to do 2 at a time, so we save on faddps
|
|
// and stuff
|
|
//
|
|
// if we do fld.d, faddz, fchkz we can branch on PM
|
|
// to determine visibility
|
|
//
|
|
//
|
|
.dual
|
|
faddp f0,f0,f0
|
|
adds -1, r0, minus1 // set up decrementing counter
|
|
fnop
|
|
adds minus1, dx, dx // correct for bla
|
|
fnop
|
|
bla minus1,dx,.t_longhand_loop // SET UP LCC ! ! ! required by bla
|
|
fnop
|
|
adds -4, paddr, paddr
|
|
|
|
.t_longhand_loop:
|
|
pfaddp g,dg,f0
|
|
addu 4,zaddr,zaddr
|
|
pfaddp r,dr,g
|
|
ld.l -4(zaddr), itemp3
|
|
pform f0,r
|
|
addu 4,paddr,paddr
|
|
pform f0,col
|
|
subu iz,itemp3,r0
|
|
fxfr col_lo, itemp2
|
|
bnc.t .t_do_replace
|
|
fnop
|
|
st.l iz, -4(zaddr)
|
|
.t_no_replace:
|
|
// walk pointers to pixel + colour
|
|
fnop
|
|
bla minus1, dx, .t_longhand_loop
|
|
fnop
|
|
adds iz,idz,iz
|
|
fnop
|
|
br .t_slow_exit
|
|
fnop
|
|
nop
|
|
.t_do_replace:
|
|
// replace pixel / zixel
|
|
fnop
|
|
adds iz,idz,iz
|
|
fnop
|
|
fld.l tex_base(itemp2), tex_val1
|
|
fnop
|
|
bla minus1, dx, .t_longhand_loop
|
|
fnop
|
|
fst.l tex_val1, r0(paddr)
|
|
|
|
|
|
// right, weve done
|
|
.t_slow_exit:
|
|
.enddual
|
|
fmov.ss f0,f0
|
|
bri r1
|
|
fnop
|
|
nop
|
|
|
|
//}}}
|
|
|
|
//}}}
|
|
|
|
|
|
|