summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMegaMech <MegaMech@users.noreply.github.com>2026-02-24 14:51:25 -0700
committerGitHub <noreply@github.com>2026-02-24 14:51:25 -0700
commit548ccf0063f6c4d6608cf87f46a347c71079c0bd (patch)
tree42708916b67dc1dd553c70199339541a401dca15
parent321d440089fc7424002879c9b2e74a4b0ffe9a8d (diff)
Impl Sky and SkyActors (#630)
* Create Cloud.cpp * Create Cloud.h * Fix the cloud * Cleanup * More cleanup * Update Track.h * Refactor SkyboxCloud position calculations * Update SkyboxStar.cpp * Update SkyboxStar.cpp * Refactor SkyboxStar.cpp by removing redundant code * Update SkyboxCloud.cpp * Refactor SkyboxSnow.cpp by reordering includes * Update SkyboxCloud.h * Refactor SkyboxStar.h for improved formatting * Impl skyboxcloud * Update comment * update comment * Work now * Fully impl Sky * Fix define * Fix args
-rw-r--r--CMakeLists.txt6
-rw-r--r--include/actor_types.h4
-rw-r--r--include/defines.h9
-rw-r--r--include/objects.h2
-rw-r--r--src/code_800029B0.c2
-rw-r--r--src/code_800029B0.h8
-rw-r--r--src/code_80057C60.c54
-rw-r--r--src/code_80057C60.h2
-rw-r--r--src/code_8006E9C0.c27
-rw-r--r--src/code_8006E9C0.h4
-rw-r--r--src/code_80086E70.c5
-rw-r--r--src/code_80086E70.h1
-rw-r--r--src/ending/code_80280000.c20
-rw-r--r--src/ending/code_80281780.c2
-rw-r--r--src/ending/code_80281C40.c6
-rw-r--r--src/engine/AllTracks.h1
-rw-r--r--src/engine/TrackBrowser.h17
-rw-r--r--src/engine/World.cpp2
-rw-r--r--src/engine/World.h3
-rw-r--r--src/engine/objects/Boos.cpp1
-rw-r--r--src/engine/registry/RegisterTracks.cpp9
-rw-r--r--src/engine/sky/Sky.cpp350
-rw-r--r--src/engine/sky/Sky.h43
-rw-r--r--src/engine/sky/SkyActor.h45
-rw-r--r--src/engine/sky/SkyCloud.cpp112
-rw-r--r--src/engine/sky/SkyCloud.h35
-rw-r--r--src/engine/sky/SkySnow.cpp183
-rw-r--r--src/engine/sky/SkySnow.h49
-rw-r--r--src/engine/sky/SkyStar.cpp165
-rw-r--r--src/engine/sky/SkyStar.h48
-rw-r--r--src/engine/tracks/BansheeBoardwalk.h1
-rw-r--r--src/engine/tracks/BowsersCastle.h1
-rw-r--r--src/engine/tracks/DKJungle.h1
-rw-r--r--src/engine/tracks/FrappeSnowland.cpp21
-rw-r--r--src/engine/tracks/FrappeSnowland.h2
-rw-r--r--src/engine/tracks/PodiumCeremony.cpp1
-rw-r--r--src/engine/tracks/PodiumCeremony.h3
-rw-r--r--src/engine/tracks/RainbowRoad.cpp9
-rw-r--r--src/engine/tracks/RainbowRoad.h2
-rw-r--r--src/engine/tracks/Skyscraper.h1
-rw-r--r--src/engine/tracks/ToadsTurnpike.cpp9
-rw-r--r--src/engine/tracks/ToadsTurnpike.h2
-rw-r--r--src/engine/tracks/Track.cpp22
-rw-r--r--src/engine/tracks/Track.h12
-rw-r--r--src/engine/tracks/WarioStadium.cpp9
-rw-r--r--src/engine/tracks/WarioStadium.h2
-rw-r--r--src/main.c51
-rw-r--r--src/port/Game.cpp23
-rw-r--r--src/port/Game.h4
-rw-r--r--src/port/ui/ContentBrowser.cpp5
-rw-r--r--src/port/ui/PortMenu.cpp8
-rw-r--r--src/racing/actors.c1
-rw-r--r--src/racing/race_logic.c8
-rw-r--r--src/racing/skybox_and_splitscreen.c292
-rw-r--r--src/racing/skybox_and_splitscreen.h25
-rw-r--r--src/render_objects.c127
-rw-r--r--src/render_objects.h19
-rw-r--r--src/update_objects.c232
-rw-r--r--src/update_objects.h9
59 files changed, 1339 insertions, 778 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c4870b59b..277d34612 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -224,7 +224,9 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/src/debug
${CMAKE_CURRENT_SOURCE_DIR}/src/engine
${CMAKE_CURRENT_SOURCE_DIR}/src/engine/tracks
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/engine/actors
${CMAKE_CURRENT_SOURCE_DIR}/src/engine/objects
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/engine/sky
${CMAKE_CURRENT_SOURCE_DIR}/src/engine/particles
${CMAKE_CURRENT_SOURCE_DIR}/src/enhancements
${CMAKE_CURRENT_SOURCE_DIR}/src/enhancements/freecam
@@ -272,8 +274,12 @@ file(GLOB_RECURSE ALL_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
"src/engine/*.h"
"src/engine/tracks/*.c"
"src/engine/tracks/*.h"
+ "src/engine/actors/*.cpp"
+ "src/engine/actors/*.h"
"src/engine/objects/*.cpp"
"src/engine/objects/*.h"
+ "src/engine/sky/*.cpp"
+ "src/engine/sky/*.h"
"src/engine/particles/*.cpp"
"src/engine/particles/*.h"
"src/enhancements/*.c"
diff --git a/include/actor_types.h b/include/actor_types.h
index 2e4c47087..947c78288 100644
--- a/include/actor_types.h
+++ b/include/actor_types.h
@@ -83,10 +83,8 @@ enum ActorType {
ACTOR_CAR,
ACTOR_KIWANO_FRUIT
};
-size_t CM_GetActorSize(void);
-#define ACTOR_LIST_SIZE CM_GetActorSize()
-struct Actor* CM_GetActor(size_t);
+#define ACTOR_LIST_SIZE CM_GetActorSize()
#define GET_ACTOR(index) CM_GetActor(index)
// Actor flags
diff --git a/include/defines.h b/include/defines.h
index 0d823a4b5..942271c11 100644
--- a/include/defines.h
+++ b/include/defines.h
@@ -124,15 +124,6 @@
#define FOUR_PLAYERS_SELECTED 4
#define SELECTED_PLAYER_DEFINES_TOTAL 5
-// Camera index into cameras array
-enum CameraId {
- CAMERA_ONE = 0,
- CAMERA_TWO,
- CAMERA_THREE,
- CAMERA_FOUR,
- CAMERA_FREECAM
-};
-
enum PlayerId {
PLAYER_NONE = -1,
PLAYER_ONE = 0,
diff --git a/include/objects.h b/include/objects.h
index 2862b7587..d6535dd06 100644
--- a/include/objects.h
+++ b/include/objects.h
@@ -421,7 +421,7 @@ extern s32 gNextFreeLeafParticle;
// See `func_800704A0` and `func_800703E0` for star initialization
typedef struct {
// rotY and posY seem relative to the camera.
- // See `func_800788F8` to see how rotY is used to decide whether and where to display clouds/stars
+ // See `func_800788F8` (SkyCloud Tick2 now) to see how rotY is used to decide whether and where to display clouds/stars
// See `func_80078A44` and `func_800789AC` to see how stars and clouds (respectively) are looped over
/* 0x00 */ u16 rotY;
/* 0x02 */ u16 posY;
diff --git a/src/code_800029B0.c b/src/code_800029B0.c
index a2402080f..42f9c279a 100644
--- a/src/code_800029B0.c
+++ b/src/code_800029B0.c
@@ -37,7 +37,7 @@ uintptr_t gCurrentlyLoadedTrackAddr = NULL;
u16 D_800DC5A8 = 0;
s32 D_800DC5AC = 0;
u16 D_800DC5B0 = 1;
-u16 D_800DC5B4 = 0;
+bool bDrawSkybox = false;
u16 D_800DC5B8 = 0;
bool bFog = false;
u16 gIsInQuitToMenuTransition = 0;
diff --git a/src/code_800029B0.h b/src/code_800029B0.h
index 1809fe665..4ea0028da 100644
--- a/src/code_800029B0.h
+++ b/src/code_800029B0.h
@@ -5,7 +5,11 @@
#include <libultraship.h>
#include <actor_types.h>
#include "camera.h"
-#include "engine/CoreMath.h"
+
+/**
+ * To include in C++, you must include libultraship.h
+ * and place this file in extern "C"
+ */
typedef struct {
/* 0x00 */ struct Controller* controllers; // gControllers ptr 800F6910
@@ -45,7 +49,7 @@ extern uintptr_t gCurrentlyLoadedTrackAddr;
extern u16 D_800DC5A8;
extern s32 D_800DC5AC;
extern u16 D_800DC5B0;
-extern u16 D_800DC5B4;
+extern bool bDrawSkybox;
extern u16 D_800DC5B8;
extern bool bFog;
extern u16 gIsInQuitToMenuTransition;
diff --git a/src/code_80057C60.c b/src/code_80057C60.c
index b7aaa3342..948285d77 100644
--- a/src/code_80057C60.c
+++ b/src/code_80057C60.c
@@ -412,31 +412,31 @@ void func_80057C60(void) {
void func_80057CE4(void) {
switch (D_8018D21C) {
case 0:
- func_802A3730(gScreenOneCtx);
+ race_set_viewport(gScreenOneCtx);
break;
case 1:
- func_802A3730(gScreenOneCtx);
+ race_set_viewport(gScreenOneCtx);
break;
case 2:
- func_802A3730(gScreenTwoCtx);
+ race_set_viewport(gScreenTwoCtx);
break;
case 3:
- func_802A3730(gScreenOneCtx);
+ race_set_viewport(gScreenOneCtx);
break;
case 4:
- func_802A3730(gScreenTwoCtx);
+ race_set_viewport(gScreenTwoCtx);
break;
case 8:
- func_802A3730(gScreenOneCtx);
+ race_set_viewport(gScreenOneCtx);
break;
case 9:
- func_802A3730(gScreenTwoCtx);
+ race_set_viewport(gScreenTwoCtx);
break;
case 10:
- func_802A3730(gScreenThreeCtx);
+ race_set_viewport(gScreenThreeCtx);
break;
case 11:
- func_802A3730(gScreenFourCtx);
+ race_set_viewport(gScreenFourCtx);
break;
}
}
@@ -458,7 +458,7 @@ void func_80057DD0(void) {
}
}
-void func_80057FC4(u32 arg0) {
+void func_80057FC4(ScreenContext* ctx, u32 arg0) {
UNUSED Gfx* temp_v1;
if ((gHUDDisable != 0)) {
@@ -473,19 +473,27 @@ void func_80057FC4(u32 arg0) {
switch (arg0) {
case 0:
- func_80051EBC();
+ func_80051EBC(ctx);
break;
case 1:
- func_80051EF8();
+ func_80051EF8(ctx);
break;
case 2:
- func_80051F9C();
+ func_80051F9C(ctx);
break;
case 3:
- func_80052044();
+ func_80052044(ctx);
break;
case 4:
- func_80052080();
+ func_80052080(ctx);
+ break;
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ if (CVarGetInteger("gMultiplayerNoFeatureCuts", 0) == true) {
+ func_80052080(ctx);
+ }
break;
}
}
@@ -1113,16 +1121,16 @@ void func_80059D00(void) {
if (!gDemoMode) {
// func_8007AA44(0);
}
- func_80078C70(0);
+ func_80078C70();
if (playerHUD[PLAYER_ONE].raceCompleteBool == 0) {
func_8005C360((gPlayerOne->speed / 18.0f) * 216.0f);
}
func_8005D0FC(PLAYER_ONE);
} else {
func_80059820(PLAYER_ONE);
- func_80078C70(1);
+ func_80078C70();
func_80059820(PLAYER_TWO);
- func_80078C70(2);
+ //func_80078C70();
}
break;
case SCREEN_MODE_2P_SPLITSCREEN_VERTICAL:
@@ -1133,14 +1141,14 @@ void func_80059D00(void) {
if (!gDemoMode) {
// func_8007AA44(0);
}
- func_80078C70(1);
+ func_80078C70();
func_8005D1F4(0);
func_80059820(PLAYER_TWO);
func_8005D0FC(PLAYER_TWO);
if (!gDemoMode) {
// func_8007AA44(1);
}
- func_80078C70(2);
+ //func_80078C70();
func_8005D1F4(1);
break;
case SCREEN_MODE_2P_SPLITSCREEN_HORIZONTAL:
@@ -1151,14 +1159,13 @@ void func_80059D00(void) {
if (!gDemoMode) {
// func_8007AA44(0);
}
- func_80078C70(3);
+ func_80078C70();
func_8005D1F4(0);
func_80059820(PLAYER_TWO);
func_8005D0FC(PLAYER_TWO);
if (!gDemoMode) {
// func_8007AA44(1);
}
- func_80078C70(4);
func_8005D1F4(1);
break;
case SCREEN_MODE_3P_4P_SPLITSCREEN:
@@ -1171,6 +1178,7 @@ void func_80059D00(void) {
if (!gDemoMode) {
// func_8007AA44(0);
}
+ func_80078C70();
func_8005D1F4(0);
func_80059820(PLAYER_TWO);
func_8005D0FC(PLAYER_TWO);
@@ -1217,7 +1225,7 @@ void func_8005A070(void) {
CM_TickParticles();
} else if (gGamestate == CREDITS_SEQUENCE) {
func_80059820(PLAYER_ONE);
- func_80078C70(0);
+ func_80078C70();
CM_TickObjects();
CM_TickParticles();
} else { // normal gameplay
diff --git a/src/code_80057C60.h b/src/code_80057C60.h
index fdb650040..3ff6e6681 100644
--- a/src/code_80057C60.h
+++ b/src/code_80057C60.h
@@ -36,7 +36,7 @@ void func_8005C674(s8, s16*, s16*, s16*);
void func_80057C60(void);
void func_80057CE4(void);
void func_80057DD0(void);
-void func_80057FC4(u32);
+void func_80057FC4(ScreenContext* screen, u32);
void render_object(ScreenContext* screen);
void render_player_snow_effect(Camera* camera);
diff --git a/src/code_8006E9C0.c b/src/code_8006E9C0.c
index fa6a96322..1ffadf8b1 100644
--- a/src/code_8006E9C0.c
+++ b/src/code_8006E9C0.c
@@ -31,6 +31,7 @@
#include "port/Engine.h"
#include "engine/editor/Editor.h"
#include "engine/tracks/Track.h"
+#include "engine/sky/Sky.h"
void init_hud(void) {
@@ -613,11 +614,11 @@ void init_stars(StarData* starList) {
D_8018D230 = 1;
}
-void func_8007055C(void) {
+void func_8007055C(ScreenContext* screen) {
s32 var_s0;
s32 var_s4;
- CM_InitClouds();
+ InitSkyActors(screen);
func_8008C23C();
}
@@ -656,8 +657,8 @@ void init_hud_one_player(void) {
find_unused_obj_index(&gItemWindowObjectByPlayerId[0]);
find_unused_obj_index(&gItemWindowObjectByPlayerId[1]);
init_object_list_index();
- func_8007055C();
- func_8007055C();
+ func_8007055C(gScreenOneCtx);
+ func_8007055C(gScreenTwoCtx);
init_course_object();
playerHUD[PLAYER_ONE].speedometerX = 0x0156;
playerHUD[PLAYER_ONE].speedometerY = 0x0106;
@@ -734,8 +735,8 @@ void init_hud_two_player_vertical(void) {
find_unused_obj_index(&gItemWindowObjectByPlayerId[1]);
init_object_list_index();
- func_8007055C();
- func_8007055C();
+ func_8007055C(gScreenOneCtx);
+ func_8007055C(gScreenTwoCtx);
init_course_object();
playerHUD[PLAYER_ONE].itemBoxX = -0x52;
@@ -799,8 +800,8 @@ void init_hud_two_player_horizontal() {
find_unused_obj_index(&gItemWindowObjectByPlayerId[1]);
init_object_list_index();
- func_8007055C();
- func_8007055C();
+ func_8007055C(gScreenOneCtx);
+ func_8007055C(gScreenTwoCtx);
init_course_object();
playerHUD[PLAYER_ONE].itemBoxY = 0x22;
@@ -872,6 +873,16 @@ void init_hud_three_four_player(void) {
find_unused_obj_index(&gItemWindowObjectByPlayerId[3]);
init_object_list_index();
+
+ if (CVarGetInteger("gMultiplayerNoFeatureCuts", false) == true) {
+ func_8007055C(gScreenOneCtx);
+ func_8007055C(gScreenTwoCtx);
+ func_8007055C(gScreenThreeCtx);
+ if (gPlayerCountSelection1 == 4) {
+ func_8007055C(gScreenFourCtx);
+ }
+ }
+
init_course_object();
playerHUD[PLAYER_ONE].itemBoxX = -0x36;
diff --git a/src/code_8006E9C0.h b/src/code_8006E9C0.h
index e41f7da1e..6859f71ac 100644
--- a/src/code_8006E9C0.h
+++ b/src/code_8006E9C0.h
@@ -23,7 +23,7 @@ void init_cloud_object(s32, s32, CloudData*);
void init_clouds(CloudData*);
void init_star_object(s32, s32, StarData*);
void init_stars(StarData*);
-void func_8007055C(void);
+void func_8007055C(ScreenContext* screen);
void func_80070714(void);
void init_course_object(void);
void init_hud_one_player(void);
@@ -31,6 +31,8 @@ void init_hud_two_player_vertical(void);
void init_hud_three_four_player(void);
void init_hud_two_player_horizontal(void);
+extern Vtx cloudvtx[4][4];
+extern Vtx cloudvtx2[3][4];
extern s16 D_800E5520[];
extern u8* gCourseOutlineTextures[0x14]; // 800e54d0
diff --git a/src/code_80086E70.c b/src/code_80086E70.c
index 4c94b3fcf..00c3fcffd 100644
--- a/src/code_80086E70.c
+++ b/src/code_80086E70.c
@@ -1946,11 +1946,6 @@ void func_8008BF64(s32 objectIndex) {
D_80183E80[2] = object->direction_angle[2];
}
-void func_8008BFC0(s32 objectIndex) {
- gObjectList[objectIndex].unk_09C = gObjectList[objectIndex].pos[0];
- gObjectList[objectIndex].unk_09E = gObjectList[objectIndex].pos[1];
-}
-
void func_8008BFFC(s32 objectIndex) {
Object* object;
diff --git a/src/code_80086E70.h b/src/code_80086E70.h
index f921405a2..3348d6e16 100644
--- a/src/code_80086E70.h
+++ b/src/code_80086E70.h
@@ -159,7 +159,6 @@ void object_origin_pos_randomize_around_xz(s32, s16, s16, u16, u16);
void object_origin_pos_randomize_around_xyz(s32, s16, s16, s16, u16, u16, u16);
void object_origin_pos_around_player_one(s32, s16, u16);
void func_8008BEA4(s32, u16, u16);
-void func_8008BFC0(s32);
void object_calculate_new_pos_offset(s32);
void func_8008BF64(s32);
void func_8008BFFC(s32);
diff --git a/src/ending/code_80280000.c b/src/ending/code_80280000.c
index 134083225..13f8cdb1b 100644
--- a/src/ending/code_80280000.c
+++ b/src/ending/code_80280000.c
@@ -52,9 +52,13 @@ void func_80280038(Camera* camera) {
gMatrixEffectCount = 0;
gMatrixHudCount = 0;
init_rdp();
- func_802A53A4();
+ race_begin_viewport(gScreenOneCtx, 0);
+ if ((CVarGetInteger("gDrawSky", true) == true)) {
+ CM_RaceDrawSky(gScreenOneCtx, 0);
+ func_80093A30(0); // Fill box for thunderbolt?
+ }
init_rdp();
- func_80057FC4(0);
+ func_80057FC4(gScreenOneCtx, 0);
gSPSetGeometryMode(gDisplayListHead++, G_ZBUFFER | G_SHADE | G_CULL_BACK | G_SHADING_SMOOTH);
guPerspective(camera->perspectiveMatrix , &perspNorm, camera->fieldOfView, gScreenAspect, CM_GetProps()->NearPersp, CM_GetProps()->FarPersp, 1.0f);
@@ -140,16 +144,24 @@ void load_credits(void) {
if (!camera) {
CM_ThrowRuntimeError("[code_80280000] [load_credits] NULL camera while attempting to create camera for player one");
}
-
CM_AttachCamera(camera, PLAYER_ONE);
gScreenOneCtx->camera = camera;
+
+ // init_hud_one_player uses a second camera for whatever reason...
+ Camera* camera2 = CM_AddCamera(spawn, 0, 0);
+ if (!camera2) {
+ CM_ThrowRuntimeError("[code_80280000] [load_credits] NULL camera while attempting to create camera for player two");
+ }
+ CM_AttachCamera(camera2, PLAYER_TWO);
+ gScreenTwoCtx->camera = camera2;
+
camera->renderMode = RENDER_FULL_SCENE;
camera->unk_B4 = 60.0f;
camera->fieldOfView = 60.0f;
gCurrentCourseId = gCreditsCourseId;
TrackBrowser_SetTrackByIdx(gCreditsCourseId);
- D_800DC5B4 = 1;
+ bDrawSkybox = true;
func_802A4D18();
set_screen();
gScreenOneCtx->screenWidth = SCREEN_WIDTH;
diff --git a/src/ending/code_80281780.c b/src/ending/code_80281780.c
index 3876fbc79..37de7df73 100644
--- a/src/ending/code_80281780.c
+++ b/src/ending/code_80281780.c
@@ -99,7 +99,7 @@ void setup_podium_ceremony(void) {
gCurrentCourseId = TRACK_ROYAL_RACEWAY;
SelectPodiumCeremony();
- D_800DC5B4 = (u16) 1;
+ bDrawSkybox = true;
set_mirror_mode(0);
gGotoMenu = 0xFFFF;
D_80287554 = 0;
diff --git a/src/ending/code_80281C40.c b/src/ending/code_80281C40.c
index d22ac69e5..d265f8824 100644
--- a/src/ending/code_80281C40.c
+++ b/src/ending/code_80281C40.c
@@ -61,7 +61,11 @@ void func_80281D00(void) {
Mat4 matrix;
UNUSED s32 pad2[3];
- func_802A53A4();
+ race_begin_viewport(gScreenOneCtx, 0);
+ if ((CVarGetInteger("gDrawSky", true) == true)) {
+ CM_RaceDrawSky(gScreenOneCtx, 0);
+ func_80093A30(0); // Fill box for thunderbolt?
+ }
init_rdp();
if (gGotoMenu != 0xFFFF) {
clear_framebuffer(0);
diff --git a/src/engine/AllTracks.h b/src/engine/AllTracks.h
index d8b55d1f8..fb5827e1e 100644
--- a/src/engine/AllTracks.h
+++ b/src/engine/AllTracks.h
@@ -21,5 +21,6 @@
#include "engine/tracks/DoubleDeck.h"
#include "engine/tracks/DKJungle.h"
#include "engine/tracks/BigDonut.h"
+#include "engine/tracks/PodiumCeremony.h"
#include "engine/tracks/TestTrack.h"
diff --git a/src/engine/TrackBrowser.h b/src/engine/TrackBrowser.h
index 4bcccf16f..89dec2f00 100644
--- a/src/engine/TrackBrowser.h
+++ b/src/engine/TrackBrowser.h
@@ -21,6 +21,9 @@ public:
TrackBrowser(const Registry<TrackInfo>& registry) {
mTracks = registry.GetAllInfo();
+
+ RemovePodiumCeremony();
+
std::sort(mTracks.begin(), mTracks.end(), [](const TrackInfo* a, const TrackInfo* b) {
return a->Id < b->Id;
});
@@ -32,6 +35,9 @@ public:
void Refresh(const Registry<TrackInfo>& registry) {
mTracks.clear();
mTracks = registry.GetAllInfo();
+
+ RemovePodiumCeremony();
+
std::sort(mTracks.begin(), mTracks.end(), [](const TrackInfo* a, const TrackInfo* b) {
return a->Id < b->Id;
});
@@ -42,6 +48,17 @@ public:
mTrackIndex = 0;
}
+ // Podium is not a valid user selectable option in the menus, remove it.
+ void RemovePodiumCeremony() {
+ mTracks.erase(
+ std::remove_if(mTracks.begin(), mTracks.end(),
+ [](const TrackInfo* track) {
+ return track && track->ResourceName == "mk:podium_ceremony";
+ }),
+ mTracks.end()
+ );
+ }
+
void SetTrack(std::string name) {
if (gTrackRegistry.Find(name)) {
gTrackRegistry.Invoke(name);
diff --git a/src/engine/World.cpp b/src/engine/World.cpp
index bc6cbfc1b..d1619ae18 100644
--- a/src/engine/World.cpp
+++ b/src/engine/World.cpp
@@ -6,6 +6,7 @@
#include <memory>
#include "objects/Object.h"
#include "port/Game.h"
+#include "engine/sky/Sky.h"
extern "C" {
#include "objects.h"
@@ -270,4 +271,5 @@ void World::CleanWorld(void) {
Objects.clear();
Emitters.clear();
Lakitus.clear();
+ Sky::Instance->GetSkyActors().clear();
}
diff --git a/src/engine/World.h b/src/engine/World.h
index db782eccf..96b620bb6 100644
--- a/src/engine/World.h
+++ b/src/engine/World.h
@@ -16,6 +16,7 @@
#include "Actor.h"
#include "StaticMeshActor.h"
#include "particles/ParticleEmitter.h"
+#include "engine/sky/SkyCloud.h"
#include "editor/Editor.h"
#include "editor/GameObject.h"
@@ -119,7 +120,7 @@ public:
std::vector<std::unique_ptr<StaticMeshActor>> StaticMeshActors;
std::vector<std::unique_ptr<AActor>> Actors;
- std::vector<std::unique_ptr<OObject>> Objects;
+ std::deque<std::unique_ptr<OObject>> Objects;
std::vector<std::unique_ptr<ParticleEmitter>> Emitters;
std::unordered_map<s32, OLakitu*> Lakitus;
diff --git a/src/engine/objects/Boos.cpp b/src/engine/objects/Boos.cpp
index 20b16355e..f05d62be1 100644
--- a/src/engine/objects/Boos.cpp
+++ b/src/engine/objects/Boos.cpp
@@ -20,6 +20,7 @@ extern "C" {
#include "menus.h"
#include "race_logic.h"
#include "external.h"
+#include "some_data.h"
}
size_t OBoos::_count = 0;
diff --git a/src/engine/registry/RegisterTracks.cpp b/src/engine/registry/RegisterTracks.cpp
index 47a6a6ff2..a347e907f 100644
--- a/src/engine/registry/RegisterTracks.cpp
+++ b/src/engine/registry/RegisterTracks.cpp
@@ -214,6 +214,15 @@ void RegisterTracks(Registry<TrackInfo>& r) {
r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<BigDonut>()); });
info = {
+ .ResourceName = "mk:podium_ceremony",
+ .Name = "podium ceremony",
+ .DebugName = "podium",
+ .Length = "1025m",
+ };
+
+ r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<PodiumCeremony>()); });
+
+ info = {
.ResourceName = "hm:test_track",
.Name = "test track",
.DebugName = "test track",
diff --git a/src/engine/sky/Sky.cpp b/src/engine/sky/Sky.cpp
new file mode 100644
index 000000000..a7b1f0676
--- /dev/null
+++ b/src/engine/sky/Sky.cpp
@@ -0,0 +1,350 @@
+#include "Sky.h"
+
+#include <libultraship.h>
+#include <libultra/gbi.h>
+#include "port/Engine.h"
+#include "port/Game.h"
+
+#include "engine/CoreMath.h"
+#include "engine/tracks/Track.h"
+
+#include "engine/sky/SkyCloud.h"
+#include "engine/sky/SkySnow.h"
+#include "engine/sky/SkyStar.h"
+
+extern "C" {
+#include "macros.h"
+#include "mk64.h"
+#include "math_util.h"
+#include "skybox_and_splitscreen.h"
+#include "menus.h"
+}
+
+Vtx Sky::mSkyboxScreenOne[8] = { // D_802B8890
+ { { { SCREEN_WIDTH, SCREEN_HEIGHT, -1 }, 0, { 0, 0 }, { 0xC8, 0xC8, 0xFF, 0xFF } } },
+ { { { SCREEN_WIDTH, 120, -1 }, 0, { 0, 0 }, { 0x1E, 0x1E, 0xFF, 0xFF } } },
+ { { { 0, 120, -1 }, 0, { 0, 0 }, { 0x1E, 0x1E, 0xFF, 0xFF } } },
+ { { { 0, SCREEN_HEIGHT, -1 }, 0, { 0, 0 }, { 0xC8, 0xC8, 0xFF, 0xFF } } },
+ { { { SCREEN_WIDTH, 120, -1 }, 0, { 0, 0 }, { 0x00, 0xDC, 0x00, 0xFF } } },
+ { { { SCREEN_WIDTH, 0, -1 }, 0, { 0, 0 }, { 0x78, 0xFF, 0x78, 0xFF } } },
+ { { { 0, 0, -1 }, 0, { 0, 0 }, { 0x78, 0xFF, 0x78, 0xFF } } },
+ { { { 0, 120, -1 }, 0, { 0, 0 }, { 0x00, 0xDC, 0x00, 0xFF } } },
+};
+
+Vtx Sky::mSkyboxScreenTwo[8] = { // D_802B8910
+ { { { SCREEN_WIDTH, SCREEN_HEIGHT, -1 }, 0, { 0, 0 }, { 0xC8, 0xC8, 0xFF, 0xFF } } },
+ { { { SCREEN_WIDTH, 120, -1 }, 0, { 0, 0 }, { 0x1E, 0x1E, 0xFF, 0xFF } } },
+ { { { 0, 120, -1 }, 0, { 0, 0 }, { 0x1E, 0x1E, 0xFF, 0xFF } } },
+ { { { 0, SCREEN_HEIGHT, -1 }, 0, { 0, 0 }, { 0xC8, 0xC8, 0xFF, 0xFF } } },
+ { { { SCREEN_WIDTH, 120, -1 }, 0, { 0, 0 }, { 0x00, 0xDC, 0x00, 0xFF } } },
+ { { { SCREEN_WIDTH, 0, -1 }, 0, { 0, 0 }, { 0x78, 0xFF, 0x78, 0xFF } } },
+ { { { 0, 0, -1 }, 0, { 0, 0 }, { 0x78, 0xFF, 0x78, 0xFF } } },
+ { { { 0, 120, -1 }, 0, { 0, 0 }, { 0x00, 0xDC, 0x00, 0xFF } } },
+};
+
+Vtx Sky::mSkyboxScreenThree[8] = { // D_802B8990
+ { { { SCREEN_WIDTH, SCREEN_HEIGHT, -1 }, 0, { 0, 0 }, { 0xC8, 0xC8, 0xFF, 0xFF } } },
+ { { { SCREEN_WIDTH, 120, -1 }, 0, { 0, 0 }, { 0x1E, 0x1E, 0xFF, 0xFF } } },
+ { { { 0, 120, -1 }, 0, { 0, 0 }, { 0x1E, 0x1E, 0xFF, 0xFF } } },
+ { { { 0, SCREEN_HEIGHT, -1 }, 0, { 0, 0 }, { 0xC8, 0xC8, 0xFF, 0xFF } } },
+ { { { SCREEN_WIDTH, 120, -1 }, 0, { 0, 0 }, { 0x00, 0xDC, 0x00, 0xFF } } },
+ { { { SCREEN_WIDTH, 0, -1 }, 0, { 0, 0 }, { 0x78, 0xFF, 0x78, 0xFF } } },
+ { { { 0, 0, -1 }, 0, { 0, 0 }, { 0x78, 0xFF, 0x78, 0xFF } } },
+ { { { 0, 120, -1 }, 0, { 0, 0 }, { 0x00, 0xDC, 0x00, 0xFF } } },
+};
+
+Vtx Sky::mSkyboxScreenFour[8] = { // D_802B8A10
+ { { { SCREEN_WIDTH, SCREEN_HEIGHT, -1 }, 0, { 0, 0 }, { 0xC8, 0xC8, 0xFF, 0xFF } } },
+ { { { SCREEN_WIDTH, 120, -1 }, 0, { 0, 0 }, { 0x1E, 0x1E, 0xFF, 0xFF } } },
+ { { { 0, 120, -1 }, 0, { 0, 0 }, { 0x1E, 0x1E, 0xFF, 0xFF } } },
+ { { { 0, SCREEN_HEIGHT, -1 }, 0, { 0, 0 }, { 0xC8, 0xC8, 0xFF, 0xFF } } },
+ { { { SCREEN_WIDTH, 120, -1 }, 0, { 0, 0 }, { 0x00, 0xDC, 0x00, 0xFF } } },
+ { { { SCREEN_WIDTH, 0, -1 }, 0, { 0, 0 }, { 0x78, 0xFF, 0x78, 0xFF } } },
+ { { { 0, 0, -1 }, 0, { 0, 0 }, { 0x78, 0xFF, 0x78, 0xFF } } },
+ { { { 0, 120, -1 }, 0, { 0, 0 }, { 0x00, 0xDC, 0x00, 0xFF } } },
+};
+
+Sky* Sky::Instance;
+
+Sky::Sky() {
+ Instance = this;
+ guMtxIdent(&mSkyboxMatrix);
+}
+
+Sky* Sky::GetSky() {
+ return Instance;
+}
+
+std::vector<std::unique_ptr<SkyActor>>& Sky::GetSkyActors() {
+ return mSkyActors;
+}
+
+void Sky::SetColours(Vtx* skybox) { // func_802A450C(Vtx* skybox)
+ s32 i;
+
+ if (bFog) {
+
+ if (gFogColour.r < 0) {
+ gFogColour.r = 0;
+ }
+
+ if (gFogColour.g < 0) {
+ gFogColour.g = 0;
+ }
+
+ if (gFogColour.b < 0) {
+ gFogColour.b = 0;
+ }
+
+ if (gFogColour.r > 255) {
+ gFogColour.r = 255;
+ }
+
+ if (gFogColour.g > 255) {
+ gFogColour.g = 255;
+ }
+
+ if (gFogColour.b > 255) {
+ gFogColour.b = 255;
+ }
+
+ for (i = 0; i < 8; i++) {
+ skybox[i].v.cn[0] = (s16) gFogColour.r;
+ skybox[i].v.cn[1] = (s16) gFogColour.g;
+ skybox[i].v.cn[2] = (s16) gFogColour.b;
+ }
+ return;
+ }
+
+ SkyboxColours* prop = (SkyboxColours*) &CM_GetProps()->Skybox;
+
+ skybox[0].v.cn[0] = prop->TopRight.r;
+ skybox[0].v.cn[1] = prop->TopRight.g;
+ skybox[0].v.cn[2] = prop->TopRight.b;
+
+ skybox[1].v.cn[0] = prop->BottomRight.r;
+ skybox[1].v.cn[1] = prop->BottomRight.g;
+ skybox[1].v.cn[2] = prop->BottomRight.b;
+
+ skybox[2].v.cn[0] = prop->BottomLeft.r;
+ skybox[2].v.cn[1] = prop->BottomLeft.g;
+ skybox[2].v.cn[2] = prop->BottomLeft.b;
+
+ skybox[3].v.cn[0] = prop->TopLeft.r;
+ skybox[3].v.cn[1] = prop->TopLeft.g;
+ skybox[3].v.cn[2] = prop->TopLeft.b;
+
+ // Floor
+ skybox[4].v.cn[0] = prop->FloorTopRight.r;
+ skybox[4].v.cn[1] = prop->FloorTopRight.g;
+ skybox[4].v.cn[2] = prop->FloorTopRight.b;
+
+ skybox[5].v.cn[0] = prop->FloorBottomRight.r;
+ skybox[5].v.cn[1] = prop->FloorBottomRight.g;
+ skybox[5].v.cn[2] = prop->FloorBottomRight.b;
+
+ skybox[6].v.cn[0] = prop->FloorBottomLeft.r;
+ skybox[6].v.cn[1] = prop->FloorBottomLeft.g;
+ skybox[6].v.cn[2] = prop->FloorBottomLeft.b;
+
+ skybox[7].v.cn[0] = prop->FloorTopLeft.r;
+ skybox[7].v.cn[1] = prop->FloorTopLeft.g;
+ skybox[7].v.cn[2] = prop->FloorTopLeft.b;
+}
+
+void Sky::Draw(ScreenContext* screen) { // func_802A4A0C(Vtx* vtx, ScreenContext* screen)
+ Camera* camera = screen->camera;
+ s16 temp_t5;
+ f32 temp_f0;
+ UNUSED s32 pad[2];
+ UNUSED u16 pad2;
+ u16 sp128;
+ Mat4 matrix1 = { 0 };
+ Mat4 matrix2 = { 0 };
+ Mat4 matrix3 = { 0 };
+ Vec3f sp5C;
+ f32 sp58;
+
+ Vtx* vtx;
+ switch(screen - gScreenContexts) {
+ case 0:
+ vtx = mSkyboxScreenOne;
+ break;
+ case 1:
+ vtx = mSkyboxScreenTwo;
+ break;
+ case 2:
+ vtx = mSkyboxScreenThree;
+ break;
+ case 3:
+ vtx = mSkyboxScreenFour;
+ break;
+ }
+
+ this->SetColours(vtx); //func_802A450C(vtx);
+ // Widescreen skybox
+ // Note that this is the correct fit for each screen due to how the viewport works
+ vtx[0].v.ob[0] = OTRGetRectDimensionFromRightEdge(SCREEN_WIDTH);
+ vtx[1].v.ob[0] = OTRGetRectDimensionFromRightEdge(SCREEN_WIDTH);
+ vtx[2].v.ob[0] = OTRGetRectDimensionFromLeftEdge(0);
+ vtx[3].v.ob[0] = OTRGetRectDimensionFromLeftEdge(0);
+
+ vtx[4].v.ob[0] = OTRGetRectDimensionFromRightEdge(SCREEN_WIDTH);
+ vtx[5].v.ob[0] = OTRGetRectDimensionFromRightEdge(SCREEN_WIDTH);
+ vtx[6].v.ob[0] = OTRGetRectDimensionFromLeftEdge(0);
+ vtx[7].v.ob[0] = OTRGetRectDimensionFromLeftEdge(0);
+
+ sp5C[0] = 0.0f;
+ sp5C[1] = 0.0f;
+ sp5C[2] = 30000.0f;
+ func_802B5564(matrix1, &sp128, camera->unk_B4, gScreenAspect, CM_GetProps()->NearPersp, CM_GetProps()->FarPersp,
+ 1.0f);
+ func_802B5794(matrix2, camera->pos, camera->lookAt);
+ mtxf_multiplication(matrix3, matrix1, matrix2);
+
+ sp58 = ((matrix3[0][3] * sp5C[0]) + (matrix3[1][3] * sp5C[1]) + (matrix3[2][3] * sp5C[2])) + matrix3[3][3];
+
+ mtxf_translate_vec3f_mat4(sp5C, matrix3);
+
+ temp_f0 = (1.0 / sp58);
+
+ sp5C[0] *= temp_f0;
+ sp5C[1] *= temp_f0;
+
+ sp5C[0] *= 160.0f;
+ sp5C[1] *= 120.0f;
+
+ temp_t5 = 120 - (s32) sp5C[1];
+ screen->cameraHeight = temp_t5;
+ vtx[1].v.ob[1] = temp_t5;
+ vtx[2].v.ob[1] = temp_t5;
+ vtx[4].v.ob[1] = temp_t5;
+ vtx[7].v.ob[1] = temp_t5;
+
+ init_rdp();
+ gDPSetRenderMode(gDisplayListHead++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
+ gSPClearGeometryMode(gDisplayListHead++, G_ZBUFFER | G_LIGHTING);
+ guOrtho(&gGfxPool->mtxScreen, 0.0f, SCREEN_WIDTH, 0.0f, SCREEN_HEIGHT, 0.0f, 5.0f, 1.0f);
+ gSPPerspNormalize(gDisplayListHead++, 0xFFFF);
+ gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&gGfxPool->mtxScreen),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
+ gSPMatrix(gDisplayListHead++, (uintptr_t)&mSkyboxMatrix, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPVertex(gDisplayListHead++, (uintptr_t)&vtx[0], 4, 0);
+ gSP2Triangles(gDisplayListHead++, 0, 3, 1, 0, 1, 3, 2, 0);
+ if (IsRainbowRoad()) {
+ gSPVertex(gDisplayListHead++, (uintptr_t)&vtx[4], 4, 0);
+ gSP2Triangles(gDisplayListHead++, 0, 3, 1, 0, 1, 3, 2, 0);
+ }
+}
+
+void Sky::DrawFloor(ScreenContext* screen) { // func_802A487C
+ init_rdp();
+
+ Vtx* vtx;
+ switch(screen - gScreenContexts) {
+ case 0:
+ vtx = mSkyboxScreenOne;
+ break;
+ case 1:
+ vtx = mSkyboxScreenTwo;
+ break;
+ case 2:
+ vtx = mSkyboxScreenThree;
+ break;
+ case 3:
+ vtx = mSkyboxScreenFour;
+ break;
+ }
+
+ // Only draw black
+ if (IsRainbowRoad()) {
+ return;
+ }
+
+ gDPSetRenderMode(gDisplayListHead++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
+ gSPClearGeometryMode(gDisplayListHead++, G_ZBUFFER | G_LIGHTING);
+ guOrtho(&gGfxPool->mtxScreen, 0.0f, SCREEN_WIDTH, 0.0f, SCREEN_HEIGHT, 0.0f, 5.0f, 1.0f);
+ gSPPerspNormalize(gDisplayListHead++, 0xFFFF);
+ gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&gGfxPool->mtxScreen),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
+ gSPMatrix(gDisplayListHead++, (uintptr_t)&mSkyboxMatrix, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPVertex(gDisplayListHead++, (uintptr_t)&vtx[4], 4, 0);
+ gSP2Triangles(gDisplayListHead++, 0, 3, 1, 0, 1, 3, 2, 0);
+}
+
+void Sky::InitActors(ScreenContext* screen) {
+ size_t iterations = 0;
+ size_t numSnow = 0;
+ Track* track = GetWorld()->GetTrack();
+
+ if (!track) {
+ printf("[Sky] No track ptr found, skipping sky actors\n");
+ return;
+ }
+
+ CloudData* cloud = &track->Props.Clouds[0];
+
+ // Handle spawning snow
+ if (track->mCloudType == Track::CloudType::SNOW) {
+ if (gPlayerCount == 1) {
+ numSnow = 50;
+ } else {
+ numSnow = 25;
+ }
+
+ for (size_t i = 0; i < numSnow; i++) {
+ mSkyActors.emplace_back(std::make_unique<SkySnow>(screen));
+ iterations += 1;
+ }
+ D_8018D230 = 0;
+ }
+
+ // Handle spawning the other cloud types
+ if (nullptr != cloud) {
+ while ((cloud->rotY != 0xFFFF) && (iterations < 50)) {
+ switch(track->mCloudType) {
+ case Track::CloudType::NONE:
+ case Track::CloudType::SNOW:
+ break;
+ case Track::CloudType::CLOUDS: {
+ mSkyActors.emplace_back(std::make_unique<SkyCloud>(screen, cloud->subType, cloud->posY, cloud->rotY, cloud->scalePercent));
+ D_8018D230 = 0;
+ break;
+ }
+ case Track::CloudType::STARS: {
+ mSkyActors.emplace_back(std::make_unique<SkyStar>(screen, cloud->subType, cloud->posY, cloud->rotY, cloud->scalePercent));
+ D_8018D230 = 1;
+ break;
+ }
+ }
+
+ cloud++;
+ iterations += 1;
+ }
+ }
+
+ D_8018D1F8 += iterations;
+ D_8018D1F0 = iterations;
+}
+
+EXTERN_C void InitSkyActors(ScreenContext* screen) {
+ Sky::Instance->InitActors(screen);
+}
+
+EXTERN_C void DrawSkyActors(ScreenContext* screen, s32 arg0) {
+ if (CVarGetInteger("gDrawSkyActors", true) == false) {
+ return;
+ }
+
+ for (auto& cloud : Sky::Instance->GetSkyActors()) {
+ if (cloud->mScreen == screen) {
+ cloud->Draw(screen, arg0);
+ }
+ }
+}
+
+EXTERN_C void TickSkyActors() {
+ for (auto& cloud : Sky::Instance->GetSkyActors()) {
+ cloud->Tick();
+ }
+}
diff --git a/src/engine/sky/Sky.h b/src/engine/sky/Sky.h
new file mode 100644
index 000000000..12c94f5a0
--- /dev/null
+++ b/src/engine/sky/Sky.h
@@ -0,0 +1,43 @@
+#ifndef SKY_H
+#define SKY_H
+
+#ifdef __cplusplus
+
+#include <libultraship/libultraship.h>
+#include <libultraship/libultra/gbi.h>
+
+#include "SkyActor.h"
+
+#include "defines.h"
+
+EXTERN_C_START
+#include "code_800029B0.h"
+EXTERN_C_END
+
+class Sky {
+public:
+ static Sky* Instance;
+ Sky();
+ virtual void Draw(ScreenContext* screen);
+ virtual void DrawFloor(ScreenContext* screen);
+ Sky* GetSky();
+ void SetColours(Vtx* skybox);
+ void InitActors(ScreenContext* screen);
+ std::vector<std::unique_ptr<SkyActor>>& GetSkyActors();
+private:
+ Mtx mSkyboxMatrix;
+ static Vtx mSkyboxScreenOne[8];
+ static Vtx mSkyboxScreenTwo[8];
+ static Vtx mSkyboxScreenThree[8];
+ static Vtx mSkyboxScreenFour[8];
+
+ std::vector<std::unique_ptr<SkyActor>> mSkyActors;
+};
+#endif // __cplusplus
+
+/** C Compatible functions **/
+EXTERN_C void InitSkyActors(ScreenContext* screen);
+EXTERN_C void TickSkyActors();
+EXTERN_C void DrawSkyActors(ScreenContext* screen, s32 arg0);
+
+#endif // SKY_H
diff --git a/src/engine/sky/SkyActor.h b/src/engine/sky/SkyActor.h
new file mode 100644
index 000000000..6e95d4e84
--- /dev/null
+++ b/src/engine/sky/SkyActor.h
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <libultraship.h>
+#include "engine/SpawnParams.h"
+#include "engine/CoreMath.h"
+
+extern "C" {
+#include "common_structs.h"
+#include "code_800029B0.h"
+}
+
+/**
+ * SkyActor base class
+ *
+ *
+ */
+class SkyActor {
+public:
+ SkyActor(ScreenContext* screen) {
+ mScreen = screen;
+ };
+ SkyActor(ScreenContext* screen, u16 cloudVariant, u16 posY, u16 rotY, u16 scalePercent) {};
+
+ virtual void Draw(ScreenContext* ctx, s32 arg0) {};
+ virtual void Tick() {};
+ ScreenContext* mScreen;
+protected:
+ f32 mScale;
+ u16 mCloudVariant;
+ u8* mTexture;
+ s32 mTextureWidth;
+ s32 mTextureHeight;
+ bool mVisible;
+ Vtx* mVtx;
+ int32_t mX;
+ int32_t mY;
+ int32_t mRotY;
+ int32_t mOldX;
+ int32_t mOldY;
+
+ s16 mUnk208;
+ s16 mUnk210;
+ f32 mUnk1E8;
+ s16 mUnk218;
+};
diff --git a/src/engine/sky/SkyCloud.cpp b/src/engine/sky/SkyCloud.cpp
new file mode 100644
index 000000000..2cad8b7c6
--- /dev/null
+++ b/src/engine/sky/SkyCloud.cpp
@@ -0,0 +1,112 @@
+#include <libultraship.h>
+#include <libultra/gbi.h>
+#include "SkyCloud.h"
+#include <vector>
+#include "engine/tracks/Track.h"
+#include "engine/World.h"
+
+#include "port/Engine.h"
+#include "port/Game.h"
+#include "port/interpolation/FrameInterpolation.h"
+
+extern "C" {
+#include "update_objects.h"
+#include "code_80057C60.h"
+#include "code_8006E9C0.h"
+#include "assets/models/common_data.h"
+#include "math_util_2.h"
+#include "render_objects.h"
+}
+
+size_t SkyCloud::_count = 0;
+
+SkyCloud::SkyCloud(ScreenContext* screen, u16 cloudVariant, u16 posY, u16 rotY, u16 scalePercent) : SkyActor(screen) {
+ _idx = _count;
+ mScreen = screen;
+ mCloudVariant = cloudVariant;
+ mY = posY;
+ mRotY = rotY;
+ mScale = (f32) scalePercent / 100.0;
+
+ if (GameEngine_ResourceGetTexTypeByName((const char*)CM_GetProps()->CloudTexture) != 1) {
+ mTexture = ((u8*) LOAD_ASSET_RAW(CM_GetProps()->CloudTexture)) + (cloudVariant * 1024);
+ mTextureWidth = 64;
+ mTextureHeight = 32;
+ mVtx = (Vtx*)D_0D005FB0;
+ } else {
+ mTexture = CM_GetProps()->CloudTexture;
+ if (strcmp((const char*)CM_GetProps()->CloudTexture, gTextureExhaust0) == 0 ||
+ strcmp((const char*)CM_GetProps()->CloudTexture, gTextureExhaust1) == 0 ||
+ strcmp((const char*)CM_GetProps()->CloudTexture, gTextureExhaust2) == 0) {
+ mTextureWidth = 64;
+ mTextureHeight = 32;
+ mVtx = cloudvtx2[cloudVariant];
+ } else {
+ mTextureWidth = 64;
+ mTextureHeight = 32;
+ mVtx = cloudvtx2[cloudVariant];
+ }
+ }
+
+ _count += 1;
+}
+
+void SkyCloud::Tick() { // func_800788F8
+ s16 cameraRot;
+
+ s16 mUnk200 = mScreen->camera->fieldOfView + 40.0f;
+ mUnk208 = ((mUnk200 / 2) * 0xB6) + 0x71C;
+ mUnk210 = (-(mUnk200 / 2) * 0xB6) - 0x71C;
+ mUnk1E8 = 1.7578125 / mUnk200;
+ mUnk218 = SCREEN_WIDTH / 2;
+
+ // Adjustable culling factor
+ const float cullingFactor = OTRGetAspectRatio();
+
+ // Calculate the cloud's rotation relative to the camera
+ cameraRot = (u16)mScreen->camera->rot[1] + (u16)mRotY;
+ // Adjust bounds based on the culling factor
+ s16 adjustedLowerBound = (s16) (mUnk210 * cullingFactor);
+ s16 adjustedUpperBound = (s16) (mUnk208 * cullingFactor);
+
+ // Check if the object is within the adjusted bounds
+ if ((cameraRot >= adjustedLowerBound) && (adjustedUpperBound >= cameraRot)) {
+ // Calculate and update the object's X position
+ // 160 (SCREEN_WIDTH / 2) + (D_8018D1E8 * cameraRot);
+ // Grab center of screen, scale by fov factor, offset based on camera rotation
+ mX = mUnk218 + (mUnk1E8 * cameraRot);
+
+ // Mark the object as visible
+ mVisible = true;
+ } else {
+ // If outside the bounds, mark the object as not visible
+ mVisible = false;
+ }
+}
+
+void SkyCloud::Draw(ScreenContext* screen, s32 arg0) { // render_clouds
+ // Object* object = &gObjectList[_objectIndex];
+ s32 posY = arg0 - mY;
+ func_8004B6C4(255, 255, 255);
+ // Skip drawing the object this frame if it warped to the other side of the screen
+ if ((fabs(mX - mOldX) > SCREEN_WIDTH / 2) || (fabs(posY - mOldY) > SCREEN_HEIGHT / 2)) {
+ mOldX = mX;
+ mOldY = posY;
+ return;
+ }
+ if (mVisible) {
+ FrameInterpolation_RecordOpenChild("render_clouds", TAG_CLOUDS((_idx << 4) | (mScreen - gScreenOneCtx)));
+
+ if (D_8018D228 != mCloudVariant) {
+ D_8018D228 = mCloudVariant;
+ func_80044DA0(mTexture, mTextureWidth, mTextureHeight);
+ }
+ func_80042330_unchanged(mX, posY, 0, mScale);
+ gSPVertex(gDisplayListHead++, (uintptr_t)mVtx, 4, 0);
+ gSPDisplayList(gDisplayListHead++, (Gfx*)common_rectangle_display);
+
+ FrameInterpolation_RecordCloseChild();
+ }
+ mOldX = mX;
+ mOldY = posY;
+}
diff --git a/src/engine/sky/SkyCloud.h b/src/engine/sky/SkyCloud.h
new file mode 100644
index 000000000..366298d39
--- /dev/null
+++ b/src/engine/sky/SkyCloud.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include <libultraship.h>
+#include "engine/SpawnParams.h"
+#include "engine/CoreMath.h"
+#include "engine/sky/SkyActor.h"
+
+extern "C" {
+#include "common_structs.h"
+#include "code_800029B0.h"
+}
+
+/**
+ * Skybox clouds
+ *
+ * @cloudVariant The cloud texture to use
+ */
+class SkyCloud : public SkyActor {
+public:
+ SkyCloud(ScreenContext* screen, u16 cloudVariant, u16 posY, u16 rotY, u16 scalePercent);
+
+ ~SkyCloud() {
+ _count--;
+ }
+
+ static size_t GetCount() {
+ return _count;
+ }
+
+ virtual void Draw(ScreenContext* ctx, s32 arg0) override;
+ virtual void Tick() override;
+private:
+ static size_t _count;
+ size_t _idx;
+};
diff --git a/src/engine/sky/SkySnow.cpp b/src/engine/sky/SkySnow.cpp
new file mode 100644
index 000000000..c9e556fba
--- /dev/null
+++ b/src/engine/sky/SkySnow.cpp
@@ -0,0 +1,183 @@
+#include <libultraship.h>
+#include <libultra/gbi.h>
+#include "SkySnow.h"
+#include <vector>
+#include "engine/tracks/Track.h"
+#include "engine/World.h"
+
+#include "port/Engine.h"
+#include "port/Game.h"
+#include "port/interpolation/FrameInterpolation.h"
+
+extern "C" {
+#include "update_objects.h"
+#include "code_80057C60.h"
+#include "code_8006E9C0.h"
+#include "assets/models/common_data.h"
+#include "assets/textures/common_data.h"
+#include "math_util_2.h"
+#include "render_objects.h"
+#include "math_util.h"
+}
+
+size_t SkySnow::_count = 0;
+
+SkySnow::SkySnow(ScreenContext* screen) : SkyActor(screen) {
+ _idx = _count;
+
+ mState = 0;
+ mState2 = 0;
+
+ _count += 1;
+}
+
+void SkySnow::Tick() {
+
+ s16 mUnk200 = mScreen->camera->fieldOfView + 40.0f;
+ mUnk208 = ((mUnk200 / 2) * 0xB6) + 0x71C;
+ mUnk210 = (-(mUnk200 / 2) * 0xB6) - 0x71C;
+ mUnk1E8 = 1.7578125 / mUnk200;
+ mUnk218 = SCREEN_WIDTH / 2;
+
+ if (D_8016559C == 0) {
+ D_8018D17C += 1;
+ if (D_8018D17C >= D_8018D1F0) {
+ D_8018D17C = 0;
+ }
+ if (mState == 0) {
+ //init_object(_objectIndex, 1);
+ mState = 1;
+ }
+ }
+
+ switch (mState) {
+ case 1:
+ SkySnow::func_80077E20();
+ break;
+ case 2:
+ SkySnow::func_80077F64(mScreen->camera);
+ if (mState2 == 0) { // unk_0AE
+ mState2 += 1;
+ //object_next_state(_objectIndex);
+ }
+ break;
+ case 0:
+ break;
+ case 3:
+ //func_80072428(_objectIndex);
+ mState = 0;
+ //mStatus = 0;
+ mVisible = false;
+ mState2 = 0;
+ break;
+ }
+}
+
+void SkySnow::Draw(ScreenContext* screen, s32 arg0) { // render_clouds
+ s32 posY = arg0 - mY;
+ func_8004B6C4(255, 255, 255);
+ // Skip drawing the object this frame if it warped to the other side of the screen
+ if ((fabs(mX - mOldX) > SCREEN_WIDTH / 2) || (fabs(posY - mOldY) > SCREEN_HEIGHT / 2)) {
+ mOldX = mX;
+ mOldY = posY;
+ return;
+ }
+
+ if (mVisible) {
+ FrameInterpolation_RecordOpenChild("render_snow", TAG_CLOUDS((_idx << 4) | (screen - gScreenOneCtx)));
+
+ if (D_8018D228 != mCloudVariant) {
+ D_8018D228 = mCloudVariant;
+ func_80044DA0((u8*)mTexture, mTextureWidth, mTextureHeight);
+ }
+ func_80042330_unchanged(mX, posY, 0, mScale);
+ gSPVertex(gDisplayListHead++, (uintptr_t)mVtx, 4, 0);
+ gSPDisplayList(gDisplayListHead++, (Gfx*)common_rectangle_display);
+
+ FrameInterpolation_RecordCloseChild();
+ }
+ mOldX = mX;
+ mOldY = posY;
+}
+
+void SkySnow::func_80077E20() {
+ u8* tex = (u8*) LOAD_ASSET(D_0D0293D8);
+ Vtx* vtx = (Vtx*) LOAD_ASSET(common_vtx_rectangle);
+
+ mTexture = tex;
+ //! @bug frappe snowland There's something up with the handling of common_vtx_rectangle and the loading of 0x10
+ //! right here
+ // root function: func_80078C70
+ mVtx = vtx;
+ mTextureWidth = 16;
+ mTextureHeight = 16;
+ mScale = 0.15f;
+ mVisible = true;
+
+ mState2 = 1; // UNK_0AE func_80086EF0
+ mState += 1;
+ //object_next_state(objectIndex);
+}
+
+void SkySnow::func_80077F64(Camera* camera) {
+
+ f64 rand;
+
+ switch (mState2) { /* irregular */
+ case 1: {
+ mDirectionAngle[1] = (camera->rot[1] + random_int(0x4000U)) - 0x2000;
+ //object_origin_pos_randomize_around_y(objectIndex, 0x00B4, 0x0014U);
+ s16 offset_y = random_int(20) - (20 / 2);
+ mOrigin.y = 180 + offset_y;
+// gObjectList[objectIndex].origin_pos[1] = y + offset_y;
+
+ rand = random_int(0x0064U);
+ mVelocity.y = (f32) (-0.75 - (f64) (f32) (rand * 0.01));
+ // gObjectList[objectIndex].velocity[1] = (f32) (-0.75 - (f64) (f32) (rand * 0.01));
+ mOffset.x = 0.0f;
+ mOffset.y = 0.0f;
+ //gObjectList[objectIndex].offset[0] = 0.0f;
+ //gObjectList[objectIndex].offset[1] = 0.0f;
+ //func_80086FD4(objectIndex);
+ mState2 += 1;
+ break;
+ }
+ case 2: {
+ //func_80077EB8(objectIndex, gObjectList[objectIndex].direction_angle[1], camera);
+ s16 temp_v0 = camera->rot[1] - mDirectionAngle[1];
+ if ((temp_v0 >= mUnk210) || (mUnk208 >= temp_v0)) {
+ mOffset.x = mUnk218 + (mUnk1E8 * (f32) temp_v0);
+ mVisible = true;
+ //set_object_flag(objectIndex, 0x00000010);
+ } else {
+ mVisible = false;
+ }
+ //clear_object_flag(objectIndex, 0x00000010);
+
+
+// object_add_velocity_offset_y(objectIndex);
+
+ mOffset.y += mVelocity.y;
+
+ //object_calculate_new_pos_offset(objectIndex);
+
+ mX = mOrigin.x + mOffset.x;
+ mY = mOrigin.y + mOffset.y;
+ //mZ = mOrigin.z + mOffset.z;
+
+ //func_8008BFC0(objectIndex);
+ if (mY <= 0.0f) {
+ //func_80086FD4(objectIndex);
+ mState2 += 1;
+ break;
+ }
+ break;
+ }
+ case 0:
+ break;
+ case 3:
+ //func_80086F60(objectIndex);
+ mState2 = 0;
+ break;
+ }
+} \ No newline at end of file
diff --git a/src/engine/sky/SkySnow.h b/src/engine/sky/SkySnow.h
new file mode 100644
index 000000000..1d9dcccc1
--- /dev/null
+++ b/src/engine/sky/SkySnow.h
@@ -0,0 +1,49 @@
+#pragma once
+
+#include <libultraship.h>
+#include "SkyCloud.h"
+#include "engine/registry/RegisterContent.h"
+#include "engine/World.h"
+#include "engine/SpawnParams.h"
+#include "engine/CoreMath.h"
+
+#include "engine/objects/Object.h"
+
+extern "C" {
+#include "common_structs.h"
+}
+
+/**
+ * Skybox Stars
+ *
+ * Inherits from SkyCloud so that stars/clouds can be stored in the same list
+ * and called the same way.
+ *
+ * @cloudVariant unused for stars
+ */
+class SkySnow : public SkyActor {
+public:
+ SkySnow(ScreenContext* screen);
+
+ ~SkySnow() {
+ _count--;
+ }
+
+ static size_t GetCount() {
+ return _count;
+ }
+
+ virtual void Draw(ScreenContext* ctx, s32 arg0) override;
+ virtual void Tick() override;
+ void func_80077E20();
+ void func_80077F64(Camera* camera);
+private:
+ static size_t _count;
+ size_t _idx;
+ s32 mState;
+ s32 mState2;
+ FVector mOffset;
+ FVector mOrigin;
+ FVector mVelocity;
+ Vec3su mDirectionAngle;
+};
diff --git a/src/engine/sky/SkyStar.cpp b/src/engine/sky/SkyStar.cpp
new file mode 100644
index 000000000..7f696d7bb
--- /dev/null
+++ b/src/engine/sky/SkyStar.cpp
@@ -0,0 +1,165 @@
+#include <libultraship.h>
+#include <libultra/gbi.h>
+#include "SkyStar.h"
+#include <vector>
+#include "engine/tracks/Track.h"
+#include "engine/World.h"
+
+#include "port/Engine.h"
+#include "port/Game.h"
+#include "port/interpolation/FrameInterpolation.h"
+
+extern "C" {
+#include "update_objects.h"
+#include "code_80057C60.h"
+#include "code_8006E9C0.h"
+#include "assets/models/common_data.h"
+#include "assets/textures/common_data.h"
+#include "math_util_2.h"
+#include "render_objects.h"
+}
+
+size_t SkyStar::_count = 0;
+
+SkyStar::SkyStar(ScreenContext* screen, u16 cloudVariant, u16 posY, u16 rotY, u16 scalePercent) : SkyActor(screen) {
+ _idx = _count;
+
+ // ItemWindowObjects* temp_v0;
+ //find_unused_obj_index(&_objectIndex);
+ //init_object(_objectIndex, 1);
+// temp_v0 = (ItemWindowObjects*) &gObjectList[_objectIndex];
+ mCloudVariant = cloudVariant;
+// temp_v0->unk_0D5 = cloudVariant;
+ // temp_v0->currentItem = ITEM_BANANA;
+ // temp_v0->direction_angle[1] = rotY;
+ mY = posY;
+// temp_v0->unk_09E = posY;
+ mScale = (f32) scalePercent / 100.0;
+// temp_v0->sizeScaling = (f32) scalePercent / 100.0;
+ mTexture = (u8*)D_0D0293D8;
+// temp_v0->activeTexture = (u8*)D_0D0293D8;
+ //func_80073404(_objectIndex, 0x10U, 0x10U, (Vtx*)common_vtx_rectangle);
+ mVtx = (Vtx*)common_vtx_rectangle;
+ mTextureWidth = 16;
+ mTextureHeight = 16;
+ mRotY = rotY;
+
+ mPrimAlpha = 0;
+ mUnk_0CF = 0;
+ mUnk_0AC = 0;
+ mUnk_0D0 = 0;
+
+
+ _count += 1;
+}
+
+void SkyStar::Tick() {
+ s16 cameraRot;
+
+ s16 mUnk200 = mScreen->camera->fieldOfView + 40.0f;
+ mUnk208 = ((mUnk200 / 2) * 0xB6) + 0x71C;
+ mUnk210 = (-(mUnk200 / 2) * 0xB6) - 0x71C;
+ mUnk1E8 = 1.7578125 / mUnk200;
+ mUnk218 = SCREEN_WIDTH / 2;
+
+ // Adjustable culling factor
+ const float cullingFactor = OTRGetAspectRatio();
+
+ // Calculate the cloud's rotation relative to the camera
+ cameraRot = (u16)mScreen->camera->rot[1] + (u16)mRotY;
+ // Adjust bounds based on the culling factor
+ s16 adjustedLowerBound = (s16) (mUnk210 * cullingFactor);
+ s16 adjustedUpperBound = (s16) (mUnk208 * cullingFactor);
+
+ // Check if the object is within the adjusted bounds
+ if ((cameraRot >= adjustedLowerBound) && (adjustedUpperBound >= cameraRot)) {
+ // Calculate and update the object's position
+ // 160 (SCREEN_WIDTH / 2) + (mUnk1E8 * cameraRot);
+ // Grab center of screen, scale by fov factor, offset based on camera rotation
+ mX = mUnk218 + (mUnk1E8 * cameraRot);
+
+ mVisible = true;
+ } else {
+ mVisible = false;
+ }
+
+ // Vary the star based on star index
+ switch (_idx % 5U) {
+ case 0:
+ star_func_80073B78(1, 0x00000028, 0x000000B4, 0x000000FF, 0, -1);
+ break;
+ case 1:
+ star_func_80073B78(1, 0x00000080, 0x000000FF, 0x000000FF, 0, -1);
+ break;
+ case 2:
+ star_func_80073B78(1, 0x00000050, 0x000000C8, 0x000000FF, 0, -1);
+ break;
+ case 3:
+ star_func_80073B78(1, 0, 0x0000009B, 0x000000FF, 0, -1);
+ break;
+ case 4:
+ star_func_80073B78(1, 0x0000005A, 0x00000080, 0x000000FF, 0, -1);
+ break;
+ }
+}
+
+void SkyStar::Draw(ScreenContext* screen, s32 arg0) { // render_stars
+ s32 posY = arg0 - mY;
+ func_8004B414(255, 255, 255, 255);
+ if (mVisible) {
+ FrameInterpolation_RecordOpenChild("render_stars", TAG_CLOUDS((_idx << 4) | (screen - gScreenOneCtx)));
+
+ func_80044DA0((u8*)mTexture, mTextureWidth, mTextureHeight);
+
+ func_8004B138(0xFF, 0xFF, 0xFF, mPrimAlpha);
+ func_80042330_unchanged(mX, posY, 0, mScale);
+ gSPVertex(gDisplayListHead++, (uintptr_t)mVtx, 4, 0);
+ gSPDisplayList(gDisplayListHead++, (Gfx*)common_rectangle_display);
+ FrameInterpolation_RecordCloseChild();
+ }
+}
+
+bool SkyStar::star_func_80073B78(s32 arg0, s32 arg3, s32 arg4, s32 arg5, s32 arg6, s32 arg7) {
+ s32 phi_t0;
+
+ phi_t0 = false;
+ if (mUnk_0CF == 0) { // s8
+ mUnk_0AC = arg6; // s16
+ if (arg0 != 0) {
+ mPrimAlpha = arg3;
+ }
+ mUnk_0D0 = arg7; // s8
+ //func_80073800(objectIndex, 1);
+ mUnk_0CF = 1;
+ } else {
+ mUnk_0AC--;
+ if (mUnk_0AC < 0) {
+ mUnk_0AC = arg6;
+ if (mUnk_0CF == 1) {
+ mPrimAlpha += arg5;
+ if (mPrimAlpha >= arg4) {
+ mPrimAlpha = arg4;
+ mUnk_0CF++;
+ }
+ } else {
+ mPrimAlpha -= arg5;
+ if (arg3 >= mPrimAlpha) {
+ mPrimAlpha = arg3;
+ if (mUnk_0D0 > 0) {
+ mUnk_0D0--;
+ }
+ if (mUnk_0D0 == 0) {
+ //func_80073800(objectIndex, 0);
+ mUnk_0CF = 0;
+ //func_8007381C(objectIndex); // does nothing? += unk_0DC
+ phi_t0 = true;
+ } else {
+ mUnk_0CF = 1;
+ }
+ }
+ }
+ }
+ }
+
+ return phi_t0;
+} \ No newline at end of file
diff --git a/src/engine/sky/SkyStar.h b/src/engine/sky/SkyStar.h
new file mode 100644
index 000000000..c12d2be5e
--- /dev/null
+++ b/src/engine/sky/SkyStar.h
@@ -0,0 +1,48 @@
+#pragma once
+
+#include <libultraship.h>
+#include "SkyCloud.h"
+#include "engine/registry/RegisterContent.h"
+#include "engine/World.h"
+#include "engine/SpawnParams.h"
+#include "engine/CoreMath.h"
+
+#include "engine/sky/SkyActor.h"
+#include "engine/objects/Object.h"
+
+extern "C" {
+#include "common_structs.h"
+}
+
+/**
+ * Skybox Stars
+ *
+ * Inherits from SkyCloud so that stars/clouds can be stored in the same list
+ * and called the same way.
+ *
+ * @cloudVariant unused for stars
+ */
+class SkyStar : public SkyActor {
+public:
+ SkyStar(ScreenContext* screen, u16 cloudVariant, u16 posY, u16 rotY, u16 scalePercent);
+
+ virtual ~SkyStar() {
+ _count--;
+ }
+
+ static size_t GetCount() {
+ return _count;
+ }
+
+ virtual void Draw(ScreenContext* ctx, s32 arg0) override;
+ virtual void Tick() override;
+ bool star_func_80073B78(s32 arg0, s32 arg3, s32 arg4, s32 arg5, s32 arg6, s32 arg7);
+private:
+ static size_t _count;
+ size_t _idx;
+
+ s16 mPrimAlpha;
+ s8 mUnk_0CF;
+ s16 mUnk_0AC;
+ s8 mUnk_0D0;
+};
diff --git a/src/engine/tracks/BansheeBoardwalk.h b/src/engine/tracks/BansheeBoardwalk.h
index 90de15c3d..3c113c5a5 100644
--- a/src/engine/tracks/BansheeBoardwalk.h
+++ b/src/engine/tracks/BansheeBoardwalk.h
@@ -25,7 +25,6 @@ public:
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void BeginPlay() override;
- //virtual void InitClouds() override;
virtual void InitTrackObjects() override;
virtual void TickTrackObjects() override;
virtual void DrawTrackObjects(s32 cameraId) override;
diff --git a/src/engine/tracks/BowsersCastle.h b/src/engine/tracks/BowsersCastle.h
index f12ed3b39..53e26e928 100644
--- a/src/engine/tracks/BowsersCastle.h
+++ b/src/engine/tracks/BowsersCastle.h
@@ -26,7 +26,6 @@ public:
virtual void Load() override;
void SpawnStockThwomp();
virtual void BeginPlay() override;
- //virtual void InitClouds() override;
virtual void InitTrackObjects() override;
virtual void TickTrackObjects() override;
virtual void DrawTrackObjects(s32 cameraId) override;
diff --git a/src/engine/tracks/DKJungle.h b/src/engine/tracks/DKJungle.h
index da7fb92fd..6454fb559 100644
--- a/src/engine/tracks/DKJungle.h
+++ b/src/engine/tracks/DKJungle.h
@@ -26,7 +26,6 @@ public:
virtual void Load() override;
virtual f32 GetWaterLevel(FVector pos, Collision* collision) override;
virtual void BeginPlay() override;
- //virtual void InitClouds() override;
virtual void InitTrackObjects() override;
virtual void TickTrackObjects() override;
virtual void DrawTrackObjects(s32 cameraId) override;
diff --git a/src/engine/tracks/FrappeSnowland.cpp b/src/engine/tracks/FrappeSnowland.cpp
index 338a2be2a..e74b02f93 100644
--- a/src/engine/tracks/FrappeSnowland.cpp
+++ b/src/engine/tracks/FrappeSnowland.cpp
@@ -100,6 +100,7 @@ FrappeSnowland::FrappeSnowland() {
Props.Clouds = NULL; // not used for frappe
Props.CloudList = NULL;
+ mCloudType = CloudType::SNOW;
Props.Skybox.TopRight = {28, 11, 90};
Props.Skybox.BottomRight = {0, 99, 164};
@@ -165,26 +166,6 @@ void FrappeSnowland::BeginPlay() {
}
}
-void FrappeSnowland::InitClouds() {
- s32 var_s0;
- s32 var_s4;
- if (gPlayerCount == 1) {
- var_s4 = 0x32;
- } else {
- var_s4 = 0x19;
- }
- for (var_s0 = 0; var_s0 < var_s4; var_s0++) {
- find_unused_obj_index(&D_8018CC80[D_8018D1F8 + var_s0]);
- }
- D_8018D1F8 += var_s0;
- D_8018D1F0 = var_s0;
- D_8018D230 = 0; // This must be turned off or mayhem ensues
-}
-
-void FrappeSnowland::TickClouds(s32 sp1C, Camera* camera) {
- func_80078170(sp1C, camera);
-}
-
void FrappeSnowland::InitTrackObjects() {
size_t objectId;
size_t i;
diff --git a/src/engine/tracks/FrappeSnowland.h b/src/engine/tracks/FrappeSnowland.h
index 523093924..e14ffcd7e 100644
--- a/src/engine/tracks/FrappeSnowland.h
+++ b/src/engine/tracks/FrappeSnowland.h
@@ -22,8 +22,6 @@ public:
virtual void Load() override;
virtual void BeginPlay() override;
- virtual void InitClouds() override;
- virtual void TickClouds(s32 sp1C, Camera* camera) override;
virtual void InitTrackObjects() override;
virtual void TickTrackObjects() override;
virtual void Draw(ScreenContext*) override;
diff --git a/src/engine/tracks/PodiumCeremony.cpp b/src/engine/tracks/PodiumCeremony.cpp
index a24e260ba..134166eb5 100644
--- a/src/engine/tracks/PodiumCeremony.cpp
+++ b/src/engine/tracks/PodiumCeremony.cpp
@@ -52,6 +52,7 @@ PodiumCeremony::PodiumCeremony() {
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = 0;
+ ResourceName = "mk:podium_ceremony";
Props.SetText(Props.Name, "royal raceway", sizeof(Props.Name));
Props.SetText(Props.DebugName, "p circuit", sizeof(Props.DebugName));
Props.SetText(Props.TrackLength, "1025m", sizeof(Props.TrackLength));
diff --git a/src/engine/tracks/PodiumCeremony.h b/src/engine/tracks/PodiumCeremony.h
index 336b73330..72f8a51b3 100644
--- a/src/engine/tracks/PodiumCeremony.h
+++ b/src/engine/tracks/PodiumCeremony.h
@@ -24,11 +24,8 @@ public:
// Constructor
explicit PodiumCeremony();
-// virtual void Load(const char* courseVtx,
-// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void BeginPlay() override;
- //virtual void InitClouds() override;
virtual void InitTrackObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
diff --git a/src/engine/tracks/RainbowRoad.cpp b/src/engine/tracks/RainbowRoad.cpp
index 8666ae74e..20e7e9a56 100644
--- a/src/engine/tracks/RainbowRoad.cpp
+++ b/src/engine/tracks/RainbowRoad.cpp
@@ -94,6 +94,7 @@ RainbowRoad::RainbowRoad() {
Props.Clouds = gToadsTurnpikeRainbowRoadStars;
Props.CloudList = gToadsTurnpikeRainbowRoadStars;
+ mCloudType = CloudType::STARS;
Props.Skybox.TopRight = {0, 0, 0};
Props.Skybox.BottomRight = {0, 0, 0};
@@ -150,14 +151,6 @@ void RainbowRoad::BeginPlay() {
}
}
-void RainbowRoad::InitClouds() {
- init_stars(this->Props.Clouds);
-}
-
-void RainbowRoad::TickClouds(s32 sp1C, Camera* camera) {
- update_stars(sp1C, camera, this->Props.CloudList);
-}
-
void RainbowRoad::InitTrackObjects() {
if (gGamestate != CREDITS_SEQUENCE) {
size_t i;
diff --git a/src/engine/tracks/RainbowRoad.h b/src/engine/tracks/RainbowRoad.h
index 47094594a..64fcb1a39 100644
--- a/src/engine/tracks/RainbowRoad.h
+++ b/src/engine/tracks/RainbowRoad.h
@@ -25,8 +25,6 @@ public:
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void BeginPlay() override;
- virtual void InitClouds() override;
- virtual void TickClouds(s32, Camera*) override;
virtual void InitTrackObjects() override;
virtual void TickTrackObjects() override;
virtual void DrawTrackObjects(s32 cameraId) override;
diff --git a/src/engine/tracks/Skyscraper.h b/src/engine/tracks/Skyscraper.h
index 526ab902f..370fe8d18 100644
--- a/src/engine/tracks/Skyscraper.h
+++ b/src/engine/tracks/Skyscraper.h
@@ -25,7 +25,6 @@ public:
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void BeginPlay() override;
- //virtual void InitClouds() override;
virtual void InitTrackObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
diff --git a/src/engine/tracks/ToadsTurnpike.cpp b/src/engine/tracks/ToadsTurnpike.cpp
index f735ba4c3..f929a56e1 100644
--- a/src/engine/tracks/ToadsTurnpike.cpp
+++ b/src/engine/tracks/ToadsTurnpike.cpp
@@ -102,6 +102,7 @@ ToadsTurnpike::ToadsTurnpike() {
Props.Clouds = gToadsTurnpikeRainbowRoadStars;
Props.CloudList = gToadsTurnpikeRainbowRoadStars;
+ mCloudType = CloudType::STARS;
FVector finish;
finish.x = -38.0f * xOrientation;
@@ -199,14 +200,6 @@ void ToadsTurnpike::BeginPlay() {
}
}
-void ToadsTurnpike::InitClouds() {
- init_stars(this->Props.Clouds);
-}
-
-void ToadsTurnpike::TickClouds(s32 sp1C, Camera* camera) {
- update_stars(sp1C, camera, this->Props.CloudList);
-}
-
void ToadsTurnpike::SomeSounds() {}
void ToadsTurnpike::WhatDoesThisDo(Player* player, int8_t playerId) {
diff --git a/src/engine/tracks/ToadsTurnpike.h b/src/engine/tracks/ToadsTurnpike.h
index 75e1c8fbb..dc69eaa15 100644
--- a/src/engine/tracks/ToadsTurnpike.h
+++ b/src/engine/tracks/ToadsTurnpike.h
@@ -25,8 +25,6 @@ public:
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void BeginPlay() override;
- virtual void InitClouds() override;
- virtual void TickClouds(s32, Camera*) override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
diff --git a/src/engine/tracks/Track.cpp b/src/engine/tracks/Track.cpp
index bd629bdce..617539217 100644
--- a/src/engine/tracks/Track.cpp
+++ b/src/engine/tracks/Track.cpp
@@ -31,6 +31,7 @@ extern "C" {
#include "math_util.h"
#include "code_80005FD0.h"
extern StaffGhost* d_mario_raceway_staff_ghost;
+extern s8 gPlayerCount;
}
void ResizeMinimap(MinimapProps* minimap) {
@@ -406,6 +407,7 @@ Track::Track() {
Props.Clouds = NULL;
Props.CloudList = NULL;
+ mCloudType = CloudType::CLOUDS;
Props.Sequence = MusicSeq::MUSIC_SEQ_UNKNOWN;
bFog = false;
@@ -465,26 +467,6 @@ void Track::SpawnActors() {
}
}
-void Track::InitClouds() {
- if (this->Props.Clouds) {
- init_clouds(this->Props.Clouds);
- }
-}
-
-void Track::TickClouds(s32 arg0, Camera* camera) {
- s32 cloudIndex;
- s32 objectIndex;
- CloudData* cloud;
-
- if (this->Props.CloudList) {
- for (cloudIndex = 0; cloudIndex < D_8018D1F0; cloudIndex++) {
- cloud = &this->Props.CloudList[cloudIndex];
- objectIndex = D_8018CC80[arg0 + cloudIndex];
- func_800788F8(objectIndex, cloud->rotY, camera);
- }
- }
-}
-
// Adjusts player speed on steep hills
void Track::SomeCollisionThing(Player* player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6,
f32* arg7) {
diff --git a/src/engine/tracks/Track.h b/src/engine/tracks/Track.h
index 3bea88ed0..8dfd1750e 100644
--- a/src/engine/tracks/Track.h
+++ b/src/engine/tracks/Track.h
@@ -307,13 +307,21 @@ typedef struct Properties {
class World; // <-- Forward declare
-class Track {
+class Track {
public:
+ enum class CloudType {
+ NONE,
+ CLOUDS,
+ SNOW,
+ STARS
+ };
// Required to save scenefile data
std::shared_ptr<Ship::Archive> Archive;
std::string ResourceName;
+
Properties Props;
+ enum CloudType mCloudType;
// This allows multiple water levels in a map.
// Ex. DK Jungle where there's a waterfall and you can drive above and below it.
@@ -343,8 +351,6 @@ public:
*/
virtual void BeginPlay();
void SpawnActors();
- virtual void InitClouds();
- virtual void TickClouds(s32, Camera*);
virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7);
virtual void InitTrackObjects();
virtual void TickTrackObjects();
diff --git a/src/engine/tracks/WarioStadium.cpp b/src/engine/tracks/WarioStadium.cpp
index 1fc47c8fb..f5f940d7f 100644
--- a/src/engine/tracks/WarioStadium.cpp
+++ b/src/engine/tracks/WarioStadium.cpp
@@ -97,6 +97,7 @@ WarioStadium::WarioStadium() {
Props.Clouds = gWarioStadiumStars;
Props.CloudList = gWarioStadiumStars;
+ mCloudType = CloudType::STARS;
FVector finish;
finish.x = (gIsMirrorMode != 0) ? 13 + 12.0f : 13 - 12.0f;
@@ -168,14 +169,6 @@ void WarioStadium::BeginPlay() {
}
}
-void WarioStadium::InitClouds() {
- init_stars(this->Props.Clouds);
-}
-
-void WarioStadium::TickClouds(s32 sp1C, Camera* camera) {
- update_stars(sp1C, camera, this->Props.CloudList);
-}
-
void WarioStadium::InitTrackObjects() {
}
diff --git a/src/engine/tracks/WarioStadium.h b/src/engine/tracks/WarioStadium.h
index 71d1d5be8..b6b6bee80 100644
--- a/src/engine/tracks/WarioStadium.h
+++ b/src/engine/tracks/WarioStadium.h
@@ -27,8 +27,6 @@ class WarioStadium : public Track {
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void BeginPlay() override;
- virtual void InitClouds() override;
- virtual void TickClouds(s32, Camera*) override;
virtual void InitTrackObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
diff --git a/src/main.c b/src/main.c
index 2fe0b453d..b682244e3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -740,50 +740,49 @@ void race_logic_loop(void) {
switch (gActiveScreenMode) {
case SCREEN_MODE_1P:
- render_screens(RENDER_SCREEN_MODE_1P_PLAYER_ONE, 0, 0);
+ render_screens(gScreenOneCtx, RENDER_SCREEN_MODE_1P_PLAYER_ONE, 0, 0);
break;
case SCREEN_MODE_2P_SPLITSCREEN_HORIZONTAL:
if (gPlayerWinningIndex == 0) {
// In VS Mode the winning player's viewport takes over the whole screen.
// Rendering the winning player last places their screen above the other screens
- render_screens(RENDER_SCREEN_MODE_2P_HORIZONTAL_PLAYER_TWO, 1, 1);
- render_screens(RENDER_SCREEN_MODE_2P_HORIZONTAL_PLAYER_ONE, 0, 0);
+ render_screens(gScreenTwoCtx, RENDER_SCREEN_MODE_2P_HORIZONTAL_PLAYER_TWO, 4, 1);
+ render_screens(gScreenOneCtx, RENDER_SCREEN_MODE_2P_HORIZONTAL_PLAYER_ONE, 3, 0);
} else {
- render_screens(RENDER_SCREEN_MODE_2P_HORIZONTAL_PLAYER_ONE, 0, 0);
- render_screens(RENDER_SCREEN_MODE_2P_HORIZONTAL_PLAYER_TWO, 1, 1);
+ render_screens(gScreenOneCtx, RENDER_SCREEN_MODE_2P_HORIZONTAL_PLAYER_ONE, 3, 0);
+ render_screens(gScreenTwoCtx, RENDER_SCREEN_MODE_2P_HORIZONTAL_PLAYER_TWO, 4, 1);
}
break;
case SCREEN_MODE_2P_SPLITSCREEN_VERTICAL:
if (gPlayerWinningIndex == 0) {
- render_screens(RENDER_SCREEN_MODE_2P_VERTICAL_PLAYER_TWO, 1, 1);
- render_screens(RENDER_SCREEN_MODE_2P_VERTICAL_PLAYER_ONE, 0, 0);
+ render_screens(gScreenTwoCtx, RENDER_SCREEN_MODE_2P_VERTICAL_PLAYER_TWO, 2, 1);
+ render_screens(gScreenOneCtx, RENDER_SCREEN_MODE_2P_VERTICAL_PLAYER_ONE, 1, 0);
} else {
- render_screens(RENDER_SCREEN_MODE_2P_VERTICAL_PLAYER_ONE, 0, 0);
- render_screens(RENDER_SCREEN_MODE_2P_VERTICAL_PLAYER_TWO, 1, 1);
+ render_screens(gScreenOneCtx, RENDER_SCREEN_MODE_2P_VERTICAL_PLAYER_ONE, 1, 0);
+ render_screens(gScreenTwoCtx, RENDER_SCREEN_MODE_2P_VERTICAL_PLAYER_TWO, 2, 1);
}
break;
case SCREEN_MODE_3P_4P_SPLITSCREEN:
if (gPlayerWinningIndex == 0) {
- render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_TWO, 1, 1);
- render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_THREE, 2, 2);
- render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_FOUR, 3, 3);
- render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_ONE, 0, 0);
+ render_screens(gScreenTwoCtx, RENDER_SCREEN_MODE_3P_4P_PLAYER_TWO, 9, 1);
+ render_screens(gScreenThreeCtx, RENDER_SCREEN_MODE_3P_4P_PLAYER_THREE, 10, 2);
+ render_screens(gScreenFourCtx, RENDER_SCREEN_MODE_3P_4P_PLAYER_FOUR, 11, 3);
+ render_screens(gScreenOneCtx, RENDER_SCREEN_MODE_3P_4P_PLAYER_ONE, 8, 0);
} else if (gPlayerWinningIndex == 1) {
- render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_ONE, 0, 0);
- render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_THREE, 2, 2);
- render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_FOUR, 3, 3);
- render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_TWO, 1, 1);
+ render_screens(gScreenOneCtx, RENDER_SCREEN_MODE_3P_4P_PLAYER_ONE, 8, 0);
+ render_screens(gScreenThreeCtx, RENDER_SCREEN_MODE_3P_4P_PLAYER_THREE, 10, 2);
+ render_screens(gScreenFourCtx, RENDER_SCREEN_MODE_3P_4P_PLAYER_FOUR, 11, 3);
+ render_screens(gScreenTwoCtx, RENDER_SCREEN_MODE_3P_4P_PLAYER_TWO, 9, 1);
} else if (gPlayerWinningIndex == 2) {
-
- render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_ONE, 0, 0);
- render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_TWO, 1, 1);
- render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_FOUR, 3, 3);
- render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_THREE, 2, 2);
+ render_screens(gScreenOneCtx, RENDER_SCREEN_MODE_3P_4P_PLAYER_ONE, 8, 0);
+ render_screens(gScreenTwoCtx, RENDER_SCREEN_MODE_3P_4P_PLAYER_TWO, 9, 1);
+ render_screens(gScreenFourCtx, RENDER_SCREEN_MODE_3P_4P_PLAYER_FOUR, 11, 3);
+ render_screens(gScreenThreeCtx, RENDER_SCREEN_MODE_3P_4P_PLAYER_THREE, 10, 2);
} else {
- render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_ONE, 0, 0);
- render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_TWO, 1, 1);
- render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_THREE, 2, 2);
- render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_FOUR, 3, 3);
+ render_screens(gScreenOneCtx, RENDER_SCREEN_MODE_3P_4P_PLAYER_ONE, 8, 0);
+ render_screens(gScreenTwoCtx, RENDER_SCREEN_MODE_3P_4P_PLAYER_TWO, 9, 1);
+ render_screens(gScreenThreeCtx, RENDER_SCREEN_MODE_3P_4P_PLAYER_THREE, 10, 2);
+ render_screens(gScreenFourCtx, RENDER_SCREEN_MODE_3P_4P_PLAYER_FOUR, 11, 3);
}
break;
}
diff --git a/src/port/Game.cpp b/src/port/Game.cpp
index ce22999d1..9a492f6b3 100644
--- a/src/port/Game.cpp
+++ b/src/port/Game.cpp
@@ -32,6 +32,7 @@
#include "engine/TrackBrowser.h"
#include "engine/RandomItemTable.h"
+#include "engine/sky/Sky.h"
#ifdef _WIN32
#include <locale.h>
@@ -47,6 +48,7 @@ extern "C" {
#include "spawn_players.h"
#include "src/enhancements/collision_viewer.h"
#include "code_800029B0.h"
+#include "code_80057C60.h"
// #include "engine/wasm.h"
}
@@ -81,6 +83,7 @@ Registry<ItemInfo> gItemRegistry;
DataRegistry<RandomItemTable> gItemTableRegistry;
std::unique_ptr<TrackBrowser> gTrackBrowser;
+std::unique_ptr<Sky> gSky;
World* GetWorld() {
return World::Instance;
@@ -91,6 +94,8 @@ void CustomEngineInit() {
// This also turns off freecam
gEditor.Disable();
+
+ gSky = std::make_unique<Sky>();
RegisterTracks(gTrackRegistry);
gTrackBrowser = std::make_unique<TrackBrowser>(gTrackRegistry);
TrackBrowser::Instance->FindCustomTracks();
@@ -361,6 +366,7 @@ void CM_DrawStaticMeshActors() {
void CM_BeginPlay() {
static bool tour = false;
auto track = GetWorld()->GetTrack();
+ GetWorld()->Actors.clear();
if (nullptr == track) {
return;
@@ -554,15 +560,14 @@ void CM_DrawParticles(s32 cameraId) {
}
}
-void CM_InitClouds() {
- if (GetWorld()->GetTrack()) {
- GetWorld()->GetTrack()->InitClouds();
- }
-}
-
-void CM_TickClouds(s32 arg0, Camera* camera) {
- if (GetWorld()->GetTrack()) {
- GetWorld()->GetTrack()->TickClouds(arg0, camera);
+void CM_RaceDrawSky(ScreenContext* screen, s32 someId) {
+ // if (bDrawSkybox) {
+ if (CVarGetInteger("gDrawSky", true) == true) {
+ Sky::Instance->Draw(screen);
+ if (gGamestate != CREDITS_SEQUENCE) {
+ func_80057FC4(screen, someId); // DrawSkyActors
+ }
+ Sky::Instance->DrawFloor(screen);
}
}
diff --git a/src/port/Game.h b/src/port/Game.h
index fdd11c7a6..f649389af 100644
--- a/src/port/Game.h
+++ b/src/port/Game.h
@@ -72,8 +72,6 @@ void CM_ActivateSecondLapLakitu(s32 playerId);
void CM_ActivateFinalLapLakitu(s32 playerId);
void CM_ActivateReverseLakitu(s32 playerId);
-void CM_InitClouds();
-
void CM_DrawActors(Camera* camera);
void CM_DrawStaticMeshActors();
@@ -102,7 +100,7 @@ void Editor_CleanWorld();
void CM_TickParticles(void);
void CM_DrawParticles(s32 cameraId);
-void CM_TickClouds(s32 arg0, Camera* camera);
+void CM_RaceDrawSky(ScreenContext* screen, s32 someId);
void CM_Waypoints(Player* player, int8_t playerId);
diff --git a/src/port/ui/ContentBrowser.cpp b/src/port/ui/ContentBrowser.cpp
index a5ef9baa3..1065007b6 100644
--- a/src/port/ui/ContentBrowser.cpp
+++ b/src/port/ui/ContentBrowser.cpp
@@ -94,6 +94,11 @@ namespace TrackEditor {
for (const TrackInfo* info : gTrackRegistry.GetAllInfo()) {
if (!info) { continue; }
+ // Skip this invalid option
+ if (info->ResourceName == "mk:podium_ceremony") {
+ continue;
+ }
+
if (!search.empty() &&
ToLower(info->Name).find(search) == std::string::npos) {
continue;
diff --git a/src/port/ui/PortMenu.cpp b/src/port/ui/PortMenu.cpp
index 9eb273f5e..09a115e32 100644
--- a/src/port/ui/PortMenu.cpp
+++ b/src/port/ui/PortMenu.cpp
@@ -565,6 +565,14 @@ void PortMenu::AddSceneVisibility() {
WidgetPath path = { "Developer", "Scene Visibility", SECTION_COLUMN_1 };
AddSidebarEntry("Developer", "Scene Visibility", 1);
+ AddWidget(path, "Draw Sky", WIDGET_CVAR_CHECKBOX)
+ .CVar("gDrawSky")
+ .Options(UIWidgets::CheckboxOptions().DefaultValue(true));
+
+ AddWidget(path, "Draw Sky Actors", WIDGET_CVAR_CHECKBOX)
+ .CVar("gDrawSkyActors")
+ .Options(UIWidgets::CheckboxOptions().DefaultValue(true));
+
AddWidget(path, "Draw Track Geometry", WIDGET_CVAR_CHECKBOX)
.CVar("gDrawTrackGeometry")
.Options(UIWidgets::CheckboxOptions().DefaultValue(true));
diff --git a/src/racing/actors.c b/src/racing/actors.c
index b407bc123..8e79331b5 100644
--- a/src/racing/actors.c
+++ b/src/racing/actors.c
@@ -1173,7 +1173,6 @@ void destroy_all_actors(void) {
void init_actors_and_load_textures(void) {
init_red_shell_texture();
destroy_all_actors();
- CM_CleanWorld();
gNumPermanentActors = 0;
CM_BeginPlay();
diff --git a/src/racing/race_logic.c b/src/racing/race_logic.c
index 4ea13aa35..ff95ecc88 100644
--- a/src/racing/race_logic.c
+++ b/src/racing/race_logic.c
@@ -414,7 +414,7 @@ void func_8028EC38(s32 arg0) {
gRaceState = RACE_UNK;
func_800CA330(25);
func_800CA388(25);
- D_800DC5B4 = 1;
+ bDrawSkybox = true;
D_800DC5B0 = 1;
D_800DC5B8 = 0;
D_802BA038 = 5;
@@ -642,7 +642,7 @@ void func_8028F4E8(void) {
func_800CA388(0x19);
gGotoMode = START_MENU_FROM_QUIT;
gRaceState = RACE_UNK;
- D_800DC5B4 = 1;
+ bDrawSkybox = true;
D_800DC5B0 = 1;
D_800DC5B8 = 0;
D_802BA038 = 5;
@@ -836,7 +836,7 @@ void func_8028FBD4(void) {
gRaceState = RACE_UNK;
func_800CA330(25);
func_800CA388(25);
- D_800DC5B4 = 1;
+ bDrawSkybox = true;
D_800DC5B0 = 1;
D_800DC5B8 = 0;
D_802BA038 = 5;
@@ -893,7 +893,7 @@ void func_8028FCBC(void) {
gCourseTimer = 0.0f;
gVBlankTimer = 0.0f;
D_800DC5B0 = 1;
- D_800DC5B4 = 1;
+ bDrawSkybox = true;
D_802BA034 = 0.008f;
D_8015F894 = 0;
if (gScreenModeSelection != SCREEN_MODE_1P) {
diff --git a/src/racing/skybox_and_splitscreen.c b/src/racing/skybox_and_splitscreen.c
index aa3a46bf8..fba19a45b 100644
--- a/src/racing/skybox_and_splitscreen.c
+++ b/src/racing/skybox_and_splitscreen.c
@@ -75,7 +75,7 @@ Vtx D_802B8A10[] = {
{ { { 0, 120, -1 }, 0, { 0, 0 }, { 0x00, 0xDC, 0x00, 0xFF } } },
};
-void func_802A3730(ScreenContext* arg0) {
+void race_set_viewport(ScreenContext* arg0) {
s32 ulx;
s32 uly;
s32 lrx;
@@ -209,7 +209,7 @@ void init_z_buffer(void) {
gDPSetFillColor(gDisplayListHead++, 0xFFFCFFFC);
gDPPipeSync(gDisplayListHead++);
gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
- gDPFillRectangle(gDisplayListHead++, 0, 0, 319, 239);
+ gDPFillRectangle(gDisplayListHead++, 0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1);
gDPPipeSync(gDisplayListHead++);
gDPSetColorImage(gDisplayListHead++, G_IM_FMT_RGBA, G_IM_SIZ_16b, SCREEN_WIDTH,
VIRTUAL_TO_PHYSICAL(gPhysicalFramebuffers[sRenderingFramebuffer]));
@@ -424,8 +424,8 @@ void func_802A487C(Vtx* arg0) {
}
}
-void func_802A4A0C(Vtx* vtx, ScreenContext* arg1) {
- Camera* camera = arg1->camera;
+void func_802A4A0C(Vtx* vtx, ScreenContext* screen) {
+ Camera* camera = screen->camera;
s16 temp_t5;
f32 temp_f0;
UNUSED s32 pad[2];
@@ -439,6 +439,7 @@ void func_802A4A0C(Vtx* vtx, ScreenContext* arg1) {
func_802A450C(vtx);
// Widescreen skybox
+ // Note that this is the correct fit for each screen due to how the viewport works
vtx[0].v.ob[0] = OTRGetRectDimensionFromRightEdge(SCREEN_WIDTH);
vtx[1].v.ob[0] = OTRGetRectDimensionFromRightEdge(SCREEN_WIDTH);
vtx[2].v.ob[0] = OTRGetRectDimensionFromLeftEdge(0);
@@ -470,7 +471,7 @@ void func_802A4A0C(Vtx* vtx, ScreenContext* arg1) {
sp5C[1] *= 120.0f;
temp_t5 = 120 - (s32) sp5C[1];
- arg1->cameraHeight = temp_t5;
+ screen->cameraHeight = temp_t5;
vtx[1].v.ob[1] = temp_t5;
vtx[2].v.ob[1] = temp_t5;
vtx[4].v.ob[1] = temp_t5;
@@ -540,259 +541,122 @@ void func_802A4EF4(void) {
}
}
-void func_802A5004(void) {
-
- init_rdp();
- func_802A3730(gScreenTwoCtx);
-
- gSPClearGeometryMode(gDisplayListHead++, G_CLEAR_ALL_MODES);
-
- gSPSetGeometryMode(gDisplayListHead++, G_SHADE | G_SHADING_SMOOTH | G_CLIPPING);
-
- func_802A39E0(gScreenTwoCtx);
- if (D_800DC5B4 != 0) {
- func_802A4A0C((Vtx*) D_802B8910, gScreenTwoCtx);
- func_80057FC4(2);
- func_802A487C((Vtx*) D_802B8910);
- func_80093A30(2);
- }
-}
-
-void func_802A50EC(void) {
-
- init_rdp();
- func_802A3730(gScreenOneCtx);
-
- gSPClearGeometryMode(gDisplayListHead++, G_CLEAR_ALL_MODES);
- gSPSetGeometryMode(gDisplayListHead++, G_SHADE | G_SHADING_SMOOTH | G_CLIPPING);
-
- func_802A39E0(gScreenOneCtx);
- if (D_800DC5B4 != 0) {
- func_802A4A0C((Vtx*) D_802B8890, gScreenOneCtx);
- func_80057FC4(1);
- func_802A487C((Vtx*) D_802B8890);
- func_80093A30(1);
- }
-}
-
-void func_802A51D4(void) {
-
- init_rdp();
- func_802A39E0(gScreenOneCtx);
- func_802A3730(gScreenOneCtx);
-
- gSPClearGeometryMode(gDisplayListHead++, G_CLEAR_ALL_MODES);
- gSPSetGeometryMode(gDisplayListHead++, G_SHADE | G_SHADING_SMOOTH | G_CLIPPING);
-
- if (D_800DC5B4 != 0) {
- func_802A4A0C((Vtx*) D_802B8890, gScreenOneCtx);
- func_80057FC4(3);
- func_802A487C((Vtx*) D_802B8890);
- func_80093A30(3);
- }
-}
-
-void func_802A52BC(void) {
-
- init_rdp();
- func_802A39E0(gScreenTwoCtx);
- func_802A3730(gScreenTwoCtx);
-
- gSPClearGeometryMode(gDisplayListHead++, G_CLEAR_ALL_MODES);
- gSPSetGeometryMode(gDisplayListHead++, G_SHADE | G_SHADING_SMOOTH | G_CLIPPING);
-
- if (D_800DC5B4 != 0) {
- func_802A4A0C((Vtx*) D_802B8910, gScreenTwoCtx);
- func_80057FC4(4);
- func_802A487C((Vtx*) D_802B8910);
- func_80093A30(4);
- }
-}
-
-void func_802A53A4(void) {
+/**
+ * Refactored function, a little wonky due to preserving
+ * the original logic.
+ *
+ * The swapping of logic may be a required for proper draw order.
+ * Or, perhaps they slapped functions in differing orders for each screen on a wim.
+ */
+void race_begin_viewport(ScreenContext* screen, s32 mode) {
init_rdp();
- func_802A3730(gScreenOneCtx);
-
- gSPClearGeometryMode(gDisplayListHead++, G_CLEAR_ALL_MODES);
- gSPSetGeometryMode(gDisplayListHead++, G_SHADE | G_SHADING_SMOOTH | G_CLIPPING);
- init_z_buffer();
- select_framebuffer();
- if (D_800DC5B4 != 0) {
- func_802A4A0C((Vtx*) D_802B8890, gScreenOneCtx);
- if (gGamestate != CREDITS_SEQUENCE) {
- func_80057FC4(0);
- }
- func_802A487C((Vtx*) D_802B8890);
- func_80093A30(0);
+ // --------------------------------------------------
+ // Depth clear BEFORE viewport (horizontal + 3P/4P)
+ // --------------------------------------------------
+ switch(gActiveScreenMode) {
+ case SCREEN_MODE_2P_SPLITSCREEN_HORIZONTAL:
+ case SCREEN_MODE_3P_4P_SPLITSCREEN:
+ func_802A39E0(screen); // Clear z-buffer only for this screen
+ break;
}
-}
-
-void func_802A54A8(void) {
- init_rdp();
- func_802A39E0(gScreenOneCtx);
- func_802A3730(gScreenOneCtx);
+ race_set_viewport(screen); // differ on p3
gSPClearGeometryMode(gDisplayListHead++, G_CLEAR_ALL_MODES);
gSPSetGeometryMode(gDisplayListHead++, G_SHADE | G_SHADING_SMOOTH | G_CLIPPING);
- if (D_800DC5B4 != 0) {
- func_802A4A0C((Vtx*) D_802B8890, gScreenOneCtx);
- func_80057FC4(8);
- func_802A487C((Vtx*) D_802B8890);
- func_80093A30(8);
+ switch(gActiveScreenMode) {
+ case SCREEN_MODE_1P:
+ init_z_buffer(); // Clear the whole z-buffer
+ select_framebuffer();
+ break;
+ case SCREEN_MODE_2P_SPLITSCREEN_VERTICAL:
+ func_802A39E0(screen); // Clear z-buffer only for this screen
+ break;
}
}
-void func_802A5590(void) {
-
+/**
+ * Creates the blank screen for player four in
+ * three player mode
+ */
+void race_blank_viewport(ScreenContext* screen) {
init_rdp();
- func_802A39E0(gScreenTwoCtx);
- func_802A3730(gScreenTwoCtx);
gSPClearGeometryMode(gDisplayListHead++, G_CLEAR_ALL_MODES);
gSPSetGeometryMode(gDisplayListHead++, G_SHADE | G_SHADING_SMOOTH | G_CLIPPING);
- if (D_800DC5B4 != 0) {
- func_802A4A0C((Vtx*) D_802B8910, gScreenTwoCtx);
- func_80057FC4(9);
- func_802A487C((Vtx*) D_802B8910);
- func_80093A30(9);
- }
-}
-
-void func_802A5678(void) {
-
- init_rdp();
- func_802A39E0(gScreenThreeCtx);
- func_802A3730(gScreenThreeCtx);
-
- gSPClearGeometryMode(gDisplayListHead++, G_CLEAR_ALL_MODES);
- gSPSetGeometryMode(gDisplayListHead++, G_SHADE | G_SHADING_SMOOTH | G_CLIPPING);
+ gDPPipeSync(gDisplayListHead++);
+ func_802A39E0(screen);
+ gDPSetCycleType(gDisplayListHead++, G_CYC_FILL);
+ gDPSetColorImage(gDisplayListHead++, G_IM_FMT_RGBA, G_IM_SIZ_16b, SCREEN_WIDTH,
+ VIRTUAL_TO_PHYSICAL(gPhysicalFramebuffers[sRenderingFramebuffer]));
+ gDPSetFillColor(gDisplayListHead++, 0x00010001);
+ gDPPipeSync(gDisplayListHead++);
+ gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 160, 120, SCREEN_WIDTH, SCREEN_HEIGHT);
+ gDPFillRectangle(gDisplayListHead++, 160, 120, OTRGetDimensionFromRightEdge(320), SCREEN_HEIGHT - 1);
+ gDPPipeSync(gDisplayListHead++);
+ gDPSetCycleType(gDisplayListHead++, G_CYC_1CYCLE);
- if (D_800DC5B4 != 0) {
- func_802A4A0C((Vtx*) D_802B8990, gScreenThreeCtx);
- func_80057FC4(10);
- func_802A487C((Vtx*) D_802B8990);
- func_80093A30(10);
- }
+ race_set_viewport(screen);
}
-void func_802A5760(void) {
-
+void race_begin_viewport_4p(ScreenContext* screen) {
init_rdp();
gSPClearGeometryMode(gDisplayListHead++, G_CLEAR_ALL_MODES);
gSPSetGeometryMode(gDisplayListHead++, G_SHADE | G_SHADING_SMOOTH | G_CLIPPING);
- if (gPlayerCountSelection1 == 3) {
-
- gDPPipeSync(gDisplayListHead++);
- func_802A39E0(gScreenFourCtx);
- gDPSetCycleType(gDisplayListHead++, G_CYC_FILL);
- gDPSetColorImage(gDisplayListHead++, G_IM_FMT_RGBA, G_IM_SIZ_16b, SCREEN_WIDTH,
- VIRTUAL_TO_PHYSICAL(gPhysicalFramebuffers[sRenderingFramebuffer]));
- gDPSetFillColor(gDisplayListHead++, 0x00010001);
- gDPPipeSync(gDisplayListHead++);
- gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 160, 120, SCREEN_WIDTH, SCREEN_HEIGHT);
- gDPFillRectangle(gDisplayListHead++, 160, 120, OTRGetDimensionFromRightEdge(320), SCREEN_HEIGHT - 1);
- gDPPipeSync(gDisplayListHead++);
- gDPSetCycleType(gDisplayListHead++, G_CYC_1CYCLE);
-
- func_802A3730(gScreenFourCtx);
-
- } else {
- func_802A3730(gScreenFourCtx);
- func_802A39E0(gScreenFourCtx);
-
- if (D_800DC5B4 != 0) {
- func_802A4A0C(D_802B8A10, gScreenFourCtx);
- func_80057FC4(11);
- func_802A487C(D_802B8A10);
- func_80093A30(11);
- }
- }
+ race_set_viewport(screen);
+ func_802A39E0(screen);
}
-void render_screens(s32 mode, s32 cameraId, s32 playerId) {
+void render_screens(ScreenContext* screen, s32 mode, s32 someId, s32 playerId) {
Mat4 matrix;
+ Camera* camera = screen->camera;
+ s32 screenId = screen - gScreenContexts;
- s32 screenId = 0;
- s32 screenMode = SCREEN_MODE_1P;
+ if (NULL == camera) {
+ printf("[skybox_and_splitscreen.c] Skipping rendering for screen %d. This viewport has no camera\n", screen - gScreenContexts);
+ return;
+ }
- switch (mode) {
- case RENDER_SCREEN_MODE_1P_PLAYER_ONE:
- func_802A53A4();
- screenId = 0;
- screenMode = SCREEN_MODE_1P;
- break;
- case RENDER_SCREEN_MODE_2P_HORIZONTAL_PLAYER_ONE:
- func_802A51D4();
- screenId = 0;
- screenMode = SCREEN_MODE_2P_SPLITSCREEN_HORIZONTAL;
- break;
- case RENDER_SCREEN_MODE_2P_HORIZONTAL_PLAYER_TWO:
- func_802A52BC();
- screenId = 1;
- screenMode = SCREEN_MODE_2P_SPLITSCREEN_HORIZONTAL;
- break;
- case RENDER_SCREEN_MODE_2P_VERTICAL_PLAYER_ONE:
- func_802A50EC();
- screenId = 0;
- screenMode = SCREEN_MODE_2P_SPLITSCREEN_VERTICAL;
- break;
- case RENDER_SCREEN_MODE_2P_VERTICAL_PLAYER_TWO:
- func_802A5004();
- screenId = 1;
- screenMode = SCREEN_MODE_2P_SPLITSCREEN_VERTICAL;
- break;
- case RENDER_SCREEN_MODE_3P_4P_PLAYER_ONE:
- func_802A54A8();
- screenId = 0;
- screenMode = SCREEN_MODE_3P_4P_SPLITSCREEN;
- break;
- case RENDER_SCREEN_MODE_3P_4P_PLAYER_TWO:
- func_802A5590();
- screenId = 1;
- screenMode = SCREEN_MODE_3P_4P_SPLITSCREEN;
- break;
- case RENDER_SCREEN_MODE_3P_4P_PLAYER_THREE:
- func_802A5678();
- screenId = 2;
- screenMode = SCREEN_MODE_3P_4P_SPLITSCREEN;
- break;
- case RENDER_SCREEN_MODE_3P_4P_PLAYER_FOUR:
- func_802A5760();
- screenId = 3;
- screenMode = SCREEN_MODE_3P_4P_SPLITSCREEN;
+ switch(mode) {
+ case RENDER_SCREEN_MODE_3P_4P_PLAYER_FOUR: // Blank screen
if (gPlayerCountSelection1 == 3) {
+ race_blank_viewport(screen);
func_80093A5C(RENDER_SCREEN_MODE_3P_4P_PLAYER_FOUR);
if (D_800DC5B8 != 0) {
render_hud(RENDER_SCREEN_MODE_3P_4P_PLAYER_FOUR);
}
gNumScreens += 1;
return;
+ } else { // Player four
+ race_begin_viewport_4p(screen);
+
+ if ((CVarGetInteger("gDrawSky", true) == true)) {
+ CM_RaceDrawSky(screen, someId);
+ func_80093A30(someId); // Fill box for thunderbolt?
+ }
}
break;
- }
+ default:
+ race_begin_viewport(screen, mode);
- ScreenContext* screen = &gScreenContexts[screenId];
- Camera* camera = screen->camera;
- cameraId = camera->cameraId;
- // CM_GetCamera(cameraId);
-
- if (NULL == camera) {
- printf("NO CAMERA SELECTED\n");
- return;
+ if ((CVarGetInteger("gDrawSky", true) == true)) {
+ CM_RaceDrawSky(screen, someId);
+ func_80093A30(someId); // Fill box for thunderbolt?
+ }
+ break;
}
- if (screenMode == SCREEN_MODE_2P_SPLITSCREEN_HORIZONTAL) {
+ if (gActiveScreenMode == SCREEN_MODE_2P_SPLITSCREEN_HORIZONTAL) {
gSPSetGeometryMode(gDisplayListHead++, G_SHADE | G_CULL_BACK | G_LIGHTING | G_SHADING_SMOOTH);
}
init_rdp();
- func_802A3730(screen);
+ race_set_viewport(screen);
gSPSetGeometryMode(gDisplayListHead++, G_ZBUFFER | G_SHADE | G_CULL_BACK | G_LIGHTING | G_SHADING_SMOOTH);
gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_OPA_SURF, G_RM_AA_ZB_OPA_SURF2);
@@ -800,7 +664,7 @@ void render_screens(s32 mode, s32 cameraId, s32 playerId) {
CM_SetViewProjection(camera);
// Create a matrix for the track and game objects
- FrameInterpolation_RecordOpenChild("track", TAG_TRACK((cameraId | (playerId << 2))));
+ FrameInterpolation_RecordOpenChild("track", TAG_TRACK((camera->cameraId | (playerId << 2))));
Mat4 trackMatrix;
mtxf_identity(trackMatrix);
if (gIsMirrorMode != 0) {
diff --git a/src/racing/skybox_and_splitscreen.h b/src/racing/skybox_and_splitscreen.h
index f198b727e..38748f36a 100644
--- a/src/racing/skybox_and_splitscreen.h
+++ b/src/racing/skybox_and_splitscreen.h
@@ -12,7 +12,7 @@
void func_802A4A0C(Vtx*, ScreenContext*);
void set_screen(void);
void set_editor_screen(void);
-void func_802A3730(ScreenContext*);
+void race_set_viewport(ScreenContext*);
void func_802A38AC(void);
void func_802A38B4(void);
void func_802A39E0(ScreenContext*);
@@ -34,25 +34,10 @@ void func_802A450C(Vtx*);
void func_802A487C(Vtx*);
void func_802A4D18(void);
void func_802A4EF4(void);
-void func_802A5004(void);
-void func_802A50EC(void);
-void func_802A51D4(void);
-void func_802A52BC(void);
-void func_802A53A4(void);
-void func_802A54A8(void);
-void func_802A5590(void);
-void func_802A5678(void);
-void func_802A5760(void);
-void render_player_one_1p_screen(void);
-void render_player_one_2p_screen_vertical(void);
-void render_player_two_2p_screen_vertical(void);
-void render_player_one_2p_screen_horizontal(void);
-void render_player_two_2p_screen_horizontal(void);
-void render_player_one_3p_4p_screen(void);
-void render_player_two_3p_4p_screen(void);
-void render_player_three_3p_4p_screen(void);
-void render_player_four_3p_4p_screen(void);
-void render_screens(s32 mode, s32 cameraId, s32 playerId);
+void race_begin_viewport(ScreenContext* screen, s32 mode);
+void race_blank_viewport(ScreenContext* screen);
+void race_begin_viewport_4p(ScreenContext* screen);
+void render_screens(ScreenContext* screen, s32 mode, s32 someId, s32 playerId);
void func_802A74BC(void);
void copy_framebuffer(s32, s32, s32, s32, u16*, u16*);
void func_802A7728(void);
diff --git a/src/render_objects.c b/src/render_objects.c
index 5e300808d..a14c3d350 100644
--- a/src/render_objects.c
+++ b/src/render_objects.c
@@ -47,6 +47,7 @@
#include "engine/Matrix.h"
#include "engine/tracks/Track.h"
#include "engine/TrackBrowser.h"
+#include "engine/sky/Sky.h"
#include "port/interpolation/FrameInterpolation.h"
#include "assets/textures/tracks/sherbet_land/sherbet_land_data.h"
@@ -3476,97 +3477,18 @@ void render_object_snowflakes_particles(void) {
gSPTexture(gDisplayListHead++, 1, 1, 0, G_TX_RENDERTILE, G_OFF);
}
-struct ObjectInterpData {
- s32 objectIndex;
- s16 x, y;
-};
-
-struct ObjectInterpData prevObject[OBJECT_LIST_SIZE] = { 0 };
-
-void render_clouds(s32 objectIndex, s16 x, s16 y) {
-
- // Search all recorded objects for the one we're drawing
- for (size_t i = 0; i < OBJECT_LIST_SIZE; i++) {
- if (objectIndex == prevObject[i].objectIndex) {
- // Coincidence!
- // 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;
- }
- }
- }
-
- if (gObjectList[objectIndex].status & 0x10) {
-
- // @port: Tag the transform.
- FrameInterpolation_RecordOpenChild("render_clouds", TAG_CLOUDS(objectIndex));
-
- if (D_8018D228 != gObjectList[objectIndex].unk_0D5) {
- D_8018D228 = gObjectList[objectIndex].unk_0D5;
- func_80044DA0(gObjectList[objectIndex].activeTexture, gObjectList[objectIndex].textureWidth,
- gObjectList[objectIndex].textureHeight);
- }
- func_80042330_unchanged(x, y, 0, gObjectList[objectIndex].sizeScaling);
- gSPVertex(gDisplayListHead++, gObjectList[objectIndex].vertex, 4, 0);
- gSPDisplayList(gDisplayListHead++, common_rectangle_display);
-
- // @port Pop the transform id.
- FrameInterpolation_RecordCloseChild();
- }
-
- // Save current cloud index and x position
- prevObject[objectIndex].x = x;
- prevObject[objectIndex].y = y;
- prevObject[objectIndex].objectIndex = objectIndex;
-}
-
-void func_800519D4(s32 objectIndex, s16 arg1, s16 arg2) {
- if (gObjectList[objectIndex].status & 0x10) {
- if (D_8018D228 != gObjectList[objectIndex].unk_0D5) {
- D_8018D228 = gObjectList[objectIndex].unk_0D5;
- func_80044DA0(gObjectList[objectIndex].activeTexture, gObjectList[objectIndex].textureWidth,
- gObjectList[objectIndex].textureHeight);
- }
- func_8004B138(0x000000FF, 0x000000FF, 0x000000FF, gObjectList[objectIndex].primAlpha);
- func_80042330_unchanged(arg1, arg2, 0U, gObjectList[objectIndex].sizeScaling);
- gSPVertex(gDisplayListHead++, gObjectList[objectIndex].vertex, 4, 0);
- gSPDisplayList(gDisplayListHead++, common_rectangle_display);
- }
-}
-
// Render clouds
-void func_80051ABC(s16 arg0, s32 arg1) {
+void func_80051ABC(ScreenContext* screen, s16 arg0, s32 arg1) {
s32 var_s0;
s32 objectIndex;
Object* object;
D_8018D228 = 0xFF;
gSPDisplayList(gDisplayListHead++, D_0D007A60);
- if ((u8) D_8018D230 != 0) {
- func_8004B414(255, 255, 255, 255);
- for (var_s0 = 0; var_s0 < D_8018D1F0; var_s0++) {
- objectIndex = D_8018CC80[arg1 + var_s0];
- object = &gObjectList[objectIndex];
- FrameInterpolation_RecordOpenChild("stars_cloud", TAG_OBJECT(object));
-
- func_800519D4(objectIndex, object->unk_09C, arg0 - object->unk_09E);
- FrameInterpolation_RecordCloseChild();
- }
- } else {
- func_8004B6C4(255, 255, 255);
- for (var_s0 = 0; var_s0 < D_8018D1F0; var_s0++) {
- objectIndex = D_8018CC80[arg1 + var_s0];
- object = &gObjectList[objectIndex];
-
- render_clouds(objectIndex, object->unk_09C, arg0 - object->unk_09E);
- }
- }
+ DrawSkyActors(screen, arg0);
}
-void func_80051C60(s16 arg0, s32 arg1) {
+void func_80051C60(ScreenContext* screen, s16 arg0, s32 arg1) {
s16 var_s5;
s32 var_s0;
s32 objectIndex;
@@ -3590,32 +3512,17 @@ void func_80051C60(s16 arg0, s32 arg1) {
D_8018D228 = 0xFF;
gSPDisplayList(gDisplayListHead++, D_0D007A60);
-
- if ((u8) D_8018D230 != 0) {
- func_8004B414(255, 255, 255, 255);
- for (var_s0 = 0; var_s0 < D_8018D1F0; var_s0++) {
- objectIndex = D_8018CC80[arg1 + var_s0];
- object = &gObjectList[objectIndex];
- func_800519D4(objectIndex, object->unk_09C, (var_s5 - object->unk_09E) / 2);
- }
- } else {
- func_8004B6C4(255, 255, 255);
- for (var_s0 = 0; var_s0 < D_8018D1F0; var_s0++) {
- objectIndex = D_8018CC80[arg1 + var_s0];
- object = &gObjectList[objectIndex];
- render_clouds(objectIndex, object->unk_09C, (var_s5 - object->unk_09E) / 2);
- }
- }
+ DrawSkyActors(screen, arg0);
}
-void func_80051EBC(void) {
- func_80051ABC(240 - gScreenOneCtx->cameraHeight, 0); // 28
+void func_80051EBC(ScreenContext* screen) {
+ func_80051ABC(screen, 240 - screen->cameraHeight, 0); // 28
}
-void func_80051EF8(void) {
+void func_80051EF8(ScreenContext* screen) {
s16 temp_a0;
- temp_a0 = 0xF0 - gScreenOneCtx->cameraHeight;
+ temp_a0 = 0xF0 - screen->cameraHeight;
if (IsKoopaTroopaBeach()) {
temp_a0 = temp_a0 - 0x30;
} else if (IsMooMooFarm()) {
@@ -3625,13 +3532,13 @@ void func_80051EF8(void) {
} else {
temp_a0 = temp_a0 - 0x30;
}
- func_80051ABC(temp_a0, 0);
+ func_80051ABC(screen, temp_a0, 0);
}
-void func_80051F9C(void) {
+void func_80051F9C(ScreenContext* screen) {
s16 temp_a0;
- temp_a0 = 0xF0 - gScreenTwoCtx->cameraHeight;
+ temp_a0 = 0xF0 - screen->cameraHeight;
if (IsKoopaTroopaBeach()) {
temp_a0 = temp_a0 - 0x30;
} else if (IsMooMooFarm()) {
@@ -3641,15 +3548,15 @@ void func_80051F9C(void) {
} else {
temp_a0 = temp_a0 - 0x30;
}
- func_80051ABC(temp_a0, D_8018D1F0);
+ func_80051ABC(screen, temp_a0, D_8018D1F0);
}
-void func_80052044(void) {
- func_80051C60(240 - gScreenOneCtx->cameraHeight, 0);
+void func_80052044(ScreenContext* screen) {
+ func_80051C60(screen, 240 - screen->cameraHeight, 0);
}
-void func_80052080(void) {
- func_80051C60(240 - gScreenTwoCtx->cameraHeight, D_8018D1F0);
+void func_80052080(ScreenContext* screen) {
+ func_80051C60(screen, 240 - screen->cameraHeight, D_8018D1F0);
}
void func_800520C0(s32 arg0) {
diff --git a/src/render_objects.h b/src/render_objects.h
index ff0b91303..083481776 100644
--- a/src/render_objects.h
+++ b/src/render_objects.h
@@ -3,6 +3,7 @@
#include <common_structs.h>
#include "main.h"
+#include "code_800029B0.h"
#ifdef __cplusplus
extern "C" {
@@ -318,16 +319,14 @@ void func_80050E34(s32, s32);
void func_800514BC(void);
void render_object_leaf_particle(s32);
void render_object_snowflakes_particles(void);
-void render_clouds(s32, s16, s16);
-void func_800519D4(s32, s16, s16);
-void func_80051ABC(s16, s32);
-void func_80051C60(s16, s32);
-void func_80051EBC(void);
-void func_80051EF8(void);
-void func_80051F9C(void);
-
-void func_80052044(void);
-void func_80052080(void);
+void func_80051ABC(ScreenContext* screen, s16, s32);
+void func_80051C60(ScreenContext* screen, s16, s32);
+void func_80051EBC(ScreenContext* screen);
+void func_80051EF8(ScreenContext* screen);
+void func_80051F9C(ScreenContext* screen);
+void func_80052044(ScreenContext* screen);
+void func_80052080(ScreenContext* screen);
+
void func_800520C0(s32);
void func_8005285C(s32);
void func_800528EC(s32);
diff --git a/src/update_objects.c b/src/update_objects.c
index 75e1671de..a8bd556bd 100644
--- a/src/update_objects.c
+++ b/src/update_objects.c
@@ -45,6 +45,7 @@
#include <assets/textures/tracks/rainbow_road/rainbow_road_data.h>
#include "engine/RaceManager.h"
+#include "engine/sky/Sky.h"
float OTRGetAspectRatio(void);
@@ -2210,123 +2211,6 @@ void update_leaf(void) {
}
}
-void func_80077D5C(s32 arg0) {
- s32 objectIndex;
- s32 var_a1;
-
- if (D_8016559C == 0) {
- for (var_a1 = 0; var_a1 < D_8018D1F0; var_a1++) {
- D_8018D17C += 1;
- if (D_8018D17C >= D_8018D1F0) {
- D_8018D17C = 0;
- }
- objectIndex = D_8018CC80[arg0 + D_8018D17C];
- if (gObjectList[objectIndex].state == 0) {
- init_object(objectIndex, 1);
- break;
- }
- }
- }
-}
-
-void func_80077E20(s32 objectIndex) {
- Vtx* vtx = (Vtx*) LOAD_ASSET(common_vtx_rectangle);
- Object* object;
-
- object = &gObjectList[objectIndex];
- object->activeTexture = D_0D0293D8;
- object->textureList = D_0D0293D8;
- //! @bug frappe snowland There's something up with the handling of common_vtx_rectangle and the loading of 0x10
- //! right here
- // root function: func_80078C70
- object->vertex = vtx;
- object->textureHeight = 0x10;
- object->textureWidth = object->textureHeight;
- object->sizeScaling = 0.15f;
- set_object_flag(objectIndex, 0x00000010);
- func_80086EF0(objectIndex);
- object->primAlpha = 0x00FF;
- object->unk_0D5 = 0;
- object->type = 0;
- object_next_state(objectIndex);
-}
-
-void func_80077EB8(s32 objectIndex, u16 arg1, Camera* camera) {
- s16 temp_v0;
-
- temp_v0 = camera->rot[1] - arg1;
- if ((temp_v0 >= D_8018D210) || (D_8018D208 >= temp_v0)) {
- gObjectList[objectIndex].offset[0] = D_8018D218 + (D_8018D1E8 * (f32) temp_v0);
- set_object_flag(objectIndex, 0x00000010);
- return;
- }
- clear_object_flag(objectIndex, 0x00000010);
-}
-
-void func_80077F64(s32 objectIndex, Camera* camera) {
-
- f64 rand;
-
- switch (gObjectList[objectIndex].unk_0AE) { /* irregular */
- case 1:
- gObjectList[objectIndex].direction_angle[1] = (camera->rot[1] + random_int(0x4000U)) - 0x2000;
- object_origin_pos_randomize_around_y(objectIndex, 0x00B4, 0x0014U);
- rand = random_int(0x0064U);
-
- gObjectList[objectIndex].velocity[1] = (f32) (-0.75 - (f64) (f32) (rand * 0.01));
- gObjectList[objectIndex].offset[0] = 0.0f;
- gObjectList[objectIndex].offset[1] = 0.0f;
- func_80086FD4(objectIndex);
- return;
- case 2:
- func_80077EB8(objectIndex, gObjectList[objectIndex].direction_angle[1], camera);
- object_add_velocity_offset_y(objectIndex);
- object_calculate_new_pos_offset(objectIndex);
- func_8008BFC0(objectIndex);
- if (gObjectList[objectIndex].pos[1] <= 0.0f) {
- func_80086FD4(objectIndex);
- return;
- }
- case 0:
- return;
- case 3:
- func_80086F60(objectIndex);
- break;
- }
-}
-
-void func_800780CC(s32 objectIndex, Camera* camera) {
- switch (gObjectList[objectIndex].state) { /* irregular */
- case 1:
- func_80077E20(objectIndex);
- return;
- case 2:
- func_80077F64(objectIndex, camera);
- if (gObjectList[objectIndex].unk_0AE == 0) {
- object_next_state(objectIndex);
- return;
- }
- case 0:
- return;
- case 3:
- func_80072428(objectIndex);
- break;
- }
-}
-
-void func_80078170(s32 arg0, Camera* arg1) {
- s32 objectIndex;
- s32 i;
-
- func_80077D5C(arg0);
- for (i = 0; i < D_8018D1F0; i++) {
- objectIndex = D_8018CC80[arg0 + i];
- if (gObjectList[objectIndex].state != 0) {
- func_800780CC(objectIndex, arg1);
- }
- }
-}
-
void func_80078220(s32 objectIndex) {
u8* tex = (u8*) LOAD_ASSET(D_0D0293D8);
Vtx* vtx = (Vtx*) LOAD_ASSET(common_vtx_rectangle);
@@ -2451,119 +2335,9 @@ void update_snowflakes(void) {
}
}
-// This function adjusted to place clouds in the sky correctly
-void func_800788F8(s32 objectIndex, u16 rot, Camera* camera) {
- s16 cameraRot;
- // Adjustable culling factor
- const float cullingFactor = OTRGetAspectRatio();
-
- // Calculate the cloud's rotation relative to the camera
- cameraRot = camera->rot[1] + rot;
-
- // Adjust bounds based on the culling factor
- s16 adjustedLowerBound = (s16) (D_8018D210 * cullingFactor);
- s16 adjustedUpperBound = (s16) (D_8018D208 * cullingFactor);
-
- // Check if the object is within the adjusted bounds
- if ((cameraRot >= adjustedLowerBound) && (adjustedUpperBound >= cameraRot)) {
- // Calculate and update the object's position
- gObjectList[objectIndex].unk_09C = (D_8018D218 + (D_8018D1E8 * cameraRot));
-
- // Mark the object as visible
- set_object_flag(objectIndex, 0x10);
- } else {
- // If outside the bounds, mark the object as not visible
- set_object_flag(objectIndex, 0x10);
- }
-}
-
-void update_clouds(s32 arg0, Camera* arg1, CloudData* cloudList) {
- s32 cloudIndex;
- s32 objectIndex;
- CloudData* cloud;
-
- for (cloudIndex = 0; cloudIndex < D_8018D1F0; cloudIndex++) {
- cloud = &cloudList[cloudIndex];
- objectIndex = D_8018CC80[arg0 + cloudIndex];
- func_800788F8(objectIndex, cloud->rotY, arg1);
- }
-}
-
-void update_stars(s32 arg0, Camera* camera, StarData* starList) {
- s32 starIndex;
- s32 objectIndex;
- StarData* star;
-
- for (starIndex = 0; starIndex < D_8018D1F0; starIndex++) {
- star = &starList[starIndex];
- objectIndex = D_8018CC80[arg0 + starIndex];
- func_800788F8(objectIndex, star->rotY, camera);
- switch (starIndex % 5U) {
- case 0:
- func_80073CB0(objectIndex, &gObjectList[objectIndex].primAlpha, 0x00000028, 0x000000B4, 0x000000FF, 0,
- -1);
- break;
- case 1:
- func_80073CB0(objectIndex, &gObjectList[objectIndex].primAlpha, 0x00000080, 0x000000FF, 0x000000FF, 0,
- -1);
- break;
- case 2:
- func_80073CB0(objectIndex, &gObjectList[objectIndex].primAlpha, 0x00000050, 0x000000C8, 0x000000FF, 0,
- -1);
- break;
- case 3:
- func_80073CB0(objectIndex, &gObjectList[objectIndex].primAlpha, 0, 0x0000009B, 0x000000FF, 0, -1);
- break;
- case 4:
- func_80073CB0(objectIndex, &gObjectList[objectIndex].primAlpha, 0x0000005A, 0x00000080, 0x000000FF, 0,
- -1);
- break;
- }
- }
-}
-
-UNUSED void func_80078C68() {
-}
-
-void func_80078C70(s32 arg0) {
- s32 sp1C;
- Camera* camera;
-
+void func_80078C70() {
if (D_801657C8 == 0) {
- switch (arg0) { /* switch 1 */
- case 0: /* switch 1 */
- sp1C = 0;
- camera = camera1;
- D_8018D200 = camera->fieldOfView + 40.0f;
- break;
- case 1: /* switch 1 */
- sp1C = 0;
- camera = camera1;
- D_8018D200 = camera->fieldOfView + 40.0f;
- break;
- case 2: /* switch 1 */
- camera = camera2;
- sp1C = D_8018D1F0;
- D_8018D200 = camera->fieldOfView + 40.0f;
- break;
- case 3: /* switch 1 */
- sp1C = 0;
- camera = camera1;
- D_8018D200 = camera->fieldOfView + 40.0f;
- break;
- case 4: /* switch 1 */
- camera = camera2;
- sp1C = D_8018D1F0;
- D_8018D200 = camera->fieldOfView + 40.0f;
- break;
- }
-
- D_8018D208 = ((D_8018D200 / 2) * 0xB6) + 0x71C;
- D_8018D210 = (-(D_8018D200 / 2) * 0xB6) - 0x71C;
- D_8018D1E8 = 1.7578125 / D_8018D200;
- D_8018D218 = 0xA0;
-
- CM_TickClouds(sp1C, camera);
+ TickSkyActors();
}
}
diff --git a/src/update_objects.h b/src/update_objects.h
index 228d40bf2..4db33ea7b 100644
--- a/src/update_objects.h
+++ b/src/update_objects.h
@@ -8,8 +8,6 @@
/** @cond */
-void func_80078170(s32 arg0, Camera* arg1);
-void func_80077D5C(s32);
s32 find_unused_obj_index(s32*);
void delete_object(s32*);
s32 func_80071FBC(void);
@@ -168,17 +166,12 @@ void func_80077B14(s32);
void func_80077B3C(s32);
void func_80077BCC(s32);
void update_leaf(void);
-void func_80077E20(s32);
void func_80078220(s32);
void func_80078288(s32);
void func_800786EC(s32);
void func_80078790(void);
void update_snowflakes(void);
-void func_800788F8(s32, u16, Camera*);
-void update_clouds(s32, Camera*, CloudData*);
-void update_stars(s32, Camera*, StarData*);
-void func_80078C68(void);
-void func_80078C70(s32);
+void func_80078C70();
void func_80078F64(void);
void func_80079054(s32);
void func_80079084(s32);