diff options
| author | MegaMech <MegaMech@users.noreply.github.com> | 2025-05-23 16:49:17 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-05-23 16:49:17 -0600 |
| commit | c2ddd2c25626b2797b9f730d77118f0e96131108 (patch) | |
| tree | be651a89fbe6f27bc6400d4f81ecab30cf6d967c | |
| parent | 98d55ab603e503c03456013b1bda0072d3e8725e (diff) | |
| parent | 9363e3d77631b1028a765c075a00293bd20c9ba7 (diff) | |
Merge branch 'transformfuncsforint' into transformsharedfromptr
38 files changed, 297 insertions, 113 deletions
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 496346cb8..6bf2a4a5b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -2,7 +2,7 @@ name: GenerateBuilds on: push: - branches: ["main"] + branches: ["*"] concurrency: group: ${{ github.workflow }}-${{ github.ref }} diff --git a/libultraship b/libultraship -Subproject d4a22ea7f78eb275b462ce542815d8368849d52 +Subproject 45c4f8d6c19c6176f5e0918917c655ea09ecc21 diff --git a/src/camera.c b/src/camera.c index 863a8f77c..6620c3ac0 100644 --- a/src/camera.c +++ b/src/camera.c @@ -1125,7 +1125,6 @@ void func_8001EE98(Player* player, Camera* camera, s8 index) { break; } if (gIsGamePaused == 0) { - FrameInterpolation_ShouldInterpolateFrame(false); switch (D_80152300[cameraIndex]) { case 3: func_8001A588(&D_80152300[cameraIndex], camera, player, index, cameraIndex); @@ -1150,7 +1149,6 @@ void func_8001EE98(Player* player, Camera* camera, s8 index) { func_8001EA0C(camera, player, index); break; } - FrameInterpolation_ShouldInterpolateFrame(true); } } diff --git a/src/code_80057C60.c b/src/code_80057C60.c index 9c46e792b..2ce053cac 100644 --- a/src/code_80057C60.c +++ b/src/code_80057C60.c @@ -6101,6 +6101,10 @@ void render_battle_balloon(Player* player, s8 arg1, s16 arg2, s8 arg3) { sp12C[1] = player->unk_048[arg3]; sp12C[2] = D_8018D7D0[arg1][arg2] - (D_8018D860[arg1][arg2] * coss(temp_t1)) - ((D_8018D890[arg1][arg2] * 8) * sins(temp_t1)); + + // @port: Tag the transform. + FrameInterpolation_RecordOpenChild((uintptr_t) player, arg1 | arg2 << 16); + mtxf_translate_rotate(mtx, sp134, sp12C); mtxf_scale(mtx, var_f20); // convert_to_fixed_point_matrix(&gGfxPool->mtxEffect[gMatrixEffectCount], sp140); @@ -6130,6 +6134,10 @@ void render_battle_balloon(Player* player, s8 arg1, s16 arg2, s8 arg3) { gSPVertex(gDisplayListHead++, gBalloonVertexPlane2, 4, 0); gSPDisplayList(gDisplayListHead++, common_square_plain_render); gSPTexture(gDisplayListHead++, 0x0001, 0x0001, 0, G_TX_RENDERTILE, G_OFF); + + // @port Pop the transform id. + FrameInterpolation_RecordCloseChild(); + gMatrixEffectCount++; } diff --git a/src/code_800AF9B0.c b/src/code_800AF9B0.c index 732a6e8e9..9876a40cb 100644 --- a/src/code_800AF9B0.c +++ b/src/code_800AF9B0.c @@ -34,15 +34,15 @@ Light D_800E8688 = { { s16 D_8018EDB0; s16 D_8018EDB2; s16 D_8018EDB4; -Vtx* D_8018EDB8; -Vtx* D_8018EDBC; +Vtx D_8018EDB8[480]; +Vtx D_8018EDBC[480]; /*** utils **/ #define SQ(x) ((x) * (x)) void func_800AF9B0(void) { - D_8018EDB8 = (void*) calloc(480, sizeof(Vtx)); - D_8018EDBC = (void*) calloc(480, sizeof(Vtx)); + // D_8018EDB8 = (void*) calloc(480, sizeof(Vtx)); + // D_8018EDBC = (void*) calloc(480, sizeof(Vtx)); } // could be a normal vertex, not a color... diff --git a/src/ending/podium_ceremony_actors.c b/src/ending/podium_ceremony_actors.c index 1e3911287..04edd018f 100644 --- a/src/ending/podium_ceremony_actors.c +++ b/src/ending/podium_ceremony_actors.c @@ -18,6 +18,7 @@ #include "code_80281C40.h" #include "math_util.h" #include <string.h> +#include "port/interpolation/FrameInterpolation.h" #include "src/port/Game.h" #include "engine/Matrix.h" @@ -262,6 +263,9 @@ void render_fireworks(Vec3f arg0, f32 arg1, s32 rgb, s16 alpha) { void firework_update(Firework* actor) { s32 i; Vec3f pos; + + // @port: Tag the transform. + FrameInterpolation_RecordOpenChild("render_fireworks", (uintptr_t) actor); if (actor->unk44 < 30) { for (i = 0; i < 10; i++) { pos[0] = actor->pos[0]; @@ -290,6 +294,8 @@ void firework_update(Firework* actor) { } } actor->unk44 += 1; + // @port Pop the transform id. + FrameInterpolation_RecordCloseChild(); } void unused_80280FA0(UNUSED CeremonyActor* actor) { diff --git a/src/engine/World.cpp b/src/engine/World.cpp index 39c3802c2..88c6717c6 100644 --- a/src/engine/World.cpp +++ b/src/engine/World.cpp @@ -22,6 +22,9 @@ extern "C" { } World::World() {} +World::~World() { + CM_CleanWorld(); +} Course* CurrentCourse; Cup* CurrentCup; @@ -81,6 +84,10 @@ u32 World::PreviousCup() { return 0; } +void World::SetCupIndex(size_t index) { + CupIndex = index; +} + void World::SetCup(Cup* cup) { if (cup) { CurrentCup = cup; diff --git a/src/engine/World.h b/src/engine/World.h index 2255a3e6a..f32cf00ff 100644 --- a/src/engine/World.h +++ b/src/engine/World.h @@ -52,6 +52,7 @@ class World { public: explicit World(); + ~World(); Course* AddCourse(std::unique_ptr<Course> course); @@ -82,6 +83,7 @@ public: void AddCup(Cup*); void SetCup(Cup* cup); + void SetCupIndex(size_t index); const char* GetCupName(); u32 GetCupIndex(); u32 NextCup(); diff --git a/src/engine/actors/Finishline.cpp b/src/engine/actors/Finishline.cpp index 0680e60bd..fb408bd14 100644 --- a/src/engine/actors/Finishline.cpp +++ b/src/engine/actors/Finishline.cpp @@ -6,6 +6,8 @@ #include "engine/Actor.h" #include "World.h" #include "assets/common_data.h" +#include "src/port/Game.h" +#include "port/interpolation/FrameInterpolation.h" extern "C" { #include "macros.h" @@ -17,6 +19,8 @@ extern f32 gKartHopInitialVelocityTable[]; extern f32 gKartGravityTable[]; } +size_t AFinishline::_count = 0; + AFinishline::AFinishline(std::optional<FVector> pos) { Name = "Finishline"; @@ -53,6 +57,8 @@ void AFinishline::Draw(Camera *camera) { return; } + FrameInterpolation_RecordOpenChild("Finishline", _count); + mtxf_pos_rotation_xyz(mtx, Pos, Rot); maxObjectsReached = render_set_position(mtx, 0) == 0; @@ -74,6 +80,8 @@ void AFinishline::Draw(Camera *camera) { } else { gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D001BD8); } + + FrameInterpolation_RecordCloseChild(); } void AFinishline::Collision(Player* player, AActor* actor) {} diff --git a/src/engine/actors/Finishline.h b/src/engine/actors/Finishline.h index 61b561a5e..3c0e84de8 100644 --- a/src/engine/actors/Finishline.h +++ b/src/engine/actors/Finishline.h @@ -27,6 +27,7 @@ public: virtual void Collision(Player* player, AActor* actor) override; virtual bool IsMod() override; + static size_t _count; bool PickedUp = false; uint32_t Timer = 0; diff --git a/src/engine/editor/Editor.cpp b/src/engine/editor/Editor.cpp index 446da7487..23a947a09 100644 --- a/src/engine/editor/Editor.cpp +++ b/src/engine/editor/Editor.cpp @@ -30,6 +30,11 @@ namespace Editor { Editor::Editor() { } + Editor::~Editor() { + ClearObjects(); + ClearMatrixPool(); + } + void Editor::Load() { printf("Editor: Loading Editor...\n"); eObjectPicker.Load(); @@ -58,10 +63,16 @@ namespace Editor { Ship::Coords mousePos = wnd->GetMousePos(); bool isMouseDown = wnd->GetMouseState(Ship::LUS_MOUSE_BTN_LEFT); - eGameObjects.erase( - std::remove_if(eGameObjects.begin(), eGameObjects.end(), - [](const auto& object) { return (*object->DespawnFlag) == object->DespawnValue; }), - eGameObjects.end()); + auto it = std::remove_if(eGameObjects.begin(), eGameObjects.end(), + [](auto& object) { + if (*object->DespawnFlag == object->DespawnValue) { + delete object; // Free the pointed-to memory + return true; // Remove the pointer from the vector + } + return false; + }); + + eGameObjects.erase(it, eGameObjects.end()); if (isMouseDown && !wasMouseDown) { // Mouse just pressed (Pressed state) diff --git a/src/engine/editor/Editor.h b/src/engine/editor/Editor.h index 759c59355..60e578b21 100644 --- a/src/engine/editor/Editor.h +++ b/src/engine/editor/Editor.h @@ -14,6 +14,7 @@ namespace Editor { class Editor { public: Editor(); + ~Editor(); ObjectPicker eObjectPicker; std::vector<GameObject*> eGameObjects; diff --git a/src/engine/editor/EditorMath.cpp b/src/engine/editor/EditorMath.cpp index 04a299563..f3833008b 100644 --- a/src/engine/editor/EditorMath.cpp +++ b/src/engine/editor/EditorMath.cpp @@ -352,8 +352,8 @@ bool IntersectRaySphere(const Ray& ray, const FVector& sphereCenter, float radiu // Transform a matrix to a matrix identity void Editor_MatrixIdentity(Mat4 mtx) { - register s32 i; - register s32 k; + s32 i; + s32 k; for (i = 0; i < 4; i++) { for (k = 0; k < 4; k++) { diff --git a/src/engine/objects/Bat.cpp b/src/engine/objects/Bat.cpp index 2056a17f7..e4f3a2086 100644 --- a/src/engine/objects/Bat.cpp +++ b/src/engine/objects/Bat.cpp @@ -23,7 +23,7 @@ OBat::OBat(const FVector& pos, const IRotator& rot) { Name = "Bat"; find_unused_obj_index(&_objectIndex); - init_texture_object(_objectIndex, (uint8_t*)d_course_banshee_boardwalk_bat_tlut, sBoardwalkTexList, 0x20U, + init_texture_object(_objectIndex, (uint8_t*) d_course_banshee_boardwalk_bat_tlut, sBoardwalkTexList, 0x20U, (u16) 0x00000040); gObjectList[_objectIndex].orientation[0] = rot.pitch; gObjectList[_objectIndex].orientation[1] = rot.roll; @@ -102,59 +102,64 @@ void OBat::Tick() { } void OBat::Draw(s32 cameraId) { - s32 var_s2; - s32 objectIndex; - Camera* temp_s7; + s32 i; + s32 objectIndex = _objectIndex; + Camera* cam = &camera1[cameraId]; - objectIndex = _objectIndex; - temp_s7 = &camera1[cameraId]; - OBat::func_80046F60((u8*)gObjectList[objectIndex].activeTLUT, (u8*)gObjectList[objectIndex].activeTexture, 0x00000020, 0x00000040, - 5); + OBat::func_80046F60((u8*) gObjectList[objectIndex].activeTLUT, (u8*) gObjectList[objectIndex].activeTexture, + 0x00000020, 0x00000040, 5); D_80183E80[0] = gObjectList[objectIndex].orientation[0]; D_80183E80[2] = gObjectList[objectIndex].orientation[2]; + if ((D_8018CFB0 != 0) || (D_8018CFC8 != 0)) { - for (var_s2 = 0; var_s2 < 40; var_s2++) { - // @port: Tag the transform. - FrameInterpolation_RecordOpenChild("Bat set 1", var_s2); - objectIndex = gObjectParticle2[var_s2]; + for (i = 0; i < 40; i++) { + objectIndex = gObjectParticle2[i]; if (objectIndex == -1) { continue; } if ((gObjectList[objectIndex].state >= 2) && (gMatrixHudCount < 0x2EF)) { + // @port: Tag the transform. + FrameInterpolation_RecordOpenChild("Bat set 1", (uintptr_t) &gObjectList[objectIndex]); + D_80183E80[1] = - func_800418AC(gObjectList[objectIndex].pos[0], gObjectList[objectIndex].pos[2], temp_s7->pos); + func_800418AC(gObjectList[objectIndex].pos[0], gObjectList[objectIndex].pos[2], cam->pos); func_800431B0(gObjectList[objectIndex].pos, D_80183E80, gObjectList[objectIndex].sizeScaling, - (Vtx*)D_0D0062B0); + (Vtx*) D_0D0062B0); + + // @port Pop the transform id. + FrameInterpolation_RecordCloseChild(); } - // @port Pop the transform id. - FrameInterpolation_RecordCloseChild(); } } + if ((D_8018CFE8 != 0) || (D_8018D000 != 0)) { - for (var_s2 = 0; var_s2 < 30; var_s2++) { - // @port: Tag the transform. - FrameInterpolation_RecordOpenChild("Bat set 2", var_s2); - objectIndex = gObjectParticle3[var_s2]; + for (i = 0; i < 30; i++) { + + objectIndex = gObjectParticle3[i]; if (objectIndex == -1) { continue; } if ((gObjectList[objectIndex].state >= 2) && (gMatrixHudCount < 0x2EF)) { + // @port: Tag the transform. + FrameInterpolation_RecordOpenChild("Bat set 2", (uintptr_t) &gObjectList[objectIndex]); + D_80183E80[1] = - func_800418AC(gObjectList[objectIndex].pos[0], gObjectList[objectIndex].pos[2], temp_s7->pos); + func_800418AC(gObjectList[objectIndex].pos[0], gObjectList[objectIndex].pos[2], cam->pos); func_800431B0(gObjectList[objectIndex].pos, D_80183E80, gObjectList[objectIndex].sizeScaling, - (Vtx*)D_0D0062B0); + (Vtx*) D_0D0062B0); + + // @port Pop the transform id. + FrameInterpolation_RecordCloseChild(); } - // @port Pop the transform id. - FrameInterpolation_RecordCloseChild(); } } gSPTexture(gDisplayListHead++, 0x0001, 0x0001, 0, G_TX_RENDERTILE, G_OFF); } void OBat::func_80046F60(u8* tlut, u8* arg1, s32 arg2, s32 arg3, s32 arg4) { - gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D007D78); + gSPDisplayList(gDisplayListHead++, (Gfx*) D_0D007D78); gDPLoadTLUT_pal256(gDisplayListHead++, tlut); rsp_load_texture_mask(arg1, arg2, arg3, arg4); } diff --git a/src/engine/objects/Boos.cpp b/src/engine/objects/Boos.cpp index 69bb95072..5f02d7876 100644 --- a/src/engine/objects/Boos.cpp +++ b/src/engine/objects/Boos.cpp @@ -83,20 +83,23 @@ void OBoos::Draw(s32 cameraId) { s32 objectIndex; for (size_t i = 0; i < _numBoos; i++) { - // @port: Tag the transform. - FrameInterpolation_RecordOpenChild("Boo", i); objectIndex = _indices[i]; //indexObjectList3[i]; if (gObjectList[objectIndex].state >= 2) { temp_s2 = func_8008A364(objectIndex, cameraId, 0x4000U, 0x00000320); if (CVarGetInteger("gNoCulling", 0) == 1) { temp_s2 = MIN(temp_s2, 0x15F91U); } + + // @port: Tag the transform. + FrameInterpolation_RecordOpenChild("Boo", (uintptr_t)&gObjectList[objectIndex]); + if (is_obj_flag_status_active(objectIndex, VISIBLE) != 0) { func_800523B8(objectIndex, cameraId, temp_s2); } + + // @port Pop the transform id. + FrameInterpolation_RecordCloseChild(); } - // @port Pop the transform id. - FrameInterpolation_RecordCloseChild(); } } diff --git a/src/engine/objects/Mole.cpp b/src/engine/objects/Mole.cpp index 91eeabebf..f623b1f52 100644 --- a/src/engine/objects/Mole.cpp +++ b/src/engine/objects/Mole.cpp @@ -323,6 +323,7 @@ void OMole::func_800821AC(s32 objectIndex, s32 arg1) { } } +// Holes void OMole::func_80054E10(s32 objectIndex) { if (gObjectList[objectIndex].state > 0) { if (is_obj_flag_status_active(objectIndex, 0x00800000) != 0) { @@ -362,7 +363,7 @@ void OMole::func_80054D00(s32 objectIndex, s32 cameraId) { if (is_obj_flag_status_active(objectIndex, VISIBLE) != 0) { // @port: Tag the transform. - FrameInterpolation_RecordOpenChild("func_80054D00", TAG_OBJECT(&gObjectList[objectIndex])); + FrameInterpolation_RecordOpenChild("func_80054D00", (uintptr_t)&gObjectList[objectIndex]); D_80183E80[0] = (s16) gObjectList[objectIndex].orientation[0]; D_80183E80[1] = @@ -378,6 +379,7 @@ void OMole::func_80054D00(s32 objectIndex, s32 cameraId) { } } +// Mole rocks void OMole::func_80054F04(s32 cameraId) { Camera* camera = &camera1[cameraId]; diff --git a/src/engine/objects/TrashBin.cpp b/src/engine/objects/TrashBin.cpp index dc62626dc..57c702275 100644 --- a/src/engine/objects/TrashBin.cpp +++ b/src/engine/objects/TrashBin.cpp @@ -65,7 +65,7 @@ void OTrashBin::Draw(s32 cameraId) { Vec3s Rot = { 0, 0x4000, 0 }; // @port: Tag the transform. - FrameInterpolation_RecordOpenChild("Bin", mtx); + FrameInterpolation_RecordOpenChild("OTrashBin", (uintptr_t) object); mtxf_pos_rotation_xyz(mtx, Pos, Rot); //mtxf_scale(mtx, 1.0f); diff --git a/src/engine/particles/StarEmitter.cpp b/src/engine/particles/StarEmitter.cpp index 242e1a75a..7cb9d9979 100644 --- a/src/engine/particles/StarEmitter.cpp +++ b/src/engine/particles/StarEmitter.cpp @@ -1,6 +1,7 @@ #include "StarEmitter.h" +#include "port/interpolation/FrameInterpolation.h" extern "C" { #include "render_objects.h" @@ -107,9 +108,13 @@ void StarEmitter::Draw(s32 cameraId) { // func_80054BE8 D_80183E80[0] = 0; for (var_s0 = 0; var_s0 < gObjectParticle3_SIZE; var_s0++) { temp_a0 = ObjectIndex[var_s0]; + // @port: Tag the transform. + FrameInterpolation_RecordOpenChild("Ceremony Stars", (uintptr_t) &ObjectIndex[var_s0]); if ((temp_a0 != -1) && (gObjectList[temp_a0].state >= 2)) { StarEmitter::func_80054AFC(temp_a0, camera->pos); } + // @port Pop the transform id. + FrameInterpolation_RecordCloseChild(); } } diff --git a/src/main.c b/src/main.c index cd8b4f677..c3f6f27d7 100644 --- a/src/main.c +++ b/src/main.c @@ -759,18 +759,21 @@ void process_game_tick(void) { func_800382DC(); } + // This looks like it should be in the switch. + // But it needs to be here for player 1 to work in all modes. + if (CVarGetInteger("gFreecam", 0) == true) { + freecam(gFreecamCamera, gPlayerOneCopy, 0); + } else { + func_8001EE98(gPlayerOneCopy, camera1, 0); + } + + // Editor requires this so the camera keeps moving while the game is paused. + if (gIsEditorPaused == true) { + return; + } + switch(gActiveScreenMode) { case SCREEN_MODE_1P: - if (CVarGetInteger("gFreecam", 0) == true) { - freecam(gFreecamCamera, gPlayerOneCopy, 0); - } else { - func_8001EE98(gPlayerOneCopy, camera1, 0); - } - - // Editor requires this so the camera keeps moving while the game is paused. - if (gIsEditorPaused == true) { - return; - } func_80028F70(); break; case SCREEN_MODE_2P_SPLITSCREEN_VERTICAL: diff --git a/src/math_util_2.c b/src/math_util_2.c index e4fc571d5..b113c6a5d 100644 --- a/src/math_util_2.c +++ b/src/math_util_2.c @@ -690,13 +690,13 @@ UNUSED void func_800421FC(s32 x, s32 y, f32 scale) { void func_80042330(s32 x, s32 y, u16 angle, f32 scale) { Mat4 matrix; - //printf("panel %d %d %d\n", x, (s32)OTRGetDimensionFromLeftEdge(x), (s32)OTRGetDimensionFromLeftEdge(0)); + // printf("panel %d %d %d\n", x, (s32)OTRGetDimensionFromLeftEdge(x), (s32)OTRGetDimensionFromLeftEdge(0)); if (gHUDModes != 2) { if (x < (SCREEN_WIDTH / 2)) { - x = (s32)OTRGetDimensionFromLeftEdge(x); + x = (s32) OTRGetDimensionFromLeftEdge(x); } else { - x = (s32)OTRGetDimensionFromRightEdge(x); + x = (s32) OTRGetDimensionFromRightEdge(x); } } @@ -710,7 +710,7 @@ void func_80042330(s32 x, s32 y, u16 angle, f32 scale) { void func_80042330_unchanged(s32 x, s32 y, u16 angle, f32 scale) { Mat4 matrix; - //printf("panel %d %d %d\n", x, (s32)OTRGetDimensionFromLeftEdge(x), (s32)OTRGetDimensionFromLeftEdge(0)); + // printf("panel %d %d %d\n", x, (s32)OTRGetDimensionFromLeftEdge(x), (s32)OTRGetDimensionFromLeftEdge(0)); mtxf_translation_x_y_rotate_z_scale_x_y(matrix, x, y, angle, scale); // convert_to_fixed_point_matrix(&gGfxPool->mtxHud[gMatrixHudCount], matrix); @@ -723,13 +723,13 @@ void func_80042330_unchanged(s32 x, s32 y, u16 angle, f32 scale) { // Allows a different way of lining up the portraits at the end of race sequence void func_80042330_portrait(s32 x, s32 y, u16 angle, f32 scale, s16 lapCount) { Mat4 matrix; - //printf("panel %d %d %d\n", x, (s32)OTRGetDimensionFromLeftEdge(x), (s32)OTRGetDimensionFromLeftEdge(0)); + // printf("panel %d %d %d\n", x, (s32)OTRGetDimensionFromLeftEdge(x), (s32)OTRGetDimensionFromLeftEdge(0)); if ((gHUDModes != 2) && (D_801657E2 == 0) || (CVarGetInteger("gImprovements", 0) == true)) { if (x < (SCREEN_WIDTH / 2)) { - x = (s32)OTRGetDimensionFromLeftEdge(x); + x = (s32) OTRGetDimensionFromLeftEdge(x); } else { - x = (s32)OTRGetDimensionFromRightEdge(x); + x = (s32) OTRGetDimensionFromRightEdge(x); } } @@ -745,9 +745,9 @@ void func_80042330_wide(s32 x, s32 y, u16 angle, f32 scale) { Mat4 matrix; if (x < (SCREEN_WIDTH / 2)) { - x = (s32)OTRGetDimensionFromLeftEdge(x); + x = (s32) OTRGetDimensionFromLeftEdge(x); } else { - x = (s32)OTRGetDimensionFromRightEdge(x); + x = (s32) OTRGetDimensionFromRightEdge(x); } mtxf_translation_x_y_rotate_z_scale_x_y(matrix, x, y, angle, scale); @@ -808,8 +808,7 @@ UNUSED void func_8004252C(Mat4 arg0, u16 arg1, u16 arg2) { arg0[2][2] = sp28 * cos_theta_y; } -void mtxf_set_matrix_transformation(Mat4 transformMatrix, Vec3f location, Vec3su rotation, - f32 scale) { +void mtxf_set_matrix_transformation(Mat4 transformMatrix, Vec3f location, Vec3su rotation, f32 scale) { FrameInterpolation_RecordSetMatrixTransformation(transformMatrix, location, rotation, scale); f32 sinX = sins(rotation[0]); @@ -864,7 +863,13 @@ void mtxf_set_matrix_scale_transl(Mat4 transformMatrix, Vec3f vec1, Vec3f vec2, * @param arg1 **/ -void mtxf_set_matrix_gObjectList(s32 objectIndex, Mat4 transformMatrix) { +struct ObjectInterpData2 { + s32 objectIndex; + f32 x, y; +}; +struct ObjectInterpData2 prevObject2[OBJECT_LIST_SIZE] = { 0 }; + +s32 mtxf_set_matrix_gObjectList(s32 objectIndex, Mat4 transformMatrix) { f32 sinX; Object* object = &gObjectList[objectIndex]; f32 sinY; @@ -896,6 +901,26 @@ void mtxf_set_matrix_gObjectList(s32 objectIndex, Mat4 transformMatrix) { transformMatrix[1][3] = 0.0f; transformMatrix[2][3] = 0.0f; transformMatrix[3][3] = 1.0f; + + // Search all recorded objects for the one we're drawing + for (int i = 0; i < OBJECT_LIST_SIZE; i++) { + if (objectIndex == prevObject2[i].objectIndex) { + // Coincidence! + // Skip drawing the object this frame if it warped to the other side of the screen + if ((fabsf(object->pos[0] - prevObject2[i].x) > 20) || (fabsf(object->pos[1] - prevObject2[i].y) > 20)) { + prevObject2[objectIndex].x = object->pos[0]; + prevObject2[objectIndex].y = object->pos[1]; + prevObject2[objectIndex].objectIndex = objectIndex; + // printf("IDX: %d X: %f Y: %f Z: %f\n", objectIndex, object->pos[0], object->pos[1], object->pos[2]); + return 1; + } + } + } + prevObject2[objectIndex].x = object->pos[0]; + prevObject2[objectIndex].y = object->pos[1]; + prevObject2[objectIndex].objectIndex = objectIndex; + + return 0; } UNUSED void mtxf_mult_first_column(Mat4 arg0, f32 arg1) { @@ -1065,7 +1090,9 @@ void rsp_set_matrix_transl_rot_scale(Vec3f arg0, Vec3f arg1, f32 arg2) { void rsp_set_matrix_gObjectList(s32 transformIndex) { Mat4 matrix; - mtxf_set_matrix_gObjectList(transformIndex, matrix); + if (mtxf_set_matrix_gObjectList(transformIndex, matrix)) { + return; + } // convert_to_fixed_point_matrix(&gGfxPool->mtxHud[gMatrixHudCount], matrix); // gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&gGfxPool->mtxHud[gMatrixHudCount++]), diff --git a/src/math_util_2.h b/src/math_util_2.h index 5d0837dd9..52b436301 100644 --- a/src/math_util_2.h +++ b/src/math_util_2.h @@ -76,7 +76,7 @@ void func_80042330_portrait(s32, s32, u16, f32, s16); void func_80042330_wide(s32, s32, u16, f32); void mtxf_set_matrix_transformation(Mat4, Vec3f, Vec3su, f32); void mtxf_set_matrix_scale_transl(Mat4, Vec3f, Vec3f, f32); -void mtxf_set_matrix_gObjectList(s32, Mat4); +s32 mtxf_set_matrix_gObjectList(s32, Mat4); void set_transform_matrix(Mat4 dest, Vec3f orientationVector, Vec3f positionVector, u16 rotationAngle, f32 scaleFactor); void vec3f_rotate_x_y(Vec3f, Vec3f, Vec3s); diff --git a/src/menus.c b/src/menus.c index d921ac740..ce9f0a643 100644 --- a/src/menus.c +++ b/src/menus.c @@ -2005,6 +2005,7 @@ void load_menu_states(s32 menuSelection) { CM_SetCup(GetBattleCup()); // gCupSelection = BATTLE_CUP; D_800DC540 = 4; + CM_SetCupIndex(BATTLE_CUP); gSubMenuSelection = SUB_MENU_MAP_SELECT_BATTLE_COURSE; } else { if (GetCup() == GetBattleCup()) { diff --git a/src/port/Engine.cpp b/src/port/Engine.cpp index 15acab0ac..70ea4054c 100644 --- a/src/port/Engine.cpp +++ b/src/port/Engine.cpp @@ -298,6 +298,9 @@ void GameEngine::Destroy() { #ifdef __SWITCH__ Ship::Switch::Exit(); #endif + GameUI::Destroy(); + delete GameEngine::Instance; + GameEngine::Instance = nullptr; } bool ShouldClearTextureCacheAtEndOfFrame = false; @@ -509,7 +512,9 @@ ImFont* GameEngine::CreateFontWithSize(float size, std::string fontPath) { initData->Path = fontPath; std::shared_ptr<Ship::Font> fontData = std::static_pointer_cast<Ship::Font>( Ship::Context::GetInstance()->GetResourceManager()->LoadResource(fontPath, false, initData)); - font = mImGuiIo->Fonts->AddFontFromMemoryTTF(fontData->Data, fontData->DataSize, size); + char* fontDataPtr = (char*)malloc(fontData->DataSize); + memcpy(fontDataPtr, fontData->Data, fontData->DataSize); + font = mImGuiIo->Fonts->AddFontFromMemoryTTF(fontDataPtr, fontData->DataSize, size); } // FontAwesome fonts need to have their sizes reduced by 2.0f/3.0f in order to align correctly float iconFontSize = size * 2.0f / 3.0f; diff --git a/src/port/Game.cpp b/src/port/Game.cpp index d72c5f120..10e8d98d1 100644 --- a/src/port/Game.cpp +++ b/src/port/Game.cpp @@ -188,6 +188,38 @@ void CustomEngineInit() { // gModelLoader.Load(); } +void CustomEngineDestroy() { + delete gMarioRaceway; + delete gChocoMountain; + delete gBowsersCastle; + delete gBansheeBoardwalk; + delete gYoshiValley; + delete gFrappeSnowland; + delete gKoopaTroopaBeach; + delete gRoyalRaceway; + delete gLuigiRaceway; + delete gMooMooFarm; + delete gToadsTurnpike; + delete gKalimariDesert; + delete gSherbetLand; + delete gRainbowRoad; + delete gWarioStadium; + delete gBlockFort; + delete gSkyscraper; + delete gDoubleDeck; + delete gDkJungle; + delete gBigDonut; + delete gPodiumCeremony; + delete gHarbour; + delete gTestCourse; + + delete gMushroomCup; + delete gFlowerCup; + delete gStarCup; + delete gSpecialCup; + delete gBattleCup; +} + extern "C" { void HM_InitIntro() { @@ -234,6 +266,10 @@ u32 GetCupIndex(void) { return gWorldInstance.GetCupIndex(); } +void CM_SetCupIndex(size_t index) { + gWorldInstance.SetCupIndex(index); +} + const char* GetCupName(void) { return gWorldInstance.CurrentCup->Name; } @@ -384,10 +420,11 @@ void CM_BeginPlay() { if (course) { // Do not spawn finishline in credits or battle mode. And if bSpawnFinishline. - if ((gGamestate != CREDITS_SEQUENCE) && (gGamestate != BATTLE) && (course->bSpawnFinishline)) { - gWorldInstance.AddActor(new AFinishline(course->FinishlineSpawnPoint)); + if ((gGamestate != CREDITS_SEQUENCE) && (gModeSelection != BATTLE)) { + if (course->bSpawnFinishline) { + gWorldInstance.AddActor(new AFinishline(course->FinishlineSpawnPoint)); + } } - gEditor.AddLight("Sun", nullptr, D_800DC610[1].l->l.dir); course->BeginPlay(); @@ -820,6 +857,7 @@ extern "C" while (WindowIsRunning()) { push_frame(); } + CustomEngineDestroy(); // GameEngine::Instance->ProcessFrame(push_frame); GameEngine::Instance->Destroy(); return 0; diff --git a/src/port/Game.h b/src/port/Game.h index 36b8ee0d4..14cc0edf6 100644 --- a/src/port/Game.h +++ b/src/port/Game.h @@ -51,6 +51,8 @@ void PreviousCourse(); void CM_SetCup(void*); +void CM_SetCupIndex(size_t index); + void CM_LoadTextures(); void CM_RenderCourse(struct UnkStruct_800DC5EC* arg0); diff --git a/src/port/SpaghettiGui.cpp b/src/port/SpaghettiGui.cpp index 09ac63234..6c703456d 100644 --- a/src/port/SpaghettiGui.cpp +++ b/src/port/SpaghettiGui.cpp @@ -12,7 +12,7 @@ #include <SDL_hints.h> #include <SDL_video.h> -#include "graphic/Fast3D/gfx_metal.h" +#include "graphic/Fast3D/backends/gfx_metal.h" #include <imgui_impl_metal.h> #include <imgui_impl_sdl2.h> #else diff --git a/src/port/interpolation/FrameInterpolation.cpp b/src/port/interpolation/FrameInterpolation.cpp index d0e0fe0f0..836e6c70c 100644 --- a/src/port/interpolation/FrameInterpolation.cpp +++ b/src/port/interpolation/FrameInterpolation.cpp @@ -12,6 +12,9 @@ extern "C" { #include "math_util.h" #include "math_util_2.h" #include "render_player.h" + +extern Mat4* gInterpolationMatrix; +void mtxf_translate(Mat4, Vec3f); } /* Frame interpolation. @@ -49,6 +52,11 @@ static bool invert_matrix(const float m[16], float invOut[16]); using namespace std; +extern "C" { +extern Mat4* gInterpolationMatrix; +void mtxf_translate(Mat4, Vec3f); +} + namespace { enum class Op { @@ -234,11 +242,6 @@ Data& append(Op op) { return m.emplace_back(); } -extern "C" { -extern Mat4* gInterpolationMatrix; -void mtxf_translate(Mat4, Vec3f); -} - MtxF* Matrix_GetCurrent() { return (MtxF*) gInterpolationMatrix; } diff --git a/src/port/interpolation/FrameInterpolation.h b/src/port/interpolation/FrameInterpolation.h index 06a7cf3d4..c59743681 100644 --- a/src/port/interpolation/FrameInterpolation.h +++ b/src/port/interpolation/FrameInterpolation.h @@ -19,7 +19,7 @@ extern "C" { #define TAG_ITEM_ADDR(x) ((u32) 0x10000000 | (u32)x) #define TAG_SMOKE_DUST(x) ((u32) 0x20000000 | (u32) (x)) #define TAG_LETTER(x) ((u32)0x30000000 | (u32) (x)) -#define TAG_OBJECT(x) ((u32)0x40000000 | (u32)(x)) +#define TAG_OBJECT(x) ((u32)0x40000000 | (u32) (uintptr_t) (x)) void FrameInterpolation_ShouldInterpolateFrame(bool shouldInterpolate); diff --git a/src/port/resource/importers/AudioBankFactory.cpp b/src/port/resource/importers/AudioBankFactory.cpp index ee400c1b5..650767881 100644 --- a/src/port/resource/importers/AudioBankFactory.cpp +++ b/src/port/resource/importers/AudioBankFactory.cpp @@ -21,6 +21,7 @@ SM64::AudioBankFactoryV0::ReadResource(std::shared_ptr<Ship::File> file, auto* instrument = new Instrument(); bool valid = reader->ReadUByte(); if(!valid){ + delete instrument; bank->instruments.push_back(nullptr); continue; } diff --git a/src/port/resource/type/AudioBank.cpp b/src/port/resource/type/AudioBank.cpp index f91b767d2..7cbe3073a 100644 --- a/src/port/resource/type/AudioBank.cpp +++ b/src/port/resource/type/AudioBank.cpp @@ -8,4 +8,21 @@ CtlEntry* AudioBank::GetPointer() { size_t AudioBank::GetPointerSize() { return sizeof(mData); } +AudioBank::~AudioBank() { + for (auto& instrument : instruments) { + if (instrument != nullptr) { + if (instrument->envelope != nullptr) { + delete[] instrument->envelope; + instrument->envelope = nullptr; + } + delete instrument; + } + + } + for (auto& drum : drums) { + delete drum; + } + instruments.clear(); + drums.clear(); +} }
\ No newline at end of file diff --git a/src/port/resource/type/AudioBank.h b/src/port/resource/type/AudioBank.h index a8541fe84..b9beefa78 100644 --- a/src/port/resource/type/AudioBank.h +++ b/src/port/resource/type/AudioBank.h @@ -47,6 +47,7 @@ class AudioBank : public Ship::Resource<CtlEntry> { using Resource::Resource; AudioBank() : Resource(std::shared_ptr<Ship::ResourceInitData>()) {} + ~AudioBank() override; CtlEntry* GetPointer(); size_t GetPointerSize(); diff --git a/src/port/resource/type/AudioSample.cpp b/src/port/resource/type/AudioSample.cpp index cbdbd6573..f9b087af7 100644 --- a/src/port/resource/type/AudioSample.cpp +++ b/src/port/resource/type/AudioSample.cpp @@ -8,4 +8,18 @@ AudioBankSample* AudioSample::GetPointer() { size_t AudioSample::GetPointerSize() { return sizeof(mData); } +AudioSample::~AudioSample() { + if (mData.sampleAddr != nullptr) { + // delete[] mData.sampleAddr; + mData.sampleAddr = nullptr; + } + if (mData.book->book != nullptr) { + delete[] mData.book->book; + mData.book->book = nullptr; + } + if (mData.loop->state != nullptr) { + delete[] mData.loop->state; + mData.loop->state = nullptr; + } +} }
\ No newline at end of file diff --git a/src/port/resource/type/AudioSample.h b/src/port/resource/type/AudioSample.h index 35f1d8d33..2d6f46c96 100644 --- a/src/port/resource/type/AudioSample.h +++ b/src/port/resource/type/AudioSample.h @@ -34,6 +34,7 @@ class AudioSample : public Ship::Resource<AudioBankSample> { using Resource::Resource; AudioSample() : Resource(std::shared_ptr<Ship::ResourceInitData>()) {} + ~AudioSample() override; AudioBankSample* GetPointer(); size_t GetPointerSize(); diff --git a/src/racing/skybox_and_splitscreen.c b/src/racing/skybox_and_splitscreen.c index 64f0da259..62399dfea 100644 --- a/src/racing/skybox_and_splitscreen.c +++ b/src/racing/skybox_and_splitscreen.c @@ -767,7 +767,7 @@ void setup_camera(Camera* camera, s32 playerId, s32 cameraId, struct UnkStruct_8 } // Setup perspective (camera movement) - FrameInterpolation_RecordOpenChild("camera", FrameInterpolation_GetCameraEpoch()); + FrameInterpolation_RecordOpenChild("camera", (FrameInterpolation_GetCameraEpoch() | (((playerId | cameraId) << 8)))); guPerspective(&gGfxPool->mtxPersp[cameraId], &perspNorm, gCameraZoom[cameraId], gScreenAspect, CM_GetProps()->NearPersp, CM_GetProps()->FarPersp, 1.0f); gSPPerspNormalize(gDisplayListHead++, perspNorm); diff --git a/src/render_objects.c b/src/render_objects.c index b83e96189..7aa06dcaf 100644 --- a/src/render_objects.c +++ b/src/render_objects.c @@ -2630,7 +2630,7 @@ void draw_simplified_lap_count(s32 playerId) { void func_8004E800(s32 playerId) { // @port: Tag the transform. - FrameInterpolation_RecordOpenChild("Player place HUD", playerId << 8); + FrameInterpolation_RecordOpenChild("Player place HUD", playerId); if (playerHUD[playerId].unk_81 != 0) { if (playerHUD[playerId].lapCount != 3) { func_8004A384(playerHUD[playerId].rankX + playerHUD[playerId].slideRankX, @@ -3453,23 +3453,24 @@ void render_object_snowflakes_particles(void) { gSPTexture(gDisplayListHead++, 1, 1, 0, G_TX_RENDERTILE, G_OFF); } -struct CloudInterpData { +struct ObjectInterpData { s32 objectIndex; - s16 x; + s16 x, y; }; -struct CloudInterpData prevClouds[OBJECT_LIST_SIZE] = { 0 }; +struct ObjectInterpData prevObject[OBJECT_LIST_SIZE] = { 0 }; void func_800518F8(s32 objectIndex, s16 x, s16 y) { - // Search all recorded clouds for the one we're drawing + // Search all recorded objects for the one we're drawing for (int i = 0; i < OBJECT_LIST_SIZE; i++) { - if (objectIndex == prevClouds[i].objectIndex) { + if (objectIndex == prevObject[i].objectIndex) { // Coincidence! - // Skip drawing the cloud this frame if it warped to the other side of the screen - if (fabs(x - prevClouds[i].x) > SCREEN_WIDTH / 2) { - prevClouds[objectIndex].x = x; - prevClouds[objectIndex].objectIndex = objectIndex; + // Skip drawing the object this frame if it warped to the other side of the screen + if ((fabs(x - prevObject[i].x) > SCREEN_WIDTH / 2) || (fabs(y - prevObject[i].y) > SCREEN_HEIGHT / 2)) { + prevObject[objectIndex].x = x; + prevObject[objectIndex].y = y; + prevObject[objectIndex].objectIndex = objectIndex; return; } } @@ -3494,8 +3495,9 @@ void func_800518F8(s32 objectIndex, s16 x, s16 y) { } // Save current cloud index and x position - prevClouds[objectIndex].x = x; - prevClouds[objectIndex].objectIndex = objectIndex; + prevObject[objectIndex].x = x; + prevObject[objectIndex].y = y; + prevObject[objectIndex].objectIndex = objectIndex; } void func_800519D4(s32 objectIndex, s16 arg1, s16 arg2) { @@ -3512,6 +3514,7 @@ void func_800519D4(s32 objectIndex, s16 arg1, s16 arg2) { } } +// Render clouds void func_80051ABC(s16 arg0, s32 arg1) { s32 var_s0; s32 objectIndex; @@ -3928,21 +3931,23 @@ void func_8005477C(s32 objectIndex, u8 arg1, Vec3f arg2) { void render_object_smoke_particles(s32 cameraId) { UNUSED s32 stackPadding[2]; Camera* sp54; - s32 var_s0; + s32 i; s32 objectIndex; Object* object; sp54 = &camera1[cameraId]; - FrameInterpolation_RecordOpenChild("SmokeParticles", TAG_OBJECT(sp54)); + gSPDisplayList(gDisplayListHead++, D_0D007AE0); load_texture_block_i8_nomirror(common_texture_particle_smoke[D_80165598], 32, 32); func_8004B72C(255, 255, 255, 255, 255, 255, 255); D_80183E80[0] = 0; D_80183E80[2] = 0x8000; - for (var_s0 = 0; var_s0 < gObjectParticle4_SIZE; var_s0++) { - objectIndex = gObjectParticle4[var_s0]; + for (i = 0; i < gObjectParticle4_SIZE; i++) { + objectIndex = gObjectParticle4[i]; if (objectIndex != NULL_OBJECT_ID) { object = &gObjectList[objectIndex]; + // @port: Tag the transform. + FrameInterpolation_RecordOpenChild("SmokeParticles", (uintptr_t) object); if (object->state >= 2) { if (object->unk_0D8 == 3) { func_8008A364(objectIndex, cameraId, 0x4000U, 0x00000514); @@ -3953,9 +3958,10 @@ void render_object_smoke_particles(s32 cameraId) { func_8005477C(objectIndex, object->unk_0D8, sp54->pos); } } + // @port Pop the transform id. + FrameInterpolation_RecordCloseChild(); } } - FrameInterpolation_RecordCloseChild(); } UNUSED void func_800557AC() { diff --git a/src/render_player.c b/src/render_player.c index 5d9d2dde2..5061826f6 100644 --- a/src/render_player.c +++ b/src/render_player.c @@ -48,7 +48,6 @@ s16 gMatrixEffectCount; s32 D_80164AF4[3]; struct_D_802F1F80* gPlayerPalette; static const char* sKartUpperTexture; -static const char* sKartLowerTexture; u16 gPlayerRedEffect[8]; u16 gPlayerGreenEffect[8]; u16 gPlayerBlueEffect[8]; @@ -1600,6 +1599,19 @@ void render_player_shadow_credits(Player* player, s8 playerId, s8 arg2) { gSPTexture(gDisplayListHead++, 1, 1, 0, G_TX_RENDERTILE, G_OFF); } +Vtx player_vtx[] = { + { { { 9, 18, -6 }, 0, { 4032, 0 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { 9, 0, -6 }, 0, { 4032, 4032 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { -9, 18, -6 }, 0, { 0, 0 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { -9, 0, -6 }, 0, { 0, 4032 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, +}; +Vtx player_vtx_flip[] = { + { { { 9, 18, -6 }, 0, { 0, 0 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { 9, 0, -6 }, 0, { 0, 4032 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { -9, 18, -6 }, 0, { 4032, 0 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { -9, 0, -6 }, 0, { 4032, 4032 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, +}; + void render_kart(Player* player, s8 playerId, s8 screenId, s8 arg3) { UNUSED s32 pad; Mat4 mtx; @@ -1727,19 +1739,15 @@ void render_kart(Player* player, s8 playerId, s8 screenId, s8 arg3) { } // Render heads - gDPLoadTextureBlock(gDisplayListHead++, sKartUpperTexture, G_IM_FMT_CI, G_IM_SIZ_8b, 64, 32, 0, + gDPLoadTextureBlock(gDisplayListHead++, sKartUpperTexture, G_IM_FMT_CI, G_IM_SIZ_8b, 64, 64, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - gSPVertex(gDisplayListHead++, &D_800DDBB4[playerId][arg3], 4, 0); - gSPDisplayList(gDisplayListHead++, common_square_plain_render); - - // Render karts - u8* test = (u8*) LOAD_ASSET(sKartUpperTexture); - gDPLoadTextureBlock(gDisplayListHead++, test + 0x7C0, G_IM_FMT_CI, G_IM_SIZ_8b, 64, 32, 0, - G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, - G_TX_NOLOD); - gSPVertex(gDisplayListHead++, &D_800DDBB4[playerId][arg3 + 4], 4, 0); - gSPDisplayList(gDisplayListHead++, common_square_plain_render); + if (arg3 == 0) { + gSPVertex(gDisplayListHead++, player_vtx, 4, 0); + } else { + gSPVertex(gDisplayListHead++, player_vtx_flip, 4, 0); + } + gSP2Triangles(gDisplayListHead++, 0, 1, 2, 0, 1, 3, 2, 0); gSPTexture(gDisplayListHead++, 1, 1, 0, G_TX_RENDERTILE, G_OFF); gDPSetAlphaCompare(gDisplayListHead++, G_AC_NONE); @@ -1964,7 +1972,7 @@ void render_player(Player* player, s8 playerId, s8 screenId) { func_80025DE8(player, playerId, screenId, var_v1); } // Allows wheels to spin - gSPInvalidateTexCache(gDisplayListHead++, sKartLowerTexture); + gSPInvalidateTexCache(gDisplayListHead++, sKartUpperTexture); } void func_80026A48(Player* player, s8 arg1) { diff --git a/src/spawn_players.c b/src/spawn_players.c index 557d6508b..96b6dcd2e 100644 --- a/src/spawn_players.c +++ b/src/spawn_players.c @@ -1195,9 +1195,6 @@ void func_8003D080(void) { func_8003C0F0(); } - // Init free cam - freecam_init(player->pos[0], player->pos[1], player->pos[2], player->rotation[1], 1, 4); - if (!gDemoMode) { switch (gActiveScreenMode) { case SCREEN_MODE_1P: @@ -1293,6 +1290,9 @@ void func_8003D080(void) { } } + // Init free cam + freecam_init(player->pos[0], player->pos[1], player->pos[2], player->rotation[1], 1, 4); + switch (gActiveScreenMode) { case SCREEN_MODE_1P: func_8003CD98(gPlayerOneCopy, camera1, 0, 0); // sic diff --git a/torch b/torch -Subproject 8e56ea0294973b7c9f8f077a131b40fce13b848 +Subproject f75facb20883570ed091e8ae733ec0539f606e5 |
