editing/reading.

This commit is contained in:
ed
2026-08-13 21:22:29 -04:00
parent ea3e30a11e
commit b8e31123e4
9 changed files with 62 additions and 152 deletions
+2 -2
View File
@@ -70,8 +70,8 @@
/* ----------------------------------------------------------------------------
* atom_reg (per-enum opt-in marker for the DWARF register-alias registry)
*
* The bare `atom_reg` token adjacent to an enum entry in mips.h / lottes_tape.h flags that alias as debug-visible for scan_source's register_alias_registry.
* The C preprocessor strips it to a comment so no runtime symbol is created; the Lua scanner reads the bare token.
* Bare `atom_reg` token adjacent to an enum entry that alias as debug-visible for scan_source's register_alias_registry.
* Lua scanner reads the bare token.
* ----------------------------------------------------------------------------*/
#define atom_reg /* atom_reg: opt the preceding enum entry into the DWARF registry */
+7 -8
View File
@@ -3,7 +3,7 @@
# include "assert.h"
#endif
#define offset_of(type, member) cast(U8,__builtin_offsetof(type,member))
#define offset_of(type, member) cast(U8,__builtin_offsetof(type,member)) // Compiler builtin version of O_
#define static_assert _Static_assert
#define typeof __typeof__
#define typeof_ptr(ptr) typeof((ptr)[0])
@@ -139,16 +139,15 @@ enum { false = 0, true = 1, true_overflow, };
typedef void Proc_(VoidFn) (void);
#define kilo(n) (C_(U4, n) << 10)
#define mega(n) (C_(U4, n) << 20)
#define giga(n) (C_(U4, n) << 30)
#define tera(n) (C_(U4, n) << 40)
#define Kilo_(n) (C_(U4, n) << 10)
#define Mega_(n) (C_(U4, n) << 20)
#define Giga_(n) (C_(U4, n) << 30)
#define Tera_(n) (C_(U4, n) << 40)
#define null C_(U4, 0)
#define nullptr C_(void*, 0)
#define O_(type, field) C_(U4, & C_(type*,0)->field)
#define OA_(type, member, idx) C_(U4, & C_(type*,0)->member[idx])
#define OT_(field) O_(typeof_ptr(& field), filed))
#define OT_(field) O_(typeof_ptr(& field), field))
#define S_(data) C_(U4, sizeof(data))
#define sop_1(op,a,b) C_(U1, s1_(a) op s1_(b))
@@ -185,7 +184,7 @@ def_signed_ops(le, <=)
#define alignas _Alignas
#define alignof _Alignof
#define byte_pad(amount, ...) B1 glue(_PAD_, __VA_ARGS__) [amount]
#define pcast(type, data) (C_(type*, & (data)) [0])
#define C_ptr(type, data) (C_(type*, & (data)) [0])
#define dbg_args(...) __VA_ARGS__
+13 -48
View File
@@ -99,6 +99,12 @@ WORD_COUNT(mac_sub_v3s4, 3)
, store_half(rt_height, base, offset + O_(Rect_S2,height))
WORD_COUNT(mac_store_rects2, 4)
/* atom_dbg_skip */
#define mac_load_word_imm(dst, imm) \
load_upper_i(dst, u4_hi(imm)) \
, or_i_self( dst, u4_lo(imm))
WORD_COUNT(mac_load_word_imm, 2)
/* atom_dbg_skip */
#define mac_load_tri_indices(r_face_cusor, r_i0, r_i1, r_i2) \
load_half_u(r_i0, r_face_cusor, 0 * S_(S2)) \
@@ -175,58 +181,17 @@ 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) \
, load_word( r_t0, r_mtx, 4) \
, nop \
, gte_mv_to_ctrl_r(r_t0, gte_cr_RT12) \
, load_word( r_t0, r_mtx, 8) \
, nop \
, gte_mv_to_ctrl_r(r_t0, gte_cr_RT13) \
, load_word( r_t0, r_mtx, 12) \
, nop \
, gte_mv_to_ctrl_r(r_t0, gte_cr_RT21) \
, load_half_u(r_t0, r_mtx, 16) \
, nop \
, gte_mv_to_ctrl_r(r_t0, gte_cr_RT22) \
, 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=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) \
, 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_t1) \
load_word(r_t1, r_off, O_(V3_S4,x)) \
, nop \
, store_word(r_t1, r_mtx, O_(MT3_S2S4,t[0])) \
#define mac_trans_mt3s3s4(r_mtx, r_off, r_t0, r_t1, r_t2) \
load_word(r_t0, r_off, O_(V3_S4,x)) \
, load_word(r_t1, r_off, O_(V3_S4,y)) \
, nop \
, load_word(r_t2, r_off, O_(V3_S4,z)) \
, store_word(r_t0, r_mtx, O_(MT3_S2S4,t[0])) \
, store_word(r_t1, r_mtx, O_(MT3_S2S4,t[1])) \
, load_word(r_t1, r_off, O_(V3_S4,z)) \
, nop \
, store_word(r_t1, r_mtx, O_(MT3_S2S4,t[2]))
WORD_COUNT(mac_trans_matrix, 9)
, store_word(r_t2, r_mtx, O_(MT3_S2S4,t[2]))
WORD_COUNT(mac_trans_mt3s3s4, 6)
#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), */ \
mac_load_word_imm(reg_transfer, cmd) \
, store_word( reg_transfer, reg_base, port)
WORD_COUNT(mac_gcmd_push, 3)
+1 -4
View File
@@ -10,10 +10,7 @@ ATOM_FILE_DEBUGGER_LINE_MARKER(gp_atom_c);
FI_ Slice_MipsCode ac_gcmd_push(AtomBuilder_R ab, U4 cmd, U4 reg_transfer, U4 reg_base, U2 port)
MipsAtomComp_Proc_(ac_gcmd_push, ab, {
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),
mac_load_word_imm(reg_transfer, cmd),
store_word( reg_transfer, reg_base, port),
})
+7 -65
View File
@@ -83,79 +83,21 @@ 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),
load_word( r_t0, r_mtx, 4), nop, gte_mv_to_ctrl_r(r_t0, gte_cr_RT12),
load_word( r_t0, r_mtx, 8), nop, gte_mv_to_ctrl_r(r_t0, gte_cr_RT13),
load_word( r_t0, r_mtx, 12), nop, gte_mv_to_ctrl_r(r_t0, gte_cr_RT21),
load_half_u(r_t0, r_mtx, 16), nop, gte_mv_to_ctrl_r(r_t0, gte_cr_RT22),
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=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),
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 = v (struct copy; libgte's TransMatrix at 0x8001a540 is just 3 store_words, no GTE, no add).
* Uses 1 GPR (r_t1 = off value) per axis; per-axis load-delay-slot pattern.
* Words: 9. Clobbers: r_t1. */
FI_ Slice_MipsCode ac_trans_matrix(AtomBuilder_R ab
FI_ Slice_MipsCode ac_trans_mt3s3s4(AtomBuilder_R ab
, U4 r_mtx, U4 r_off
, U4 r_t1
) MipsAtomComp_Proc_(ac_trans_matrix, ab, {
load_word(r_t1, r_off, O_(V3_S4,x)),
nop,
store_word(r_t1, r_mtx, O_(MT3_S2S4,t[0])),
, U4 r_t0, U4 r_t1, U4 r_t2
) MipsAtomComp_Proc_(ac_trans_mt3s3s4, ab, {
load_word(r_t0, r_off, O_(V3_S4,x)),
load_word(r_t1, r_off, O_(V3_S4,y)),
nop,
load_word(r_t2, r_off, O_(V3_S4,z)),
store_word(r_t0, r_mtx, O_(MT3_S2S4,t[0])),
store_word(r_t1, r_mtx, O_(MT3_S2S4,t[1])),
load_word(r_t1, r_off, O_(V3_S4,z)),
nop,
store_word(r_t1, r_mtx, O_(MT3_S2S4,t[2])),
store_word(r_t2, r_mtx, O_(MT3_S2S4,t[2])),
})
#pragma endregion MACs (Mips Atom Components)
+5 -16
View File
@@ -440,22 +440,11 @@ enum { _C2_TX_SUBS_ = 0
#define gte_cmdw_mvmva_pass1_c11 (gte_cmd_base | enc_gte_v(2) | enc_gte_mx(3) | enc_gte_cmd(gte_cmd_mvmva))
#define gte_cmdw_mvmva_no_tr gte_cmdw_mvmva_ir
/* MVMVA pass 2 — EXACT C11 ApplyMatrixLV command.
* Command word: 0x4A49E012.
* bits 31-26: 010010 = COP2
* bit 25: 1 (CO set)
* bits 24-20: 01001 = 9 (fake_cmd)
* bit 19: 1 (sf=1)
* bits 18-17: 00 (mx=0, RT matrix)
* bits 16-15: 11 (v=3, IR)
* bits 14-13: 11 (cv=3, no translation)
* bits 5-0: 010010 = MVMVA
* sf=1, mx=0, v=3, cv=3. Pass 2 reads RT matrix, IR input, >>12. */
#define gte_cmdw_mvmva_c11_pass2_exact 0x4A49E012
/* MVMVA pass 1 — C11's exact command: 0x4A41E012.
* bit 25: 1, sf=0, mx=0, v=3, cv=3. Pass 1 reads RT matrix, IR input, no shift. */
#define gte_cmdw_mvmva_c11_pass1_exact 0x4A41E012
/* MVMVA pass 2 — C11 ApplyMatrixLV command.
* Decoded: op_cop2 | CO | fake_cmd=4 | sf=1 (>>12) | mx=0 (RT matrix) | v=3 (IR) | cv=3 (no translation) | lm=0 | cmd=MVMVA.
* Reads (RT row · IR) >> 12 into MAC1/2/3. Per-field composition (no opaque literal)
* keeps the bit layout visible at the call site + matches the libgte C-side byte-exact. */
#define gte_cmdw_mvmva_c11_pass2 (gte_cmd_base | enc_gte_fake_cmd(4) | enc_gte_sf(1) | enc_gte_v(3) | enc_gte_mx(0) | enc_gte_cv(3) | enc_gte_cmd(gte_cmd_mvmva))
/* MVMVA: sf=1 (>>12), mx=0 (RT matrix), v=0 (V0), cv=3 (no TR). */
#define gte_cmdw_mvmva_sf1_mx0_v0_cv3 (gte_cmd_base | enc_gte_sf(1) | enc_gte_cv(3) | enc_gte_v(0) | enc_gte_mx(0) | enc_gte_cmd(gte_cmd_mvmva))
+5 -5
View File
@@ -106,10 +106,10 @@ FI_ void mul_a3s4(A3_S4_R out_a, A3_S4 b) {
(out_a[0])[2] *= b[2];
}
FI_ void add_v3s4 (V3_S4_R out_a, V3_S4 b) { add_a3s4 (pcast(A3_S4_R, out_a), pcast(A3_S4, b)); }
FI_ void add_v3s4_fp(V3_S4_R out_a, V3_S4 b) { add_a3s4_fp(pcast(A3_S4_R, out_a), pcast(A3_S4, b)); }
FI_ void add_v3s4 (V3_S4_R out_a, V3_S4 b) { add_a3s4 (C_ptr(A3_S4_R, out_a), C_ptr(A3_S4, b)); }
FI_ void add_v3s4_fp(V3_S4_R out_a, V3_S4 b) { add_a3s4_fp(C_ptr(A3_S4_R, out_a), C_ptr(A3_S4, b)); }
FI_ void sub_v3s4 (V3_S4_R out_a, V3_S4 b) { sub_a3s4 (pcast(A3_S4_R, out_a), pcast(A3_S4, b)); }
FI_ void sub_v3s4_fp(V3_S4_R out_a, V3_S4 b) { sub_a3s4_fp(pcast(A3_S4_R, out_a), pcast(A3_S4, b)); }
FI_ void sub_v3s4 (V3_S4_R out_a, V3_S4 b) { sub_a3s4 (C_ptr(A3_S4_R, out_a), C_ptr(A3_S4, b)); }
FI_ void sub_v3s4_fp(V3_S4_R out_a, V3_S4 b) { sub_a3s4_fp(C_ptr(A3_S4_R, out_a), C_ptr(A3_S4, b)); }
FI_ void mul_v3s4 (V3_S4_R out_a, V3_S4 b) { mul_a3s4 (pcast(A3_S4_R, out_a), pcast(A3_S4, b)); }
FI_ void mul_v3s4 (V3_S4_R out_a, V3_S4 b) { mul_a3s4 (C_ptr(A3_S4_R, out_a), C_ptr(A3_S4, b)); }
+18
View File
@@ -2,11 +2,29 @@
# include "gen/macs.h"
# include "gen/offsets.h"
# include "bios.h"
# include "mips.h"
# include "lottes_tape.h"
#endif
ATOM_FILE_DEBUGGER_LINE_MARKER(mips_atom_c);
#pragma region MACs (Mips Atom Components)
// Tired of this signature:
FI_ Slice_MipsCode ac_load_word_imm(AtomBuilder_R ab, Reg dst, U4 imm)
atom_dbg_skip MipsAtomComp_Proc_(ac_load_word_imm, ab, {
load_upper_i(dst, u4_hi(imm)),
or_i_self( dst, u4_lo(imm)),
})
// Can I get away with this instead?
// atom_dbg_skip FI_ Slice_MipsCode
// ac_load_word_imm(AtomBuilder_R ab, Reg dst, U4 imm) MipsAtomComp_Proc_(ab, {
// load_upper_i(dst, u4_hi(imm)),
// or_i_self( dst, u4_lo(imm)),
// })
#pragma endregion MACs (Mips Atom Components)
#pragma region Baked Atoms
/* Flushes the Instruction Cache (PSX A-function 0x44 via BIOS stub at 0xA0).
+1 -1
View File
@@ -549,7 +549,7 @@ internal MipsAtom_(screen_env_init) atom_info(atom_phase(screen_init)
) {
/* display[0] = (0, 0, 320, 240); rest of struct zeroed. */
add_ui(R_ScreenX, R_0, ScreenRes_X), add_ui(R_ScreenY, R_0, ScreenRes_Y),
mac_store_v2s2(R_ScreenX, R_ScreenY, R_ScreenBuf, O_(DisplayEnv,display_area.width) + OA_(DoubleBuffer,display,0)),
mac_store_v2s2(R_ScreenX, R_ScreenY, R_ScreenBuf, O_(DisplayEnv,display_area.width) + O_(DoubleBuffer,display[0])),
store_word(R_0, R_ScreenBuf, O_(DisplayEnv,display_area) + O_(DoubleBuffer,display[0])),
store_word(R_0, R_ScreenBuf, O_(DisplayEnv,screen) + O_(DoubleBuffer,display[0])),
store_word(R_0, R_ScreenBuf, O_(DisplayEnv,vinterlace) + O_(DoubleBuffer,display[0])),