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>
720 lines
17 KiB
ArmAsm
720 lines
17 KiB
ArmAsm
.align 8
|
|
.text
|
|
|
|
//{{{ register trace macro
|
|
|
|
//}}}
|
|
|
|
// void xform_light_project ( VERTEX *v1,
|
|
// int n_verts,
|
|
// int strip_shade,
|
|
// int front_face,
|
|
// VIEW *eye,
|
|
// LIGHTSOURCE *blondie,
|
|
// MATRIX quad_aligned_m,
|
|
// MATERIAL *m,
|
|
// int do_project_and_texture,
|
|
// float texscale,
|
|
// int pmesh )
|
|
|
|
//{{{ declare registers
|
|
//{{{ parameters
|
|
// parameters
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//}}}
|
|
//{{{ local floats -- all registers used !
|
|
// local floats
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// these must be double-aligned
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// for transforming
|
|
|
|
|
|
|
|
//}}}
|
|
//{{{ local ints and pointers -- all registers used !
|
|
// local ints and pointers
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//}}}
|
|
|
|
|
|
|
|
//}}}
|
|
//{{{ define offsets into some types
|
|
// fields in r28 structure
|
|
|
|
|
|
|
|
|
|
// fields in material structure
|
|
|
|
|
|
|
|
// fields in view structure
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// fields in vertex structure
|
|
|
|
|
|
|
|
|
|
|
|
//}}}
|
|
|
|
// r17 guaranteed > 0
|
|
|
|
.globl _fn_xform_light_project
|
|
|
|
.align 8
|
|
//
|
|
//
|
|
|
|
_fn_xform_light_project::
|
|
|
|
//{{{ save volatiles
|
|
fst.d f2, -8(sp) // 1
|
|
fst.d f4, -16(sp) // 1
|
|
fst.d f6, -24(sp) // 1
|
|
st.l r15, -28(sp) // 2
|
|
st.l r14, -32(sp) // 2
|
|
st.l r13, -36(sp) // 2
|
|
st.l r12, -40(sp) // 2
|
|
st.l r11, -44(sp) // 2
|
|
st.l r10, -48(sp) // 2
|
|
st.l r9, -52(sp) // 2
|
|
st.l r8, -56(sp) // 2
|
|
adds -64, sp, sp // 1
|
|
|
|
fxfr f8 , r9 // 2
|
|
//}}}
|
|
|
|
//{{{ cache matrix
|
|
fld.q 0( r22 ), f4 // 2
|
|
fld.q 16( r22 ), f8 // 2
|
|
fld.q 32( r22 ), f12 // 2
|
|
fld.q 48( r22 ), f16 // 2
|
|
//}}}
|
|
|
|
|
|
//{{{ initialize state
|
|
//
|
|
// load various floating-point constants into spare integer registers
|
|
//
|
|
orh ha%.C00066, r0, r31 // 1
|
|
ld.l l%.C00066(r31), r14 // 2
|
|
|
|
orh ha%.C00067, r0, r31 // 1
|
|
ld.l l%.C00067(r31), r13 // 2
|
|
|
|
orh ha%.C00068, r0, r31 // 1
|
|
ld.l l%.C00068(r31), r15 // 2
|
|
|
|
orh ha%.C00069, r0, r31 // 1
|
|
ld.l l%.C00069(r31), r12 // 2
|
|
|
|
orh ha%_sub_pxl_correct, r0, r31 // 1
|
|
ld.l l%_sub_pxl_correct(r31), r10 // 2
|
|
|
|
ixfr r14 , f21 // 2
|
|
//
|
|
// r29 = r23 ->specular_table;
|
|
//
|
|
ld.l (11*4) ( r23 ), r29 // 2
|
|
//
|
|
// f2 = r20 ->screen_half_width;
|
|
// f3 = r20 ->screen_half_height;
|
|
// f20 = r20 ->zscale;
|
|
//
|
|
orh ha%.Czscale, r0, r31
|
|
fld.l l%.Czscale(r31), f30
|
|
|
|
fld.l ( (37*4) )( r20 ), f2 // 1
|
|
fld.l ( (39*4) )( r20 ), f3 // 1
|
|
fld.l ( (42*4) )( r20 ), f20 // 1
|
|
fmul.ss f20 , f30 , f20
|
|
//
|
|
// f7 = r20 ->d;
|
|
// f11 =1.0f;
|
|
// NB .C00066 must be 1.0f
|
|
//
|
|
fld.l ( (33*4) )( r20 ), f7 // 2
|
|
ixfr r14 , f11 // 2
|
|
//
|
|
// f15 = f2 *( r20 ->shift_x + 1.0f);
|
|
// f19 = f3 *( r20 ->shift_y + 1.0f);
|
|
//
|
|
fld.l ( (44*4) )( r20 ), f15 // 2
|
|
fld.l ( (45*4) )( r20 ), f19 // 2
|
|
fadd.ss f11 , f15 , f15 // 3
|
|
fadd.ss f11 , f19 , f19 // 3
|
|
fmul.ss f2 , f15 , f15 // 3
|
|
fmul.ss f3 , f19 , f19 // 1
|
|
//
|
|
// if ( r18 & strip_shade_coloured) {
|
|
// r26 = 0;
|
|
// r27 = 0;
|
|
// }
|
|
//
|
|
and 2, r18 , r0 // 1
|
|
bc .not_cooked // 3
|
|
mov r0, r26
|
|
mov r16 , r11 // 1
|
|
br .end_check
|
|
mov r0, r27
|
|
|
|
//
|
|
// else if ( r18 & strip_shade_smooth) {
|
|
// r26 = 1;
|
|
// r27 = 0;
|
|
// r11 = r16 ;
|
|
// }
|
|
//
|
|
|
|
.not_cooked::
|
|
and 1, r18 , r0 // 1
|
|
bc .not_smooth // 2
|
|
adds 0x1, r0, r26 // 1
|
|
mov r16 , r11 // 1
|
|
br .end_check // 2
|
|
mov r0, r27 // 1
|
|
|
|
//
|
|
// else {
|
|
// r26 = r17 -2;
|
|
// r27 = -1;
|
|
// r11 = r16 +1;
|
|
// }
|
|
//
|
|
|
|
.not_smooth::
|
|
adds -2, r17 , r26
|
|
adds -1, r0, r27
|
|
adds 56, r16 , r11
|
|
|
|
.end_check::
|
|
|
|
btne 0x0, r19 , .dont_tweak_factor // 3
|
|
ixfr r13 , f21
|
|
|
|
.dont_tweak_factor::
|
|
//}}}
|
|
|
|
//{{{ LOOP : transform point - CHECK FOR W-COORD == 0, and dont do it!
|
|
//
|
|
// f22 = r16 ->position[0];
|
|
// f22 = r16 ->position[1];
|
|
// f23 = r16 ->position[2];
|
|
//
|
|
// rx=( f22 * f4 )+( f23 * f8 )+( f24 * f12 )+tx;
|
|
// ry=( f22 * f5 )+( f23 * f9 )+( f24 * f13 )+ty;
|
|
// rz=( f22 * f6 )+( f23 * f10 )+( f24 * f14 )+tz;
|
|
//
|
|
// this can be optimized by about 5 ticks i think, NOTE use
|
|
// T as staging-post and all will be well, maybe use KR for f24 ?
|
|
//
|
|
//
|
|
// first fix nverts !!!
|
|
|
|
adds -1, r17 , r17
|
|
|
|
fld.d 0( r16 ), f22 // 4
|
|
.vertex_loop::
|
|
fld.d 48( r22 ), f16 // 2
|
|
fld.l 56( r22 ), f18 // 2
|
|
|
|
bte 0x0, r25 , .vertex_proceed
|
|
|
|
ld.l 12( r16 ), r31
|
|
and 1, r31, r0
|
|
bnc .vertex_proceed
|
|
|
|
// r16 ++;
|
|
// r11 ++;
|
|
//
|
|
// r26 += r27 ;
|
|
// r17 --;
|
|
|
|
adds 56 , r16 , r16
|
|
adds 56 , r11 , r11
|
|
adds r27 , r26 , r26
|
|
adds -1, r17 , r17 // carry set if nverts>1
|
|
bnc.t .vertex_loop
|
|
fld.d 0( r16 ), f22
|
|
|
|
br .xf_exit
|
|
nop
|
|
|
|
.vertex_proceed::
|
|
|
|
pfmul.ss f22 , f4 ,f0 // 1
|
|
pfmul.ss f23 , f8 ,f0 // 1
|
|
pfmul.ss f22 , f5 ,f0 // 1
|
|
fld.l 8( r16 ), f24 // 1
|
|
pfmul.ss f23 , f9 , f30 // 1
|
|
pfmul.ss f22 , f6 , f31 // 1
|
|
pfadd.ss f30 , f31 ,f0 // 1
|
|
pfmul.ss f23 , f10 , f30 // 1
|
|
pfmul.ss f24 , f12 , f31 // 1
|
|
pfadd.ss f30 , f31 ,f0 // 1
|
|
pfmul.ss f24 , f13 , f30 // 1
|
|
pfmul.ss f24 , f14 , f31 // 1
|
|
pfadd.ss f30 , f31 ,f0 // 1
|
|
m12apm.ss f0,f0,f0 // 1
|
|
m12apm.ss f0,f0,f0 // 1
|
|
m12apm.ss f0,f0,f0 // 1
|
|
|
|
r2ap1.ss f16 ,f0,f0 // 1
|
|
r2ap1.ss f17 ,f0,f0 // 1
|
|
r2ap1.ss f18 ,f0,f0 // 1
|
|
|
|
pfadd.ss f0,f0, f22 // 1
|
|
pfadd.ss f0,f0, f23 // 1
|
|
pfadd.ss f0,f0, f24 // 1
|
|
|
|
fst.l f24 , 12( r16 ) // uninverted z goes in W-slot
|
|
//}}}
|
|
|
|
//{{{ project point does the john rhoades sub-pixel correction
|
|
//
|
|
// f29 = f7 /rz;
|
|
//
|
|
|
|
and 0x1, r24 , r0
|
|
bc .dont_project
|
|
|
|
ixfr r15 , f30 // f30 = 2.0 // 1
|
|
frcp.ss f24 , f29 // f29 = first guess // 1
|
|
fmul.ss f24 , f29 , f31 // first guess * divisor // 3
|
|
fsub.ss f30 , f31 , f31 // 2.0 - (fg*d) // 3
|
|
fmul.ss f29 , f31 , f29 // 2nd guess // 3
|
|
fmul.ss f24 , f29 , f31 // g2*d // 3
|
|
fsub.ss f30 , f31 , f31 // 2.0 - g2*d // 3
|
|
fmul.ss f29 , f31 , f29 // 3rd guess, real 1/z // 3
|
|
ixfr r10 , f31 // put john rhoades into f31
|
|
fmul.ss f7 , f29 , f29 // 3rd guess, real 1/z // 3
|
|
//
|
|
// f22 =(rx* f2 * f29 )+ f15 ;
|
|
// f23 =(ry* f3 * f29 )+ f19 ;
|
|
// no longer f24 = f11 -( f20 * f29 );
|
|
//
|
|
// but
|
|
// f24 = f20 * f29 (where f24 =1 at near clip, 0 at infinity)
|
|
// and we z-buffer by newz > zbuf => keep
|
|
//
|
|
// NB we need to do the John Rhoades thing by adding on a BIG number then
|
|
// subtracting it again
|
|
//
|
|
pfmul.ss f20 , f29 , f0
|
|
pfmul.ss f22 , f2 , f0
|
|
pfmul.ss f23 , f3 , f0
|
|
mi2pt.ss f29 , f0, f24 // got real f24
|
|
mimt1s2.ss f0, f0, f0 // m-3 * f29
|
|
mimt1s2.ss f0, f0, f0 // m-3 * f29
|
|
pfmul.ss f0, f0, f0 // push f29 * f22 * f2 to m-3
|
|
i2p1.ss f15 , f0, f24 // and fire add
|
|
i2p1.ss f19 , f0, f0 // again
|
|
|
|
pfsub.ss f0, f31 , f0 // push -john rhoades into pipe
|
|
i2ap1.ss f31 , f0, f0 // add x to BIG
|
|
i2ap1.ss f31 , f0, f0 // add y to BIG
|
|
pfadd.ss f0, f0, f31 // f31 now -BIG
|
|
i2ap1.ss f31 , f0, f0 // subtract BIG from x
|
|
i2ap1.ss f31 , f0, f0 // subtract BIG from y
|
|
pfadd.ss f0, f0, f0 // x+BIG-BIG now in adder stage 3
|
|
pfadd.ss f0, f0, f22
|
|
pfadd.ss f0, f0, f23
|
|
|
|
// r16 ->position[0] = f22 ;
|
|
// r16 ->position[1] = f23 ;
|
|
// r16 ->position[2] = f24 ;
|
|
|
|
.dont_project::
|
|
fst.d f22 , 0( r16 )
|
|
.dont_texture::
|
|
fst.l f24 , 8( r16 ) // 1
|
|
|
|
//}}}
|
|
|
|
//{{{ r28 point
|
|
// if ( r26 ) {
|
|
bte 0x0, r26 , .dont_light // 1
|
|
|
|
.do_lighting::
|
|
|
|
// load surface normal of vertex to be lit up
|
|
fld.d ( (8*4) +0)( r11 ), f22
|
|
orh ha%_ambientR, r0, r31 // 1
|
|
mov r21 , r8
|
|
fld.l ( (8*4) +8)( r11 ), f24
|
|
or l%_ambientR, r31, r31 // 2
|
|
fld.d 0(r31), f16
|
|
fld.l 8(r31), f18
|
|
pfmul.ss f21 , f22 , f0
|
|
pfmul.ss f21 , f23 , f0
|
|
pfmul.ss f21 , f24 , f0
|
|
pfmul.ss f0, f0, f22
|
|
pfmul.ss f0, f0, f23
|
|
pfmul.ss f0, f0, f24
|
|
|
|
// for ( r8 = r21 ; r8 ; r8 = r8 ->next ) {
|
|
|
|
bte 0x0, r8 , .lighting_done
|
|
//
|
|
// need to compute
|
|
// f25 =( f22 * f26 ) + ( f23 * f27 ) + ( f24 * f28 );
|
|
//
|
|
fld.l ( (5*4) +0)( r8 ), f26
|
|
.next_bulb::
|
|
fld.l ( (5*4) +4)( r8 ), f27
|
|
fld.l ( (5*4) +8)( r8 ), f28
|
|
|
|
.align 8
|
|
|
|
pfmul.ss f22 , f26 , f0
|
|
pfmul.ss f23 , f27 , f0 // pipeline states AFTER this instruction
|
|
pfmul.ss f24 , f28 , f0 // nlz nly nlx ? ? ? ?
|
|
r2ap1.ss f0, f0, f0 // f22 . f26 into T
|
|
r2pt.ss f0, f0, f0 // adder 1 = f22 . f26 + f23 . f27
|
|
pfadd.ss f0, f0, f0 // adder 2
|
|
pfadd.ss f0, f0, f0 // adder 3
|
|
m12apm.ss f0, f0, f0 // add-3 + mul-3
|
|
pfadd.ss f0, f0, f0 //
|
|
pfadd.ss f0, f0, f0 //
|
|
pfadd.ss f0, f0, f25
|
|
|
|
pfgt.ss f25 , f0, f0
|
|
bnc .no_diffuse
|
|
|
|
fld.l ( (9*4) )( r8 ), f30
|
|
fld.l ( (9*4) +4)( r8 ), f31
|
|
fld.l ( (9*4) +8)( r8 ), f29
|
|
|
|
pfmul.ss f25 , f30 , f0
|
|
pfmul.ss f25 , f31 , f0
|
|
pfmul.ss f25 , f29 , f0
|
|
mr2p1.ss f16 , f0, f0
|
|
mr2p1.ss f17 , f0, f0
|
|
mr2p1.ss f18 , f0, f0
|
|
pfadd.ss f0, f0, f16
|
|
pfadd.ss f0, f0, f17
|
|
pfadd.ss f0, f0, f18
|
|
|
|
// indirect off r8 next field
|
|
.no_diffuse::
|
|
|
|
ld.l r0( r8 ), r8
|
|
xor r0, r8 , r0
|
|
bnc.t .next_bulb
|
|
fld.l ( (5*4) +0)( r8 ), f26
|
|
|
|
// f16 , f17 , f18 hold the accumulated r28 r g bs
|
|
// now multiply by surface colour
|
|
|
|
ixfr r12 , f25
|
|
|
|
fld.l ( (4) )( r23 ), f30
|
|
fld.l ( (4) +4)( r23 ), f31
|
|
fld.l ( (4) +8)( r23 ), f29
|
|
|
|
pfmul.ss f25 , f30 , f0
|
|
pfmul.ss f25 , f31 , f0
|
|
pfmul.ss f25 , f29 , f0
|
|
pfmul.ss f0, f0, f30
|
|
pfmul.ss f16 , f30 , f31
|
|
pfmul.ss f17 , f31 , f29
|
|
pfmul.ss f18 , f29 , f0
|
|
pfmul.ss f0, f0, f16
|
|
pfmul.ss f0, f0, f17
|
|
pfmul.ss f0, f0, f18
|
|
|
|
fst.l f16 , ( (8*4) )( r11 ) // 1
|
|
fst.l f17 , (4+ (8*4) )( r11 ) // 1
|
|
fst.l f18 , (8+ (8*4) )( r11 ) // 1
|
|
|
|
.dont_light::
|
|
.lighting_done::
|
|
|
|
//}}}
|
|
|
|
//{{{ loop tail
|
|
// r16 ++;
|
|
// r11 ++;
|
|
//
|
|
// r26 += r27 ;
|
|
// r17 --;
|
|
|
|
adds 56 , r16 , r16
|
|
adds 56 , r11 , r11
|
|
adds r27 , r26 , r26
|
|
adds -1, r17 , r17 // carry set if nverts>1
|
|
bnc.t .vertex_loop
|
|
fld.d 0( r16 ), f22
|
|
|
|
|
|
//}}}
|
|
|
|
//{{{ unsave volatiles, exit
|
|
.xf_exit::
|
|
adds 64, sp, sp
|
|
fld.d -8(sp), f2
|
|
fld.d -16(sp), f4
|
|
fld.d -24(sp), f6
|
|
ld.l -28(sp), r15
|
|
ld.l -32(sp), r14
|
|
ld.l -36(sp), r13
|
|
ld.l -40(sp), r12
|
|
ld.l -44(sp), r11
|
|
ld.l -48(sp), r10
|
|
ld.l -52(sp), r9
|
|
bri r1
|
|
ld.l -56(sp), r8
|
|
|
|
//}}}
|
|
|
|
|
|
|
|
//{{{ fn_inv (computes 1/z)
|
|
.align 8
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.globl _fn_inv
|
|
.align 8
|
|
_fn_inv::
|
|
|
|
orh ha%.C00068, r0, r31
|
|
fld.l l%.C00068(r31), f12
|
|
frcp.ss f8 , f11 // f11 = first guess
|
|
fmul.ss f8 , f11 , f10 // first guess * divisor
|
|
fsub.ss f12 , f10 , f10 // 2.0 - (fg*d)
|
|
fmul.ss f11 , f10 , f11 // 2nd guess
|
|
fmul.ss f8 , f11 , f10 // g2*d
|
|
fsub.ss f12 , f10 , f10 // 2.0 - g2*d
|
|
bri r1
|
|
fmul.ss f10 , f11 , f8 // 3rd guess, real 1/z
|
|
|
|
//}}}
|
|
|
|
//{{{ constants and strings
|
|
.align 8
|
|
.globl _sub_pxl_correct
|
|
|
|
.C00066:
|
|
.long 0x3f800000 // 1.00000000E+00
|
|
|
|
.C00067:
|
|
.long 0xbf800000 // -1.00000000E+00
|
|
|
|
.C00068:
|
|
.long 0x40000000 // 2.00000000E+00
|
|
|
|
.C00069:
|
|
.long 0x43800000 // 256.00000000E+00
|
|
|
|
_sub_pxl_correct:
|
|
.long 0x00000000 // 0x49000000 // 5.24288000E+05
|
|
|
|
.Czscale: // (0)
|
|
.long 0x497fffff // 1.04857588E+06
|
|
// .long 0x49fffffe // 2.09715175E+06
|
|
|
|
.about_to_xform::
|
|
.string "about to xform"
|
|
.byte 0x0
|
|
|
|
.xformed::
|
|
.string "xformed"
|
|
.byte 0x0
|
|
|
|
.projected::
|
|
.string "projected"
|
|
.byte 0x0
|
|
//}}}
|
|
|
|
|
|
//{{{ quad matrices
|
|
.data
|
|
|
|
.globl _ambientR
|
|
.globl _ambientG
|
|
.globl _ambientB
|
|
|
|
_ambientR:
|
|
.long 0x3eb33333 // 3.49999994E-01
|
|
|
|
_ambientG:
|
|
.long 0x3eb33333 // 3.49999994E-01
|
|
|
|
_ambientB:
|
|
.long 0x3eb33333 // 3.49999994E-01
|
|
|
|
|
|
.align 16
|
|
|
|
_quad_f_matrix:: // (64)
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
|
|
.align 16
|
|
_quad_b_matrix:: // (64)
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
.long 0
|
|
|
|
//}}}
|