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