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

744 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
#define cr m30
#define cg m31
#define cb m32
#define surfr f30
#define surfg f31
#define surfb f29
// for transforming
#define tmp1 f30
#define tmp2 f31
//}}}
//{{{ 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)
#define lightcol_offs (9*4)
#define light_type_offs (12*4)
// fields in material structure
#define specular_table_offs (11*4)
#define surf_kd_offs (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
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::
fld.d 48(quad_m), m30 // 2
fld.l 56(quad_m), m32 // 2
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
orh ha%_ambientR, r0, r31 // 1
mov blondie, bulb
fld.l (norm_offs+8)(light_v), nz
or l%_ambientR, r31, r31 // 2
fld.d 0(r31), cr
fld.l 8(r31), cb
pfmul.ss normfactor, nx, f0
pfmul.ss normfactor, ny, f0
pfmul.ss normfactor, nz, f0
pfmul.ss f0, f0, nx
pfmul.ss f0, f0, ny
pfmul.ss f0, f0, nz
// for (bulb=blondie; bulb; bulb=bulb->next ) {
bte 0x0, bulb, .lighting_done
//
// need to compute
// fdot=(nx*lx) + (ny*ly) + (nz*lz);
//
fld.l (xformpos_offs+0)(bulb), lx
.next_bulb::
fld.l (xformpos_offs+4)(bulb), ly
fld.l (xformpos_offs+8)(bulb), lz
.align 8
pfmul.ss nx, lx, f0
pfmul.ss ny, ly, f0 // pipeline states AFTER this instruction
pfmul.ss nz, lz, f0 // nlz nly nlx ? ? ? ?
r2ap1.ss f0, f0, f0 // nx.lx into T
r2pt.ss f0, f0, f0 // adder 1 = nx.lx + ny.ly
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, fdot
pfgt.ss fdot, f0, f0
bnc .no_diffuse
fld.l (lightcol_offs)(bulb), surfr
fld.l (lightcol_offs+4)(bulb), surfg
fld.l (lightcol_offs+8)(bulb), surfb
pfmul.ss fdot, surfr, f0
pfmul.ss fdot, surfg, f0
pfmul.ss fdot, surfb, f0
mr2p1.ss cr, f0, f0
mr2p1.ss cg, f0, f0
mr2p1.ss cb, f0, f0
pfadd.ss f0, f0, cr
pfadd.ss f0, f0, cg
pfadd.ss f0, f0, cb
// indirect off bulb next field
.no_diffuse::
ld.l r0(bulb), bulb
xor r0, bulb, r0
bnc.t .next_bulb
fld.l (xformpos_offs+0)(bulb), lx
// cr, cg, cb hold the accumulated light r g bs
// now multiply by surface colour
ixfr two_fifty_six, fdot
fld.l (surf_kd_offs)(surf), surfr
fld.l (surf_kd_offs+4)(surf), surfg
fld.l (surf_kd_offs+8)(surf), surfb
pfmul.ss fdot, surfr, f0
pfmul.ss fdot, surfg, f0
pfmul.ss fdot, surfb, f0
pfmul.ss f0, f0, surfr
pfmul.ss cr, surfr, surfg
pfmul.ss cg, surfg, surfb
pfmul.ss cb, surfb, f0
pfmul.ss f0, f0, cr
pfmul.ss f0, f0, cg
pfmul.ss f0, f0, cb
fst.l cr, (normcol_offs)(light_v) // 1
fst.l cg, (4+normcol_offs)(light_v) // 1
fst.l cb, (8+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
// .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
//}}}