mirror of
https://github.com/Ed94/pikuma_ps1.git
synced 2026-08-09 00:58:16 +00:00
Completed C-side of: Camera Transformation chapter. Now todo atom tape translation...
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
// source: C:\projects\Pikuma\ps1\code\duffle\lottes_tape.h
|
// source: C:\projects\Pikuma\ps1\code\duffle\lottes_tape.h
|
||||||
// source: C:\projects\Pikuma\ps1\code\duffle\bios.h
|
// source: C:\projects\Pikuma\ps1\code\duffle\bios.h
|
||||||
// source: C:\projects\Pikuma\ps1\code\duffle\psyq.h
|
// source: C:\projects\Pikuma\ps1\code\duffle\psyq.h
|
||||||
|
// source: C:\projects\Pikuma\ps1\code\duffle\pad.c
|
||||||
// source: C:\projects\Pikuma\ps1\code\duffle\math.atom.c
|
// source: C:\projects\Pikuma\ps1\code\duffle\math.atom.c
|
||||||
// source: C:\projects\Pikuma\ps1\code\duffle\mips.atom.c
|
// source: C:\projects\Pikuma\ps1\code\duffle\mips.atom.c
|
||||||
// source: C:\projects\Pikuma\ps1\code\duffle\gte.atom.c
|
// source: C:\projects\Pikuma\ps1\code\duffle\gte.atom.c
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
// source: C:\projects\Pikuma\ps1\code\duffle\lottes_tape.h
|
// source: C:\projects\Pikuma\ps1\code\duffle\lottes_tape.h
|
||||||
// source: C:\projects\Pikuma\ps1\code\duffle\bios.h
|
// source: C:\projects\Pikuma\ps1\code\duffle\bios.h
|
||||||
// source: C:\projects\Pikuma\ps1\code\duffle\psyq.h
|
// source: C:\projects\Pikuma\ps1\code\duffle\psyq.h
|
||||||
|
// source: C:\projects\Pikuma\ps1\code\duffle\pad.c
|
||||||
// source: C:\projects\Pikuma\ps1\code\duffle\math.atom.c
|
// source: C:\projects\Pikuma\ps1\code\duffle\math.atom.c
|
||||||
// source: C:\projects\Pikuma\ps1\code\duffle\mips.atom.c
|
// source: C:\projects\Pikuma\ps1\code\duffle\mips.atom.c
|
||||||
// source: C:\projects\Pikuma\ps1\code\duffle\gte.atom.c
|
// source: C:\projects\Pikuma\ps1\code\duffle\gte.atom.c
|
||||||
|
|||||||
@@ -53,16 +53,16 @@ FI_ Slice_MipsCode ac_gte_store_g4_p3(U4 r_primitive_cursor) atom_dbg_skip MipsA
|
|||||||
|
|
||||||
#pragma region Bsked Atoms
|
#pragma region Bsked Atoms
|
||||||
|
|
||||||
typedef Struct_(Binds_SetGteWorld) {
|
typedef Struct_(Binds_SetGteMT3S2S4) {
|
||||||
M3_S2* transform;
|
MT3_S2S4* transform;
|
||||||
};
|
};
|
||||||
internal MipsAtom_(set_gte_world) atom_info(
|
internal MipsAtom_(set_gte_mt3s2s4) atom_info(
|
||||||
atom_bind(Binds_SetGteWorld)
|
atom_bind(Binds_SetGteMT3S2S4)
|
||||||
, atom_reads(R_TapePtr)
|
, atom_reads(R_TapePtr)
|
||||||
){
|
){
|
||||||
/* Pop matrix address from tape into R_T3 ($11) */
|
/* Pop matrix address from tape into R_T3 ($11) */
|
||||||
load_word(R_T3, R_TapePtr, O_(Binds_SetGteWorld,transform)),
|
load_word(R_T3, R_TapePtr, O_(Binds_SetGteMT3S2S4,transform)),
|
||||||
add_ui_self( R_TapePtr, S_(Binds_SetGteWorld)),
|
add_ui_self( R_TapePtr, S_(Binds_SetGteMT3S2S4)),
|
||||||
/* Load 3x3 Rotation + 3x1 Translation from R_T3 into GTE CONTROL Regs (ctc2) */
|
/* Load 3x3 Rotation + 3x1 Translation from R_T3 into GTE CONTROL Regs (ctc2) */
|
||||||
load_word(R_T0, R_T3, 0), load_word(R_T1, R_T3, 4),
|
load_word(R_T0, R_T3, 0), load_word(R_T1, R_T3, 4),
|
||||||
gte_mv_to_ctrl_r(R_T0, gte_cr_RT11), gte_mv_to_ctrl_r(R_T1, gte_cr_RT12),
|
gte_mv_to_ctrl_r(R_T0, gte_cr_RT11), gte_mv_to_ctrl_r(R_T1, gte_cr_RT12),
|
||||||
|
|||||||
+34
-3
@@ -26,8 +26,8 @@ typedef Struct_(Extent2_S4) { S4 width; S4 height; };
|
|||||||
typedef Struct_(V2_U1) { U1 x; U1 y; };
|
typedef Struct_(V2_U1) { U1 x; U1 y; };
|
||||||
typedef Struct_(V2_S2) { S2 x; S2 y; };
|
typedef Struct_(V2_S2) { S2 x; S2 y; };
|
||||||
typedef Struct_(V2_S4) { S4 x; S4 y; };
|
typedef Struct_(V2_S4) { S4 x; S4 y; };
|
||||||
typedef Struct_(V3_S2) { S2 x; S2 y; S2 z; S2 pad; };
|
typedef Struct_(V3_S2) { S2 x; S2 y; S2 z; S2 pad; }; // PSY-Q: SVECTOR
|
||||||
typedef Struct_(V3_S4) { S4 x; S4 y; S4 z; S4 pad; };
|
typedef Struct_(V3_S4) { S4 x; S4 y; S4 z; S4 pad; }; // PSY-Q: VECTOR
|
||||||
typedef Struct_(V4_S2) { S2 x; S2 y; S2 z; S2 w; };
|
typedef Struct_(V4_S2) { S2 x; S2 y; S2 z; S2 w; };
|
||||||
typedef Struct_(V4_S4) { S4 x; S4 y; S4 z; S4 w; };
|
typedef Struct_(V4_S4) { S4 x; S4 y; S4 z; S4 w; };
|
||||||
|
|
||||||
@@ -37,13 +37,19 @@ typedef Struct_(R2_S4) { V2_S4 p0; V2_S4 p1; };
|
|||||||
typedef Struct_(Rect_S2) { S2 x; S2 y; S2 width; S2 height; };
|
typedef Struct_(Rect_S2) { S2 x; S2 y; S2 width; S2 height; };
|
||||||
typedef Struct_(Rect_S4) { S4 x; S4 y; S4 width; S4 height; };
|
typedef Struct_(Rect_S4) { S4 x; S4 y; S4 width; S4 height; };
|
||||||
|
|
||||||
typedef Struct_(M3_S2) { A3x3_S2 m; A3_S4 t; };
|
typedef Struct_(MT3_S2S4) { A3x3_S2 m; A3_S4 t; }; // PSY-Q: MATRIX
|
||||||
|
|
||||||
typedef Array_(V2_U1, 2);
|
typedef Array_(V2_U1, 2);
|
||||||
typedef Array_(V2_S2, 2);
|
typedef Array_(V2_S2, 2);
|
||||||
typedef Array_(V2_S2, 3);
|
typedef Array_(V2_S2, 3);
|
||||||
typedef Array_(V2_S2, 4);
|
typedef Array_(V2_S2, 4);
|
||||||
|
|
||||||
|
enum {
|
||||||
|
fp_one = (1 << 12),
|
||||||
|
};
|
||||||
|
|
||||||
|
#define v3s4_fp_one() v3s4(fp_one, fp_one, fp_one)
|
||||||
|
|
||||||
#define v2s2(x,y) (V2_S2){x,y}
|
#define v2s2(x,y) (V2_S2){x,y}
|
||||||
#define v3s2(x,y,z) (V3_S2){x,y,z,0}
|
#define v3s2(x,y,z) (V3_S2){x,y,z,0}
|
||||||
#define v3s4(x,y,z) (V3_S4){x,y,z,0}
|
#define v3s4(x,y,z) (V3_S4){x,y,z,0}
|
||||||
@@ -62,5 +68,30 @@ FI_ void add_a3s4_fp(A3_S4_R out_a, A3_S4 b) {
|
|||||||
(out_a[0])[2] += b[2] >> 1;
|
(out_a[0])[2] += b[2] >> 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FI_ void sub_a3s4(A3_S4_R out_a, A3_S4 b) {
|
||||||
|
(out_a[0])[0] -= b[0];
|
||||||
|
(out_a[0])[1] -= b[1];
|
||||||
|
(out_a[0])[2] -= b[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
FI_ void sub_a3s4_fp(A3_S4_R out_a, A3_S4 b) {
|
||||||
|
(out_a[0])[0] -= b[0] >> 1;
|
||||||
|
(out_a[0])[1] -= b[1] >> 1;
|
||||||
|
(out_a[0])[2] -= b[2] >> 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FI_ void mul_a3s4(A3_S4_R out_a, A3_S4 b) {
|
||||||
|
(out_a[0])[0] *= b[0];
|
||||||
|
(out_a[0])[1] *= b[1];
|
||||||
|
(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 (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_fp(V3_S4_R out_a, V3_S4 b) { add_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 (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 mul_v3s4 (V3_S4_R out_a, V3_S4 b) { mul_a3s4 (pcast(A3_S4_R, out_a), pcast(A3_S4, b)); }
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
#ifdef INTELLISENSE_DIRECTIVES
|
||||||
|
# include "dsl.h"
|
||||||
|
# include "gcc_asm.h"
|
||||||
|
# include "mips.h"
|
||||||
|
# include "bios.h"
|
||||||
|
# include "pad.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Uses ONE 8-byte frame allocated via the compiler's standard prologue.
|
||||||
|
* 4 wasted-arg words for B(12h) InitPAD2 are at [SP+0..15] but are not explicitly allocated.
|
||||||
|
* Compiler handles the MIPS O32 "wasted stack" convention for us by treating the B-call as a 4-arg call.
|
||||||
|
*
|
||||||
|
* The buffer pointers are passed as arguments so the compiler keeps them in callee-saved registers;
|
||||||
|
* The B(12h) asm volatile block does NOT clobber those registers (it clobbers only the volatile GPRs + B-table arg registers explicitly).
|
||||||
|
* The C-level writes after the call re-load the pointers from their callee-saved homes.
|
||||||
|
*
|
||||||
|
* The clobber list for both B-calls names the full BIOS destroy set documented in kernelbios.md:167-174 (R1..R15, R24..R25, R31, HI/LO).
|
||||||
|
* The kernel-ABI "volatile GPRs" subset is clb_mem_drain; the rest of the destroy set is enumerated explicitly here. */
|
||||||
|
NI_ void pad_bios_init_start(PadBiosRaw* raw0, PadBiosRaw* raw1)
|
||||||
|
{
|
||||||
|
/* Pin raw0 + raw1 to $a0 + $a1 via rgcc; the B(12h) call uses these directly.
|
||||||
|
* The `(void)` casts mark them as unread after the call so the compiler doesn't need to move them back. */
|
||||||
|
register PadBiosRaw* p0 rgcc(R_A0) = raw0;
|
||||||
|
register PadBiosRaw* p1 rgcc(R_A1) = raw1;
|
||||||
|
(void)p0; (void)p1;
|
||||||
|
|
||||||
|
// TODO(Ed): Properly annotate the raw values in the inline asm instructions.
|
||||||
|
// Use enums.
|
||||||
|
|
||||||
|
/* B(12h) InitPAD2(raw0, 0x22, raw1, 0x22)
|
||||||
|
* $a0 = raw0 (rgcc-bound; survives the sequence below)
|
||||||
|
* $a1 = raw1 (preserved into $a2 before $a1 is overwritten)
|
||||||
|
* $a2 = raw1 (moved from $a1; survives $a1's overwrite)
|
||||||
|
* $a3 = 0x22 (immediate)
|
||||||
|
* $t1 = 0x12 (function number)
|
||||||
|
* $t2 = 0xB0 (BIOS B-table address) */
|
||||||
|
asm volatile(
|
||||||
|
asm_words(
|
||||||
|
or_u( rarg_2, rarg_1, rdiscard), /* $a2 = $a1 = raw1 */
|
||||||
|
add_ui( rarg_1, rdiscard, bios_pad_buffer_size), /* $a1 = 0x22 */
|
||||||
|
add_ui( rarg_3, rdiscard, bios_pad_buffer_size), /* $a3 = 0x22 */
|
||||||
|
add_ui( rtmp_1, rdiscard, bios_init_pad_2), /* $t1 = 0x12 */
|
||||||
|
add_ui( rtmp_2, rdiscard, bios_btable_addr), /* $t2 = 0xB0 */
|
||||||
|
call_reg(rtmp_2), /* jalr $t2, $ra */
|
||||||
|
nop /* BD slot */
|
||||||
|
)
|
||||||
|
asm_rpins, r_use(p0), r_use(p1)
|
||||||
|
asm_clobber:
|
||||||
|
rlit(R_AT),
|
||||||
|
rlit(R_V0), rlit(R_V1),
|
||||||
|
rlit(R_T0), rlit(R_T1), rlit(R_T2), rlit(R_T3), rlit(R_T4),
|
||||||
|
rlit(R_T5), rlit(R_T6), rlit(R_T7), rlit(R_T8), rlit(R_T9),
|
||||||
|
rlit(R_RA),
|
||||||
|
clb_mem_drain
|
||||||
|
);
|
||||||
|
|
||||||
|
/* The C-level writes re-load the pointers via the parameter names and write 0xFF to each
|
||||||
|
* buffer's status byte to mark the initial-state hazard documented in kernelbios.md:1621-1624. */
|
||||||
|
u1_v(raw0)[0] = 0xFF;
|
||||||
|
u1_v(raw1)[0] = 0xFF;
|
||||||
|
|
||||||
|
/* B(13h) StartPAD2() — no args. The BIOS preserves $sp. */
|
||||||
|
asm volatile(
|
||||||
|
asm_words(
|
||||||
|
add_ui( rtmp_1, rdiscard, bios_start_pad_2), /* $t1 = 0x13 */
|
||||||
|
add_ui( rtmp_2, rdiscard, bios_btable_addr), /* $t2 = 0xB0 (re-load) */
|
||||||
|
call_reg(rtmp_2), /* jalr $t2, $ra */
|
||||||
|
nop /* BD slot */
|
||||||
|
)
|
||||||
|
asm_clobber:
|
||||||
|
rlit(R_AT),
|
||||||
|
rlit(R_V0), rlit(R_V1),
|
||||||
|
rlit(R_T0), rlit(R_T1), rlit(R_T2), rlit(R_T3), rlit(R_T4),
|
||||||
|
rlit(R_T5), rlit(R_T6), rlit(R_T7), rlit(R_T8), rlit(R_T9),
|
||||||
|
rlit(R_RA),
|
||||||
|
clb_mem_drain
|
||||||
|
);
|
||||||
|
}
|
||||||
+2
-3
@@ -33,9 +33,6 @@ enum {
|
|||||||
Pad1 = 1 << PadId_Offset,
|
Pad1 = 1 << PadId_Offset,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define pad0_(btn_id) (btn_id << Pad0)
|
|
||||||
#define pad1_(btn_id) (btn_id << Pad1)
|
|
||||||
|
|
||||||
/* =============================================================================
|
/* =============================================================================
|
||||||
* BIOS pad-buffer subsystem: docs/psx-spx/docs/kernelbios.md (B(12h) + B(13h))
|
* BIOS pad-buffer subsystem: docs/psx-spx/docs/kernelbios.md (B(12h) + B(13h))
|
||||||
* ============================================================================= */
|
* ============================================================================= */
|
||||||
@@ -113,3 +110,5 @@ typedef Struct_(PadState) {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
internal void pad_bios_init_start(PadBiosRaw* raw0, PadBiosRaw* raw1);
|
||||||
|
|||||||
+17
-5
@@ -64,9 +64,9 @@ typedef Struct_(Tile) {
|
|||||||
Linear Algebra
|
Linear Algebra
|
||||||
*/
|
*/
|
||||||
|
|
||||||
M3_S2* m3s2_rotation (V3_S2* vec, M3_S2* mat) asm("RotMatrix");
|
MT3_S2S4* mt3s2s4_rotation (V3_S2* vec, MT3_S2S4* mat) asm("RotMatrix");
|
||||||
M3_S2* m3s2_translation(M3_S2* mat, V3_S4* vec) asm("TransMatrix");
|
MT3_S2S4* mt3s2s4_translation(MT3_S2S4* mat, V3_S4* vec) asm("TransMatrix");
|
||||||
M3_S2* m3s2_scale (M3_S2* mat, V3_S4* vec) asm("ScaleMatrix");
|
MT3_S2S4* mt3s2s4_scale (MT3_S2S4* mat, V3_S4* vec) asm("ScaleMatrix");
|
||||||
|
|
||||||
// Rotation, Translation, Perspective
|
// Rotation, Translation, Perspective
|
||||||
|
|
||||||
@@ -99,5 +99,17 @@ FI_ S4 rtp_avg_nclip_a4_v3s2(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gte_matrix_set_rotation (M3_S2* mat) asm("SetRotMatrix");
|
void gte_matrix_set_rotation (MT3_S2S4* mat) asm("SetRotMatrix");
|
||||||
void gte_matrix_set_translation(M3_S2* mat) asm("SetTransMatrix");
|
void gte_matrix_set_translation(MT3_S2S4* mat) asm("SetTransMatrix");
|
||||||
|
|
||||||
|
// Einheit, Metrication to unit vector. "Normalization", not Orthogonal "Normal, Normalis". Directionalization.
|
||||||
|
S4 normalize_v3s4(V3_S4* v0, V3_S4* v1) asm("VectorNormal");
|
||||||
|
|
||||||
|
V3_S4* mul_m3s2_v3s4(MT3_S2S4* m, V3_S4* v, V3_S4* result) asm("ApplyMatrixLV");
|
||||||
|
|
||||||
|
MT3_S2S4* trans_m3s2(MT3_S2S4* m, V3_S4* off) asm("TransMatrix");
|
||||||
|
|
||||||
|
MT3_S2S4* gte_comp_coord_m3s2(MT3_S2S4* m0, MT3_S2S4* m1, MT3_S2S4* result) asm("CompMatrixLV");
|
||||||
|
|
||||||
|
// TODO(Ed): Want to interpret this under the lens of Eric Lengyel's geometric algebra
|
||||||
|
void cross_v3s4(V3_S4* v0, V3_S4* v1, V3_S4* result) asm("OuterProduct12");
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#pragma region hello_camera
|
#pragma region hello_camera
|
||||||
|
|
||||||
|
|
||||||
// --- atom: pad_apply_input (60 words) ---
|
// --- atom: pad_input_cube_rotation (60 words) ---
|
||||||
|
|
||||||
#define _atom_offset_dpad_left_exit_dpad_left 6
|
#define _atom_offset_dpad_left_exit_dpad_left 6
|
||||||
#define _atom_offset_dpad_right_exit_dpad_right 6
|
#define _atom_offset_dpad_right_exit_dpad_right 6
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ enum {
|
|||||||
R_CubeRot = R_T1 atom_reg,
|
R_CubeRot = R_T1 atom_reg,
|
||||||
R_FloorRot = R_T2 atom_reg,
|
R_FloorRot = R_T2 atom_reg,
|
||||||
};
|
};
|
||||||
internal MipsAtom_(pad_apply_input) atom_info(atom_bind(Binds_PadApplyInput)
|
internal MipsAtom_(pad_input_cube_rotation) atom_info(atom_bind(Binds_PadApplyInput)
|
||||||
, atom_reads(R_T0, R_CubeRot, R_FloorRot, R_T3, R_T4, R_PadStateT5, R_TapePtr)
|
, atom_reads(R_T0, R_CubeRot, R_FloorRot, R_T3, R_T4, R_PadStateT5, R_TapePtr)
|
||||||
, atom_writes( R_CubeRot, R_FloorRot)
|
, atom_writes( R_CubeRot, R_FloorRot)
|
||||||
) {
|
) {
|
||||||
@@ -225,7 +225,7 @@ internal MipsAtom_(pad_apply_input) atom_info(atom_bind(Binds_PadApplyInput)
|
|||||||
// Note(Ed): Potential op with delay slot?
|
// Note(Ed): Potential op with delay slot?
|
||||||
|
|
||||||
/* D-pad Left: cube_rot.y += 30, floor_rot.y += 5. */
|
/* D-pad Left: cube_rot.y += 30, floor_rot.y += 5. */
|
||||||
and_i(R_T3, R_T0, pad0_(Pad_Left)), branch_le_zero(R_T3, atom_offset(dpad_left, exit_dpad_left)),
|
and_i(R_T3, R_T0, Pad_Left), branch_le_zero(R_T3, atom_offset(dpad_left, exit_dpad_left)),
|
||||||
load_half( R_T4, R_CubeRot, O_(V3_S2,y)), /* BD-slot */
|
load_half( R_T4, R_CubeRot, O_(V3_S2,y)), /* BD-slot */
|
||||||
load_half( R_T3, R_FloorRot, O_(V3_S2,y)),
|
load_half( R_T3, R_FloorRot, O_(V3_S2,y)),
|
||||||
add_si( R_T4, R_T4, 30),
|
add_si( R_T4, R_T4, 30),
|
||||||
@@ -235,7 +235,7 @@ internal MipsAtom_(pad_apply_input) atom_info(atom_bind(Binds_PadApplyInput)
|
|||||||
atom_label(exit_dpad_left)
|
atom_label(exit_dpad_left)
|
||||||
|
|
||||||
/* D-pad Right: cube_rot.y -= 30, floor_rot.y -= 5. */
|
/* D-pad Right: cube_rot.y -= 30, floor_rot.y -= 5. */
|
||||||
and_i(R_T3, R_T0, pad0_(Pad_Right)), branch_le_zero(R_T3, atom_offset(dpad_right, exit_dpad_right)),
|
and_i(R_T3, R_T0, Pad_Right), branch_le_zero(R_T3, atom_offset(dpad_right, exit_dpad_right)),
|
||||||
load_half( R_T4, R_CubeRot, O_(V3_S2,y)), /* BD-slot */
|
load_half( R_T4, R_CubeRot, O_(V3_S2,y)), /* BD-slot */
|
||||||
load_half( R_T3, R_FloorRot, O_(V3_S2,y)),
|
load_half( R_T3, R_FloorRot, O_(V3_S2,y)),
|
||||||
add_si( R_T4, R_T4, -30),
|
add_si( R_T4, R_T4, -30),
|
||||||
@@ -312,6 +312,32 @@ atom_label(exit_stick)
|
|||||||
mac_yield_tail(),
|
mac_yield_tail(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
R_Cam = R_T4 atom_reg,
|
||||||
|
};
|
||||||
|
typedef Struct_(Binds_PadInputCam) {
|
||||||
|
Camera* cam;
|
||||||
|
};
|
||||||
|
internal MipsAtom_(pad_input_cam) atom_info(atom_bind(Binds_PadInputCam)) {
|
||||||
|
load_word(R_Cam, R_TapePtr, O_(Binds_PadInputCam,cam)),
|
||||||
|
add_ui_self( R_TapePtr, S_(Binds_PadInputCam)),
|
||||||
|
// TODO(Ed): Implement.
|
||||||
|
|
||||||
|
mac_yield(),
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
_LookAt_WIP,
|
||||||
|
};
|
||||||
|
typedef Struct_(Binds_ResolveLookAt) {
|
||||||
|
U1 bla;
|
||||||
|
};
|
||||||
|
internal MipsAtom_(resolve_look_at) atom_info(atom_bind(Binds_ResolveLookAt)) {
|
||||||
|
add_ui_self(R_TapePtr, S_(Binds_ResolveLookAt)),
|
||||||
|
|
||||||
|
mac_yield(),
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
R_PrimCursor = R_T7 atom_reg atom_type(U4*), /* VRAM output cursor (primitive buffer) */
|
R_PrimCursor = R_T7 atom_reg atom_type(U4*), /* VRAM output cursor (primitive buffer) */
|
||||||
R_FaceCursor = R_T4 atom_reg atom_type(V4_S2*), /* Cube face-index cursor (V4_S2*); floor context switches to V3_S2* via atom_phase */
|
R_FaceCursor = R_T4 atom_reg atom_type(V4_S2*), /* Cube face-index cursor (V4_S2*); floor context switches to V3_S2* via atom_phase */
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#pragma endregion Duffle Headers
|
#pragma endregion Duffle Headers
|
||||||
|
|
||||||
#pragma region Duffle TUs
|
#pragma region Duffle TUs
|
||||||
|
#include "duffle/pad.c"
|
||||||
#include "duffle/math.atom.c"
|
#include "duffle/math.atom.c"
|
||||||
#include "duffle/mips.atom.c"
|
#include "duffle/mips.atom.c"
|
||||||
#include "duffle/gte.atom.c"
|
#include "duffle/gte.atom.c"
|
||||||
@@ -62,7 +63,10 @@ typedef Struct_(SMemory) {
|
|||||||
|
|
||||||
U4 MemTape[MemTape_Len];
|
U4 MemTape[MemTape_Len];
|
||||||
|
|
||||||
M3_S2 tform_world;
|
MT3_S2S4 tform_world;
|
||||||
|
MT3_S2S4 tform_view;
|
||||||
|
|
||||||
|
Camera cam;
|
||||||
|
|
||||||
Ent_Cube cube;
|
Ent_Cube cube;
|
||||||
Ent_Floor floor;
|
Ent_Floor floor;
|
||||||
@@ -75,6 +79,9 @@ typedef Struct_(SMemory) {
|
|||||||
global SMemory smem;
|
global SMemory smem;
|
||||||
extern SMemory smem;
|
extern SMemory smem;
|
||||||
|
|
||||||
|
#define pad0_btn_(btn) btn & smem.pad[0].buttons
|
||||||
|
#define pad1_btn_(btn) btn & smem.pad[1].buttons
|
||||||
|
|
||||||
I_ B1* prim__alloc(U4 type_width, Str8 type_name) {
|
I_ B1* prim__alloc(U4 type_width, Str8 type_name) {
|
||||||
gknown PrimitiveArena* pa = & smem.primitives;
|
gknown PrimitiveArena* pa = & smem.primitives;
|
||||||
gknown B1* buf = (B1*) r_(smem.primitives.buf)[smem.active_buf_id];
|
gknown B1* buf = (B1*) r_(smem.primitives.buf)[smem.active_buf_id];
|
||||||
@@ -85,77 +92,31 @@ I_ B1* prim__alloc(U4 type_width, Str8 type_name) {
|
|||||||
}
|
}
|
||||||
#define prim_alloc(type) (type*)prim__alloc(S_(type), slit( stringify(type)))
|
#define prim_alloc(type) (type*)prim__alloc(S_(type), slit( stringify(type)))
|
||||||
|
|
||||||
/* Uses ONE 8-byte frame allocated via the compiler's standard prologue.
|
void
|
||||||
* The 4 wasted-arg words for B(12h) InitPAD2 live at [SP+0..15] but are not explicitly allocated.
|
resolve_look_at_c11(MT3_S2S4* look_at, V3_S4* eye, V3_S4* target, V3_S4* up_in) {
|
||||||
* The compiler handles the MIPS O32 "wasted stack" convention for us by treating the B-call as a 4-arg call.
|
// TODO(Ed): Want to interpret this under the lens of Eric Lengyel's geometric algebra
|
||||||
*
|
V3_S4 right, up, forward;
|
||||||
* The buffer pointers are passed as arguments so the compiler keeps them in callee-saved registers;
|
V3_S4 ux, uy, uz;
|
||||||
* The B(12h) asm volatile block does NOT clobber those registers (it clobbers only the volatile GPRs + the B-table arg registers explicitly).
|
V3_S4 pos, off;
|
||||||
* The C-level writes after the call re-load the pointers from their callee-saved homes.
|
|
||||||
*
|
|
||||||
* The clobber list for both B-calls names the full BIOS destroy set documented in kernelbios.md:167-174 (R1..R15, R24..R25, R31, HI/LO).
|
|
||||||
* The kernel-ABI "volatile GPRs" subset is clb_system; the rest of the destroy set is enumerated explicitly here. */
|
|
||||||
NI_ void pad_bios_init_start(PadBiosRaw* raw0, PadBiosRaw* raw1)
|
|
||||||
{
|
|
||||||
/* Pin raw0 + raw1 to $a0 + $a1 via rgcc; the B(12h) call uses these directly.
|
|
||||||
* The `(void)` casts mark them as unread after the call so the compiler doesn't need to move them back. */
|
|
||||||
register PadBiosRaw* p0 rgcc(R_A0) = raw0;
|
|
||||||
register PadBiosRaw* p1 rgcc(R_A1) = raw1;
|
|
||||||
(void)p0; (void)p1;
|
|
||||||
|
|
||||||
// TODO(Ed): Properly annotate the raw values in the inline asm instructions.
|
forward = target[0]; sub_v3s4(& forward, eye[0]);
|
||||||
// Use enums.
|
normalize_v3s4(& forward, & uz);
|
||||||
|
|
||||||
/* B(12h) InitPAD2(raw0, 0x22, raw1, 0x22)
|
cross_v3s4(& uz, up_in, & right); normalize_v3s4(& right, & ux);
|
||||||
* $a0 = raw0 (rgcc-bound; survives the sequence below)
|
cross_v3s4(& uz, & ux, & up); normalize_v3s4(& up, & uy);
|
||||||
* $a1 = raw1 (preserved into $a2 before $a1 is overwritten)
|
|
||||||
* $a2 = raw1 (moved from $a1; survives $a1's overwrite)
|
|
||||||
* $a3 = 0x22 (immediate)
|
|
||||||
* $t1 = 0x12 (function number)
|
|
||||||
* $t2 = 0xB0 (BIOS B-table address) */
|
|
||||||
asm volatile(
|
|
||||||
asm_words(
|
|
||||||
or_u( rarg_2, rarg_1, rdiscard), /* $a2 = $a1 = raw1 */
|
|
||||||
add_ui( rarg_1, rdiscard, bios_pad_buffer_size), /* $a1 = 0x22 */
|
|
||||||
add_ui( rarg_3, rdiscard, bios_pad_buffer_size), /* $a3 = 0x22 */
|
|
||||||
add_ui( rtmp_1, rdiscard, bios_init_pad_2), /* $t1 = 0x12 */
|
|
||||||
add_ui( rtmp_2, rdiscard, bios_btable_addr), /* $t2 = 0xB0 */
|
|
||||||
call_reg(rtmp_2), /* jalr $t2, $ra */
|
|
||||||
nop /* BD slot */
|
|
||||||
)
|
|
||||||
asm_rpins, r_use(p0), r_use(p1)
|
|
||||||
asm_clobber:
|
|
||||||
rlit(R_AT),
|
|
||||||
rlit(R_V0), rlit(R_V1),
|
|
||||||
rlit(R_T0), rlit(R_T1), rlit(R_T2), rlit(R_T3), rlit(R_T4),
|
|
||||||
rlit(R_T5), rlit(R_T6), rlit(R_T7), rlit(R_T8), rlit(R_T9),
|
|
||||||
rlit(R_RA),
|
|
||||||
clb_mem_drain
|
|
||||||
);
|
|
||||||
|
|
||||||
/* The C-level writes re-load the pointers via the parameter names and write 0xFF to each
|
look_at->m[0][0] = ux.x; look_at->m[0][1] = ux.y; look_at->m[0][2] = ux.z;
|
||||||
* buffer's status byte to mark the initial-state hazard documented in kernelbios.md:1621-1624. */
|
look_at->m[1][0] = uy.x; look_at->m[1][1] = uy.y; look_at->m[1][2] = uy.z;
|
||||||
u1_v(raw0)[0] = 0xFF;
|
look_at->m[2][0] = uz.x; look_at->m[2][1] = uz.y; look_at->m[2][2] = uz.z;
|
||||||
u1_v(raw1)[0] = 0xFF;
|
|
||||||
|
pos = eye[0]; mul_v3s4(& pos, v3s4(-1,-1,-1));
|
||||||
|
|
||||||
/* B(13h) StartPAD2() — no args. The BIOS preserves $sp. */
|
mul_m3s2_v3s4(look_at, & pos, & off);
|
||||||
asm volatile(
|
trans_m3s2(look_at, & off);
|
||||||
asm_words(
|
|
||||||
add_ui( rtmp_1, rdiscard, bios_start_pad_2), /* $t1 = 0x13 */
|
|
||||||
add_ui( rtmp_2, rdiscard, bios_btable_addr), /* $t2 = 0xB0 (re-load) */
|
|
||||||
call_reg(rtmp_2), /* jalr $t2, $ra */
|
|
||||||
nop /* BD slot */
|
|
||||||
)
|
|
||||||
asm_clobber:
|
|
||||||
rlit(R_AT),
|
|
||||||
rlit(R_V0), rlit(R_V1),
|
|
||||||
rlit(R_T0), rlit(R_T1), rlit(R_T2), rlit(R_T3), rlit(R_T4),
|
|
||||||
rlit(R_T5), rlit(R_T6), rlit(R_T7), rlit(R_T8), rlit(R_T9),
|
|
||||||
rlit(R_RA),
|
|
||||||
clb_mem_drain
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FI_ void camera_look_at_c11(Camera* c, V3_S4* target, V3_S4* up_in) { resolve_look_at_c11(& c->look_at, & c->pos, target, up_in); }
|
||||||
|
|
||||||
GCC_OPTIMIZATION_DISABLE
|
GCC_OPTIMIZATION_DISABLE
|
||||||
void update(PrimitiveArena* pa, U4* ordering_buf)
|
void update(PrimitiveArena* pa, U4* ordering_buf)
|
||||||
{
|
{
|
||||||
@@ -171,11 +132,36 @@ void update(PrimitiveArena* pa, U4* ordering_buf)
|
|||||||
tb_emit_(pad_bios_snapshot);
|
tb_emit_(pad_bios_snapshot);
|
||||||
tb_data_(raw, & smem.pad_raw[1]);
|
tb_data_(raw, & smem.pad_raw[1]);
|
||||||
tb_data_(state, & smem.pad[1]);
|
tb_data_(state, & smem.pad[1]);
|
||||||
// Demo input
|
|
||||||
tb_emit_(pad_apply_input);
|
// TODO(Ed): Implement based on below.
|
||||||
tb_data_(state, & smem.pad[0]);
|
// tb_emit_(pad_input_cam);
|
||||||
tb_data_(cube_rot, & smem.cube.rot);
|
// tb_data_(cam, & smem.cam);
|
||||||
tb_data_(floor_rot, & smem.floor.rot);
|
|
||||||
|
if (pad0_btn_(Pad_Left)) {
|
||||||
|
smem.cam.pos.x -= 50;
|
||||||
|
}
|
||||||
|
if (pad0_btn_(Pad_Right)) {
|
||||||
|
smem.cam.pos.x += 50;
|
||||||
|
}
|
||||||
|
if (pad0_btn_(Pad_Up)) {
|
||||||
|
smem.cam.pos.y -= 50;
|
||||||
|
}
|
||||||
|
if (pad0_btn_(Pad_Down)) {
|
||||||
|
smem.cam.pos.y += 50;
|
||||||
|
}
|
||||||
|
if (pad0_btn_(Pad_Cross)) {
|
||||||
|
smem.cam.pos.z -= 50;
|
||||||
|
}
|
||||||
|
if (pad0_btn_(Pad_Circle)) {
|
||||||
|
smem.cam.pos.z += 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Demo input (not longer using)
|
||||||
|
// tb_emit_(pad_input_cube_rotation);
|
||||||
|
// tb_data_(state, & smem.pad[0]);
|
||||||
|
// tb_data_(cube_rot, & smem.cube.rot);
|
||||||
|
// tb_data_(floor_rot, & smem.floor.rot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,15 +188,34 @@ void update(PrimitiveArena* pa, U4* ordering_buf)
|
|||||||
A2_S2 p; //???
|
A2_S2 p; //???
|
||||||
S4 flag; //????
|
S4 flag; //????
|
||||||
|
|
||||||
|
// Camera Look at
|
||||||
|
if (1)
|
||||||
|
{
|
||||||
|
camera_look_at_c11(& smem.cam, & smem.cube.pos, & v3s4(0, -fp_one, 0));
|
||||||
|
}
|
||||||
|
// Camera look at (Tape)
|
||||||
|
if (0)
|
||||||
|
{
|
||||||
|
tb.used = 0; tb_scope_run(& tb) {
|
||||||
|
tb_emit_(resolve_look_at);
|
||||||
|
// tb_data_();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Draw cube
|
// Draw cube
|
||||||
if (1)
|
if (1)
|
||||||
{
|
{
|
||||||
m3s2_rotation (& smem.cube.rot, & smem.tform_world);
|
mt3s2s4_rotation (& smem.cube.rot, & smem.tform_world);
|
||||||
m3s2_translation(& smem.tform_world, & smem.cube.pos);
|
mt3s2s4_translation(& smem.tform_world, & smem.cube.pos);
|
||||||
m3s2_scale (& smem.tform_world, & smem.cube.scale);
|
mt3s2s4_scale (& smem.tform_world, & smem.cube.scale);
|
||||||
gte_matrix_set_rotation (& smem.tform_world);
|
|
||||||
gte_matrix_set_translation(& smem.tform_world);
|
// Combine world and look_at matrix.
|
||||||
|
gte_comp_coord_m3s2(& smem.cam.look_at, & smem.tform_world, & smem.tform_view);
|
||||||
|
gte_matrix_set_rotation (& smem.tform_view);
|
||||||
|
gte_matrix_set_translation(& smem.tform_view);
|
||||||
|
|
||||||
|
// gte_matrix_set_rotation (& smem.tform_world);
|
||||||
|
// gte_matrix_set_translation(& smem.tform_world);
|
||||||
|
|
||||||
U4 prim_base = u4_(pa->buf[smem.active_buf_id]);
|
U4 prim_base = u4_(pa->buf[smem.active_buf_id]);
|
||||||
U4 prim_cursor = prim_base + pa->used;
|
U4 prim_cursor = prim_base + pa->used;
|
||||||
@@ -238,9 +243,15 @@ void update(PrimitiveArena* pa, U4* ordering_buf)
|
|||||||
// Draw floor
|
// Draw floor
|
||||||
if (1)
|
if (1)
|
||||||
{
|
{
|
||||||
m3s2_rotation (& smem.floor.rot, & smem.tform_world);
|
mt3s2s4_rotation (& smem.floor.rot, & smem.tform_world);
|
||||||
m3s2_translation(& smem.tform_world, & smem.floor.pos);
|
mt3s2s4_translation(& smem.tform_world, & smem.floor.pos);
|
||||||
m3s2_scale (& smem.tform_world, & smem.floor.scale);
|
mt3s2s4_scale (& smem.tform_world, & smem.floor.scale);
|
||||||
|
|
||||||
|
// Combine world and look_at matrix.
|
||||||
|
gte_comp_coord_m3s2(& smem.cam.look_at, & smem.tform_world, & smem.tform_view);
|
||||||
|
|
||||||
|
gte_matrix_set_rotation (& smem.tform_view);
|
||||||
|
gte_matrix_set_translation(& smem.tform_view);
|
||||||
|
|
||||||
U4 prim_base = u4_(pa->buf[smem.active_buf_id]);
|
U4 prim_base = u4_(pa->buf[smem.active_buf_id]);
|
||||||
U4 prim_cursor = prim_base + pa->used;
|
U4 prim_cursor = prim_base + pa->used;
|
||||||
@@ -250,8 +261,8 @@ void update(PrimitiveArena* pa, U4* ordering_buf)
|
|||||||
|
|
||||||
// Prepare the tape. (Push protocol to tape)
|
// Prepare the tape. (Push protocol to tape)
|
||||||
tb.used = 0; tb_scope(& tb) {
|
tb.used = 0; tb_scope(& tb) {
|
||||||
tb_emit(& tb, set_gte_world);
|
// tb_emit(& tb, set_gte_mt3s2s4);
|
||||||
tb_data(& tb, u4_(& smem.tform_world));
|
// tb_data(& tb, u4_(& smem.tform_view));
|
||||||
|
|
||||||
tb_emit(& tb, rbind_floor_f3_face);
|
tb_emit(& tb, rbind_floor_f3_face);
|
||||||
// TODO(Ed): Just use a single context struct ref?
|
// TODO(Ed): Just use a single context struct ref?
|
||||||
@@ -297,6 +308,7 @@ int main(void)
|
|||||||
smem.scratchpad = C_(U4_V, 0x1F800000);
|
smem.scratchpad = C_(U4_V, 0x1F800000);
|
||||||
// smem.primitives.used = 0;
|
// smem.primitives.used = 0;
|
||||||
// smem.active_buf_id = 0;
|
// smem.active_buf_id = 0;
|
||||||
|
smem.cam.pos = v3s4(500, -1000, -1500);
|
||||||
/*Persistent Entity Setup*/{
|
/*Persistent Entity Setup*/{
|
||||||
ent_cube128_init(& smem.cube.verts, & smem.cube.faces); {
|
ent_cube128_init(& smem.cube.verts, & smem.cube.faces); {
|
||||||
Ent_Cube* cube = & smem.cube;
|
Ent_Cube* cube = & smem.cube;
|
||||||
|
|||||||
@@ -21,12 +21,6 @@ enum {
|
|||||||
ScreenRes_CenterY = (ScreenRes_Y >> 1),
|
ScreenRes_CenterY = (ScreenRes_Y >> 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
|
||||||
fp_one = (1 << 12),
|
|
||||||
};
|
|
||||||
|
|
||||||
#define v3s4_fp_one() v3s4(fp_one, fp_one, fp_one)
|
|
||||||
|
|
||||||
typedef U4 OrderingTable_Buffer[OrderingTbl_Len];
|
typedef U4 OrderingTable_Buffer[OrderingTbl_Len];
|
||||||
typedef Array_(OrderingTable_Buffer, 2);
|
typedef Array_(OrderingTable_Buffer, 2);
|
||||||
|
|
||||||
@@ -100,3 +94,9 @@ typedef Struct_(Ent_Floor) {
|
|||||||
A4_V3_S2 verts;
|
A4_V3_S2 verts;
|
||||||
A2_V3_S2 faces;
|
A2_V3_S2 faces;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef Struct_(Camera) {
|
||||||
|
V3_S4 pos;
|
||||||
|
V3_S2 rot;
|
||||||
|
MT3_S2S4 look_at;
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user