Completed C-side of: Camera Transformation chapter. Now todo atom tape translation...

This commit is contained in:
ed
2026-08-08 16:42:07 -04:00
parent 917b764d95
commit 68b87f1c8b
11 changed files with 268 additions and 108 deletions
+1
View File
@@ -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
+1
View File
@@ -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
+6 -6
View File
@@ -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
View File
@@ -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)); }
+78
View File
@@ -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
View File
@@ -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
View File
@@ -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");
+1 -1
View File
@@ -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
+29 -3
View File
@@ -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 */
+93 -81
View File
@@ -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;
/* B(13h) StartPAD2() — no args. The BIOS preserves $sp. */ pos = eye[0]; mul_v3s4(& pos, v3s4(-1,-1,-1));
asm volatile(
asm_words( mul_m3s2_v3s4(look_at, & pos, & off);
add_ui( rtmp_1, rdiscard, bios_start_pad_2), /* $t1 = 0x13 */ trans_m3s2(look_at, & off);
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;
+6 -6
View File
@@ -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;
};