diff --git a/code/duffle/gen/macs.h b/code/duffle/gen/macs.h index e2c9069..e20e7a3 100644 --- a/code/duffle/gen/macs.h +++ b/code/duffle/gen/macs.h @@ -16,6 +16,7 @@ // 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\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\mips.atom.c // source: C:\projects\Pikuma\ps1\code\duffle\gte.atom.c diff --git a/code/duffle/gen/offsets.h b/code/duffle/gen/offsets.h index 4417594..3d5988c 100644 --- a/code/duffle/gen/offsets.h +++ b/code/duffle/gen/offsets.h @@ -13,6 +13,7 @@ // 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\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\mips.atom.c // source: C:\projects\Pikuma\ps1\code\duffle\gte.atom.c diff --git a/code/duffle/gte.atom.c b/code/duffle/gte.atom.c index eb131ce..9bc8f8f 100644 --- a/code/duffle/gte.atom.c +++ b/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 -typedef Struct_(Binds_SetGteWorld) { - M3_S2* transform; +typedef Struct_(Binds_SetGteMT3S2S4) { + MT3_S2S4* transform; }; -internal MipsAtom_(set_gte_world) atom_info( - atom_bind(Binds_SetGteWorld) +internal MipsAtom_(set_gte_mt3s2s4) atom_info( + atom_bind(Binds_SetGteMT3S2S4) , atom_reads(R_TapePtr) ){ /* Pop matrix address from tape into R_T3 ($11) */ - load_word(R_T3, R_TapePtr, O_(Binds_SetGteWorld,transform)), - add_ui_self( R_TapePtr, S_(Binds_SetGteWorld)), + load_word(R_T3, R_TapePtr, O_(Binds_SetGteMT3S2S4,transform)), + add_ui_self( R_TapePtr, S_(Binds_SetGteMT3S2S4)), /* 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), gte_mv_to_ctrl_r(R_T0, gte_cr_RT11), gte_mv_to_ctrl_r(R_T1, gte_cr_RT12), diff --git a/code/duffle/math.h b/code/duffle/math.h index b1c8656..a518231 100644 --- a/code/duffle/math.h +++ b/code/duffle/math.h @@ -26,8 +26,8 @@ typedef Struct_(Extent2_S4) { S4 width; S4 height; }; typedef Struct_(V2_U1) { U1 x; U1 y; }; typedef Struct_(V2_S2) { S2 x; S2 y; }; typedef Struct_(V2_S4) { S4 x; S4 y; }; -typedef Struct_(V3_S2) { S2 x; S2 y; S2 z; S2 pad; }; -typedef Struct_(V3_S4) { S4 x; S4 y; S4 z; S4 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; }; // PSY-Q: VECTOR typedef Struct_(V4_S2) { S2 x; S2 y; S2 z; S2 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_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_S2, 2); typedef Array_(V2_S2, 3); 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 v3s2(x,y,z) (V3_S2){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; } +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_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)); } + + diff --git a/code/duffle/pad.c b/code/duffle/pad.c new file mode 100644 index 0000000..22dba47 --- /dev/null +++ b/code/duffle/pad.c @@ -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 + ); +} diff --git a/code/duffle/pad.h b/code/duffle/pad.h index 7d1da32..87a9301 100644 --- a/code/duffle/pad.h +++ b/code/duffle/pad.h @@ -33,9 +33,6 @@ enum { 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)) * ============================================================================= */ @@ -113,3 +110,5 @@ typedef Struct_(PadState) { }; }; }; + +internal void pad_bios_init_start(PadBiosRaw* raw0, PadBiosRaw* raw1); diff --git a/code/duffle/psyq.h b/code/duffle/psyq.h index da885e6..39def23 100644 --- a/code/duffle/psyq.h +++ b/code/duffle/psyq.h @@ -64,9 +64,9 @@ typedef Struct_(Tile) { Linear Algebra */ -M3_S2* m3s2_rotation (V3_S2* vec, M3_S2* mat) asm("RotMatrix"); -M3_S2* m3s2_translation(M3_S2* mat, V3_S4* vec) asm("TransMatrix"); -M3_S2* m3s2_scale (M3_S2* mat, V3_S4* vec) asm("ScaleMatrix"); +MT3_S2S4* mt3s2s4_rotation (V3_S2* vec, MT3_S2S4* mat) asm("RotMatrix"); +MT3_S2S4* mt3s2s4_translation(MT3_S2S4* mat, V3_S4* vec) asm("TransMatrix"); +MT3_S2S4* mt3s2s4_scale (MT3_S2S4* mat, V3_S4* vec) asm("ScaleMatrix"); // 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_translation(M3_S2* mat) asm("SetTransMatrix"); +void gte_matrix_set_rotation (MT3_S2S4* mat) asm("SetRotMatrix"); +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"); diff --git a/code/hello_camera/gen/offsets.h b/code/hello_camera/gen/offsets.h index c04cf3b..7daa1ea 100644 --- a/code/hello_camera/gen/offsets.h +++ b/code/hello_camera/gen/offsets.h @@ -8,7 +8,7 @@ #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_right_exit_dpad_right 6 diff --git a/code/hello_camera/hello_camera.atom.c b/code/hello_camera/hello_camera.atom.c index ce64f55..bbd7e14 100644 --- a/code/hello_camera/hello_camera.atom.c +++ b/code/hello_camera/hello_camera.atom.c @@ -210,7 +210,7 @@ enum { R_CubeRot = R_T1 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_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? /* 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_T3, R_FloorRot, O_(V3_S2,y)), 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) /* 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_T3, R_FloorRot, O_(V3_S2,y)), add_si( R_T4, R_T4, -30), @@ -312,6 +312,32 @@ atom_label(exit_stick) 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 { 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 */ diff --git a/code/hello_camera/hello_camera.c b/code/hello_camera/hello_camera.c index b2ed29b..52e24d3 100644 --- a/code/hello_camera/hello_camera.c +++ b/code/hello_camera/hello_camera.c @@ -31,6 +31,7 @@ #pragma endregion Duffle Headers #pragma region Duffle TUs +#include "duffle/pad.c" #include "duffle/math.atom.c" #include "duffle/mips.atom.c" #include "duffle/gte.atom.c" @@ -62,7 +63,10 @@ typedef Struct_(SMemory) { U4 MemTape[MemTape_Len]; - M3_S2 tform_world; + MT3_S2S4 tform_world; + MT3_S2S4 tform_view; + + Camera cam; Ent_Cube cube; Ent_Floor floor; @@ -75,6 +79,9 @@ typedef Struct_(SMemory) { global 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) { gknown PrimitiveArena* pa = & smem.primitives; 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))) -/* Uses ONE 8-byte frame allocated via the compiler's standard prologue. - * The 4 wasted-arg words for B(12h) InitPAD2 live at [SP+0..15] but are not explicitly allocated. - * The 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 + the 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_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; +void +resolve_look_at_c11(MT3_S2S4* look_at, V3_S4* eye, V3_S4* target, V3_S4* up_in) { +// TODO(Ed): Want to interpret this under the lens of Eric Lengyel's geometric algebra + V3_S4 right, up, forward; + V3_S4 ux, uy, uz; + V3_S4 pos, off; - // TODO(Ed): Properly annotate the raw values in the inline asm instructions. - // Use enums. + forward = target[0]; sub_v3s4(& forward, eye[0]); + normalize_v3s4(& forward, & uz); - /* 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 - ); + cross_v3s4(& uz, up_in, & right); normalize_v3s4(& right, & ux); + cross_v3s4(& uz, & ux, & up); normalize_v3s4(& up, & uy); - /* 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; + look_at->m[0][0] = ux.x; look_at->m[0][1] = ux.y; look_at->m[0][2] = ux.z; + look_at->m[1][0] = uy.x; look_at->m[1][1] = uy.y; look_at->m[1][2] = uy.z; + look_at->m[2][0] = uz.x; look_at->m[2][1] = uz.y; look_at->m[2][2] = uz.z; + + pos = eye[0]; mul_v3s4(& pos, v3s4(-1,-1,-1)); - /* 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 - ); + mul_m3s2_v3s4(look_at, & pos, & off); + trans_m3s2(look_at, & off); } +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 void update(PrimitiveArena* pa, U4* ordering_buf) { @@ -171,11 +132,36 @@ void update(PrimitiveArena* pa, U4* ordering_buf) tb_emit_(pad_bios_snapshot); tb_data_(raw, & smem.pad_raw[1]); tb_data_(state, & smem.pad[1]); - // Demo input - tb_emit_(pad_apply_input); - tb_data_(state, & smem.pad[0]); - tb_data_(cube_rot, & smem.cube.rot); - tb_data_(floor_rot, & smem.floor.rot); + + // TODO(Ed): Implement based on below. + // tb_emit_(pad_input_cam); + // tb_data_(cam, & smem.cam); + + 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; //??? 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 if (1) { - m3s2_rotation (& smem.cube.rot, & smem.tform_world); - m3s2_translation(& smem.tform_world, & smem.cube.pos); - m3s2_scale (& smem.tform_world, & smem.cube.scale); - gte_matrix_set_rotation (& smem.tform_world); - gte_matrix_set_translation(& smem.tform_world); + mt3s2s4_rotation (& smem.cube.rot, & smem.tform_world); + mt3s2s4_translation(& smem.tform_world, & smem.cube.pos); + mt3s2s4_scale (& smem.tform_world, & smem.cube.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); + + // 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_cursor = prim_base + pa->used; @@ -238,9 +243,15 @@ void update(PrimitiveArena* pa, U4* ordering_buf) // Draw floor if (1) { - m3s2_rotation (& smem.floor.rot, & smem.tform_world); - m3s2_translation(& smem.tform_world, & smem.floor.pos); - m3s2_scale (& smem.tform_world, & smem.floor.scale); + mt3s2s4_rotation (& smem.floor.rot, & smem.tform_world); + mt3s2s4_translation(& smem.tform_world, & smem.floor.pos); + 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_cursor = prim_base + pa->used; @@ -250,8 +261,8 @@ void update(PrimitiveArena* pa, U4* ordering_buf) // Prepare the tape. (Push protocol to tape) tb.used = 0; tb_scope(& tb) { - tb_emit(& tb, set_gte_world); - tb_data(& tb, u4_(& smem.tform_world)); + // tb_emit(& tb, set_gte_mt3s2s4); + // tb_data(& tb, u4_(& smem.tform_view)); tb_emit(& tb, rbind_floor_f3_face); // TODO(Ed): Just use a single context struct ref? @@ -297,6 +308,7 @@ int main(void) smem.scratchpad = C_(U4_V, 0x1F800000); // smem.primitives.used = 0; // smem.active_buf_id = 0; + smem.cam.pos = v3s4(500, -1000, -1500); /*Persistent Entity Setup*/{ ent_cube128_init(& smem.cube.verts, & smem.cube.faces); { Ent_Cube* cube = & smem.cube; diff --git a/code/hello_camera/hello_camera.h b/code/hello_camera/hello_camera.h index 8c3f9ce..9c0de65 100644 --- a/code/hello_camera/hello_camera.h +++ b/code/hello_camera/hello_camera.h @@ -21,12 +21,6 @@ enum { 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 Array_(OrderingTable_Buffer, 2); @@ -100,3 +94,9 @@ typedef Struct_(Ent_Floor) { A4_V3_S2 verts; A2_V3_S2 faces; }; + +typedef Struct_(Camera) { + V3_S4 pos; + V3_S2 rot; + MT3_S2S4 look_at; +};