summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKiritoDv <kiritodev01@gmail.com>2024-10-16 12:46:19 -0600
committerKiritoDv <kiritodev01@gmail.com>2024-10-16 12:46:19 -0600
commite5ed74b97877d30ea7010a76a54c48b3df99ca8b (patch)
tree913e619dbf21fdb94a7e23471a3a6143a934d16c /src
parentd423e04c3fdb14aed21e99656623554f9fcd6ef8 (diff)
parent0b23e06b7729ddd38d40cf600caa363e7d0b8253 (diff)
Merge branch 'starfield' into interpolation
Diffstat (limited to 'src')
-rw-r--r--src/engine/fox_bg.c242
-rw-r--r--src/engine/fox_play.c95
-rw-r--r--src/sys/sys_memory.c4
3 files changed, 284 insertions, 57 deletions
diff --git a/src/engine/fox_bg.c b/src/engine/fox_bg.c
index 566ff05b..b5023e92 100644
--- a/src/engine/fox_bg.c
+++ b/src/engine/fox_bg.c
@@ -101,11 +101,59 @@ f32 sGroundPositions360z[4] = {
-6000.0f,
};
+// Declare global variables for screen dimensions
+float gCurrentScreenWidth = 320.0f * 3; // Default width
+float gCurrentScreenHeight = 240.0f * 3; // Default height
+
+// Custom floating-point modulo function (replaces fmodf)
+float FloatMod(float a, float b) {
+ float result = a - ((int) (a / b)) * b;
+ if (result < 0.0f) {
+ result += b;
+ }
+ return result;
+}
+
+// Define a single 1x1 star as two triangles
+static Vtx starVerts[4] = {
+ // Format: VTX(x, y, z, s, t, r, g, b, a)
+ VTX(0, 0, 0, 0, 0, 255, 255, 255, 255), // Bottom-left
+ VTX(0, 1, 0, 0, 0, 255, 255, 255, 255), // Top-left
+ VTX(1, 0, 0, 0, 0, 255, 255, 255, 255), // Bottom-right
+ VTX(1, 1, 0, 0, 0, 255, 255, 255, 255), // Top-right
+};
+
+// Display list to render the two triangles forming the star quad
+static Gfx starDL[] = {
+ gsSPVertex(starVerts, ARRAY_COUNT(starVerts), 0),
+ gsSP2Triangles(0, 1, 2, 0, 1, 2, 3, 0),
+ gsSPEndDisplayList(),
+};
+
+// Display list to render the two triangles forming the partial star quad
+static Gfx starDLPartial[] = {
+ gsSPVertex(starVerts, ARRAY_COUNT(starVerts), 0),
+ gsSP2Triangles(0, 1, 2, 0, 1, 2, 3, 0),
+ gsSPEndDisplayList(),
+};
+
+// Setup render state for stars
+static Gfx starSetupDL[] = {
+ gsSPTexture(0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF), // Disable texturing
+ gsSPClearGeometryMode(G_ZBUFFER | G_SHADE | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR | G_CULL_BACK |
+ G_SHADING_SMOOTH),
+ //gsDPPipeSync(),
+ gsDPSetCombineMode(G_CC_PRIMITIVE, G_CC_PRIMITIVE), // Use primitive color
+ gsDPSetOtherMode(G_AD_NOTPATTERN | G_CD_MAGICSQ | G_CK_NONE | G_TC_FILT | G_TF_BILERP | G_TT_NONE | G_TL_TILE |
+ G_TD_CLAMP | G_TP_PERSP | G_CYC_1CYCLE | G_PM_NPRIMITIVE,
+ G_AC_NONE | G_ZS_PIXEL | G_RM_OPA_SURF | G_RM_OPA_SURF2),
+ gsSPEndDisplayList(),
+};
+
+// @port: Starfield drawn with triangles, re-engineered by @Tharo & @TheBoy181
void Background_DrawStarfield(void) {
f32 by;
f32 bx;
- s16 vy;
- s16 vx;
s32 i;
s32 starCount;
f32 zCos;
@@ -115,24 +163,40 @@ void Background_DrawStarfield(void) {
f32* xStar;
f32* yStar;
u32* color;
+ float currentScreenWidth;
+ float currentScreenHeight;
+ float starfieldWidth;
+ float starfieldHeight;
+ float vx;
+ float vy;
+ const float STAR_MARGIN = 10.0f; // Margin to hide seam stars
+
+ // Set projection to orthographic before drawing stars
+ Lib_InitOrtho(&gMasterDisp);
+
+ gSPDisplayList(gMasterDisp++, starSetupDL);
+
+ // Get current screen dimensions
+ currentScreenWidth = gCurrentScreenWidth;
+ currentScreenHeight = gCurrentScreenHeight;
+ starfieldWidth = 1.0f * currentScreenWidth;
+ starfieldHeight = 1.0f * currentScreenHeight;
- gDPPipeSync(gMasterDisp++);
- gDPSetCycleType(gMasterDisp++, G_CYC_FILL);
- gDPSetCombineMode(gMasterDisp++, G_CC_SHADE, G_CC_SHADE);
- gDPSetRenderMode(gMasterDisp++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
starCount = gStarCount;
+
if (starCount != 0) {
- if (gStarfieldX >= 1.5f * SCREEN_WIDTH) {
- gStarfieldX -= 1.5f * SCREEN_WIDTH;
+ // Wrapping logic for starfield positions
+ if (gStarfieldX >= starfieldWidth) {
+ gStarfieldX -= starfieldWidth;
}
- if (gStarfieldY >= 1.5f * SCREEN_HEIGHT) {
- gStarfieldY -= 1.5f * SCREEN_HEIGHT;
+ if (gStarfieldY >= starfieldHeight) {
+ gStarfieldY -= starfieldHeight;
}
if (gStarfieldX < 0.0f) {
- gStarfieldX += 1.5f * SCREEN_WIDTH;
+ gStarfieldX += starfieldWidth;
}
if (gStarfieldY < 0.0f) {
- gStarfieldY += 1.5f * SCREEN_HEIGHT;
+ gStarfieldY += starfieldHeight;
}
xField = gStarfieldX;
yField = gStarfieldY;
@@ -144,35 +208,86 @@ void Background_DrawStarfield(void) {
if (gGameState != GSTATE_PLAY) {
starCount = 1000;
}
+
+ starCount = starCount * 3; // Adjust multiplier as needed
+
zCos = __cosf(gStarfieldRoll);
zSin = __sinf(gStarfieldRoll);
+
for (i = 0; i < starCount; i++, yStar++, xStar++, color++) {
+ // Adjust star positions with field offsets
bx = *xStar + xField;
by = *yStar + yField;
- if (bx >= 1.25f * SCREEN_WIDTH) {
- bx -= 1.5f * SCREEN_WIDTH;
+
+ // Wrapping logic for individual stars along X-axis
+ if (bx >= starfieldWidth) {
+ bx -= starfieldWidth;
+ }
+ if (bx < 0.0f) {
+ bx += starfieldWidth;
}
- bx -= SCREEN_WIDTH / 2.0f;
- if (by >= 1.25f * SCREEN_HEIGHT) {
- by -= 1.5f * SCREEN_HEIGHT;
+ // Wrapping logic for individual stars along Y-axis
+ if (by >= starfieldHeight) {
+ by -= starfieldHeight;
+ }
+ if (by < 0.0f) {
+ by += starfieldHeight;
}
- by -= SCREEN_HEIGHT / 2.0f;
-
- vx = (zCos * bx) + (zSin * by) + SCREEN_WIDTH / 2.0f;
- vy = (-zSin * bx) + (zCos * by) + SCREEN_HEIGHT / 2.0f;
- if ((vx >= 0) && (vx < SCREEN_WIDTH) && (vy > 0) && (vy < SCREEN_HEIGHT)) {
- gDPPipeSync(gMasterDisp++);
- gDPSetFillColor(gMasterDisp++, *color);
- gDPFillRectangle(gMasterDisp++, vx, vy, vx, vy);
+
+ // Center the positions
+ bx -= starfieldWidth / 2.0f;
+ by -= starfieldHeight / 2.0f;
+
+ // Apply rotation
+ vx = (zCos * bx) + (zSin * by) + currentScreenWidth / 2.0f;
+ vy = (-zSin * bx) + (zCos * by) + currentScreenHeight / 2.0f;
+
+ // Check if the star is within the visible screen area with margin
+ if ((vx >= STAR_MARGIN) && (vx < currentScreenWidth - STAR_MARGIN) && (vy >= STAR_MARGIN) &&
+ (vy < currentScreenHeight - STAR_MARGIN)) {
+ // @recomp Tag the transform.
+ // gEXMatrixGroupDecomposed(gMasterDisp++, TAG_STARFIELD + i, G_EX_PUSH, G_MTX_MODELVIEW,
+ // G_EX_COMPONENT_AUTO, G_EX_COMPONENT_AUTO, G_EX_COMPONENT_AUTO,
+ // G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP,
+ // G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_AUTO, G_EX_EDIT_ALLOW);
+
+ // Translate to (vx, vy) in ortho coordinates
+ Matrix_Push(&gGfxMatrix);
+ Matrix_Translate(gGfxMatrix, vx - (currentScreenWidth / 2.0f), -(vy - (currentScreenHeight / 2.0f)),
+ 0.0f, MTXF_NEW);
+ Matrix_SetGfxMtx(&gMasterDisp);
+ Matrix_Pop(&gGfxMatrix);
+
+ // Convert color from fill color (assuming RGB5A1) to RGBA8
+ u8 r = ((*color >> 11) & 0x1F);
+ r = (r << 3) | (r >> 2); // Convert 5-bit to 8-bit
+ u8 g = ((*color >> 6) & 0x1F);
+ g = (g << 3) | (g >> 2); // Convert 5-bit to 8-bit
+ u8 b = ((*color >> 1) & 0x1F);
+ b = (b << 3) | (b >> 2); // Convert 5-bit to 8-bit
+ u8 a = 255; // Fully opaque
+
+ gDPSetPrimColor(gMasterDisp++, 0, 0, r, g, b, a);
+
+ // Draw the star using the predefined display list
+ gSPDisplayList(gMasterDisp++, starDL);
+
+ // Pop the transform id
+ // gEXPopMatrixGroup(gMasterDisp++, G_MTX_MODELVIEW);
}
}
}
+
+ // Restore original perspective after drawing stars
+ Lib_InitPerspective(&gMasterDisp);
+
+ // Finalize rendering state
gDPPipeSync(gMasterDisp++);
gDPSetColorDither(gMasterDisp++, G_CD_MAGICSQ);
}
-void Background_DrawPartialStarfield(s32 yMin, s32 yMax) {
+void Background_DrawPartialStarfield(s32 yMin, s32 yMax) { // Stars that are in the Epilogue
f32 by;
f32 bx;
s16 vy;
@@ -186,22 +301,30 @@ void Background_DrawPartialStarfield(s32 yMin, s32 yMax) {
f32* sp60;
f32* sp5C;
u32* sp58;
+
+ // Get current screen dimensions
+ float currentScreenWidth = gCurrentScreenWidth;
+ float currentScreenHeight = gCurrentScreenHeight;
+ float starfieldWidth = 1.0f * currentScreenWidth;
+ float starfieldHeight = 1.0f * currentScreenHeight;
+
+ // Graphics pipeline setup
gDPPipeSync(gMasterDisp++);
gDPSetCycleType(gMasterDisp++, G_CYC_FILL);
gDPSetCombineMode(gMasterDisp++, G_CC_SHADE, G_CC_SHADE);
gDPSetRenderMode(gMasterDisp++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
- if (gStarfieldX >= 1.5f * SCREEN_WIDTH) {
- gStarfieldX -= 1.5f * SCREEN_WIDTH;
+ if (gStarfieldX >= 1.5f * currentScreenWidth) {
+ gStarfieldX -= 1.5f * currentScreenWidth;
}
- if (gStarfieldY >= 1.5f * SCREEN_HEIGHT) {
- gStarfieldY -= 1.5f * SCREEN_HEIGHT;
+ if (gStarfieldY >= 1.5f * currentScreenHeight) {
+ gStarfieldY -= 1.5f * currentScreenHeight;
}
if (gStarfieldX < 0.0f) {
- gStarfieldX += 1.5f * SCREEN_WIDTH;
+ gStarfieldX += 1.5f * currentScreenWidth;
}
if (gStarfieldY < 0.0f) {
- gStarfieldY += 1.5f * SCREEN_HEIGHT;
+ gStarfieldY += 1.5f * currentScreenHeight;
}
spf68 = gStarfieldX;
@@ -217,21 +340,50 @@ void Background_DrawPartialStarfield(s32 yMin, s32 yMax) {
for (i = 0; i < var_s2; i++, sp5C++, sp60++, sp58++) {
bx = *sp60 + spf68;
by = *sp5C + spf64;
- if (bx >= SCREEN_WIDTH * 1.25f) {
- bx -= 1.5f * SCREEN_WIDTH;
+ if (bx >= starfieldWidth * 1.25f) {
+ bx -= 1.5f * starfieldWidth;
}
- bx -= SCREEN_WIDTH / 2.0f;
- if (by >= SCREEN_HEIGHT * 1.25f) {
- by -= 1.5f * SCREEN_HEIGHT;
+ bx -= starfieldWidth / 2.0f;
+ if (by >= starfieldHeight * 1.25f) {
+ by -= 1.5f * starfieldHeight;
}
- by -= SCREEN_HEIGHT / 2.0f;
-
- vx = (cos * bx) + (sin * by) + SCREEN_WIDTH / 2.0f;
- vy = (-sin * bx) + (cos * by) + SCREEN_HEIGHT / 2.0f;
- if ((vx >= 0) && (vx < SCREEN_WIDTH) && (yMin < vy) && (vy < yMax)) {
- gDPPipeSync(gMasterDisp++);
- gDPSetFillColor(gMasterDisp++, *sp58);
- gDPFillRectangle(gMasterDisp++, vx, vy, vx, vy);
+ by -= starfieldHeight / 2.0f;
+
+ // Apply rotation
+ vx = (cos * bx) + (sin * by) + currentScreenWidth / 2.0f;
+ vy = (-sin * bx) + (cos * by) + currentScreenHeight / 2.0f;
+
+ // Check if the star is within the visible screen area
+ if ((vx >= 0) && (vx < currentScreenWidth) && (yMin < vy) && (vy < yMax)) {
+ // Tag the transform. Assuming TAG_STARFIELD is a defined base tag value
+ // @recomp Tag the transform.
+ // gEXMatrixGroupDecomposed(gMasterDisp++, TAG_STARFIELD + i, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_COMPONENT_AUTO,
+ // G_EX_COMPONENT_AUTO, G_EX_COMPONENT_AUTO, G_EX_COMPONENT_INTERPOLATE,
+ // G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE,
+ // G_EX_ORDER_AUTO, G_EX_EDIT_ALLOW);
+ // Translate to (vx, vy) in ortho coordinates
+ Matrix_Push(&gGfxMatrix);
+ Matrix_Translate(gGfxMatrix, vx - (currentScreenWidth / 2.0f), -(vy - (currentScreenHeight / 2.0f)), 0.0f,
+ MTXF_NEW);
+ Matrix_SetGfxMtx(&gMasterDisp);
+ Matrix_Pop(&gGfxMatrix);
+
+ // Convert color from fill color (assuming RGB5A1) to RGBA8
+ u8 r = ((*sp58 >> 11) & 0x1F);
+ r = (r << 3) | (r >> 2); // Convert 5-bit to 8-bit
+ u8 g = ((*sp58 >> 6) & 0x1F);
+ g = (g << 3) | (g >> 2); // Convert 5-bit to 8-bit
+ u8 b = ((*sp58 >> 1) & 0x1F);
+ b = (b << 3) | (b >> 2); // Convert 5-bit to 8-bit
+ u8 a = 255; // Fully opaque
+
+ gDPSetPrimColor(gMasterDisp++, 0, 0, r, g, b, a);
+
+ // Draw the star using the predefined display list
+ gSPDisplayList(gMasterDisp++, starDLPartial);
+
+ // Pop the transform id
+ // gEXPopMatrixGroup(gMasterDisp++, G_MTX_MODELVIEW);
}
}
gDPPipeSync(gMasterDisp++);
diff --git a/src/engine/fox_play.c b/src/engine/fox_play.c
index c38ef870..3e423881 100644
--- a/src/engine/fox_play.c
+++ b/src/engine/fox_play.c
@@ -22,6 +22,9 @@
#include "assets/ast_area_6.h"
#include "assets/ast_zoness.h"
+extern float gCurrentScreenWidth;
+extern float gCurrentScreenHeight;
+
UNK_TYPE D_800D2F50 = 0; // unused
s32 sOverheadCam = 0;
f32 sOverheadCamDist = 0.0f;
@@ -559,7 +562,7 @@ void Play_InitEnvironment(void) {
D_ctx_80178544 = 40;
gFovY = 45.0f;
}
-
+/*
void Play_GenerateStarfield(void) {
u32 i;
@@ -574,34 +577,92 @@ void Play_GenerateStarfield(void) {
gStarFillColors[i] = FILL_COLOR(gStarColors[i % ARRAY_COUNT(gStarColors)]);
}
}
+*/
+void Play_GenerateStarfield(void) {
+ u32 i;
+ float currentScreenWidth = gCurrentScreenWidth;
+ float currentScreenHeight = gCurrentScreenHeight;
+ float starfieldWidth = 1.0f * currentScreenWidth;
+ float starfieldHeight = 1.0f * currentScreenHeight;
+
+ MEM_ARRAY_ALLOCATE(gStarOffsetsX, 3000);
+ MEM_ARRAY_ALLOCATE(gStarOffsetsY, 3000);
+ MEM_ARRAY_ALLOCATE(gStarFillColors, 3000);
+
+ Rand_SetSeed(1, 29000, 9876);
+
+ for (i = 0; i < 3000; i++) {
+ gStarOffsetsX[i] = RAND_FLOAT_SEEDED(starfieldWidth);
+ gStarOffsetsY[i] = RAND_FLOAT_SEEDED(starfieldHeight);
+ gStarFillColors[i] = FILL_COLOR(gStarColors[i % ARRAY_COUNT(gStarColors)]);
+ }
+}
void Play_SetupStarfield(void) {
+ // Get current screen dimensions
+ float currentScreenWidth = gCurrentScreenWidth;
+ float currentScreenHeight = gCurrentScreenHeight;
+ float baseAspectRatio = 4.0f / 3.0f; // Original aspect ratio
+ float baseScreenWidth = gCurrentScreenHeight * baseAspectRatio;
+ float baseArea = baseScreenWidth * gCurrentScreenHeight;
+ float currentArea = currentScreenWidth * currentScreenHeight;
+ float areaRatio = currentArea / baseArea;
+
Play_GenerateStarfield();
gGroundHeight = -25000.0f;
- gStarCount = 600;
+
+ // Base star count adjusted for screen area
+ gStarCount = (s32) (600 * areaRatio);
+ if (gStarCount > 1000) {
+ gStarCount = 1000; // Cap the star count to 1000
+ }
+
+ // Adjust star count based on the current level
if (gCurrentLevel == LEVEL_AREA_6) {
- gStarCount = 300;
+ gStarCount = (s32) (300 * areaRatio);
+ if (gStarCount > 1000) {
+ gStarCount = 1000;
+ }
}
if (gCurrentLevel == LEVEL_UNK_15) {
- gStarCount = 400;
+ gStarCount = (s32) (400 * areaRatio);
+ if (gStarCount > 1000) {
+ gStarCount = 1000;
+ }
}
if (gGameState != GSTATE_PLAY) {
- gStarCount = 800;
+ gStarCount = (s32) (800 * areaRatio);
+ if (gStarCount > 1000) {
+ gStarCount = 1000;
+ }
}
if (gCurrentLevel == LEVEL_FORTUNA) {
- gStarCount = 500;
+ gStarCount = (s32) (500 * areaRatio);
+ if (gStarCount > 1000) {
+ gStarCount = 1000;
+ }
}
if (gVersusMode) {
- gStarCount = 0;
+ gStarCount = 0; // No stars in versus mode
}
if (gCurrentLevel == LEVEL_BOLSE) {
- gStarCount = 300;
+ gStarCount = (s32) (300 * areaRatio);
+ if (gStarCount > 1000) {
+ gStarCount = 1000;
+ }
gGroundHeight = -0.0f;
}
if (gCurrentLevel == LEVEL_TRAINING) {
- gStarCount = 800;
+ gStarCount = (s32) (800 * areaRatio);
+ if (gStarCount > 1000) {
+ gStarCount = 1000;
+ }
gGroundHeight = -0.0f;
}
+
+ // Initialize starfield position with dynamic screen dimensions
+ gStarfieldX = currentScreenWidth;
+ gStarfieldY = currentScreenHeight;
}
void Player_PlaySfx(f32* sfxSrc, u32 sfxId, s32 mode) {
@@ -6370,27 +6431,39 @@ void Camera_SetStarfieldPos(f32 xEye, f32 yEye, f32 zEye, f32 xAt, f32 yAt, f32
f32 tempf;
f32 sp20;
+ // Get current screen dimensions
+ float currentScreenWidth = gCurrentScreenWidth;
+ float currentScreenHeight = gCurrentScreenHeight;
+ float starfieldWidth = 1.0f * currentScreenWidth;
+ float starfieldHeight = 1.0f * currentScreenHeight;
+
yaw = -Math_Atan2F(xEye - xAt, zEye - zAt);
tempf = sqrtf(SQ(zEye - zAt) + SQ(xEye - xAt));
pitch = -Math_Atan2F(yEye - yAt, tempf);
+
+ // Adjust yaw to stay within the range [-π/2, π/2]
if (yaw >= M_PI / 2) {
yaw -= M_PI;
}
if (yaw <= -M_PI / 2) {
yaw += M_PI;
}
+
tempf = 0.0f;
if (gCurrentLevel == LEVEL_UNK_15) {
tempf = gPlayer[0].cam.eye.y * 0.03f;
}
+ // Calculate new starfield positions
sp30 = (-pitch * (-8.0f / 3.0f * M_RTOD) * 2.0f) + 3000.0f + gStarfieldScrollY + tempf;
sp34 = (yaw * (-8.0f / 3.0f * M_RTOD) * 2.0f) + 3000.0f + gStarfieldScrollX;
sp20 = gStarfieldX;
- gStarfieldX = Math_ModF(sp34, SCREEN_WIDTH * 1.5f);
- gStarfieldY = Math_ModF(sp30, SCREEN_HEIGHT * 1.5f);
+ // Wrap the starfield positions within the starfield dimensions
+ gStarfieldX = FloatMod(sp34, starfieldWidth);
+ gStarfieldY = FloatMod(sp30, starfieldHeight);
+ // Special case handling for specific game state and level
if ((gGameState == GSTATE_PLAY) && (gPlayer[0].state_1C8 == PLAYERSTATE_1C8_LEVEL_INTRO) &&
(gCurrentLevel == LEVEL_METEO)) {
if (fabsf(gStarfieldX - sp20) < 50.0f) {
diff --git a/src/sys/sys_memory.c b/src/sys/sys_memory.c
index 12954908..1525ee95 100644
--- a/src/sys/sys_memory.c
+++ b/src/sys/sys_memory.c
@@ -1,6 +1,8 @@
#include "sys.h"
-s32 sMemoryBuffer[0x8800];
+// s32 sMemoryBuffer[0x8800];
+// @ port: Increase memory buffer size.
+s32 sMemoryBuffer[1000000];
s32* sMemoryPtr;
void Memory_FreeAll(void) {