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>
407 lines
10 KiB
Scheme
407 lines
10 KiB
Scheme
//{{{ 16 bit zbuffer, 8 bit pixels
|
|
//{{{ about zbuffer.ss
|
|
//
|
|
// zbuffer.s
|
|
//
|
|
|
|
|
|
|
|
// 16 bit Z buffer routine.
|
|
//
|
|
// This routine takes a scan line segment and performs
|
|
// a standard z check across the segment, whilst interpolating z
|
|
//
|
|
// The routine assumes a pixel size of 8 bits.
|
|
// All scan segments are flat shaded.
|
|
|
|
|
|
// Assume following inputs
|
|
//
|
|
// int length; ; no. of pixels in segment
|
|
// fpoint zstart; ; z start value
|
|
// fpoint deltaz; ; delta z with x
|
|
// pixel cstart; ; initial colour
|
|
// pixel deltac; ; delta colour with x
|
|
//
|
|
//
|
|
|
|
// r1 return address
|
|
// r2 stack pointer
|
|
// r3 frame pointer
|
|
// r4..r15 local variables left unchanged by subroutine
|
|
// r16..r27 parameters and temporaries, not preserved by subroutines
|
|
// r28..r30 temporaries, not preserved by subroutine
|
|
// r31 addressing temporary
|
|
//
|
|
// f0/f1 zero
|
|
// f2..f7 local values, preserved by subroutine
|
|
// f8..f15 parameters and temporaries, not preserved by subroutine
|
|
// f16..f31 temporary
|
|
//
|
|
//}}}
|
|
|
|
// ROUTINE PARAMETRS
|
|
|
|
define(sp, r2) //stack pointer
|
|
define(Zaddr, r16) // zixel address
|
|
define(Paddr, r17) // pixel address
|
|
define(Zstart, r18) // start z value
|
|
define(dZ, r19) // delta z for each pixel
|
|
define(Xstart, r20) // start x value
|
|
define(length, r21) // total no. of pixels in segment
|
|
define(Col, r22) // start colour
|
|
|
|
|
|
//
|
|
// GLOBAL DATA
|
|
//
|
|
|
|
|
|
//
|
|
// LOCALS
|
|
|
|
define(i, r28)
|
|
define(lc, r29)
|
|
define(itemp1, r29)
|
|
define(itemp2, r30)
|
|
define(itemp3, r31)
|
|
|
|
define(oldZval, f8) //current z buffer value
|
|
define(newZval, f10) // new z value
|
|
|
|
define(lZmaskl, f12) // mask for left end of scan segment
|
|
define(lZmaskl1, f12)
|
|
define(lZmaskl2, f13)
|
|
define(lZmaskh, f14)
|
|
define(lZmaskh1, f14)
|
|
define(lZmaskh2, f15)
|
|
|
|
define(rZmaskl, f16) // mask for right end of scan segment
|
|
define(rZmaskl1, f16)
|
|
define(rZmaskl2, f17)
|
|
define(rZmaskh, f18)
|
|
define(rZmaskh1, f18)
|
|
define(rZmaskh2, f19)
|
|
|
|
define(iZval, f20) // interpolated z value
|
|
|
|
define(colour, f22) // 8 pixels of constant colour
|
|
define(colourl, f22)
|
|
define(colourh, f23)
|
|
define(ftemp1, f24) // temporary val
|
|
define(ftemp2, f26)
|
|
|
|
define(iZ, f26) // z interpolator
|
|
define(iZl, f26)
|
|
define(iZh, f27)
|
|
|
|
define(aZl, f28) // z accumulator
|
|
define(aZh, f29)
|
|
define(aZ, f28)
|
|
define(aZ1, f28)
|
|
define(aZ2, f30)
|
|
|
|
|
|
//
|
|
// Table of Z masks for un-aligned accesses
|
|
//
|
|
.data; .align .double
|
|
|
|
|
|
lZmask_table:: .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
|
|
.long 0x0000FFFF, 0x00000000, 0x00000000, 0x00000000
|
|
.long 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000
|
|
.long 0xFFFFFFFF, 0x0000FFFF, 0x00000000, 0x00000000
|
|
.long 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000
|
|
.long 0xFFFFFFFF, 0xFFFFFFFF, 0x0000FFFF, 0x00000000
|
|
.long 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000
|
|
.long 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000FFFF
|
|
|
|
rZmask_table:: .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
|
|
.long 0xFFFF0000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
|
|
.long 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
|
|
.long 0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFFFFFFFF
|
|
.long 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF
|
|
.long 0x00000000, 0x00000000, 0xFFFF0000, 0xFFFFFFFF
|
|
.long 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF
|
|
.long 0x00000000, 0x00000000, 0x00000000, 0xFFFF0000
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
//
|
|
|
|
.globl _zbufferSegment
|
|
.text
|
|
|
|
_zbufferSegment::
|
|
|
|
|
|
// generate colour
|
|
ixfr Col,colourl
|
|
fmov.ss colourl,colourh
|
|
|
|
// generate left and right masks
|
|
|
|
and 7,Xstart,itemp1 // determine alignment of start pixel
|
|
subs 8,itemp1,itemp2 // 4 - align
|
|
subs length,itemp2,length // adjust length
|
|
and 7,length,itemp3 // determine alignment
|
|
|
|
mov lZmask_table,itemp2
|
|
shl 4,itemp1,i
|
|
adds itemp2,i,itemp2
|
|
fld.q 0(itemp2),lZmaskl
|
|
|
|
mov rZmask_table,itemp2
|
|
shl 4,itemp3,i
|
|
adds itemp2,i,itemp2
|
|
fld.q 0(itemp2),rZmaskl
|
|
|
|
subs 0,length,r0
|
|
bc over64bits // check for only 64 bit segment
|
|
|
|
fxfr lZmaskl1,i
|
|
fxfr rZmaskl1,itemp2
|
|
or i,itemp2,itemp2
|
|
ixfr itemp2,lZmaskl1
|
|
fxfr lZmaskl2,i
|
|
fxfr rZmaskl2,itemp2
|
|
or i,itemp2,itemp2
|
|
ixfr itemp2,lZmaskl2
|
|
|
|
fxfr lZmaskh1,i
|
|
fxfr rZmaskh1,itemp2
|
|
or i,itemp2,itemp2
|
|
ixfr itemp2,lZmaskh1
|
|
fxfr lZmaskh2,i
|
|
fxfr rZmaskh2,itemp2
|
|
or i,itemp2,itemp2
|
|
ixfr itemp2,lZmaskh2
|
|
|
|
over64bits:
|
|
|
|
|
|
|
|
// initialise accumulator to Zstart - ndZ
|
|
|
|
ixfr itemp1,ftemp1
|
|
ixfr dZ,ftemp2
|
|
|
|
// 2 free cycles here
|
|
fmlow.dd ftemp1,ftemp2,ftemp1 // n * dZ
|
|
// 4 free cycles here so
|
|
adds -8,Zaddr,Zaddr // anticipate autoincrement
|
|
adds -8,Paddr,Paddr // anticipate autoincrement
|
|
|
|
fxfr ftemp1,itemp1
|
|
subs Zstart,itemp1,itemp2
|
|
ixfr itemp2,aZl
|
|
fmov.ss aZl, aZh //accumulator = Zstart-ndZ | Zstart-ndZ
|
|
|
|
|
|
.dual
|
|
|
|
|
|
// Process first 1 -> 8 pixels
|
|
|
|
// interpolate z over first pixels
|
|
|
|
fmov.ss f0,iZl // iZl = 0
|
|
shl 1,dZ,itemp1
|
|
fnop
|
|
ixfr itemp1,iZh // iZh = 2dZ
|
|
|
|
faddz aZ1,iZ,aZ1 // first result
|
|
shl 1,itemp1,itemp1 // 4dZ
|
|
|
|
fnop
|
|
ixfr dZ,iZl // iZl = dZ
|
|
fnop
|
|
ixfr dZ,iZh // iZh = dZ
|
|
|
|
faddz aZ1,iZ,aZ2 // second result
|
|
fld.d 8(Zaddr)++,oldZval // get first 4 zbuffer values
|
|
|
|
form lZmaskl,iZval // merge -> zval
|
|
ixfr itemp1,iZl // iZl = 4dZ
|
|
|
|
fzchks oldZval,iZval,newZval // check z over current pixels
|
|
ixfr itemp1,iZh // iZh = 4dZ
|
|
|
|
// interpolate z over next 4 pixels
|
|
|
|
faddz aZ1,iZ,aZ1
|
|
fld.d 8(Zaddr)++,oldZval // load old Zixel
|
|
|
|
faddz aZ2,iZ,aZ2
|
|
fst.d newZval,-8(Zaddr) // store new Zixel
|
|
|
|
form lZmaskh,iZval
|
|
nop
|
|
|
|
|
|
// if length > 8 then traverse rest of segment
|
|
|
|
fzchks oldZval,iZval,newZval // check z for next 4 Pixels
|
|
subs 8,length,r0
|
|
fnop
|
|
bnc last_8_pixels
|
|
|
|
fnop
|
|
adds -8,r0,i // loop increment
|
|
fnop
|
|
adds -8,length,lc // ensure loop for length only
|
|
fnop
|
|
bla i,lc,loop1
|
|
fnop
|
|
nop
|
|
|
|
loop1:
|
|
|
|
// interpolate z over next 4 pixels
|
|
|
|
faddz aZ1,iZ,aZ1
|
|
fld.d 8(Zaddr)++,oldZval // load old Zixel
|
|
|
|
faddz aZ2,iZ,aZ2
|
|
fst.d newZval,-8(Zaddr) // store new Zixel
|
|
|
|
form f0,iZval
|
|
pst.d colour,8(Paddr)++ // store new Pixel
|
|
|
|
fzchks oldZval,iZval,newZval // check z for next 4 Pixels
|
|
nop
|
|
|
|
// interpolate z over next 4 pixels
|
|
|
|
faddz aZ1,iZ,aZ1
|
|
fld.d 8(Zaddr)++,oldZval // load old Zixel
|
|
|
|
faddz aZ2,iZ,aZ2
|
|
fst.d newZval,-8(Zaddr) // store new Zixel
|
|
|
|
form f0,iZval
|
|
bla i,lc,loop1
|
|
|
|
fzchks oldZval,iZval,newZval // check z for next 4 pixels
|
|
adds -8,length,length
|
|
|
|
|
|
endloop1:
|
|
|
|
|
|
|
|
// less than 8 pixels left at this stage
|
|
|
|
last_8_pixels:
|
|
|
|
fnop
|
|
subs 4,length,r0
|
|
|
|
fnop
|
|
bnc last_pixels
|
|
|
|
// > 4 pixels left
|
|
|
|
// interpolate z over last 5->7 pixels
|
|
|
|
faddz aZ1,iZ,aZ1
|
|
fld.d 8(Zaddr)++,oldZval // load old Zixels
|
|
|
|
faddz aZ2,iZ,aZ2
|
|
fst.d newZval,-8(Zaddr) // store new Zixels
|
|
|
|
form rZmaskl,iZval
|
|
pst.d colour,8(Paddr)++ // store new Pixel
|
|
|
|
fzchks oldZval,iZval,newZval // check z for next 4 pixels
|
|
adds -4,length,length
|
|
|
|
|
|
// 1 -> 4 pixels left
|
|
|
|
// interpolate z over last n pixels (1 - 4 pixels remain)
|
|
|
|
faddz aZ1,iZ,aZ1
|
|
fld.d 8(Zaddr)++,oldZval // load old Zixels
|
|
|
|
faddz aZ2,iZ,aZ2
|
|
fst.d newZval,-8(Zaddr) // store new Zixels
|
|
|
|
form rZmaskh,iZval
|
|
nop
|
|
|
|
.enddual
|
|
fzchks oldZval,iZval,newZval
|
|
adds -4,length,length
|
|
|
|
fnop
|
|
fst.d newZval,0(Zaddr) // store final Zixels
|
|
|
|
bri r1
|
|
pst.d colour,8(Paddr)++ // store final Pixels
|
|
|
|
|
|
|
|
// last 0 -> 4 pixels
|
|
|
|
last_pixels:
|
|
|
|
fnop
|
|
subs 0,length,r0
|
|
fnop
|
|
bnc exit
|
|
|
|
// 1 -> 4 pixels left
|
|
|
|
// interpolate z over last n pixels (1 - 4 pixels remain)
|
|
|
|
faddz aZ1,iZ,aZ1
|
|
fld.d 8(Zaddr)++,oldZval // load old Zixels
|
|
|
|
faddz aZ2,iZ,aZ2
|
|
fst.d newZval,-8(Zaddr) // store new Zixels
|
|
|
|
form rZmaskl,iZval
|
|
pst.d colour,8(Paddr)++ // store new Pixels
|
|
|
|
.enddual
|
|
fzchks oldZval,iZval,newZval
|
|
adds -4,length,length
|
|
|
|
fzchks f0,oldZval,f0 // shift PM right 4
|
|
fst.d newZval,0(Zaddr) // store final Zixels
|
|
// NOTE: to shift PM and leave top
|
|
// 4 bits clear src2 < src1
|
|
|
|
bri r1
|
|
pst.d colour,8(Paddr)++ // store final Pixels
|
|
|
|
|
|
// O.K complete now
|
|
|
|
exit:
|
|
.enddual
|
|
|
|
|
|
fnop
|
|
fst.d newZval,0(Zaddr) // store final Zixels
|
|
|
|
bri r1
|
|
pst.d colour,8(Paddr)++ // store final Pixels
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// THE END
|
|
//}}}
|