Final ideation before finish updates lua metaprogram before hello-cdrom

This commit is contained in:
ed
2026-08-21 00:23:28 -04:00
parent f1801343e2
commit b2858b3c73
8 changed files with 64 additions and 74 deletions
+1 -7
View File
@@ -160,7 +160,7 @@
* ----------------------------------------------------------------------------*/ * ----------------------------------------------------------------------------*/
#define atom_bind(binds_struct) /* atom_bind(binds_struct) */ #define atom_bind(binds_struct) /* atom_bind(binds_struct) */
#define Binds_(type) (tmpl(Binds,type) // TODO(Ed): Do we want to use this? #define Binds_(type) (tmpl(Binds,type)) // TODO(Ed): Do we want to use this?
/* ============================================================================ /* ============================================================================
* atom_label / atom_offset — branch target machinery * atom_label / atom_offset — branch target machinery
@@ -179,9 +179,3 @@
#define atom_offset(F, T) atom_offset_ ## F ## _ ## T #define atom_offset(F, T) atom_offset_ ## F ## _ ## T
// atom_label is a pure annotation for the metaprogram's offset calculations. // atom_label is a pure annotation for the metaprogram's offset calculations.
#define atom_label(name) /* atom_label anchor: name */ #define atom_label(name) /* atom_label anchor: name */
// WIP: Atoms Assocated closely with each other to form a tape procedure. (Maybe also a phase in a procedure/pipeline?)
#define AtomBundle_(name) Struct_(tmpl(AtomBundle,name))
#define AtomBundle_Len(name) S_(tmpl(AtomBundle,name))/S_(MipsAtom*)
#define AtomBundleEntry_(bundle,entry) tmpl(bundle,entry)
+7 -7
View File
@@ -228,21 +228,21 @@ WORD_COUNT(mac_gte_op_cross_v3s4, 13)
WORD_COUNT(mac_gte_store_f3, 3) WORD_COUNT(mac_gte_store_f3, 3)
/* atom_dbg_skip */ /* atom_dbg_skip */
#define mac_gte_load_tri_verts(r_vert_base, r_v0, r_v1, r_v2) \ #define mac_gte_load_tri_verts(vbase, v0, v1, v2) \
shift_lleft(R_AT, r_v0, v3s2_byteoff) \ shift_lleft(R_AT, v0, v3s2_byteoff) \
, add_u_self(R_AT, r_vert_base) \ , add_u_self(R_AT, vbase) \
, load_word(R_V0, R_AT, O_(V3_S2,x)) \ , load_word(R_V0, R_AT, O_(V3_S2,x)) \
, load_word(R_V1, R_AT, O_(V3_S2,z)) \ , load_word(R_V1, R_AT, O_(V3_S2,z)) \
, LdSlot_ gte_mv_to_data_r(R_V0, C2_VXY0) \ , LdSlot_ gte_mv_to_data_r(R_V0, C2_VXY0) \
, gte_mv_to_data_r(R_V1, C2_VZ0) \ , gte_mv_to_data_r(R_V1, C2_VZ0) \
, shift_lleft(R_AT, r_v1, v3s2_byteoff) \ , shift_lleft(R_AT, v1, v3s2_byteoff) \
, add_u_self(R_AT, r_vert_base) \ , add_u_self(R_AT, vbase) \
, load_word(R_V0, R_AT, O_(V3_S2,x)) \ , load_word(R_V0, R_AT, O_(V3_S2,x)) \
, load_word(R_V1, R_AT, O_(V3_S2,z)) \ , load_word(R_V1, R_AT, O_(V3_S2,z)) \
, LdSlot_ gte_mv_to_data_r(R_V0, C2_VXY1) \ , LdSlot_ gte_mv_to_data_r(R_V0, C2_VXY1) \
, gte_mv_to_data_r(R_V1, C2_VZ1) \ , gte_mv_to_data_r(R_V1, C2_VZ1) \
, shift_lleft(R_AT, r_v2, v3s2_byteoff) \ , shift_lleft(R_AT, v2, v3s2_byteoff) \
, add_u_self(R_AT, r_vert_base) \ , add_u_self(R_AT, vbase) \
, load_word(R_V0, R_AT, O_(V3_S2,x)) \ , load_word(R_V0, R_AT, O_(V3_S2,x)) \
, load_word(R_V1, R_AT, O_(V3_S2,z)) \ , load_word(R_V1, R_AT, O_(V3_S2,z)) \
, LdSlot_ gte_mv_to_data_r(R_V0, C2_VXY2) \ , LdSlot_ gte_mv_to_data_r(R_V0, C2_VXY2) \
+10 -10
View File
@@ -63,10 +63,10 @@ FI_ Slice_MipsCode ac_gte_store_f3(AtomBuilder_R ab, U4 r_primitive_cursor) atom
}) })
/* Words: 18; Translates indices to vertex addresses and pushes them to GTE */ /* Words: 18; Translates indices to vertex addresses and pushes them to GTE */
I_ Slice_MipsCode ac_gte_load_tri_verts(AtomBuilder_R ab, U4 r_vert_base, U4 r_v0, U4 r_v1, U4 r_v2) atom_dbg_skip MipsAtomComp_Proc_(ab, { I_ Slice_MipsCode ac_gte_load_tri_verts(AtomBuilder_R ab, Reg vbase, Reg v0, Reg v1, Reg v2) atom_dbg_skip MipsAtomComp_Proc_(ab, {
shift_lleft(R_AT, r_v0, v3s2_byteoff), add_u_self(R_AT, r_vert_base), load_word(R_V0, R_AT, O_(V3_S2,x)), load_word(R_V1, R_AT, O_(V3_S2,z)), LdSlot_ gte_mv_to_data_r(R_V0, C2_VXY0), gte_mv_to_data_r(R_V1, C2_VZ0), shift_lleft(R_AT, v0, v3s2_byteoff), add_u_self(R_AT, vbase), load_word(R_V0, R_AT, O_(V3_S2,x)), load_word(R_V1, R_AT, O_(V3_S2,z)), LdSlot_ gte_mv_to_data_r(R_V0, C2_VXY0), gte_mv_to_data_r(R_V1, C2_VZ0),
shift_lleft(R_AT, r_v1, v3s2_byteoff), add_u_self(R_AT, r_vert_base), load_word(R_V0, R_AT, O_(V3_S2,x)), load_word(R_V1, R_AT, O_(V3_S2,z)), LdSlot_ gte_mv_to_data_r(R_V0, C2_VXY1), gte_mv_to_data_r(R_V1, C2_VZ1), shift_lleft(R_AT, v1, v3s2_byteoff), add_u_self(R_AT, vbase), load_word(R_V0, R_AT, O_(V3_S2,x)), load_word(R_V1, R_AT, O_(V3_S2,z)), LdSlot_ gte_mv_to_data_r(R_V0, C2_VXY1), gte_mv_to_data_r(R_V1, C2_VZ1),
shift_lleft(R_AT, r_v2, v3s2_byteoff), add_u_self(R_AT, r_vert_base), load_word(R_V0, R_AT, O_(V3_S2,x)), load_word(R_V1, R_AT, O_(V3_S2,z)), LdSlot_ gte_mv_to_data_r(R_V0, C2_VXY2), gte_mv_to_data_r(R_V1, C2_VZ2), shift_lleft(R_AT, v2, v3s2_byteoff), add_u_self(R_AT, vbase), load_word(R_V0, R_AT, O_(V3_S2,x)), load_word(R_V1, R_AT, O_(V3_S2,z)), LdSlot_ gte_mv_to_data_r(R_V0, C2_VXY2), gte_mv_to_data_r(R_V1, C2_VZ2),
}) })
/* Words: 3; Stores the 3 transformed (V2_S2 screen) vertices of the /* Words: 3; Stores the 3 transformed (V2_S2 screen) vertices of the
@@ -267,11 +267,11 @@ internal S2 const gte_normalize_sqr_tbl[192] align_(2) = {
0x0820, 0x081c, 0x0818, 0x0814, 0x0810, 0x080c, 0x0808, 0x0804, 0x0820, 0x081c, 0x0818, 0x0814, 0x0810, 0x080c, 0x0808, 0x0804,
}; };
typedef Struct_(Binds_NormalizeV3S4) { typedef Struct_(Binds_normalize_v3s4) {
U2 src_offset; /* offset of src V3_S4 within the BIOS scratchpad */ U2 src_offset; /* offset of src V3_S4 within the BIOS scratchpad */
U2 dst_offset; /* offset of dst V3_S4 within the BIOS scratchpad */ U2 dst_offset; /* offset of dst V3_S4 within the BIOS scratchpad */
}; };
typedef Struct_(RegUse_build_normalize_v3s4) { typedef Struct_(RegUse_normalize_v3s4) {
union { Reg_(V3_S4) res, src; }; union { Reg_(V3_S4) res, src; };
union { Reg r0, src_ptr, mac2; }; union { Reg r0, src_ptr, mac2; };
union { Reg r1, dst_ptr; }; union { Reg r1, dst_ptr; };
@@ -282,13 +282,13 @@ typedef Struct_(RegUse_build_normalize_v3s4) {
}; };
/* ─── Full normalize (all 4 stages inline) ─── /* ─── Full normalize (all 4 stages inline) ───
* Generic 4-stage GTE normalize (SQR → sum+LZCR → align+sqrtbl → GPF+srav). */ * Generic 4-stage GTE normalize (SQR → sum+LZCR → align+sqrtbl → GPF+srav). */
internal MipsAtom* build_normalize_v3s4(AtomArena_R aa, RegUse_build_normalize_v3s4 r) internal MipsAtom* normalize_v3s4(AtomArena_R aa, RegUse_normalize_v3s4 r)
MipsAtom_Proc_(aa, { MipsAtom_Proc_(aa, {
load_half(r.src_offset, R_TapePtr, O_(Binds_NormalizeV3S4, src_offset)), load_half(r.src_offset, R_TapePtr, O_(Binds_normalize_v3s4, src_offset)),
load_half(r.dst_offset, R_TapePtr, O_(Binds_NormalizeV3S4, dst_offset)), load_half(r.dst_offset, R_TapePtr, O_(Binds_normalize_v3s4, dst_offset)),
LdSlot_ add_u(r.src_ptr, R_ScratchBase, r.src_offset), LdSlot_ add_u(r.src_ptr, R_ScratchBase, r.src_offset),
LdSlot_ add_u(r.dst_ptr, R_ScratchBase, r.dst_offset), LdSlot_ add_u(r.dst_ptr, R_ScratchBase, r.dst_offset),
LdSlot_ add_ui_self(R_TapePtr, S_(Binds_NormalizeV3S4)), LdSlot_ add_ui_self(R_TapePtr, S_(Binds_normalize_v3s4)),
mac_load_v3s4(r.src, r.src_ptr, 0), mac_load_v3s4(r.src, r.src_ptr, 0),
+9
View File
@@ -163,6 +163,12 @@ typedef Slice_(MipsAtom);
// Used for trivial mappings from one atom component proc to the command of a more baser (meant for type-mapping) // Used for trivial mappings from one atom component proc to the command of a more baser (meant for type-mapping)
#define MipsAtomComp_ProcMap_(ab, base_command) atom_dbg_skip MipsAtomComp_Proc_(ab, {base_command }) #define MipsAtomComp_ProcMap_(ab, base_command) atom_dbg_skip MipsAtomComp_Proc_(ab, {base_command })
// WIP: Atoms Assocated closely with each other to form a tape procedure. (Maybe also a phase in a procedure/pipeline?)
#define AtomBundle_(name) Struct_(tmpl(AtomBundle,name))
#define AtomBundle_Len(name) S_(tmpl(AtomBundle,name))/S_(MipsAtom*)
#define AtomBundleEntry_(bundle,entry) tmpl(bundle,entry)
/* Line-table anchor: gcc only adds a file to the .debug_line file table when the contains line-numbered content. /* Line-table anchor: gcc only adds a file to the .debug_line file table when the contains line-numbered content.
Files containing only atoms and atom components. Files containing only atoms and atom components.
Place `ATOM_FILE_LINE_MARKER();` once at file scope in any `.atom.c` that defines atoms. Place `ATOM_FILE_LINE_MARKER();` once at file scope in any `.atom.c` that defines atoms.
@@ -247,6 +253,9 @@ FI_ void tb_data(TapeBuilder* tb, U4 data) { u4_r(tb->ptr)[tb->used] = u4
FI_ void tb_bind(TapeBuilder* tb, Slice data) { mem_copy(tb->ptr + tb->used * S_(MipsCode), u4_(data.ptr), data.len); tb->used += data.len / S_(MipsCode); } FI_ void tb_bind(TapeBuilder* tb, Slice data) { mem_copy(tb->ptr + tb->used * S_(MipsCode), u4_(data.ptr), data.len); tb->used += data.len / S_(MipsCode); }
#define tb_bind_(tb,type,...) tb_bind(tb, (Slice){ (B1*)(& (type){__VA_ARGS__}), S_(type) }); static_assert(S_(type) % S_(MipsCode) == 0) #define tb_bind_(tb,type,...) tb_bind(tb, (Slice){ (B1*)(& (type){__VA_ARGS__}), S_(type) }); static_assert(S_(type) % S_(MipsCode) == 0)
#define tb_emit_wbind_(tb,atom,...) tb_emit(tb,atom); tb_bind_(tb,tmpl(Binds,atom),__VA_ARGS__)
#define tb_emit_wbind2_(tb,atom,type,...) tb_emit(tb,atom); tb_bind_(tb,type,__VA_ARGS__)
FI_ Tape tb_end (TapeBuilder* tb) { tb_emit(tb,tape_exit); return (Tape){ C_(U4*,tb->ptr), tb->used }; } FI_ Tape tb_end (TapeBuilder* tb) { tb_emit(tb,tape_exit); return (Tape){ C_(U4*,tb->ptr), tb->used }; }
FI_ Tape tb_slice(TapeBuilder tb) { return (Tape){ C_(U4*,tb.ptr), tb.used }; } FI_ Tape tb_slice(TapeBuilder tb) { return (Tape){ C_(U4*,tb.ptr), tb.used }; }
#define tb_scope(tb) for(U4 tbs_once=0;tbs_once==0;++tbs_once,tb_emit(tb,tape_exit)) #define tb_scope(tb) for(U4 tbs_once=0;tbs_once==0;++tbs_once,tb_emit(tb,tape_exit))
+2 -9
View File
@@ -4,10 +4,7 @@
# include "math.h" # include "math.h"
#endif #endif
/* PSX button bit positions — 1:1 with PSX-SPX docs at docs/psx-spx/docs/controllersandmemorycards.md:405-421. // PSX button bit positions: PSX-SPX docs/psx-spx/docs/controllersandmemorycards.md:405-421.
* Wire is active-low (0 = pressed).
* The decoder atom computes buttons = (~raw_buttons) & 0xFFFF;
* active-low-to-active-high inversion is applied bit-by-bit. */
typedef Enum_(U2, PadBtns) { typedef Enum_(U2, PadBtns) {
Bit_(Pad_Select, 0), Bit_(Pad_Select, 0),
Bit_(Pad_L3, 1), Bit_(Pad_L3, 1),
@@ -62,11 +59,7 @@ typedef Enum_(U4, PadStatus) {
PadStatus_Invalid, PadStatus_Invalid,
}; };
/* Distinct from the game-facing PadStatus enum: PadRawStatus_Ok and PadRawStatus_Timeout are raw BIOS values; // Distinct from the game-facing PadStatus enum: PadRawStatus_Ok and PadRawStatus_Timeout are raw BIOS values
* PadStatus_* are game-facing post-decode states. PadUnknownId_Sentinel is written by the decoder
* when the controller id does not match any known controller type.
* PadAxisCentered_Word: Four-byte 0x80 pattern used to clear / center
* four byte axes at PadState.left_x through PadState.right_y. */
typedef Enum_(U1, PadRawStatus) { typedef Enum_(U1, PadRawStatus) {
PadRawStatus_Ok = 0x00, PadRawStatus_Ok = 0x00,
PadRawStatus_Timeout = 0xFF, PadRawStatus_Timeout = 0xFF,
+1 -1
View File
@@ -104,7 +104,7 @@ void gte_matrix_set_translation(MT3_S2S4* mat) asm("SetTransMatrix");
// Einheit, Metrication to unit vector. "Normalization", not Orthogonal "Normal, Normalis". Directionalization. // Einheit, Metrication to unit vector. "Normalization", not Orthogonal "Normal, Normalis". Directionalization.
// RGA(Lengyel): Normalize the bulk of a zero-weight direction. This is not finite-point unitization (which forces w=1). // RGA(Lengyel): Normalize the bulk of a zero-weight direction. This is not finite-point unitization (which forces w=1).
S4 normalize_v3s4(V3_S4* v0, V3_S4* v1) asm("VectorNormal"); S4 psy_normalize_v3s4(V3_S4* v0, V3_S4* v1) asm("VectorNormal");
// RGA(Lengyel): Apply the matrix expansion of a rigid transformation. // RGA(Lengyel): Apply the matrix expansion of a rigid transformation.
// Motor antiproduct is equivalent for unitized points; LA form is what GTE consumes. // Motor antiproduct is equivalent for unitized points; LA form is what GTE consumes.
+1 -1
View File
@@ -155,7 +155,7 @@ atom_info(atom_bind(Binds_ResolveLookAtSub)) MipsAtom_Proc_(aa, {
}) })
typedef Struct_(Binds_ResolveLookAt_PopulateMT3S4S2) { typedef Struct_(Binds_ResolveLookAt_PopulateMT3S4S2) {
U4 look_at; /* MT3_S2S4* — destination matrix address */ MT3_S2S4* look_at; /* MT3_S2S4* — destination matrix address */
}; };
typedef Struct_(RegUse_resolve_look_at_populate_mt3s4s2) { typedef Struct_(RegUse_resolve_look_at_populate_mt3s4s2) {
Reg look_at; Reg look_at;
+33 -39
View File
@@ -80,9 +80,6 @@ typedef Struct_(SMemory) {
PadBiosRaw pad_raw[2]; PadBiosRaw pad_raw[2];
PadState pad[2]; PadState pad[2];
// TODO(Ed): We don't need this we can just cast at any point an address to a desired view of scratchpad, we have the address.
U4_V scratchpad; // d-cache
U1 ct_init_atom_mem[CT_InitAtomMem_Size]; U1 ct_init_atom_mem[CT_InitAtomMem_Size];
MipsAtom* normalize_v3s4; MipsAtom* normalize_v3s4;
MipsAtom* gte_cross_v3s4; MipsAtom* gte_cross_v3s4;
@@ -114,7 +111,7 @@ I_ void resolve_look_at_c11(MT3_S2S4* look_at, P3_S4* eye, P3_S4* target, V3_S4*
V3_S4 pos, off; V3_S4 pos, off;
forward = target[0]; sub_v3s4(& forward, eye[0]); // RGA(Lengyel): Affine point - point = zero-weight direction. forward = target[0]; sub_v3s4(& forward, eye[0]); // RGA(Lengyel): Affine point - point = zero-weight direction.
normalize_v3s4(& forward, & uz); // RGA(Lengyel): Normalize the direction bulk. Not finite-point unitization. psy_normalize_v3s4(& forward, & uz); // RGA(Lengyel): Normalize the direction bulk. Not finite-point unitization.
cross_v3s4(& uz, up_in, & right); normalize_v3s4(& right, & ux); // RGA(Lengyel): Complement(Wedge(forward, up_in)) -> right axis. cross_v3s4(& uz, up_in, & right); normalize_v3s4(& right, & ux); // RGA(Lengyel): Complement(Wedge(forward, up_in)) -> right axis.
cross_v3s4(& uz, & ux, & up); normalize_v3s4(& up, & uy); // RGA(Lengyel): Complement(Wedge(forward, right)) -> up axis. cross_v3s4(& uz, & ux, & up); normalize_v3s4(& up, & uy); // RGA(Lengyel): Complement(Wedge(forward, right)) -> up axis.
@@ -149,8 +146,8 @@ internal void compile_init_atoms(void) {
}); });
regfile_reset(& rf); regfile_reset(& rf);
smem.normalize_v3s4 = build_normalize_v3s4(& ab, smem.normalize_v3s4 = normalize_v3s4(& ab,
RegUse_(build_normalize_v3s4) { RegUse_(normalize_v3s4) {
.res = ralloc_v3(), .res = ralloc_v3(),
.r0 = ralloc(), .r0 = ralloc(),
.r1 = ralloc(), .r1 = ralloc(),
@@ -208,37 +205,36 @@ I_ void resolve_look_at(TapeBuilder_R tb, MT3_S2S4* look_at, P3_S4* eye, P3_S4*
/* Typed view of the scratchpad for field-address arithmetic. */ /* Typed view of the scratchpad for field-address arithmetic. */
ResolveLookAtScratch* sp = C_scratch(ResolveLookAtScratch*); ResolveLookAtScratch* sp = C_scratch(ResolveLookAtScratch*);
AtomBundle_resolve_look_at_R bundle = C_(void*, smem.resolve_look_at_bundle); AtomBundle_resolve_look_at_R bundle = C_(void*, smem.resolve_look_at_bundle);
tb_emit(tb, bundle->input_and_sub); { tb_emit(tb, bundle->input_and_sub); tb_bind_(tb, Binds_ResolveLookAtSub,
tb_data(tb, u4_(target)); .target = target,
tb_data(tb, u4_(eye)); .eye = eye,
tb_data(tb, u4_(up_in)); .up_in = up_in,
} );
tb_emit(tb, bundle->normalize_fwd_uz); { tb_emit(tb, bundle->normalize_fwd_uz); tb_bind_(tb, Binds_normalize_v3s4,
// tb_data(tb, u4_(O_(ResolveLookAtScratch, fwd) | (O_(ResolveLookAtScratch, uz) << 16))); .src_offset = O_(ResolveLookAtScratch,fwd),
tb_bind_(tb, Binds_NormalizeV3S4, .dst_offset = O_(ResolveLookAtScratch,uz),
.src_offset = O_(ResolveLookAtScratch,fwd), );
.dst_offset = O_(ResolveLookAtScratch,uz), tb_emit(tb, bundle->cross_to_right); tb_bind_(tb, Binds_gte_cross_v3s4,
); .src_a = & sp->uz,
} .src_b = & sp->up_in,
tb_emit(tb, bundle->cross_to_right); { .out = & sp->right,
tb_data(tb, u4_(& sp->uz)); );
tb_data(tb, u4_(& sp->up_in)); tb_emit(tb, bundle->normalize_right_ux); tb_bind_(tb, Binds_normalize_v3s4,
tb_data(tb, u4_(& sp->right)); .src_offset = O_(ResolveLookAtScratch,right),
} .dst_offset = O_(ResolveLookAtScratch,ux),
tb_emit(tb, bundle->normalize_right_ux); { );
tb_data(tb, u4_(O_(ResolveLookAtScratch, right) | (O_(ResolveLookAtScratch, ux) << 16))); tb_emit(tb, bundle->cross_to_up); tb_bind_(tb, Binds_gte_cross_v3s4,
} .src_a = & sp->uz,
tb_emit(tb, bundle->cross_to_up); { .src_b = & sp->ux,
tb_data(tb, u4_(& sp->uz)); .out = & sp->up,
tb_data(tb, u4_(& sp->ux)); );
tb_data(tb, u4_(& sp->up)); tb_emit(tb, bundle->normalize_up_uy); tb_bind_(tb, Binds_normalize_v3s4,
} .src_offset = O_(ResolveLookAtScratch,up),
tb_emit(tb, bundle->normalize_up_uy); { .dst_offset = O_(ResolveLookAtScratch,uy),
tb_data(tb, u4_(O_(ResolveLookAtScratch, up) | (O_(ResolveLookAtScratch, uy) << 16))); );
} tb_emit(tb, bundle->populate_mt3s4s2); tb_bind_(tb, Binds_ResolveLookAt_PopulateMT3S4S2,
tb_emit(tb, bundle->populate_mt3s4s2); { .look_at = look_at,
tb_data(tb, u4_(look_at)); );
}
} }
FI_ void camera_look_at(TapeBuilder_R tb, Camera* c, P3_S4* target, V3_S4* up_in) { resolve_look_at(tb, & c->look_at, & c->pos, target, up_in); } FI_ void camera_look_at(TapeBuilder_R tb, Camera* c, P3_S4* target, V3_S4* up_in) { resolve_look_at(tb, & c->look_at, & c->pos, target, up_in); }
@@ -397,8 +393,6 @@ GCC_OPTIMIZATION_DISABLE
int main(void) int main(void)
{ {
smem = (SMemory){0}; smem = (SMemory){0};
// TODO(Ed): remove this field we don't need it in smem.
smem.scratchpad = C_(U4_V, Scratchpad_Loc);
// 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); smem.cam.pos = v3s4(500, -1000, -1500);