.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 //}}}