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

2303 lines
16 KiB
ArmAsm

// nicked from output of PGC Rel 1.4 -opt 2
.text
.align 8
.text
//{{{ Heavy description
//
// DIVISION pxpl5 support code
//
// over and above the normal transform / light / clip, pxpl5
// requires triangles to be prepared for display by converting them
// into screen-space linear expressions. Both scan-conversion and shading
// information need to be so converted
//
// constructing linear expressions for scan-conversion is EDGIZing
// constructing linear expressions for shading is PLANARIZing
// putting triangles into 64x128 pixel bins is BINITIZing
//
// these are some optimized routines for edgizing, planarizing and
// binitizing
//
// it is clear that this software is just not fast enough when coded in C for
// 2 reasons - inefficient register usage (crap compiler) and excessive memory
// hits. Memory hits occur at function calls, where stack frames are moved
// and registers saved away to adhere to C calling conventions - lets trash
// the calling conventions (and make this undebuggable!)
//
// The functions below are very optimized to NEVER hit memory. The price
// we pay is that they are not directly callable in C - the C-callable
// code is in pxpl5tri.ss, and is a bunch of triangle functions, which
// save away volatile registers, chain together calls to these functions,
// then restore registers and return
//
// HOWEVER - note safe_binitize_fn, which every 256 triangles or so is forced
// to call some C, and which may under worst-case circumstances call malloc.
// dont be scared, it works
//
// depressing timings - the gayboy coding of planarize executes in 116 ticks,
// the steroid-laden version 73 ticks - this is for 32 fpu ops. So, I
// shall make this even worse, by introducing a zbuf_plus2_fn, which
// both z-buffers, AND planarizes 2 other functions at the same time. This
// can take advantage of the 3-ness of the i860 pipe by unrolling 3
// planarizations at once. It is also optimized for the PAZ primitive of
// z-buffer, luminance, specularity - using z-buffer, planar, planar I get
// 97k triangles/sec .. lets try to get 130k from zbuf_plus2_fn
//
// oh rats - the VERTEX and NORM_COL are now separated in memory - I need to
// pass in offset from Z, otherOffset from Z into z_buf_plus2
//
// define some useful registers, which are
// pointers to 4 vertices rv1 .. rv4
// 4 x coordinates fx1 .. fx4
// 4 y coordinates fy1 .. fy4
// 3 value coordinates fv1 .. fv3
// minimaxes fminx, fminy, fmaxx, fmaxy
// repeated expressions fx23, fx31, fx12, fC
//}}}
//
//
// integer registers first
//
//
//
//
//
// fp registers
//
//
// screen-space minimax for binitizing
// PASS NO FLOAT PARAMETERS IN HERE OR YOU ARE S T U F F E D
//
// x, y coords for tris/quads
// repeated expressions fx32, fx13, fx21, fC
// screen-space function values for planarizing
//{{{ some housekeeping code
//{{{ tex_scalefac
.globl _tex_scalefac
.align 8
_tex_scalefac::
//
// f8 , 2, 3 hold 3 z values - find which is biggest, scale
// it up to have no leading zeros, return scale factor (1.0, 2.0 etc)
// sign bit guaranteed not set
// z not yet munged by scale bits, so z in range 0.0 .. 1.0
// biggest test is easy - fxfr to integer registers,
// do integer compare to determine biggest
// extract exponent from biggest, all 3 zs
//
// use r31 to hold max, use int parameter registers as temporaries
//
// this would appear to take 16ish ticks
//
fxfr f8 , r16
fxfr f9 , r17
fxfr f10 , r18
subs r16 , r17 , r0
bc i2_gt_i1
subs r16 , r18 , r0
bnc.t igotmax
mov r16 , r31
br igotmax
mov r18 , r31
i2_gt_i1::
subs r17 , r18 , r0
bnc.t igotmax
mov r17 , r31
br igotmax
mov r18 , r31
igotmax::
//
// compute exponent difference between 0.999 and max
//
// dont worry, its just IEEE-754 - read the i860 databook
//
// warning - it may fall down in a heap if we ever give it
// a denormal, so just set the far clipping plane somewhere
// sensible - i will work out where
//
andh 0x7f80, r31, r31 // extract exponent of max
orh 0x7e80, r0, r16
subu r16 , r31, r31 // and we have magic
bri r1
ixfr r31, f8
//}}}
//{{{ _trunc_test ( int *truncy, float a, float b, float c )
.globl _trunc_test
.align 8
_trunc_test::
adds -64, sp, sp
fst.d f2, 0(sp)
fst.d f4, 8(sp)
fst.d f6, 16(sp)
fst.d f8, 24(sp)
st.l r4, 28(sp)
st.l r5, 32(sp)
st.l r6, 36(sp)
pftrunc.sd f8, f0
pftrunc.sd f9, f0
pftrunc.sd f10, f0
pfadd.sd f0, f0, f2
pfadd.sd f0, f0, f4
pfadd.sd f0, f0, f6
fxfr f2, r4
fxfr f4, r5
fxfr f6, r6
st.l r4, 0(r16)
st.l r5, 4(r16)
st.l r6, 8(r16)
fld.d 0(sp), f2
fld.d 8(sp), f4
fld.d 16(sp), f6
fld.d 24(sp), f8
ld.l 28(sp), r4
ld.l 32(sp), r5
ld.l 36(sp), r6
bri r1
adds 64, sp, sp
//}}}
//{{{ give_fp returns value of frame pointer
.globl _give_fp
.align 8
// binitize a primitive
_give_fp::
bri r1
addu r0, r3, r16
//}}}
//{{{ give_stepping
.globl _give_stepping
.align 8
_give_stepping::
ld.c epsr, r16
shr 8, r16, r16
bri r1
and 0x1f, r16, r16
//}}}
//{{{ give_860type
.globl _give_860type
.align 8
_give_860type::
ld.c epsr, r16
bri r1
and 0xff, r16, r16
//}}}
//}}}
//
// these are the function prototypes
//
// extern void preplanarize_fn ( float *coeffs, VERTEX *v1, VERTEX *v2, VERTEX *v3, VERTEX *v4 );
// extern void edgize_tri_fn ( void );
// extern void edgize_quad_fn ( void );
// extern void zbuffer_fn ( void );
// extern void zb_plus2_fn ( void );
// extern void planarize_fn ( int pp5_opcode, int index );
// extern void binitize_fn ( int macro_lo, int macro_hi,
// int scrmaxx, int scrmaxy, int scrbinsx )
// extern void safe_binitize_fn ( int macro_lo, int macro_hi, int scrbinsx )
//
//{{{ fsr access
// .globl _getFsr
// .align 8
//_getFsr::
// bri r1
// ld.c fsr, r16
//
//
// .globl _setFsr
// .align 8
//_setFsr::
// bri r1
// st.c r16, fsr
//}}}
//{{{ _reg_dump
.globl _reg_dump
.align 8
_reg_dump::
//{{{ proc entry - save r1 r2 r3
addu -256, sp, sp
st.l r1,0(sp)
adds 256,sp,r1
// save r2 **before** call into stack frame
st.l r1,4(sp)
st.l fp,8(sp)
//}}}
//{{{ save r4..r31, f2..f31
st.l r4, 12(sp)
st.l r5, 16(sp)
st.l r6, 20(sp)
st.l r7, 24(sp)
st.l r8, 28(sp)
st.l r9, 32(sp)
st.l r10, 36(sp)
st.l r11, 40(sp)
st.l r12, 44(sp)
st.l r13, 48(sp)
st.l r14, 52(sp)
st.l r15, 56(sp)
st.l r16, 60(sp)
//st.l r17, 64(sp)
st.l r18, 68(sp)
st.l r19, 72(sp)
st.l r20, 76(sp)
st.l r21, 80(sp)
st.l r22, 84(sp)
st.l r23, 88(sp)
st.l r24, 92(sp)
st.l r25, 96(sp)
st.l r26, 100(sp)
st.l r27, 104(sp)
st.l r28, 108(sp)
st.l r29, 112(sp)
st.l r30, 116(sp)
st.l r31, 120(sp)
adds 120, sp, sp
fst.l f2, 4(sp)++
fst.l f3, 4(sp)++
fst.l f4, 4(sp)++
fst.l f5, 4(sp)++
fst.l f6, 4(sp)++
fst.l f7, 4(sp)++
fst.l f8, 4(sp)++
fst.l f9, 4(sp)++
fst.l f10, 4(sp)++
fst.l f11, 4(sp)++
fst.l f12, 4(sp)++
fst.l f13, 4(sp)++
fst.l f14, 4(sp)++
fst.l f15, 4(sp)++
fst.l f16, 4(sp)++
fst.l f17, 4(sp)++
fst.l f18, 4(sp)++
fst.l f19, 4(sp)++
fst.l f20, 4(sp)++
fst.l f21, 4(sp)++
fst.l f22, 4(sp)++
fst.l f23, 4(sp)++
fst.l f24, 4(sp)++
fst.l f25, 4(sp)++
fst.l f26, 4(sp)++
fst.l f27, 4(sp)++
fst.l f28, 4(sp)++
fst.l f29, 4(sp)++
fst.l f30, 4(sp)++
fst.l f31, 4(sp)++
adds -240, sp, sp
//}}}
call _trace_regs
mov sp, r16
//{{{ restore all
ld.l 12(sp) , r4
ld.l 16(sp) , r5
ld.l 20(sp) , r6
ld.l 24(sp) , r7
ld.l 28(sp) , r8
ld.l 32(sp) , r9
ld.l 36(sp) , r10
ld.l 40(sp) , r11
ld.l 44(sp) , r12
ld.l 48(sp) , r13
ld.l 52(sp) , r14
ld.l 56(sp) , r15
ld.l 60(sp) , r16
ld.l 64(sp) , r17
ld.l 68(sp) , r18
ld.l 72(sp) , r19
ld.l 76(sp) , r20
ld.l 80(sp) , r21
ld.l 84(sp) , r22
ld.l 88(sp) , r23
ld.l 92(sp) , r24
ld.l 96(sp) , r25
ld.l 100(sp) , r26
ld.l 104(sp) , r27
ld.l 108(sp) , r28
ld.l 112(sp) , r29
ld.l 116(sp) , r30
ld.l 120(sp) , r31
adds 120, sp, sp
fld.l 4(sp)++, f2
fld.l 4(sp)++, f3
fld.l 4(sp)++, f4
fld.l 4(sp)++, f5
fld.l 4(sp)++, f6
fld.l 4(sp)++, f7
fld.l 4(sp)++, f8
fld.l 4(sp)++, f9
fld.l 4(sp)++, f10
fld.l 4(sp)++, f11
fld.l 4(sp)++, f12
fld.l 4(sp)++, f13
fld.l 4(sp)++, f14
fld.l 4(sp)++, f15
fld.l 4(sp)++, f16
fld.l 4(sp)++, f17
fld.l 4(sp)++, f18
fld.l 4(sp)++, f19
fld.l 4(sp)++, f20
fld.l 4(sp)++, f21
fld.l 4(sp)++, f22
fld.l 4(sp)++, f23
fld.l 4(sp)++, f24
fld.l 4(sp)++, f25
fld.l 4(sp)++, f26
fld.l 4(sp)++, f27
fld.l 4(sp)++, f28
fld.l 4(sp)++, f29
fld.l 4(sp)++, f30
fld.l 4(sp)++, f31
adds -240, sp, sp
//}}}
//{{{ proc exit
ld.l 0(sp),r1
ld.l 8(sp),fp
bri r1
addu 256, sp, sp
//}}}
//}}}
// constant for 1/x code
.data
.align 8
.Cmax_x: // (0)
.C640:
.long 0x442fbf5c // 7.02989990E+02
.Cmax_y: // (0)
.C480:
.long 0x43ff7eb8 // 5.10989990E+02
.C00037: // (0)
.long 0x40000000 // 2.00000000E+00
.C362436: // (0)
.long 0x3ecccccd // 4.00000006E-01
.Czscale1024: // (0)
.long 0x49800000 // 1.04857600E+06
.Czscale: // (0)
.long 0x497fffff // 1.04857588E+06
.Ctexscale: // (0)
.long 0x477fffff // 6.55359883E+04
.tri_entry:
.string "triangle entry"
.byte 0x0
.tri_preplanarize:
.string "preplanarize"
.byte 0x0
.tri_edgeized:
.string "edgized triangle"
.byte 0x0
.tri_zbufized:
.string "zbuffered triangle"
.byte 0x0
.tri_planarized:
.string "planarized something"
.byte 0x0
.preplane_gotc:
.string "halfway thru preplane"
.byte 0x0
.plane_loadedvs:
.string "planarize - have loaded fv1 etc."
.byte 0x0
.bini_full:
.string "bin full"
.byte 0x0
.bini_doneminimax:
.string "binitize, done minimax"
.byte 0x0
.bini_notfull:
.string "bin not full"
.byte 0x0
.bini_start:
.string "bin start binitize"
.byte 0x0
.bini_minimax:
.string "bin got minimaxes"
.byte 0x0
.bini_endfull:
.string "end of bin full"
.byte 0x0
.bini_more_x:
.string "more than 1 x-bin"
.byte 0x0
.bini_more_y:
.string "more than 1 y-bin"
.byte 0x0
.bini_x_loop:
.string "x-loop in binitize"
.byte 0x0
.bini_check_usage:
.string "check usage count"
.byte 0x0
.r5r6r7opcodes:
.string "r5 r6 r7 have opcodes?"
.byte 0x0
.bini_pipe_minimax:
.string "computed minimax piped"
.byte 0x0