From b8e31123e49971508cdbb498ff9ae7c0202e4a26 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Thu, 13 Aug 2026 21:22:29 -0400 Subject: [PATCH] editing/reading. --- code/duffle/dsl.atom.h | 4 +- code/duffle/dsl.h | 15 +++--- code/duffle/gen/macs.h | 63 ++++++----------------- code/duffle/gp.atom.c | 5 +- code/duffle/gte.atom.c | 72 +++------------------------ code/duffle/gte.h | 21 ++------ code/duffle/math.h | 10 ++-- code/duffle/mips.atom.c | 22 +++++++- code/hello_camera/hello_camera.atom.c | 2 +- 9 files changed, 62 insertions(+), 152 deletions(-) diff --git a/code/duffle/dsl.atom.h b/code/duffle/dsl.atom.h index 4d1f4a9..42bd7cb 100644 --- a/code/duffle/dsl.atom.h +++ b/code/duffle/dsl.atom.h @@ -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 */ diff --git a/code/duffle/dsl.h b/code/duffle/dsl.h index e3e8466..e7de8af 100644 --- a/code/duffle/dsl.h +++ b/code/duffle/dsl.h @@ -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__ diff --git a/code/duffle/gen/macs.h b/code/duffle/gen/macs.h index 4c8dd95..325aa13 100644 --- a/code/duffle/gen/macs.h +++ b/code/duffle/gen/macs.h @@ -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) @@ -291,6 +256,6 @@ WORD_COUNT(mac_pad_set_status, 2) /* atom_dbg_skip */ #define mac_pad_store_inverted_buttons(r_buttons, r_pad_state) \ nor_u( r_buttons, r_buttons, R_0) \ -, store_half( r_buttons, r_pad_state, O_(PadState, buttons)) +, store_half( r_buttons, r_pad_state, O_(PadState,buttons)) WORD_COUNT(mac_pad_store_inverted_buttons, 2) diff --git a/code/duffle/gp.atom.c b/code/duffle/gp.atom.c index adf95bf..d40cc4a 100644 --- a/code/duffle/gp.atom.c +++ b/code/duffle/gp.atom.c @@ -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), }) diff --git a/code/duffle/gte.atom.c b/code/duffle/gte.atom.c index c992ffa..eed8df0 100644 --- a/code/duffle/gte.atom.c +++ b/code/duffle/gte.atom.c @@ -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) diff --git a/code/duffle/gte.h b/code/duffle/gte.h index 7950e7d..2e5ce78 100644 --- a/code/duffle/gte.h +++ b/code/duffle/gte.h @@ -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)) diff --git a/code/duffle/math.h b/code/duffle/math.h index 40e08e9..4eefeff 100644 --- a/code/duffle/math.h +++ b/code/duffle/math.h @@ -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)); } diff --git a/code/duffle/mips.atom.c b/code/duffle/mips.atom.c index dd0d157..bc80024 100644 --- a/code/duffle/mips.atom.c +++ b/code/duffle/mips.atom.c @@ -1,12 +1,30 @@ #ifdef INTELLISENSE_DIRECTIVES -# include "gen/macs.h" -# include "gen/offsets.h" +# 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). diff --git a/code/hello_camera/hello_camera.atom.c b/code/hello_camera/hello_camera.atom.c index da80ca6..aca34aa 100644 --- a/code/hello_camera/hello_camera.atom.c +++ b/code/hello_camera/hello_camera.atom.c @@ -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])),