Files
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

704 lines
19 KiB
Scheme

.align 8
.text
//{{{ register trace macro
#define trace_regs(label)\
adds -16, sp, sp; \
st.l r1, 4(sp); \
adds -256, sp, sp; \
st.l r17, 64(sp); \
orh ha%label, r0, r17; \
or l%label, r17, r17; \
call _reg_dump; \
adds 256, sp, sp; \
ld.l 4(sp), r1; \
adds 16, sp, sp
//}}}
// 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
#define v1 r16
#define n_verts r17
#define strip_shade r18
#define front_face r19
#define eye r20
#define blondie r21
#define quad_m r22
#define surf r23
#define do_project r24
#define pmesh r25
#define parm_ks f8
//}}}
//{{{ local floats -- all registers used !
// local floats
#define m00 f4
#define m01 f5
#define m02 f6
#define m10 f8
#define m11 f9
#define m12 f10
#define m20 f12
#define m21 f13
#define m22 f14
#define m30 f16
#define m31 f17
#define m32 f18
#define wx f2
#define wy f3
#define eye_d f7
#define zmax f11
#define shx f15
#define shy f19
#define wz f20
#define normfactor f21
// these must be double-aligned
#define px f22
#define py f23
#define pz f24
#define fdot f25
#define lx f26
#define ly f27
#define lz f28
#define hx lx
#define hy ly
#define hz lz
#define invz f29
#define nx px
#define ny py
#define nz pz
// these must be a double register
#define cdiff f30
#define cspec f31
// for transforming
#define tmp1 cdiff
#define tmp2 cspec
//}}}
//{{{ local ints and pointers -- all registers used !
// local ints and pointers
#define bulb r8
#define dolighting r26
#define lightbump r27
#define light r28
#define phong_table r29
#define dot r30
#define two_point_0 r15
#define one_point_0 r14
#define minus_one r13
#define two_fifty_six r12
#define light_v r11
#define john_rhoades r10
#define ks r9
//}}}
#define vertex_size 56
//}}}
//{{{ define offsets into some types
// fields in light structure
#define xformpos_offs (5*4)
// fields in material structure
#define specular_table_offs (11*4)
// fields in view structure
#define d_offs (33*4)
#define screen_half_width_offs (37*4)
#define screen_half_height_offs (39*4)
#define zscale_offs (42*4)
#define shift_x_offs (44*4)
#define shift_y_offs (45*4)
// fields in vertex structure
#define norm_offs (8*4)
#define normcol_offs norm_offs
#define tex_offs (12*4)
#define phong_precision_m1 127
//}}}
// n_verts 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 parm_ks, ks // 2
//}}}
//{{{ cache matrix
fld.q 0(quad_m), m00 // 2
fld.q 16(quad_m), m10 // 2
fld.q 32(quad_m), m20 // 2
fld.q 48(quad_m), m30 // 2
//}}}
//{{{ initialize state
//
// load various floating-point constants into spare integer registers
//
orh ha%.C00066, r0, r31 // 1
ld.l l%.C00066(r31), one_point_0 // 2
orh ha%.C00067, r0, r31 // 1
ld.l l%.C00067(r31), minus_one // 2
orh ha%.C00068, r0, r31 // 1
ld.l l%.C00068(r31), two_point_0 // 2
orh ha%.C00069, r0, r31 // 1
ld.l l%.C00069(r31), two_fifty_six // 2
orh ha%_sub_pxl_correct, r0, r31 // 1
ld.l l%_sub_pxl_correct(r31), john_rhoades // 2
// hack
// or r0, r0, john_rhoades
ixfr one_point_0, normfactor // 2
//
// phong_table=surf->specular_table;
//
ld.l specular_table_offs(surf), phong_table // 2
//
// wx =eye->screen_half_width;
// wy =eye->screen_half_height;
// wz =eye->zscale;
//
orh ha%.Czscale, r0, r31
fld.l l%.Czscale(r31), tmp1
fld.l (screen_half_width_offs)(eye), wx // 1
fld.l (screen_half_height_offs)(eye), wy // 1
fld.l (zscale_offs)(eye), wz // 1
fmul.ss wz, tmp1, wz
//
// eye_d=eye->d;
// zmax =1.0f;
// NB .C00066 must be 1.0f
//
fld.l (d_offs)(eye), eye_d // 2
ixfr one_point_0, zmax // 2
//
// shx=wx*(eye->shift_x + 1.0f);
// shy=wy*(eye->shift_y + 1.0f);
//
fld.l (shift_x_offs)(eye), shx // 2
fld.l (shift_y_offs)(eye), shy // 2
fadd.ss zmax, shx, shx // 3
fadd.ss zmax, shy, shy // 3
fmul.ss wx, shx, shx // 3
fmul.ss wy, shy, shy // 1
//
// if (strip_shade & strip_shade_coloured) {
// dolighting = 0;
// lightbump = 0;
// }
//
and 2, strip_shade, r0 // 1
bc .not_cooked // 3
mov r0, dolighting
mov v1, light_v // 1
br .end_check
mov r0, lightbump
//
// else if (strip_shade & strip_shade_smooth) {
// dolighting = 1;
// lightbump = 0;
// light_v = v1;
// }
//
.not_cooked::
and 1, strip_shade, r0 // 1
bc .not_smooth // 2
adds 0x1, r0, dolighting // 1
mov v1, light_v // 1
br .end_check // 2
mov r0, lightbump // 1
//
// else {
// dolighting = n_verts-2;
// lightbump = -1;
// light_v = v1+1;
// }
//
.not_smooth::
adds -2, n_verts, dolighting
adds -1, r0, lightbump
adds 56, v1, light_v
.end_check::
btne 0x0, front_face, .dont_tweak_factor // 3
ixfr minus_one, normfactor
.dont_tweak_factor::
//}}}
//{{{ LOOP : transform point - CHECK FOR W-COORD == 0, and dont do it!
//
// px=v1->position[0];
// px=v1->position[1];
// py=v1->position[2];
//
// rx=(px*m00)+(py*m10)+(pz*m20)+tx;
// ry=(px*m01)+(py*m11)+(pz*m21)+ty;
// rz=(px*m02)+(py*m12)+(pz*m22)+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 pz?
//
//
// first fix nverts !!!
adds -1, n_verts, n_verts
fld.d 0(v1),px // 4
.vertex_loop::
bte 0x0, pmesh, .vertex_proceed
ld.l 12(v1), r31
and 1, r31, r0
bnc .vertex_proceed
// v1++;
// light_v++;
//
// dolighting+=lightbump;
// n_verts--;
adds vertex_size, v1, v1
adds vertex_size, light_v, light_v
adds lightbump, dolighting, dolighting
adds -1, n_verts, n_verts // carry set if nverts>1
bnc.t .vertex_loop
fld.d 0(v1),px
br .xf_exit
nop
.vertex_proceed::
pfmul.ss px,m00,f0 // 1
pfmul.ss py,m10,f0 // 1
pfmul.ss px,m01,f0 // 1
fld.l 8(v1),pz // 1
pfmul.ss py,m11,tmp1 // 1
pfmul.ss px,m02,tmp2 // 1
pfadd.ss tmp1,tmp2,f0 // 1
pfmul.ss py,m12,tmp1 // 1
pfmul.ss pz,m20,tmp2 // 1
pfadd.ss tmp1,tmp2,f0 // 1
pfmul.ss pz,m21,tmp1 // 1
pfmul.ss pz,m22,tmp2 // 1
pfadd.ss tmp1,tmp2,f0 // 1
m12apm.ss f0,f0,f0 // 1
m12apm.ss f0,f0,f0 // 1
m12apm.ss f0,f0,f0 // 1
r2ap1.ss m30,f0,f0 // 1
r2ap1.ss m31,f0,f0 // 1
r2ap1.ss m32,f0,f0 // 1
pfadd.ss f0,f0,px // 1
pfadd.ss f0,f0,py // 1
pfadd.ss f0,f0,pz // 1
fst.l pz, 12(v1) // uninverted z goes in W-slot
//}}}
//{{{ project point does the john rhoades sub-pixel correction
//
// invz=eye_d/rz;
//
#define two tmp1
and 0x1, do_project, r0
bc .dont_project
ixfr two_point_0, two // tmp1 = 2.0 // 1
frcp.ss pz, invz // invz = first guess // 1
fmul.ss pz, invz, tmp2 // first guess * divisor // 3
fsub.ss two, tmp2, tmp2 // 2.0 - (fg*d) // 3
fmul.ss invz, tmp2, invz // 2nd guess // 3
fmul.ss pz, invz, tmp2 // g2*d // 3
fsub.ss two, tmp2, tmp2 // 2.0 - g2*d // 3
fmul.ss invz, tmp2, invz // 3rd guess, real 1/z // 3
ixfr john_rhoades, tmp2 // put john rhoades into tmp2
fmul.ss eye_d, invz, invz // 3rd guess, real 1/z // 3
//
// px=(rx*wx*invz)+shx;
// py=(ry*wy*invz)+shy;
// no longer pz=zmax-(wz*invz);
//
// but
// pz=wz*invz (where pz=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 wz, invz, f0
pfmul.ss px, wx, f0
pfmul.ss py, wy, f0
mi2pt.ss invz, f0, pz // got real pz
mimt1s2.ss f0, f0, f0 // m-3 * invz
mimt1s2.ss f0, f0, f0 // m-3 * invz
pfmul.ss f0, f0, f0 // push invz*px*wx to m-3
i2p1.ss shx, f0, pz // and fire add
i2p1.ss shy, f0, f0 // again
pfsub.ss f0, tmp2, f0 // push -john rhoades into pipe
i2ap1.ss tmp2, f0, f0 // add x to BIG
i2ap1.ss tmp2, f0, f0 // add y to BIG
pfadd.ss f0, f0, tmp2 // tmp2 now -BIG
i2ap1.ss tmp2, f0, f0 // subtract BIG from x
i2ap1.ss tmp2, f0, f0 // subtract BIG from y
pfadd.ss f0, f0, f0 // x+BIG-BIG now in adder stage 3
pfadd.ss f0, f0, px
pfadd.ss f0, f0, py
// v1->position[0] = px;
// v1->position[1] = py;
// v1->position[2] = pz;
.dont_project::
fst.d px, 0(v1)
.dont_texture::
fst.l pz, 8(v1) // 1
//}}}
//{{{ light point
// if (dolighting) {
bte 0x0, dolighting, .dont_light // 1
.do_lighting::
// load surface normal of vertex to be lit up
fld.d (norm_offs+0)(light_v), nx
fmov.dd f0, cdiff
fmul.ss normfactor, nx, nx
fld.l (norm_offs+8)(light_v), nz
fmul.ss normfactor, ny, ny
mov blondie, bulb
fmul.ss normfactor, nz, nz
// for (bulb=blondie; bulb; bulb=bulb->next ) {
bte 0x0, bulb, .lighting_done
//
// ok, go for ultra-pipelining, firing off both diffuse and specular
// lighting computations at same time
// need to compute
// fdot=(nx*lx) + (ny*ly) + (nz*lz);
//
// where lxyz is light direction cosine, and
//
// and dot =(int) ((nx*hx) + (ny*hy) + (nz*hz));
//
// where hxyz is 'half-vector' direction cosine,
// nxyz is surface normal
//
fld.l (xformpos_offs+0)(bulb), lx
.next_bulb::
fld.l (xformpos_offs+4)(bulb), ly
ld.l (xformpos_offs+12)(bulb), r31
.align 8
// to aid comprehension
//
// m12tpm fsrc1 * fsrc2, m-3 + T, a-3 -> fdest
// mm12ttpm fsrc1 * fsrc2, m-3 + T, m-3->T, m-3 -> fdest
// mimt1p2 KI * m-3, fsrc1 + fsrc2, m-3->T, m-3 -> fdest
// i2ap1 KI * fsrc2, fsrc1 + a-3, m-3->T, a-3 -> dest
d.pfmul.ss nx, lx, f0
fld.l (xformpos_offs+8)(bulb), lz
d.pfmul.ss ny, ly, f0 // pipeline states AFTER this instruction
fld.l 0(r31), hx // M A T
pfmul.ss nz, lz, f0 // nlz nly nlx ? ? ? ?
fld.l 4(r31), hy
mm12ttpm.ss nx, hx, f0 // nhx nlz nly ? ? ? nlx
fld.l 8(r31), hz
m12tpm.ss ny, hy, f0 // nhy nhx nlz nlxy ? ? ?
mm12ttpm.ss nz, hz, hx // nhz nhy nhx ? nlxy ? ? hz=nlz
mm12ttpm.ss hx, f0, f0 // ? nhz nhy ? ? nlxy nhx
m12tpm.ss f0, f0, hz // ? ? nhz nhxy ? ? ? hx=nlxy
mimt1p2.ss hz, hx, hy // ? ? ? nlxyz nhxy ? ? hy=nhz
pfadd.ss f0, f0, f0 // ? ? ? ? nlxyz nhxy ?
i2ap1.ss hy, f0, f0 // ? ? ? nhxyz ? nlxyz ?
pfadd.ss f0, f0, fdot // ? ? ? ? nhxyz ? ?
pfadd.ss f0, f0, f0 // ? ? ? ? ? nhxyz ?
pfgt.ss fdot, f0, hz
bnc .no_diffuse
fadd.ss fdot, cdiff, cdiff
.no_diffuse:: // above = 16
pfgt.ss hz, f0, f0
bnc .no_specular
// this is needed to exponentiate in frame buffer
// fadd.ss cspec, hz, cspec
ftrunc.sd hz, hx
fxfr hx, dot // 1
subs r0, dot, r0
bnc .no_specular // 1
subs phong_precision_m1, dot, r0 // 1
bnc .no_phong_clamp // 1
or phong_precision_m1, r0, dot // 1
.no_phong_clamp::
shl 2, dot, dot
fld.l dot(phong_table), hz
fadd.ss cspec, hz, cspec
.no_specular::
// indirect off bulb next field
ixfr ks, hz
ld.l r0(bulb), bulb
ixfr two_fifty_six, hx
xor r0, bulb, r0
bnc.t .next_bulb
fld.l (xformpos_offs+0)(bulb), lx
fmul.ss hx, cdiff, cdiff
fmul.ss hz, cspec, cspec
fst.d cdiff, (normcol_offs)(light_v) // 1
.dont_light::
.lighting_done::
//}}}
//{{{ loop tail
// v1++;
// light_v++;
//
// dolighting+=lightbump;
// n_verts--;
adds vertex_size, v1, v1
adds vertex_size, light_v, light_v
adds lightbump, dolighting, dolighting
adds -1, n_verts, n_verts // carry set if nverts>1
bnc.t .vertex_loop
fld.d 0(v1),px
//}}}
//{{{ 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
#undef tmp1
#undef tmp2
#undef invz
#undef pz
#undef two
#define pz f8
#define tmp1 f9
#define tmp2 f10
#define invz f11
#define two f12
.globl _fn_inv
.align 8
_fn_inv::
orh ha%.C00068, r0, r31
fld.l l%.C00068(r31), two
frcp.ss pz, invz // invz = first guess
fmul.ss pz, invz, tmp2 // first guess * divisor
fsub.ss two, tmp2, tmp2 // 2.0 - (fg*d)
fmul.ss invz, tmp2, invz // 2nd guess
fmul.ss pz, invz, tmp2 // g2*d
fsub.ss two, tmp2, tmp2 // 2.0 - g2*d
bri r1
fmul.ss tmp2, invz, pz // 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
.about_to_xform::
.string "about to xform"
.byte 0x0
.xformed::
.string "xformed"
.byte 0x0
.projected::
.string "projected"
.byte 0x0
//}}}
//{{{ quad matrices
.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
//}}}