Files
pikuma_ps1/code/gte_hello/hello_gte_tape.c
T
2026-07-09 13:30:13 -04:00

194 lines
8.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#ifdef INTELLISENSE_DIRECTIVES
# include "duffle/lottes_tape.h"
# include "duffle/atom_dsl.h"
# include "hello_gte.h"
# include "tape_atom.metadata.h"
# include "gen/hello_gte_tape.offsets.h"
#endif
#pragma region MACs (Mips Atom components)
/* The macros mac_format_f3_color and mac_gte_store_f3 moved to
* lottes_tape.h during the Phase 3 gp.h overhaul. Both are now RGB-form
* (mac_format_f3_color takes _r, _g, _b byte values rather than raw
* 16-bit half-words). */
#pragma endregion MACs
#pragma region Baked Atoms
typedef Struct_(Binds_CubeTri) {
U4 PrimCursor;
U4 FaceCursor;
U4 VertBase;
U4 OtBase;
};
internal MipsAtom_(rbind_cube_g4_face) {
/* Pop 4 arguments from the tape directly into the workspace registers */
load_word(R_PrimCursor, R_TapePtr, O_(Binds_CubeTri,PrimCursor)),
load_word(R_FaceCursor, R_TapePtr, O_(Binds_CubeTri,FaceCursor)),
load_word(R_VertBase, R_TapePtr, O_(Binds_CubeTri,VertBase)),
load_word(R_OtBase, R_TapePtr, O_(Binds_CubeTri,OtBase)),
add_ui_self( R_TapePtr, S_(Binds_CubeTri)),
// Note(Ed): This entire thing is argument shuffle?
// TODO(Ed): Eliminate
mac_yield()
};
/* ============================================================================
* cube_g4_face — Draw one cube face (Gouraud-shaded quad) via the GTE tape pipeline
* ============================================================================
*
* Reads 4 indices from R_FaceCur (V4_S2 = 8 bytes), loads 4 vertices into
* the GTE, runs the PsyQ RotAverageNclip4 sequence, and renders a Poly_G4.
*/
atom_region (cube_g4_face, REGION_PRIM_ARENA)
atom_group (cube_g4_face, GROUP_RENDER_PRIMS)
atom_cadence (cube_g4_face, CADENCE_FRAME)
atom_annot(cube_g4_face, phase_work,
atom_reads( R_PrimCursor, R_FaceCursor, R_VertBase, R_OtBase),
atom_writes(R_PrimCursor, R_FaceCursor))
internal
MipsAtom_(cube_g4_face) {
/* ── 1. Load 4 face indices from R_FaceCur (V4_S2 = 8 bytes) ───────── */
load_half_u(R_T0, R_FaceCursor, 0 * S_(S2)),
load_half_u(R_T1, R_FaceCursor, 1 * S_(S2)),
load_half_u(R_T2, R_FaceCursor, 2 * S_(S2)),
load_half_u(R_T3, R_FaceCursor, 3 * S_(S2)),
/* ── 2. Load V0, V1, V2 into GTE (parallel to mac_load_tri_verts) ── */
mac_load_tri_verts(R_T0, R_T1, R_T2),
/* ── 3. RTPT — transforms V0/V1/V2 → SXY0/SXY1/SXY2 + SZ1/SZ2/SZ3 ─── */
nop2, gte_cmdw_rotate_translate_perspective_triple,
/* ── 4. NCLIP — backface culling on SXY0/SXY1/SXY2 (p0,p1,p2) ──────── */
/* MUST be done BEFORE V3-RTPS overwrites SXY0 with p3. */
nop2, gte_cmdw_nclip,
/* ── 5. Cull check: skip format/insert if MAC0 ≤ 0 (backface) ───────── */
nop2, gte_mv_from_data_r(R_T0, C2_MAC0),
nop, /* COP2 stall */
branch_le_zero(R_T0, atom_offset(cull, cube_g4_face_exit)),
nop, /* BD slot */
/* ── 6. Format c0..c3 (color+code words) BEFORE V3-RTPS ─────────────── */
store_word(R_0, R_PrimCursor, O_(Poly_G4, tag)),
mac_format_g4_color(
/* c0 magenta */ 0xFF, 0x00, 0xFF,
/* c1 yellow */ 0xFF, 0xFF, 0x00,
/* c2 cyan */ 0x00, 0xFF, 0xFF,
/* c3 green */ 0x00, 0xFF, 0x00),
/* ── 7. Store p0..p2 BEFORE V3-RTPS overwrites SXY0 ─────────────────── */
mac_gte_store_g4_p012_post_rtpt_pre_rtps(),
/* ── 8. Load V3 = verts[face->w] into V0 ─────────────────────────────── */
shift_lleft(R_AT, R_T3, v3s2_byteoff), add_u(R_AT, R_AT, R_VertBase),
load_word(R_V0, R_AT, O_(V3_S2, x)), load_word(R_V1, R_AT, O_(V3_S2, z)),
gte_mv_to_data_r(R_V0, C2_VXY0), gte_mv_to_data_r(R_V1, C2_VZ0),
/* ── 9. RTPS — transforms V0 (now V3) → SXY0 (p3) + SZ3 ─────────────── */
nop2, gte_cmdw_rotate_translate_perspective_single,
mac_gte_store_g4_p3_post_rtps(),
/* ── 10. AVSZ4 — average Z from SZ0/SZ1/SZ2/SZ3 ─────────────────────── */
nop2, gte_cmdw_avg_sort_z4,
nop2, gte_mv_from_data_r(R_T1, C2_OTZ),
/* ── 11. Bounds check OTZ < OrderingTbl_Len ─────────────────────────── */
add_ui( R_AT, R_0, OrderingTbl_Len),
set_lt_u( R_AT, R_T1, R_AT),
branch_equal(R_AT, R_0, atom_offset(bounds_chk, cube_g4_face_exit)), nop,
/* ── 12. Insert into Ordering Table (length = 8 words for Poly_G4) ──── */
mac_insert_ot_tag(R_T1, Poly_G4),
/* ── 13. Advance cursors & yield (both branch targets land here) ────── */
atom_label(cube_g4_face_exit)
add_ui_self(R_PrimCursor, S_(Poly_G4)), /* 9 words = Poly_G4 */
add_ui_self(R_FaceCursor, S_(S2) * 4), /* 4 × S2 = 8 bytes */
mac_yield()
};
typedef Struct_(Binds_FloorTri) {
U4 PrimCursor;
U4 FaceCursor;
U4 VertBase;
U4 OtBase;
};
atom_region(rbind_floor_f3_face, REGION_PRIM_ARENA)
atom_group(rbind_floor_f3_face, GROUP_RENDER_FLOOR)
atom_cadence(rbind_floor_f3_face, CADENCE_FRAME)
atom_annot(rbind_floor_f3_face, phase_bind
, atom_reads()
, atom_writes(R_PrimCursor, R_FaceCursor, R_VertBase, R_OtBase))
internal
MipsAtom_(rbind_floor_f3_face) {
/* Pop 4 arguments from the tape directly into the workspace registers */
load_word(R_PrimCursor, R_TapePtr, O_(Binds_FloorTri,PrimCursor)),
load_word(R_FaceCursor, R_TapePtr, O_(Binds_FloorTri,FaceCursor)),
load_word(R_VertBase, R_TapePtr, O_(Binds_FloorTri,VertBase)),
load_word(R_OtBase, R_TapePtr, O_(Binds_FloorTri,OtBase)),
add_ui_self( R_TapePtr, S_(Binds_FloorTri)),
mac_yield()
};
atom_region( floor_f3_face, REGION_PRIM_ARENA)
atom_group( floor_f3_face, GROUP_RENDER_FLOOR)
atom_cadence(floor_f3_face, CADENCE_FRAME)
atom_annot( floor_f3_face, phase_work,
atom_reads( R_PrimCursor, R_FaceCursor, R_VertBase, R_OtBase),
atom_writes(R_PrimCursor, R_FaceCursor))
internal
MipsAtom_(floor_f3_face) {
mac_load_tri_indices(R_T0, R_T1, R_T2),
mac_load_tri_verts( R_T0, R_T1, R_T2),
nop2, gte_cmdw_rotate_translate_perspective_triple,
nop2, gte_cmdw_nclip,
/* Culling (Branch forward if Backface) */
nop2, gte_mv_from_data_r(R_T0, C2_MAC0),
nop,
branch_le_zero(R_T0, atom_offset(culling, floor_f3_face_exit)), nop,
/* Format Primitive */
// mac_format_f3_color(0x20FF, 0xFFFF), // works
mac_format_f3_color(0xFF, 0xFF, 0xFF), // RGB-form (R=FF, G=FF, B=FF = white)
mac_gte_store_f3_post_rtpt(),
/* Calculate Depth */
nop2, gte_avg_sort_z3,
nop2, gte_mv_from_data_r(R_T1, C2_OTZ),
/* Bounds Check OTZ < 2048 (Branch forward to skip insertion) */
add_ui( R_AT, R_0, OrderingTbl_Len),
set_lt_u( R_AT, R_T1, R_AT),
branch_equal(R_AT, R_0, atom_offset(bounds_chk, floor_f3_face_exit)), nop,
/* Insert into Ordering Table Linked List */
mac_insert_ot_tag(R_T1, Poly_F3),
add_ui_self(R_PrimCursor, S_(Poly_F3)), /* Advance Prim Cursor (5 words) */
// Note(Ed): No bounds checking, should be checked before atom runs.
/* Advance Input Cursor & Yield (Both branch targets land here) */
atom_label(floor_f3_face_exit)
add_ui_self(R_FaceCursor, S_(S2) * 4), /* Advance Face Cursor (4 * S2 = 8 bytes) */
mac_yield()
};
typedef Struct_(Binds_SyncPrimitiveArena) { U4 used; U4 cursor; };
atom_region( sync_primitive_arena, REGION_PRIM_ARENA)
atom_group( sync_primitive_arena, GROUP_RENDER_FLOOR)
atom_cadence(sync_primitive_arena, CADENCE_FRAME)
atom_annot( sync_primitive_arena, phase_work,
atom_reads( R_TapePtr, R_PrimCursor),
atom_writes(R_TapePtr))
internal MipsAtom_(sync_primitive_arena) {
load_word(R_AT, R_TapePtr, O_(Binds_SyncPrimitiveArena,used)),
load_word(R_T0, R_TapePtr, O_(Binds_SyncPrimitiveArena,cursor)),
add_ui_self( R_TapePtr, S_(Binds_SyncPrimitiveArena)),
/* Calculate byte offset and store directly back to RAM */
sub_u( R_T0, R_PrimCursor, R_T0), // R_T0 = R_PrimCursor - binds.cursor
store_word(R_T0, R_AT, 0), // R_AT[0] = R_T0
mac_yield()
};
#pragma endregion Baked Atoms