This commit is contained in:
ed
2026-08-12 20:09:57 -04:00
parent 7807047dc0
commit 9b6b5535f5
4 changed files with 152 additions and 2 deletions
+54
View File
@@ -175,6 +175,60 @@ WORD_COUNT(mac_gte_sqr_v3, 8)
, shift_aright_var(r_dz, r_dz, r_shift)
WORD_COUNT(mac_gte_gpf_scale, 13)
#define mac_apply_matrix_lv(r_mtx, r_vec, r_out, r_t0, r_t1, r_t2) \
load_word(r_t0, r_mtx, 0) \
, nop \
, gte_mv_to_ctrl_r(r_t0, gte_cr_RT11_Code) \
, load_word(r_t0, r_mtx, 4) \
, nop \
, gte_mv_to_ctrl_r(r_t0, gte_cr_RT12_Code) \
, load_word(r_t0, r_mtx, 8) \
, nop \
, gte_mv_to_ctrl_r(r_t0, gte_cr_RT13_Code) \
, load_word(r_t0, r_mtx, 12) \
, nop \
, gte_mv_to_ctrl_r(r_t0, gte_cr_RT21_Code) \
, load_half_u(r_t0, r_mtx, 16) \
, nop \
, gte_mv_to_ctrl_r(r_t0, gte_cr_RT22_Code) \
, nop2 /* Load PACKED pos into V0 (libgte SVECTOR layout).
* r_vec points to atom-0-staged packed data ((pos.y << 16) | pos.x at +0, pos.z at +4).
* LWC2 base register MUST be the pointer r_vec, NOT the loaded value r_t0. */ \
, load_word(r_t0, r_vec, 0) \
, nop \
, gte_lw(C2_VXY0, r_vec, 0) \
, load_word(r_t0, r_vec, 4) \
, nop \
, gte_lw(C2_VZ0, r_vec, 4) /* RTPS cv=1 (no translation accumulation; BK is zero-initialized), sf=0, v=0, mx=0.
* 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. */ \
, gte_cmdw_rtps_no_tr /* Read MAC1/2/3 → out. */ \
, gte_mv_from_data_r(r_t0, C2_MAC1) \
, gte_mv_from_data_r(r_t1, C2_MAC2) \
, gte_mv_from_data_r(r_t2, C2_MAC3) \
, nop \
, store_word(r_t0, r_out, 0) \
, store_word(r_t1, r_out, 4) \
, store_word(r_t2, r_out, 8)
WORD_COUNT(mac_apply_matrix_lv, 31)
#define mac_trans_matrix(r_mtx, r_off, r_t0, r_t1) \
load_word(r_t0, r_mtx, O_(MT3_S2S4,t[0])) \
, load_word(r_t1, r_off, O_(V3_S4,x)) \
, add_u(r_t0, r_t0, r_t1) \
, store_word(r_t0, r_mtx, O_(MT3_S2S4,t[0])) \
, load_word(r_t0, r_mtx, O_(MT3_S2S4,t[1])) \
, load_word(r_t1, r_off, O_(V3_S4,y)) \
, add_u(r_t0, r_t0, r_t1) \
, store_word(r_t0, r_mtx, O_(MT3_S2S4,t[1])) \
, load_word(r_t0, r_mtx, O_(MT3_S2S4,t[2])) \
, load_word(r_t1, r_off, O_(V3_S4,z)) \
, add_u(r_t0, r_t0, r_t1) \
, store_word(r_t0, r_mtx, O_(MT3_S2S4,t[2]))
WORD_COUNT(mac_trans_matrix, 12)
#define mac_gcmd_push(cmd, reg_transfer, reg_base, port) \
load_upper_i(reg_transfer, u4_hi(cmd)) \
, or_i_self( reg_transfer, u4_lo(cmd)) /* load_upper_i(reg_transfer, cmd >> 16), // or_i_self( reg_transfer, cmd & 0xFFFF), */ \
+84
View File
@@ -83,6 +83,90 @@ FI_ Slice_MipsCode ac_gte_gpf_scale(AtomBuilder_R ab, U4 r_sx, U4 r_sy, U4 r_sz,
shift_aright_var(r_dz, r_dz, r_shift),
})
/* ─── APPLY MATRIX LV (libgte ApplyMatrixLV port) ───
* Atom component — auto-generates mac_apply_matrix_lv Mac composer macro.
* Uses GTE RTPS (cv=1, sf=1, v=0) with lwc2-loaded V0/VZ0 inputs.
* Per PSX-SPX `geometrytransformationenginegte.md` lines 416-418:
* IR1 = MAC1 = (TRX*1000h + RT11*VX0 + RT12*VY0 + RT13*VZ0) SAR (sf*12)
* IR2 = MAC2 = (TRY*1000h + RT21*VX0 + RT22*VY0 + RT23*VZ0) SAR (sf*12)
* IR3 = MAC3 = (TRZ*1000h + RT31*VX0 + RT32*VY0 + RT33*VZ0) SAR (sf*12)
* RTPS uses the FULL row of the rotation matrix (not just diagonal like MVMVA with mx=0).
* libgte's `gte_ApplyMatrix` calls `gte_rtv0()` = RTPS cv=1 v=0 mx=0.
* Per `gte.h` line 405 the body sets cv=3 (BK, zero-initialized) so no TR contribution.
*
* Operands:
* r_mtx : MT3_S2S4* (matrix pointer)
* r_vec : U4 (pointer to PACKED V0 data — (pos.y << 16) | pos.x at +0, pos.z at +4)
* r_out : V3_S4* (output pointer; MAC1/2/3 stored here)
* r_t0/1/2 : 3 GPR codes for matrix load + intermediate state
* Words: ~26. Clobbers: r_t0, r_t1, r_t2 (C2 $0..$4, VXY0/VZ0, MAC1/2/3, SXY0/1/2). */
FI_ Slice_MipsCode ac_apply_matrix_lv(AtomBuilder_R ab
, U4 r_mtx, U4 r_vec, U4 r_out
, U4 r_t0, U4 r_t1, U4 r_t2
) MipsAtomComp_Proc_(ac_apply_matrix_lv, ab, {
/* Load MATRIX rows into GTE RT11..RT33 (libgte convention: ctc2 to C2 $0..$4 in order).
* load_half_u zero-extends the last word so RT33 = m[2][2] and TRX = 0. */
load_word(r_t0, r_mtx, 0), nop,
gte_mv_to_ctrl_r(r_t0, gte_cr_RT11_Code),
load_word(r_t0, r_mtx, 4), nop,
gte_mv_to_ctrl_r(r_t0, gte_cr_RT12_Code),
load_word(r_t0, r_mtx, 8), nop,
gte_mv_to_ctrl_r(r_t0, gte_cr_RT13_Code),
load_word(r_t0, r_mtx, 12), nop,
gte_mv_to_ctrl_r(r_t0, gte_cr_RT21_Code),
load_half_u(r_t0, r_mtx, 16), nop,
gte_mv_to_ctrl_r(r_t0, gte_cr_RT22_Code),
nop2,
/* Load PACKED pos into V0 (libgte SVECTOR layout).
* r_vec points to atom-0-staged packed data ((pos.y << 16) | pos.x at +0, pos.z at +4).
* LWC2 base register MUST be the pointer r_vec, NOT the loaded value r_t0. */
load_word(r_t0, r_vec, 0), nop,
gte_lw(C2_VXY0, r_vec, 0),
load_word(r_t0, r_vec, 4), nop,
gte_lw(C2_VZ0, r_vec, 4),
/* RTPS cv=1 (no translation accumulation; BK is zero-initialized), sf=0, v=0, mx=0.
* 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. */
gte_cmdw_rtps_no_tr,
/* Read MAC1/2/3 → out. */
gte_mv_from_data_r(r_t0, C2_MAC1),
gte_mv_from_data_r(r_t1, C2_MAC2),
gte_mv_from_data_r(r_t2, C2_MAC3),
nop,
store_word(r_t0, r_out, 0),
store_word(r_t1, r_out, 4),
store_word(r_t2, r_out, 8),
})
/* ─── TRANS MATRIX (libgte TransMatrix port) ───
* Atom component — auto-generates mac_trans_matrix Mac composer macro.
* m->t += off. Uses 2 GPRs via per-axis load-delay-slot pattern.
* Words: 12. Clobbers: r_t0, r_t1. */
FI_ Slice_MipsCode ac_trans_matrix(AtomBuilder_R ab
, U4 r_mtx, U4 r_off
, U4 r_t0, U4 r_t1
) MipsAtomComp_Proc_(ac_trans_matrix, ab, {
load_word(r_t0, r_mtx, O_(MT3_S2S4,t[0])),
load_word(r_t1, r_off, O_(V3_S4,x)),
add_u(r_t0, r_t0, r_t1),
store_word(r_t0, r_mtx, O_(MT3_S2S4,t[0])),
load_word(r_t0, r_mtx, O_(MT3_S2S4,t[1])),
load_word(r_t1, r_off, O_(V3_S4,y)),
add_u(r_t0, r_t0, r_t1),
store_word(r_t0, r_mtx, O_(MT3_S2S4,t[1])),
load_word(r_t0, r_mtx, O_(MT3_S2S4,t[2])),
load_word(r_t1, r_off, O_(V3_S4,z)),
add_u(r_t0, r_t0, r_t1),
store_word(r_t0, r_mtx, O_(MT3_S2S4,t[2])),
})
#pragma endregion MACs (Mips Atom Components)
#pragma region Atom Procs
+13
View File
@@ -391,6 +391,19 @@ enum { _C2_TX_SUBS_ = 0
* The wedge alias is the 3D complement interpretation of the same 3 scalars (MAC1..MAC3). */
#define gte_cmdw_mvmva (gte_cmd_base | enc_gte_cmd(gte_cmd_mvmva))
/* MVMVA with sf=1 (12-bit shift), cv=3 (no translation), v=3 (IR): for ApplyMatrixLV.
* Reads input from IR1/2/3 (loaded via mtc2 rt, C2_IRx). MAC1/2/3 = (RT row · IR) >> 12.
* The 12-bit shift produces values like R*pos >> 12, matching the libgte C-side ApplyMatrixLV output.
* Note: PCSX-Redux's MVMVA interpretation differs from the spec on some matrix layouts.
*/
#define gte_cmdw_mvmva_ir (gte_cmd_base | enc_gte_sf(1) | enc_gte_cv(3) | enc_gte_v(3) | enc_gte_cmd(gte_cmd_mvmva))
#define gte_cmdw_mvmva_no_tr gte_cmdw_mvmva_ir
/* RTPS with sf=1 (12-bit shift, no translation): matches the output of libgte's
* ApplyMatrixLV when the GTE pipeline expects R*pos >> 12. The shift produces
* values like (-270, 710, 1713) which match the C11 reference path. */
#define gte_cmdw_rtps_sf1 (gte_cmd_base | enc_gte_sf(1) | enc_gte_cv(3) | enc_gte_cmd(gte_cmd_rtps))
/* SQR / GPF cosmetic-bits compat helpers.
* Each command's `_compat` macro ORs in the `fake_cmd` field value libgte happens to emit.
* The hardware ignores these bits (per PSX-SPX line 48). */
+1 -2
View File
@@ -369,8 +369,7 @@ void update(PrimitiveArena* pa, U4* ordering_buf)
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(& smem.cam.look_at, & pos, & off); trans_m3s2( & smem.cam.look_at, & off);
}
// Draw cube