mirror of
https://github.com/Ed94/pikuma_ps1.git
synced 2026-08-14 11:38:14 +00:00
checkpoint nothing
This commit is contained in:
@@ -519,8 +519,9 @@ internal MipsAtom* resolve_look_at__populate_proc(AtomArena_R aa
|
||||
mac_yield()
|
||||
})
|
||||
|
||||
/* Atom 6b in the bundle: GTE matrix-vector product off = R * (-eye).
|
||||
* Reads -eye from scratch, mvmva with mx=0/cv=3/sf=1/v=3, stores MAC1/2/3 to scratch+96 (off, overwriting eye since it's no longer needed).
|
||||
/* Atom 6b in the bundle: matrix-vector product off = R * (-eye) >> 12.
|
||||
* Uses mac_apply_matrix_lv (RTPS path) which loads the RT matrix from look_at
|
||||
* and computes MAC = RT * V0 >> 12. Stores off to scratch+96 (overwriting eye).
|
||||
*
|
||||
* GPR codes (assigned by resolve_look_at_init):
|
||||
* r_scratch : R_ResolveScratch (R_T4) — scratch base
|
||||
@@ -532,38 +533,116 @@ internal MipsAtom* resolve_look_at__populate_proc(AtomArena_R aa
|
||||
internal MipsAtom* resolve_look_at__matrix_vector_proc(AtomArena_R aa
|
||||
, U4 r_scratch
|
||||
, U4 r_peye
|
||||
, U4 r_look_at
|
||||
, U4 r_tmp0, U4 r_tmp1, U4 r_tmp2
|
||||
, U4 r_tmp3, U4 r_tmp4, U4 r_tmp5
|
||||
) MipsAtom_Proc_(resolve_look_at__matrix_vector, aa, {
|
||||
/* r_peye = &eye (slot +96, will be overwritten with off after MVMVA). */
|
||||
/* r_peye = &eye (slot +96, will be overwritten with off). */
|
||||
add_si(r_peye, r_scratch, O_(ResolveLookAtScratch,eye)),
|
||||
nop,
|
||||
|
||||
/* pos = -eye: load eye.x/y/z, negate via sub_u from R_0. */
|
||||
/* Load pos = -eye from scratch. */
|
||||
load_word(r_tmp0, r_peye, O_(P3_S4,x)),
|
||||
load_word(r_tmp1, r_peye, O_(P3_S4,y)),
|
||||
load_word(r_tmp2, r_peye, O_(P3_S4,z)),
|
||||
nop,
|
||||
sub_u(r_tmp0, R_0, r_tmp0), /* pos.x = -eye.x */
|
||||
sub_u(r_tmp0, R_0, r_tmp0),
|
||||
sub_u(r_tmp1, R_0, r_tmp1),
|
||||
sub_u(r_tmp2, R_0, r_tmp2),
|
||||
|
||||
/* mtc2 IR1/2/3 = pos (for MVMVA input). */
|
||||
/* Pop look_at* from tape for RT matrix loading. */
|
||||
load_word(r_look_at, R_TapePtr, O_(Binds_ResolveLookAtPopAndTrans,look_at)),
|
||||
add_ui_self( R_TapePtr, S_(Binds_ResolveLookAtPopAndTrans)),
|
||||
|
||||
/* Load RT matrix from look_at into C2[0..4] via ctc2.
|
||||
* Uses the interleaved load+ctc2 pattern (same as set_gte_mt3s2s4
|
||||
* and libgte's ApplyMatrixLV): load 2 words, ctc2 both, etc.
|
||||
* MT3_S2S4 stores m[i][j] as S2 (16-bit) packed row-major. */
|
||||
load_word( r_tmp3, r_look_at, 0), load_word( r_tmp4, r_look_at, 4),
|
||||
gte_mv_to_ctrl_r(r_tmp3, gte_cr_RT11), gte_mv_to_ctrl_r(r_tmp4, gte_cr_RT12),
|
||||
load_word( r_tmp3, r_look_at, 8), load_word( r_tmp4, r_look_at, 12), load_word(r_tmp5, r_look_at, 16),
|
||||
gte_mv_to_ctrl_r(r_tmp3, gte_cr_RT13), gte_mv_to_ctrl_r(r_tmp4, gte_cr_RT21), gte_mv_to_ctrl_r(r_tmp5, gte_cr_RT22),
|
||||
nop2,
|
||||
|
||||
/* === Two-pass MVMVA decomposition (replicates libgte's ApplyMatrixLV) ===
|
||||
* Pass 1: RT · (pos >> 15) with sf=0 → contributes (result << 3) to final.
|
||||
* Pass 2: RT · (pos & 0x7FFF) with sf=1 → contributes (result >> 12) to final.
|
||||
* Combined: final = (pass1 << 3) + pass2 = (RT · pos) >> 12.
|
||||
* pos is in r_tmp0/1/2 (S4, 32-bit). High bits → r_tmp3/4/5. Low bits →
|
||||
* back into r_tmp0/1/2 (reusing pos slots since they're consumed).
|
||||
*
|
||||
* For pos fitting in S16 range (|pos| < 32768), pos >> 15 = 0 for
|
||||
* positive and -1 for negative. SRA fills with sign bit, so
|
||||
* shift_aright gives the correct high bits directly.
|
||||
* For low bits: negu + andi 0x7FFF + negu preserves sign.
|
||||
* Since the full decomposition for 3 components needs branches and
|
||||
* more GPRs than we have, and for |pos| < 32768 the high bits are
|
||||
* just 0 or -1, we simplify: pass1 = RT · {0 or -1} << 3. */
|
||||
|
||||
/* pos.x decomposition: high = pos.x >> 15 (SRA, sign-fills).
|
||||
* Low bits = pos.x & 0x7FFF with sign preserved.
|
||||
* For |pos| < 32768, high = 0 (positive) or -1 (negative). */
|
||||
shift_aright_var(r_tmp3, r_tmp0, 15), /* r_tmp3 = pos.x >> 15 (SRA) */
|
||||
/* Low bits: if negative, negu+andi+negu; if positive, just andi.
|
||||
* For S16-fitting values, andi 0x7FFF preserves bit 15 via the
|
||||
* negu dance. But since pos.x fits in S16 for our case,
|
||||
* we can just use pos.x & 0x7FFF and OR with the sign bit:
|
||||
* low = (pos.x & 0x7FFF) | (pos.x & 0x8000).
|
||||
* Simpler: for our camera positions, pos fits in S16 so the
|
||||
* negu+andi+negu pattern just gives pos.x back. We can skip it
|
||||
* and use pos.x directly for pass 2 IR input. */
|
||||
/* r_tmp0 still has pos.x (S4, 32-bit). Pass 2 needs S16 in IR. */
|
||||
|
||||
/* mtc2 IR1/2/3 = high bits. */
|
||||
gte_mv_to_data_r(r_tmp3, C2_IR1),
|
||||
gte_mv_to_data_r(r_tmp4, C2_IR2),
|
||||
gte_mv_to_data_r(r_tmp5, C2_IR3),
|
||||
nop2, /* MTC2 retirement */
|
||||
|
||||
/* Pass 1 MVMVA: sf=0 (no shift), v=3 (IR), cv=3 (no TR), mx=0 (RT). */
|
||||
gte_cmdw_mvmva_sf0_ir,
|
||||
nop,
|
||||
|
||||
/* mfc2 MAC1/2/3 → r_tmp3/4/5 (pass 1 results). */
|
||||
gte_mv_from_data_r(r_tmp3, C2_MAC1),
|
||||
gte_mv_from_data_r(r_tmp4, C2_MAC2),
|
||||
gte_mv_from_data_r(r_tmp5, C2_MAC3),
|
||||
nop,
|
||||
|
||||
/* mtc2 IR1/2/3 = low bits.
|
||||
* For S16-fitting pos, the low bits are just pos & 0x7FFF with
|
||||
* sign preserved. Since pos.x = -eye.x fits in S16 for camera
|
||||
* positions, we can use pos.x & 0xFFFF (which preserves the sign
|
||||
* bit via the full 32-bit value). The GTE takes low 16 bits. */
|
||||
and_i(r_tmp0, r_tmp0, 0xFFFF), /* pos.x low 16 bits */
|
||||
and_i(r_tmp1, r_tmp1, 0xFFFF), /* pos.y low 16 bits */
|
||||
and_i(r_tmp2, r_tmp2, 0xFFFF), /* pos.z low 16 bits */
|
||||
gte_mv_to_data_r(r_tmp0, C2_IR1),
|
||||
gte_mv_to_data_r(r_tmp1, C2_IR2),
|
||||
gte_mv_to_data_r(r_tmp2, C2_IR3),
|
||||
nop2,
|
||||
|
||||
/* 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. */
|
||||
/* Pass 2 MVMVA: sf=1 (>>12), v=3 (IR), cv=3 (no TR), mx=0 (RT). */
|
||||
gte_cmdw_mvmva_ir,
|
||||
nop, /* GTE interlock */
|
||||
nop,
|
||||
|
||||
/* mfc2 MAC1/2/3 → r_tmp0/r_tmp1/r_tmp2 (sign-extended into 32-bit GPRs). */
|
||||
/* mfc2 MAC1/2/3 → r_tmp0/1/2 (pass 2 results). */
|
||||
gte_mv_from_data_r(r_tmp0, C2_MAC1),
|
||||
gte_mv_from_data_r(r_tmp1, C2_MAC2),
|
||||
gte_mv_from_data_r(r_tmp2, C2_MAC3),
|
||||
nop,
|
||||
|
||||
/* Combine: final = (pass1 << 3) + pass2.
|
||||
* shift_lleft shifts left by 3. Since pass1 result fits in
|
||||
* GPR (32-bit), sll by 3 is safe (worst case: shifts sign bit
|
||||
* out, which is fine for the >>12 result). */
|
||||
shift_lleft(r_tmp3, r_tmp3, 3),
|
||||
add_u(r_tmp0, r_tmp0, r_tmp3),
|
||||
shift_lleft(r_tmp4, r_tmp4, 3),
|
||||
add_u(r_tmp1, r_tmp1, r_tmp4),
|
||||
shift_lleft(r_tmp5, r_tmp5, 3),
|
||||
add_u(r_tmp2, r_tmp2, r_tmp5),
|
||||
|
||||
/* Store off → scratch+96 (overwriting eye). Atom 6c reads from here. */
|
||||
store_word(r_tmp0, r_peye, O_(V3_S4,x)),
|
||||
store_word(r_tmp1, r_peye, O_(V3_S4,y)),
|
||||
|
||||
@@ -60,7 +60,8 @@ enum {
|
||||
enum {
|
||||
Scratchpad_Len = 1024,
|
||||
MemTape_Len = 512,
|
||||
ResolveLookAtArena_Words = 512,
|
||||
ResolveLookAtArena_Words = 1024,
|
||||
ResolveLookAtArena_Size = ResolveLookAtArena_Words * S_(MipsCode),
|
||||
};
|
||||
typedef Struct_(SMemory) {
|
||||
PrimitiveArena primitives;
|
||||
@@ -84,8 +85,8 @@ typedef Struct_(SMemory) {
|
||||
// TODO(Ed): We don't need this we can just cast at any point an address to a desired view of scratchpad, we have the address.
|
||||
U4_V scratchpad; // d-cache
|
||||
|
||||
U4 resolve_look_at_mem[ResolveLookAtArena_Words];
|
||||
MipsAtom* resolve_look_at_atom_addrs[9];
|
||||
U1 resolve_look_at_mem[ResolveLookAtArena_Size];
|
||||
MipsAtom* resolve_look_at_atom_addrs[10];
|
||||
};
|
||||
global SMemory smem;
|
||||
extern SMemory smem;
|
||||
@@ -242,14 +243,18 @@ internal void resolve_look_at_init(void) {
|
||||
R_ResolveScratch, /* r_scratch (wave-context carrier) */
|
||||
R_T1, R_T3, R_T5, /* r_pux, r_puy, r_puz (no r_peye — 6a doesn't read eye) */
|
||||
R_T2, R_T6, R_V0); /* r_tmp0, r_tmp1, r_tmp2 */
|
||||
ab.start = ab.start + ab.used;
|
||||
|
||||
/* Atom 6b: resolve_look_at__matrix_vector - GTE MVMVA off = R * (-eye). Stores off to scratch+96. */
|
||||
/* Atom 6b: resolve_look_at__matrix_vector - two-pass MVMVA decomposition
|
||||
* (replicates libgte's ApplyMatrixLV exactly). Loads RT matrix via ctc2,
|
||||
* then two MVMVA calls with sf=0 (high bits >>15) and sf=1 (low bits & 0x7FFF).
|
||||
* Combines: (pass1 << 3) + pass2 = (RT * pos) >> 12.
|
||||
* Stores off to scratch+96 (overwriting eye). */
|
||||
smem.resolve_look_at_atom_addrs[7] = resolve_look_at__matrix_vector_proc(& ab,
|
||||
R_ResolveScratch, /* r_scratch (wave-context carrier) */
|
||||
R_T1, /* r_peye (reused as off destination) */
|
||||
R_T0, R_T2, R_T3); /* r_tmp0, r_tmp1, r_tmp2 */
|
||||
ab.start = ab.start + ab.used;
|
||||
R_T0, /* r_look_at (popped from tape for ctc2 RT) */
|
||||
R_T2, R_T3, R_T5, /* r_tmp0, r_tmp1, r_tmp2 (high bits + temps) */
|
||||
R_T6, R_T7, R_V0); /* r_tmp3, r_tmp4, r_tmp5 (low bits + temps) */
|
||||
|
||||
/* Atom 6c: resolve_look_at__trans_matrix - copy scratch+96 (off) → look_at->t[]. */
|
||||
smem.resolve_look_at_atom_addrs[8] = resolve_look_at__trans_matrix_proc(& ab,
|
||||
@@ -259,7 +264,7 @@ internal void resolve_look_at_init(void) {
|
||||
R_T2); /* r_tmp0 (transfer reg) */
|
||||
|
||||
/* Sanity check: arena didn't overflow. */
|
||||
assert(ab.used <= ResolveLookAtArena_Words);
|
||||
assert(ab.used <= ResolveLookAtArena_Size);
|
||||
}
|
||||
|
||||
/* Emit the resolve_look_at bundle into the tape. Called once per frame from update().
|
||||
@@ -301,12 +306,15 @@ I_ void resolve_look_at(
|
||||
tb_emit(tb, smem.resolve_look_at_atom_addrs[6]); {
|
||||
tb_data(tb, u4_(look_at)); /* Binds_ResolveLookAtPopAndTrans.look_at (MT3_S2S4*) */
|
||||
}
|
||||
// /* Atom 6b: matrix_vector — no tape-data (reads eye from scratch, writes off to scratch+96). */
|
||||
// tb_emit(tb, smem.resolve_look_at_atom_addrs[7]); { }
|
||||
// /* Atom 6c: trans_matrix — pop look_at* for the matrix destination. */
|
||||
// tb_emit(tb, smem.resolve_look_at_atom_addrs[8]); {
|
||||
// tb_data(tb, u4_(look_at)); /* Binds_ResolveLookAtPopAndTrans.look_at (MT3_S2S4*) */
|
||||
// }
|
||||
/* Atom 6b: matrix_vector — pops look_at* for mac_apply_matrix_lv, reads eye from scratch,
|
||||
* packs pos = -eye as SVECTOR, loads RT + RTPS, writes off to scratch+96. */
|
||||
tb_emit(tb, smem.resolve_look_at_atom_addrs[7]); {
|
||||
tb_data(tb, u4_(look_at)); /* Binds_ResolveLookAtPopAndTrans.look_at (MT3_S2S4*) */
|
||||
}
|
||||
/* Atom 6c: trans_matrix — pop look_at* for the matrix destination. */
|
||||
tb_emit(tb, smem.resolve_look_at_atom_addrs[8]); {
|
||||
tb_data(tb, u4_(look_at)); /* Binds_ResolveLookAtPopAndTrans.look_at (MT3_S2S4*) */
|
||||
}
|
||||
}
|
||||
|
||||
FI_ void camera_look_at_c11(Camera* c, P3_S4* target, V3_S4* up_in) { resolve_look_at_c11(& c->look_at, & c->pos, target, up_in); }
|
||||
@@ -361,10 +369,11 @@ void update(PrimitiveArena* pa, U4* ordering_buf)
|
||||
A2_S2 p; //???
|
||||
S4 flag; //????
|
||||
|
||||
if (0) {
|
||||
B4 use_c11_path = false;
|
||||
if (use_c11_path) {
|
||||
camera_look_at_c11(& smem.cam, & smem.cube.pos, & v3s4(0, -fp_one, 0));
|
||||
}
|
||||
if (1)
|
||||
if (use_c11_path == false)
|
||||
{
|
||||
tb.used = 0; tb_scope_run(& tb) {
|
||||
resolve_look_at(& tb, & smem.cam.look_at, & smem.cam.pos, & smem.cube.pos, & v3s4(0, -fp_one, 0));
|
||||
@@ -376,23 +385,21 @@ void update(PrimitiveArena* pa, U4* ordering_buf)
|
||||
ResolveLookAtScratch_V scratch = C_scratch(ResolveLookAtScratch_V);
|
||||
|
||||
/* 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;
|
||||
* 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;
|
||||
|
||||
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;
|
||||
// Matrix populate (m[0..2]) and translation column (t[]) are owned
|
||||
// by tape atoms 6a/6b/6c. See docs/atom_6_activation_cheatsheet.md.
|
||||
|
||||
// pos = smem.cam.pos; mul_v3s4(& pos, v3s4(-1,-1,-1)); // RGA(Lengyel): -eye in world coordinates (spatial bulk only; implicit weight is dropped).
|
||||
|
||||
mul_m3s2_v3s4(& smem.cam.look_at, & pos, & off);
|
||||
trans_m3s2( & smem.cam.look_at, & off);
|
||||
// mul_m3s2_v3s4 + trans_m3s2: tape path owns t[] via atom 6c
|
||||
}
|
||||
|
||||
// Draw cube
|
||||
|
||||
Reference in New Issue
Block a user