diff --git a/code/duffle/gen/macs.h b/code/duffle/gen/macs.h index 0123d30..2b2c4eb 100644 --- a/code/duffle/gen/macs.h +++ b/code/duffle/gen/macs.h @@ -199,13 +199,9 @@ WORD_COUNT(mac_gte_gpf_scale, 13) , gte_lw(C2_VXY0, r_vec, 0) \ , load_word(r_t0, r_vec, 4) \ , nop \ -, gte_lw(C2_VZ0, r_vec, 4) /* RTPS cv=3 (no translation contribution: TRX/TRY/TRZ are zeroed, BK is zero-initialized), - * sf=1 (integer, no shift = full 32-bit R*pos product), v=0 (uses V0 input), mx=0 (rotation matrix). - * MAC1 = RT11*V0.x + RT12*V0.y + RT13*V0.z + 0 - * MAC2 = RT21*V0.x + RT22*V0.y + RT23*V0.z + 0 - * MAC3 = RT31*V0.x + RT32*V0.y + RT33*V0.z + 0 - * Side effect: RTPS also writes SXY0/1/2 and SZ0..SZ3 (perspective projection). Ignored. - * Note: gte_cmdw_rtps_no_tr (the cv=3 alias) was removed from gte.h. Use gte_cmdw_rtps_sf1. */ \ +, gte_lw(C2_VZ0, r_vec, 4) /* RTPS: cv=3 (no translation), sf=1 (no shift, integer), v=0 (V0 input), + * mx=0 (rotation matrix). MAC = RT row · V0 + 0. RTPS also writes + * SXY0/1/2 + SZ0..SZ3 (perspective division); ignored. */ \ , gte_cmdw_rtps_sf1 /* Read MAC1/2/3 → out. */ \ , gte_mv_from_data_r(r_t0, C2_MAC1) \ , gte_mv_from_data_r(r_t1, C2_MAC2) \ diff --git a/code/duffle/gte.atom.c b/code/duffle/gte.atom.c index c278b65..0e8bfda 100644 --- a/code/duffle/gte.atom.c +++ b/code/duffle/gte.atom.c @@ -126,13 +126,9 @@ FI_ Slice_MipsCode ac_apply_matrix_lv(AtomBuilder_R ab load_word(r_t0, r_vec, 4), nop, gte_lw(C2_VZ0, r_vec, 4), - /* RTPS cv=3 (no translation contribution: TRX/TRY/TRZ are zeroed, BK is zero-initialized), - * sf=1 (integer, no shift = full 32-bit R*pos product), v=0 (uses V0 input), mx=0 (rotation matrix). - * MAC1 = RT11*V0.x + RT12*V0.y + RT13*V0.z + 0 - * MAC2 = RT21*V0.x + RT22*V0.y + RT23*V0.z + 0 - * MAC3 = RT31*V0.x + RT32*V0.y + RT33*V0.z + 0 - * Side effect: RTPS also writes SXY0/1/2 and SZ0..SZ3 (perspective projection). Ignored. - * Note: gte_cmdw_rtps_no_tr (the cv=3 alias) was removed from gte.h. Use gte_cmdw_rtps_sf1. */ + /* RTPS: cv=3 (no translation), sf=1 (no shift, integer), v=0 (V0 input), + * mx=0 (rotation matrix). MAC = RT row · V0 + 0. RTPS also writes + * SXY0/1/2 + SZ0..SZ3 (perspective division); ignored. */ gte_cmdw_rtps_sf1, /* Read MAC1/2/3 → out. */ @@ -266,7 +262,7 @@ internal S2 const gte_normalize_sqr_tbl[192] align_(2) = { * Pipeline: clobbers IR0..3, MAC1..3, LZCS, LZCR. */ /* MipsAtom_Proc_ wrapper: declares the static MipsCode[] body, then calls atombuilder_unroll(ab, ...) to copy the encoded instructions into the caller's MipsAtomBuilder arena. */ -I_ MipsAtom* normalize_v3s4_proc(AtomArena_R aa, U4 r_scratch /* GPR code: scratch base carrier (e.g., R_T4 = R_ResolveScratch) */ +internal MipsAtom* normalize_v3s4_proc(AtomArena_R aa, U4 r_scratch /* GPR code: scratch base carrier (e.g., R_T4 = R_ResolveScratch) */ , U4 r_src_offset, U4 r_dst_offset /* GPR codes: PARAMETERIZED offsets (caller passes O_ macros) */ , U4 r_src_ptr, U4 r_dst_ptr, U4 r_tmp /* GPR codes: 3 scratch regs (src/dst computed + tmp) */ , U4 r_mac1_scratch, U4 r_mac2_scratch /* GPR codes: 2 more: MAC1/MAC2 scratch */ diff --git a/code/duffle/lottes_tape.h b/code/duffle/lottes_tape.h index c0a9e71..be5c64e 100644 --- a/code/duffle/lottes_tape.h +++ b/code/duffle/lottes_tape.h @@ -23,7 +23,7 @@ * directly executed chain of assemby arrays (Atoms) that terminate with a yield sequence to the next atom. * These eventually lead to a terminal atom for the tape which is defined below as "tape_exit". * - * This behaves as one of the simplest runtime harnesses ontop of a host-enviornment's execution engine + * It behaves as one of the simplest runtime harnesses ontop of a host-enviornment's execution engine * to author and compose programs with. From here various conventions can be further applied. * To make things easier to understand it may be better to focus on what this ABI does not have. * It does not have have any branching within the tape but relative branches within atoms or between atoms. @@ -42,7 +42,7 @@ * automatic register allocation means the user cannot ignore excessive argument shuffle across workload or * waves and thier phases. Crossing ABI boundaries to other runtimes that do has obviouss penalties. * - * Learning data-oreinted code becomes a natural progression. Your not fighting a stack-based procedural + * Learning data-oriented code becomes a natural progression. Your not fighting a stack-based procedural * paradigm that wants to argument shuffle. There is no ambiguity due to the lack of constraints, for example, * on how the user may "call" a procedure in traditional random dispatch runtimes. The user does have to * hammer down "rules" or patterns for massaging the compiler to dissolve those call frames; just to get diff --git a/code/hello_camera/hello_camera.atom.c b/code/hello_camera/hello_camera.atom.c index 9718ecf..3eaa413 100644 --- a/code/hello_camera/hello_camera.atom.c +++ b/code/hello_camera/hello_camera.atom.c @@ -36,7 +36,7 @@ MipsAtomComp_Proc_(ac_put_disp_env, ab, { mac_gcmd_push(gp0_word_draw_area_bottom_right_320x240, reg_transfer, reg_base, port), }) -FI_ Slice_MipsCode ac_put_draw_env(AtomBuilder_R ab, U4 reg_transfer, U4 reg_base, U2 port) +I_ Slice_MipsCode ac_put_draw_env(AtomBuilder_R ab, U4 reg_transfer, U4 reg_base, U2 port) MipsAtomComp_Proc_(ac_put_draw_env, ab, { /* * ORIGIN: each code word corresponds to the EXACT value libpsyx's PutDrawEnv function would compute for the same DrawEnv settings. @@ -221,7 +221,7 @@ typedef Struct_(Binds_ResolveLookAtSub) { * * Pool cost: 8 GPRs + R_T4 (carrier) + R_AT + R_V0 (hardcoded) = 11 GPRs. */ -I_ MipsAtom* resolve_look_at__input_and_sub_proc(AtomArena_R aa, U4 r_scratch +internal MipsAtom* resolve_look_at__input_and_sub_proc(AtomArena_R aa, U4 r_scratch , U4 r_target_ptr,U4 r_eye_ptr, U4 r_up_in_ptr , U4 r_tmp0, U4 r_tmp1, U4 r_tmp2, U4 r_tmp3 ) MipsAtom_Proc_(resolve_look_at__input_and_sub, aa, { @@ -288,7 +288,7 @@ I_ MipsAtom* resolve_look_at__input_and_sub_proc(AtomArena_R aa, U4 r_scratch */ /* Atom 2: cross uz × up_in → right. */ -I_ MipsAtom* resolve_look_at__cross_uz_up_in_to_right_proc(AtomArena_R aa, U4 r_scratch +internal MipsAtom* resolve_look_at__cross_uz_up_in_to_right_proc(AtomArena_R aa, U4 r_scratch , U4 r_a, U4 r_b, U4 r_c /* load a.x/y/z; result out.x/y/z */ , U4 r_d /* load b.x */ , U4 r_f, U4 r_g, U4 r_h /* r_f = &right (out ptr), r_g = &uz, r_h = &up_in */ @@ -372,7 +372,7 @@ I_ MipsAtom* resolve_look_at__cross_uz_up_in_to_right_proc(AtomArena_R aa, U4 r_ }) /* Atom 4: cross uz × ux → up. */ -I_ MipsAtom* resolve_look_at__cross_uz_ux_to_up_proc(AtomArena_R aa, U4 r_scratch +internal MipsAtom* resolve_look_at__cross_uz_ux_to_up_proc(AtomArena_R aa, U4 r_scratch , U4 r_a, U4 r_b, U4 r_c /* load a.x/y/z; result out.x/y/z */ , U4 r_d /* load b.x */ , U4 r_f, U4 r_g, U4 r_h /* r_f = &up (out ptr), r_g = &uz, r_h = &ux */ @@ -395,13 +395,9 @@ I_ MipsAtom* resolve_look_at__cross_uz_ux_to_up_proc(AtomArena_R aa, U4 r_scratc load_word(R_V0, r_h, O_(V3_S4,z)), nop, - /* FIX 2026-08-11: OP reads D1/D2/D3 from RT11/RT22/RT33 control registers - * ($0/$2/$4), NOT from V0/V1/V2 input data registers. The previous body - * wrote ux to C2_VXY0/VZ0/VXY1 — D1/D2/D3 were whatever stale RT values - * the previous atom left, so the GTE computed garbage MAC values. Fix: - * mirror atom 1's pattern (cfc2 RT11/RT22 save + ctc2 RT13/RT22/RT11 - * load uz diagonal + mtc2 IR1/2/3 load ux + ctc2 RT restore). - * See SESSION_2026-08-11b §5.2 for the empirical verification. */ + /* OP reads D1/D2/D3 from RT11/RT22/RT33 ($0/$2/$4), not V0/V1/V2. + * Mirror atom 1: cfc2 RT save, ctc2 RT diagonal from uz, mtc2 IR from ux, + * ctc2 RT restore. */ /* Save the two RT control-register slots OP will clobber (reusing * r_g/r_h — they're no longer needed as scratch pointers). */ @@ -472,7 +468,7 @@ typedef Struct_(Binds_ResolveLookAtPopAndTrans) { * MVMVA computes R * pos (with cv=0/mx=0/sf=0/v=0); MAC1/2/3 = R * (-eye). * Pool cost: r_look_at (1) + r_scratch (R_T4 carrier) + 4 ptr regs + 3 tmp regs = 9 GPRs. */ -I_ MipsAtom* resolve_look_at__populate_proc(AtomArena_R aa +internal MipsAtom* resolve_look_at__populate_proc(AtomArena_R aa , U4 r_look_at , U4 r_scratch , U4 r_pux, U4 r_puy, U4 r_puz @@ -533,7 +529,7 @@ I_ MipsAtom* resolve_look_at__populate_proc(AtomArena_R aa * * Pool cost: r_scratch (carrier) + 1 ptr reg + 3 tmp regs = 5 GPRs. */ -I_ MipsAtom* resolve_look_at__matrix_vector_proc(AtomArena_R aa +internal MipsAtom* resolve_look_at__matrix_vector_proc(AtomArena_R aa , U4 r_scratch , U4 r_peye , U4 r_tmp0, U4 r_tmp1, U4 r_tmp2 @@ -557,11 +553,8 @@ I_ MipsAtom* resolve_look_at__matrix_vector_proc(AtomArena_R aa gte_mv_to_data_r(r_tmp2, C2_IR3), nop2, - /* MVMVA sf=1 (no shift = integer), cv=3 (no TR), mx=0 (rotation matrix), v=3 (IR vector). - * The pre-set rotation matrix is the one set by the preceding set_gte_world atom. - * NOTE: For R*pos >> 12 byte-for-byte match with C11's ApplyMatrixLV, would need sf=0 - * (4.12 fixed-point shift). Plain gte_cmdw_mvmva defaults to sf=0 — use that for VRAM match. - * Per SESSION_2026-08-12 §6 this is a known gap. */ + /* MVMVA: sf=1 (integer, no shift), cv=3 (no TR), mx=0 (rotation matrix), + * v=3 (IR vector). Pre-set rotation matrix is the one set by set_gte_world. */ gte_cmdw_mvmva_ir, nop, /* GTE interlock */ @@ -604,7 +597,7 @@ I_ MipsAtom* resolve_look_at__trans_matrix_proc(AtomArena_R aa add_si(r_off_ptr, r_scratch, O_(ResolveLookAtScratch,eye)), nop, - /* mac_trans_matrix(r_look_at, r_off_ptr, r_tmp0) — uses r_tmp0 as the transfer reg. */ + /* Copy off → look_at.t[] (mac_trans_matrix: m->t = v). */ mac_trans_matrix(r_look_at, r_off_ptr, r_tmp0), mac_yield() diff --git a/code/hello_camera/hello_camera.c b/code/hello_camera/hello_camera.c index 8ae5a61..e3cae3a 100644 --- a/code/hello_camera/hello_camera.c +++ b/code/hello_camera/hello_camera.c @@ -103,8 +103,7 @@ I_ B1* prim__alloc(U4 type_width, Str8 type_name) { } #define prim_alloc(type) (type*)prim__alloc(S_(type), slit( stringify(type))) -void -resolve_look_at_c11(MT3_S2S4* look_at, P3_S4* eye, P3_S4* target, V3_S4* up_in) { +I_ void resolve_look_at_c11(MT3_S2S4* look_at, P3_S4* eye, P3_S4* target, V3_S4* up_in) { // RGA(Lengyel): Build matrix expansion of a rigid transformation. Corresponding motor is not constructed; we write the LA form for GTE. // Preconditions: eye != target, up_in not collinear with (target - eye). V3_S4 right, up, forward; @@ -376,20 +375,19 @@ void update(PrimitiveArena* pa, U4* ordering_buf) ResolveLookAtScratch_V scratch = C_scratch(ResolveLookAtScratch_V); - // Atom 0: Works (tape emits fwd to scratch+0; C-side reads it back) - forward = scratch->fwd; - uz = scratch->uz; - right = scratch->right; - ux = scratch->ux; - up = scratch->up; // ← atom 4's output (replaces C-side cross_v3s4) - uy = scratch->uy; // ← atom 5's output (replaces C-side normalize_v3s4) + /* Atoms 0-5 emit into scratch; bundle dispatch for atom 6 is still + * commented at the resolve_look_at_init helper. Until atom 6 is + * enabled, populate look_at.m[][] from the wave-context outputs. */ + forward = scratch->fwd; + uz = scratch->uz; + right = scratch->right; + ux = scratch->ux; + up = scratch->up; + uy = scratch->uy; - // cross_v3s4(& uz, & ux, & up); normalize_v3s4(& up, & uy); - - // Atom 6 not yet enabled: populate look_at.m[][] from ux/uy/uz here. - // smem.cam.look_at.m[0][0] = ux.x; smem.cam.look_at.m[0][1] = ux.y; smem.cam.look_at.m[0][2] = ux.z; - // smem.cam.look_at.m[1][0] = uy.x; smem.cam.look_at.m[1][1] = uy.y; smem.cam.look_at.m[1][2] = uy.z; - // smem.cam.look_at.m[2][0] = uz.x; smem.cam.look_at.m[2][1] = uz.y; smem.cam.look_at.m[2][2] = uz.z; + smem.cam.look_at.m[0][0] = ux.x; smem.cam.look_at.m[0][1] = ux.y; smem.cam.look_at.m[0][2] = ux.z; + smem.cam.look_at.m[1][0] = uy.x; smem.cam.look_at.m[1][1] = uy.y; smem.cam.look_at.m[1][2] = uy.z; + smem.cam.look_at.m[2][0] = uz.x; smem.cam.look_at.m[2][1] = uz.y; smem.cam.look_at.m[2][2] = uz.z; // pos = smem.cam.pos; mul_v3s4(& pos, v3s4(-1,-1,-1)); // RGA(Lengyel): -eye in world coordinates (spatial bulk only; implicit weight is dropped).