mirror of https://github.com/zeldaret/mm.git
790 lines
26 KiB
C
790 lines
26 KiB
C
#include "global.h"
|
|
|
|
s32 sMatAnimStep;
|
|
u32 sMatAnimFlags;
|
|
f32 sMatAnimAlphaRatio;
|
|
|
|
// Default displaylist that sets a valid displaylist into all of the segments.
|
|
static Gfx sSceneDrawDefaultDL[] = {
|
|
gsSPSegment(0x08, gEmptyDL),
|
|
gsSPSegment(0x09, gEmptyDL),
|
|
gsSPSegment(0x0A, gEmptyDL),
|
|
gsSPSegment(0x0B, gEmptyDL),
|
|
gsSPSegment(0x0C, gEmptyDL),
|
|
gsSPSegment(0x0D, gEmptyDL),
|
|
gsSPSegment(0x06, gEmptyDL),
|
|
gsDPPipeSync(),
|
|
gsDPSetPrimColor(0, 0, 128, 128, 128, 128),
|
|
gsDPSetEnvColor(128, 128, 128, 128),
|
|
gsSPEndDisplayList(),
|
|
};
|
|
|
|
/**
|
|
* Executes the current scene draw config handler.
|
|
*/
|
|
void Scene_Draw(PlayState* play) {
|
|
static void (*sSceneDrawConfigHandlers[])(PlayState*) = {
|
|
Scene_DrawConfigDefault,
|
|
Scene_DrawConfigMatAnim,
|
|
Scene_DrawConfigDoNothing,
|
|
Scene_DrawConfig3, // unused, leftover from OoT
|
|
Scene_DrawConfig4, // unused, leftover from OoT
|
|
Scene_DrawConfig5, // unused
|
|
Scene_DrawConfigGreatBayTemple,
|
|
Scene_DrawConfigMatAnimManualStep,
|
|
};
|
|
|
|
sSceneDrawConfigHandlers[play->sceneConfig](play);
|
|
}
|
|
|
|
/**
|
|
* SceneTableEntry Draw Config 0:
|
|
* Default scene draw config function. This just executes `sSceneDrawDefaultDL`.
|
|
*/
|
|
void Scene_DrawConfigDefault(PlayState* play) {
|
|
OPEN_DISPS(play->state.gfxCtx);
|
|
|
|
gSPDisplayList(POLY_OPA_DISP++, sSceneDrawDefaultDL);
|
|
gSPDisplayList(POLY_XLU_DISP++, sSceneDrawDefaultDL);
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
|
}
|
|
|
|
/**
|
|
* Returns a pointer to a single layer texture scroll displaylist.
|
|
*/
|
|
Gfx* AnimatedMat_TexScroll(PlayState* play, AnimatedMatTexScrollParams* params) {
|
|
return Gfx_TexScroll(play->state.gfxCtx, params->xStep * sMatAnimStep, -(params->yStep * sMatAnimStep),
|
|
params->width, params->height);
|
|
}
|
|
|
|
/**
|
|
* Animated Material Type 0:
|
|
* Scrolls a single layer texture using the provided `AnimatedMatTexScrollParams`.
|
|
*/
|
|
void AnimatedMat_DrawTexScroll(PlayState* play, s32 segment, void* params) {
|
|
AnimatedMatTexScrollParams* texScrollParams = (AnimatedMatTexScrollParams*)params;
|
|
Gfx* texScrollDList = AnimatedMat_TexScroll(play, texScrollParams);
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
|
|
|
if (sMatAnimFlags & 1) {
|
|
gSPSegment(POLY_OPA_DISP++, segment, texScrollDList);
|
|
}
|
|
|
|
if (sMatAnimFlags & 2) {
|
|
gSPSegment(POLY_XLU_DISP++, segment, texScrollDList);
|
|
}
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
|
}
|
|
|
|
/**
|
|
* Returns a pointer to a two layer texture scroll displaylist.
|
|
*/
|
|
Gfx* AnimatedMat_TwoLayerTexScroll(PlayState* play, AnimatedMatTexScrollParams* params) {
|
|
return Gfx_TwoTexScroll(play->state.gfxCtx, 0, params[0].xStep * sMatAnimStep, -(params[0].yStep * sMatAnimStep),
|
|
params[0].width, params[0].height, 1, params[1].xStep * sMatAnimStep,
|
|
-(params[1].yStep * sMatAnimStep), params[1].width, params[1].height);
|
|
}
|
|
|
|
/**
|
|
* Animated Material Type 1:
|
|
* Scrolls a two layer texture using the provided `AnimatedMatTexScrollParams`.
|
|
*/
|
|
void AnimatedMat_DrawTwoTexScroll(PlayState* play, s32 segment, void* params) {
|
|
AnimatedMatTexScrollParams* texScrollParams = (AnimatedMatTexScrollParams*)params;
|
|
Gfx* texScrollDList = AnimatedMat_TwoLayerTexScroll(play, texScrollParams);
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
|
|
|
if (sMatAnimFlags & 1) {
|
|
gSPSegment(POLY_OPA_DISP++, segment, texScrollDList);
|
|
}
|
|
|
|
if (sMatAnimFlags & 2) {
|
|
gSPSegment(POLY_XLU_DISP++, segment, texScrollDList);
|
|
}
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
|
}
|
|
|
|
/**
|
|
* Generates a displaylist that sets the prim and env color, and stores it in the provided segment ID.
|
|
*/
|
|
void AnimatedMat_SetColor(PlayState* play, s32 segment, F3DPrimColor* primColorResult, F3DEnvColor* envColor) {
|
|
Gfx* gfx = GRAPH_ALLOC(play->state.gfxCtx, 3 * sizeof(Gfx));
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
|
|
|
// clang-format off
|
|
if (sMatAnimFlags & 1) { gSPSegment(POLY_OPA_DISP++, segment, gfx); }
|
|
if (sMatAnimFlags & 2) { gSPSegment(POLY_XLU_DISP++, segment, gfx); }
|
|
// clang-format on
|
|
|
|
gDPSetPrimColor(gfx++, 0, primColorResult->lodFrac, primColorResult->r, primColorResult->g, primColorResult->b,
|
|
(u8)(primColorResult->a * sMatAnimAlphaRatio));
|
|
|
|
if (envColor != NULL) {
|
|
gDPSetEnvColor(gfx++, envColor->r, envColor->g, envColor->b, envColor->a);
|
|
}
|
|
|
|
gSPEndDisplayList(gfx++);
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
|
}
|
|
|
|
/**
|
|
* Animated Material Type 2:
|
|
* Color key frame animation without linear interpolation.
|
|
*/
|
|
void AnimatedMat_DrawColor(PlayState* play, s32 segment, void* params) {
|
|
AnimatedMatColorParams* colorAnimParams = (AnimatedMatColorParams*)params;
|
|
F3DPrimColor* primColor = Lib_SegmentedToVirtual(colorAnimParams->primColors);
|
|
F3DEnvColor* envColor;
|
|
s32 curFrame = sMatAnimStep % colorAnimParams->keyFrameLength;
|
|
|
|
primColor += curFrame;
|
|
envColor = (colorAnimParams->envColors != NULL)
|
|
? (F3DEnvColor*)Lib_SegmentedToVirtual(colorAnimParams->envColors) + curFrame
|
|
: NULL;
|
|
|
|
AnimatedMat_SetColor(play, segment, primColor, envColor);
|
|
}
|
|
|
|
/**
|
|
* Linear Interpolation
|
|
*/
|
|
s32 AnimatedMat_Lerp(s32 min, s32 max, f32 norm) {
|
|
return (s32)((max - min) * norm) + min;
|
|
}
|
|
|
|
/**
|
|
* Animated Material Type 3:
|
|
* Color key frame animation with linear interpolation.
|
|
*/
|
|
void AnimatedMat_DrawColorLerp(PlayState* play, s32 segment, void* params) {
|
|
AnimatedMatColorParams* colorAnimParams = (AnimatedMatColorParams*)params;
|
|
F3DPrimColor* primColorMax = Lib_SegmentedToVirtual(colorAnimParams->primColors);
|
|
F3DEnvColor* envColorMax;
|
|
u16* keyFrames = Lib_SegmentedToVirtual(colorAnimParams->keyFrames);
|
|
s32 curFrame = sMatAnimStep % colorAnimParams->keyFrameLength;
|
|
s32 endFrame;
|
|
s32 relativeFrame; // relative to the start frame
|
|
s32 startFrame;
|
|
f32 norm;
|
|
F3DPrimColor* primColorMin;
|
|
F3DPrimColor primColorResult;
|
|
F3DEnvColor* envColorMin;
|
|
F3DEnvColor envColorResult;
|
|
s32 i;
|
|
|
|
keyFrames++;
|
|
i = 1;
|
|
|
|
while (colorAnimParams->keyFrameCount > i) {
|
|
if (curFrame < *keyFrames) {
|
|
break;
|
|
}
|
|
i++;
|
|
keyFrames++;
|
|
}
|
|
|
|
startFrame = keyFrames[-1];
|
|
endFrame = keyFrames[0] - startFrame;
|
|
relativeFrame = curFrame - startFrame;
|
|
norm = (f32)relativeFrame / (f32)endFrame;
|
|
|
|
primColorMax += i;
|
|
primColorMin = primColorMax - 1;
|
|
primColorResult.r = AnimatedMat_Lerp(primColorMin->r, primColorMax->r, norm);
|
|
primColorResult.g = AnimatedMat_Lerp(primColorMin->g, primColorMax->g, norm);
|
|
primColorResult.b = AnimatedMat_Lerp(primColorMin->b, primColorMax->b, norm);
|
|
primColorResult.a = AnimatedMat_Lerp(primColorMin->a, primColorMax->a, norm);
|
|
primColorResult.lodFrac = AnimatedMat_Lerp(primColorMin->lodFrac, primColorMax->lodFrac, norm);
|
|
|
|
if (colorAnimParams->envColors) {
|
|
envColorMax = Lib_SegmentedToVirtual(colorAnimParams->envColors);
|
|
envColorMax += i;
|
|
envColorMin = envColorMax - 1;
|
|
envColorResult.r = AnimatedMat_Lerp(envColorMin->r, envColorMax->r, norm);
|
|
envColorResult.g = AnimatedMat_Lerp(envColorMin->g, envColorMax->g, norm);
|
|
envColorResult.b = AnimatedMat_Lerp(envColorMin->b, envColorMax->b, norm);
|
|
envColorResult.a = AnimatedMat_Lerp(envColorMin->a, envColorMax->a, norm);
|
|
} else {
|
|
envColorMax = NULL;
|
|
}
|
|
|
|
AnimatedMat_SetColor(play, segment, &primColorResult, (envColorMax != NULL) ? &envColorResult : NULL);
|
|
}
|
|
|
|
/**
|
|
* Lagrange interpolation
|
|
*/
|
|
f32 Scene_LagrangeInterp(s32 n, f32 x[], f32 fx[], f32 xp) {
|
|
f32 weights[50];
|
|
f32 xVal;
|
|
f32 m;
|
|
f32 intp;
|
|
f32* xPtr1;
|
|
f32* fxPtr;
|
|
f32* weightsPtr;
|
|
f32* xPtr2;
|
|
s32 i;
|
|
s32 j;
|
|
|
|
for (i = 0, xPtr1 = x, fxPtr = fx, weightsPtr = weights; i < n; i++) {
|
|
for (xVal = *xPtr1, m = 1.0f, j = 0, xPtr2 = x; j < n; j++) {
|
|
if (j != i) {
|
|
m *= xVal - (*xPtr2);
|
|
}
|
|
xPtr2++;
|
|
}
|
|
|
|
xPtr1++;
|
|
*weightsPtr = (*fxPtr) / m;
|
|
fxPtr++;
|
|
weightsPtr++;
|
|
}
|
|
|
|
for (intp = 0.0f, i = 0, weightsPtr = weights; i < n; i++) {
|
|
for (m = 1.0f, j = 0, xPtr2 = x; j < n; j++) {
|
|
if (j != i) {
|
|
m *= xp - (*xPtr2);
|
|
}
|
|
xPtr2++;
|
|
}
|
|
|
|
intp += (*weightsPtr) * m;
|
|
weightsPtr++;
|
|
}
|
|
|
|
return intp;
|
|
}
|
|
|
|
/**
|
|
* Lagrange interpolation specifically for colors
|
|
*/
|
|
u8 Scene_LagrangeInterpColor(s32 n, f32 x[], f32 fx[], f32 xp) {
|
|
s32 intp = Scene_LagrangeInterp(n, x, fx, xp);
|
|
|
|
// Clamp between 0 and 255 to ensure the color value does not overflow in either direction
|
|
return CLAMP(intp, 0, 255);
|
|
}
|
|
|
|
/**
|
|
* Animated Material Type 4:
|
|
* Color key frame animation with non-linear interpolation.
|
|
*/
|
|
void AnimatedMat_DrawColorNonLinearInterp(PlayState* play, s32 segment, void* params) {
|
|
AnimatedMatColorParams* colorAnimParams = (AnimatedMatColorParams*)params;
|
|
F3DPrimColor* primColorCur = Lib_SegmentedToVirtual(colorAnimParams->primColors);
|
|
F3DEnvColor* envColorCur = Lib_SegmentedToVirtual(colorAnimParams->envColors);
|
|
u16* keyFrames = Lib_SegmentedToVirtual(colorAnimParams->keyFrames);
|
|
f32 curFrame = sMatAnimStep % colorAnimParams->keyFrameLength;
|
|
F3DPrimColor primColorResult;
|
|
F3DEnvColor envColorResult;
|
|
f32 x[50];
|
|
f32 fxPrimR[50];
|
|
f32 fxPrimG[50];
|
|
f32 fxPrimB[50];
|
|
f32 fxPrimA[50];
|
|
f32 fxPrimLodFrac[50];
|
|
f32 fxEnvR[50];
|
|
f32 fxEnvG[50];
|
|
f32 fxEnvB[50];
|
|
f32 fxEnvA[50];
|
|
f32* xPtr = x;
|
|
f32* fxPrimRPtr = fxPrimR;
|
|
f32* fxPrimGPtr = fxPrimG;
|
|
f32* fxPrimBPtr = fxPrimB;
|
|
f32* fxPrimAPtr = fxPrimA;
|
|
f32* fxPrimLodFracPtr = fxPrimLodFrac;
|
|
f32* fxEnvRPtr = fxEnvR;
|
|
f32* fxEnvGPtr = fxEnvG;
|
|
f32* fxEnvBPtr = fxEnvB;
|
|
f32* fxEnvAPtr = fxEnvA;
|
|
s32 i;
|
|
|
|
for (i = 0; i < colorAnimParams->keyFrameCount; i++) {
|
|
*xPtr = *keyFrames;
|
|
*fxPrimRPtr = primColorCur->r;
|
|
*fxPrimGPtr = primColorCur->g;
|
|
*fxPrimBPtr = primColorCur->b;
|
|
*fxPrimAPtr = primColorCur->a;
|
|
*fxPrimLodFracPtr = primColorCur->lodFrac;
|
|
|
|
primColorCur++;
|
|
fxPrimRPtr++;
|
|
fxPrimGPtr++;
|
|
fxPrimBPtr++;
|
|
fxPrimAPtr++;
|
|
fxPrimLodFracPtr++;
|
|
|
|
if (envColorCur != NULL) {
|
|
*fxEnvRPtr = envColorCur->r;
|
|
*fxEnvGPtr = envColorCur->g;
|
|
*fxEnvBPtr = envColorCur->b;
|
|
*fxEnvAPtr = envColorCur->a;
|
|
|
|
envColorCur++;
|
|
fxEnvRPtr++;
|
|
fxEnvGPtr++;
|
|
fxEnvBPtr++;
|
|
fxEnvAPtr++;
|
|
}
|
|
|
|
keyFrames++;
|
|
xPtr++;
|
|
}
|
|
|
|
primColorResult.r = Scene_LagrangeInterpColor(colorAnimParams->keyFrameCount, x, fxPrimR, curFrame);
|
|
primColorResult.g = Scene_LagrangeInterpColor(colorAnimParams->keyFrameCount, x, fxPrimG, curFrame);
|
|
primColorResult.b = Scene_LagrangeInterpColor(colorAnimParams->keyFrameCount, x, fxPrimB, curFrame);
|
|
primColorResult.a = Scene_LagrangeInterpColor(colorAnimParams->keyFrameCount, x, fxPrimA, curFrame);
|
|
primColorResult.lodFrac = Scene_LagrangeInterpColor(colorAnimParams->keyFrameCount, x, fxPrimLodFrac, curFrame);
|
|
|
|
if (colorAnimParams->envColors != NULL) {
|
|
envColorCur = Lib_SegmentedToVirtual(colorAnimParams->envColors);
|
|
envColorResult.r = Scene_LagrangeInterpColor(colorAnimParams->keyFrameCount, x, fxEnvR, curFrame);
|
|
envColorResult.g = Scene_LagrangeInterpColor(colorAnimParams->keyFrameCount, x, fxEnvG, curFrame);
|
|
envColorResult.b = Scene_LagrangeInterpColor(colorAnimParams->keyFrameCount, x, fxEnvB, curFrame);
|
|
envColorResult.a = Scene_LagrangeInterpColor(colorAnimParams->keyFrameCount, x, fxEnvA, curFrame);
|
|
} else {
|
|
envColorCur = NULL;
|
|
}
|
|
|
|
AnimatedMat_SetColor(play, segment, &primColorResult, (envColorCur != NULL) ? &envColorResult : NULL);
|
|
}
|
|
|
|
/**
|
|
* Animated Material Type 5:
|
|
* Cycles between a list of textures (imagine like a GIF)
|
|
*/
|
|
void AnimatedMat_DrawTexCycle(PlayState* play, s32 segment, void* params) {
|
|
AnimatedMatTexCycleParams* texAnimParams = params;
|
|
TexturePtr* texList = Lib_SegmentedToVirtual(texAnimParams->textureList);
|
|
u8* texId = Lib_SegmentedToVirtual(texAnimParams->textureIndexList);
|
|
s32 curFrame = sMatAnimStep % texAnimParams->keyFrameLength;
|
|
TexturePtr tex = Lib_SegmentedToVirtual(texList[texId[curFrame]]);
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
|
|
|
if (sMatAnimFlags & 1) {
|
|
gSPSegment(POLY_OPA_DISP++, segment, tex);
|
|
}
|
|
|
|
if (sMatAnimFlags & 2) {
|
|
gSPSegment(POLY_XLU_DISP++, segment, tex);
|
|
}
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
|
}
|
|
|
|
/**
|
|
* This is the main function that handles the animated material system.
|
|
* There are six different animated material types, which should be set in the provided `AnimatedMaterial`.
|
|
*/
|
|
void AnimatedMat_DrawMain(PlayState* play, AnimatedMaterial* matAnim, f32 alphaRatio, u32 step, u32 flags) {
|
|
static void (*sMatAnimDrawHandlers[])(PlayState*, s32 segment, void* params) = {
|
|
AnimatedMat_DrawTexScroll, AnimatedMat_DrawTwoTexScroll, AnimatedMat_DrawColor,
|
|
AnimatedMat_DrawColorLerp, AnimatedMat_DrawColorNonLinearInterp, AnimatedMat_DrawTexCycle,
|
|
};
|
|
s32 segmentAbs;
|
|
s32 segment;
|
|
|
|
sMatAnimAlphaRatio = alphaRatio;
|
|
sMatAnimStep = step;
|
|
sMatAnimFlags = flags;
|
|
|
|
if ((matAnim != NULL) && (matAnim->segment != 0)) {
|
|
do {
|
|
segment = matAnim->segment;
|
|
segmentAbs = ABS_ALT(segment) + 7;
|
|
sMatAnimDrawHandlers[matAnim->type](play, segmentAbs, Lib_SegmentedToVirtual(matAnim->params));
|
|
matAnim++;
|
|
} while (segment >= 0);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Draws an animated material to both OPA and XLU buffers.
|
|
*/
|
|
void AnimatedMat_Draw(PlayState* play, AnimatedMaterial* matAnim) {
|
|
AnimatedMat_DrawMain(play, matAnim, 1, play->gameplayFrames, 3);
|
|
}
|
|
|
|
/**
|
|
* Draws an animated material to only the OPA buffer.
|
|
*/
|
|
void AnimatedMat_DrawOpa(PlayState* play, AnimatedMaterial* matAnim) {
|
|
AnimatedMat_DrawMain(play, matAnim, 1, play->gameplayFrames, 1);
|
|
}
|
|
|
|
/**
|
|
* Draws an animated material to only the XLU buffer.
|
|
*/
|
|
void AnimatedMat_DrawXlu(PlayState* play, AnimatedMaterial* matAnim) {
|
|
AnimatedMat_DrawMain(play, matAnim, 1, play->gameplayFrames, 2);
|
|
}
|
|
|
|
/**
|
|
* Draws an animated material with an alpha ratio (0.0 - 1.0) both OPA and XLU buffers.
|
|
*/
|
|
void AnimatedMat_DrawAlpha(PlayState* play, AnimatedMaterial* matAnim, f32 alphaRatio) {
|
|
AnimatedMat_DrawMain(play, matAnim, alphaRatio, play->gameplayFrames, 3);
|
|
}
|
|
|
|
/**
|
|
* Draws an animated material with an alpha ratio (0.0 - 1.0) to only the OPA buffer.
|
|
*/
|
|
void AnimatedMat_DrawAlphaOpa(PlayState* play, AnimatedMaterial* matAnim, f32 alphaRatio) {
|
|
AnimatedMat_DrawMain(play, matAnim, alphaRatio, play->gameplayFrames, 1);
|
|
}
|
|
|
|
/**
|
|
* Draws an animated material with an alpha ratio (0.0 - 1.0) to only the XLU buffer.
|
|
*/
|
|
void AnimatedMat_DrawAlphaXlu(PlayState* play, AnimatedMaterial* matAnim, f32 alphaRatio) {
|
|
AnimatedMat_DrawMain(play, matAnim, alphaRatio, play->gameplayFrames, 2);
|
|
}
|
|
|
|
/**
|
|
* Draws an animated material with a step to both the OPA and XLU buffers.
|
|
*/
|
|
void AnimatedMat_DrawStep(PlayState* play, AnimatedMaterial* matAnim, u32 step) {
|
|
AnimatedMat_DrawMain(play, matAnim, 1, step, 3);
|
|
}
|
|
|
|
/**
|
|
* Draws an animated material with a step to only the OPA buffer.
|
|
*/
|
|
void AnimatedMat_DrawStepOpa(PlayState* play, AnimatedMaterial* matAnim, u32 step) {
|
|
AnimatedMat_DrawMain(play, matAnim, 1, step, 1);
|
|
}
|
|
|
|
/**
|
|
* Draws an animated material with a step to only the XLU buffer.
|
|
*/
|
|
void AnimatedMat_DrawStepXlu(PlayState* play, AnimatedMaterial* matAnim, u32 step) {
|
|
AnimatedMat_DrawMain(play, matAnim, 1, step, 2);
|
|
}
|
|
|
|
/**
|
|
* Draws an animated material with an alpha ratio (0.0 - 1.0) and a step to both the OPA and XLU buffers.
|
|
*/
|
|
void AnimatedMat_DrawAlphaStep(PlayState* play, AnimatedMaterial* matAnim, f32 alphaRatio, u32 step) {
|
|
AnimatedMat_DrawMain(play, matAnim, alphaRatio, step, 3);
|
|
}
|
|
|
|
/**
|
|
* Draws an animated material with an alpha ratio (0.0 - 1.0) and a step to only the OPA buffer.
|
|
*/
|
|
void AnimatedMat_DrawAlphaStepOpa(PlayState* play, AnimatedMaterial* matAnim, f32 alphaRatio, u32 step) {
|
|
AnimatedMat_DrawMain(play, matAnim, alphaRatio, step, 1);
|
|
}
|
|
|
|
/**
|
|
* Draws an animated material with an alpha ratio (0.0 - 1.0) and a step to only the XLU buffer.
|
|
*/
|
|
void AnimatedMat_DrawAlphaStepXlu(PlayState* play, AnimatedMaterial* matAnim, f32 alphaRatio, u32 step) {
|
|
AnimatedMat_DrawMain(play, matAnim, alphaRatio, step, 2);
|
|
}
|
|
|
|
/**
|
|
* SceneTableEntry Draw Config 1:
|
|
* Allows the usage of the animated material system in scenes.
|
|
*/
|
|
void Scene_DrawConfigMatAnim(PlayState* play) {
|
|
AnimatedMat_Draw(play, play->sceneMaterialAnims);
|
|
}
|
|
|
|
/**
|
|
* SceneTableEntry Draw Config 3:
|
|
* This config is unused, although it is identical to the grotto scene config from Ocarina of Time.
|
|
*/
|
|
void Scene_DrawConfig3(PlayState* play) {
|
|
u32 frames;
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
|
|
|
frames = play->gameplayFrames;
|
|
|
|
gSPSegment(POLY_XLU_DISP++, 0x08, Gfx_TexScroll(play->state.gfxCtx, 0, (frames * 1) % 64, 256, 16));
|
|
|
|
gSPSegment(POLY_XLU_DISP++, 0x09,
|
|
Gfx_TwoTexScroll(play->state.gfxCtx, 0, 127 - (frames % 128), (frames * 1) % 128, 32, 32, 1,
|
|
frames % 128, (frames * 1) % 128, 32, 32));
|
|
|
|
gSPSegment(POLY_OPA_DISP++, 0x0A,
|
|
Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 32, 32, 1, 0, 127 - (frames * 1) % 128, 32, 32));
|
|
|
|
gSPSegment(POLY_OPA_DISP++, 0x0B, Gfx_TexScroll(play->state.gfxCtx, 0, (frames * 1) % 128, 32, 32));
|
|
|
|
gSPSegment(
|
|
POLY_XLU_DISP++, 0x0C,
|
|
Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, (frames * 50) % 2048, 8, 512, 1, 0, (frames * 60) % 2048, 8, 512));
|
|
|
|
gSPSegment(POLY_OPA_DISP++, 0x0D,
|
|
Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 32, 64, 1, 0, (frames * 1) % 128, 32, 32));
|
|
|
|
gDPPipeSync(POLY_XLU_DISP++);
|
|
gDPSetEnvColor(POLY_XLU_DISP++, 128, 128, 128, 128);
|
|
|
|
gDPPipeSync(POLY_OPA_DISP++);
|
|
gDPSetEnvColor(POLY_OPA_DISP++, 128, 128, 128, 128);
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
|
}
|
|
|
|
/**
|
|
* SceneTableEntry Draw Config 4:
|
|
* This config is unused and just has a single TwoTexScroll intended for two 32x32 textures (likely two water textures).
|
|
* It is identical to the Castle Courtyard and Sacred Forest Meadow scene config from Ocarina of Time.
|
|
*/
|
|
void Scene_DrawConfig4(PlayState* play) {
|
|
u32 frames;
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
|
|
|
frames = play->gameplayFrames;
|
|
|
|
gSPSegment(POLY_XLU_DISP++, 0x08,
|
|
Gfx_TwoTexScroll(play->state.gfxCtx, 0, 127 - frames % 128, (frames * 1) % 128, 32, 32, 1, frames % 128,
|
|
(frames * 1) % 128, 32, 32));
|
|
|
|
gDPPipeSync(POLY_OPA_DISP++);
|
|
gDPSetEnvColor(POLY_OPA_DISP++, 128, 128, 128, 128);
|
|
|
|
gDPPipeSync(POLY_XLU_DISP++);
|
|
gDPSetEnvColor(POLY_XLU_DISP++, 128, 128, 128, 128);
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
|
}
|
|
|
|
/**
|
|
* SceneTableEntry Draw Config 2:
|
|
* Has no effect, and is only used in SPOT00 (cutscene scene).
|
|
*/
|
|
void Scene_DrawConfigDoNothing(PlayState* play) {
|
|
}
|
|
|
|
/**
|
|
* Stores a displaylist in the provided segment ID that sets a render mode from the index provided.
|
|
*/
|
|
void Scene_SetRenderModeXlu(PlayState* play, s32 index, u32 flags) {
|
|
static Gfx sRenderModeSetNoneDL[] = {
|
|
gsSPEndDisplayList(),
|
|
// These instructions will never get executed
|
|
gsSPEndDisplayList(),
|
|
gsSPEndDisplayList(),
|
|
gsSPEndDisplayList(),
|
|
};
|
|
static Gfx sRenderModeSetXluSingleCycleDL[] = {
|
|
gsDPSetRenderMode(AA_EN | Z_CMP | IM_RD | CLR_ON_CVG | CVG_DST_WRAP | ZMODE_XLU | FORCE_BL |
|
|
GBL_c1(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1),
|
|
G_RM_AA_ZB_XLU_SURF2),
|
|
gsSPEndDisplayList(),
|
|
// These instructions will never get executed
|
|
gsDPSetRenderMode(AA_EN | Z_CMP | IM_RD | CLR_ON_CVG | CVG_DST_WRAP | ZMODE_XLU | FORCE_BL |
|
|
GBL_c1(G_BL_CLR_FOG, G_BL_A_SHADE, G_BL_CLR_IN, G_BL_1MA),
|
|
G_RM_AA_ZB_XLU_SURF2),
|
|
gsSPEndDisplayList(),
|
|
};
|
|
static Gfx sRenderModeSetXluTwoCycleDL[] = {
|
|
gsDPSetRenderMode(AA_EN | Z_CMP | Z_UPD | IM_RD | CLR_ON_CVG | CVG_DST_WRAP | ZMODE_XLU | FORCE_BL |
|
|
GBL_c1(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1),
|
|
AA_EN | Z_CMP | Z_UPD | IM_RD | CLR_ON_CVG | CVG_DST_WRAP | ZMODE_XLU | FORCE_BL |
|
|
GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)),
|
|
gsSPEndDisplayList(),
|
|
// These instructions will never get executed
|
|
gsDPSetRenderMode(AA_EN | Z_CMP | Z_UPD | IM_RD | CLR_ON_CVG | CVG_DST_WRAP | ZMODE_XLU | FORCE_BL |
|
|
GBL_c1(G_BL_CLR_FOG, G_BL_A_SHADE, G_BL_CLR_IN, G_BL_1MA),
|
|
AA_EN | Z_CMP | Z_UPD | IM_RD | CLR_ON_CVG | CVG_DST_WRAP | ZMODE_XLU | FORCE_BL |
|
|
GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)),
|
|
gsSPEndDisplayList(),
|
|
};
|
|
static Gfx* sDLists[] = {
|
|
sRenderModeSetNoneDL,
|
|
sRenderModeSetXluSingleCycleDL,
|
|
sRenderModeSetXluTwoCycleDL,
|
|
};
|
|
Gfx* dList = sDLists[index];
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
|
|
|
if (flags & 1) {
|
|
gSPSegment(POLY_OPA_DISP++, 0x0C, dList);
|
|
}
|
|
|
|
if (flags & 2) {
|
|
gSPSegment(POLY_XLU_DISP++, 0x0C, dList);
|
|
}
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
|
}
|
|
|
|
/**
|
|
* Although this function is unused, it will store a displaylist in the provided segment ID that sets the culling mode
|
|
* from the index provided.
|
|
*/
|
|
void Scene_SetCullFlag(PlayState* play, s32 index, u32 flags) {
|
|
static Gfx sSetBackCullDL[] = {
|
|
gsSPSetGeometryMode(G_CULL_BACK),
|
|
gsSPEndDisplayList(),
|
|
};
|
|
static Gfx sSetFrontCullDL[] = {
|
|
gsSPSetGeometryMode(G_CULL_FRONT),
|
|
gsSPEndDisplayList(),
|
|
};
|
|
static Gfx* sDLists[] = {
|
|
sSetBackCullDL,
|
|
sSetFrontCullDL,
|
|
};
|
|
Gfx* dList = sDLists[index];
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
|
|
|
if (flags & 1) {
|
|
gSPSegment(POLY_OPA_DISP++, 0x0C, dList);
|
|
}
|
|
|
|
if (flags & 2) {
|
|
gSPSegment(POLY_XLU_DISP++, 0x0C, dList);
|
|
}
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
|
}
|
|
|
|
/**
|
|
* SceneTableEntry Draw Config 5:
|
|
* This config is unused, and its purpose is unknown.
|
|
*/
|
|
void Scene_DrawConfig5(PlayState* play) {
|
|
u32 dListIndex;
|
|
u32 alpha;
|
|
|
|
if (play->roomCtx.unk7A[0] != 0) {
|
|
dListIndex = 1;
|
|
alpha = play->roomCtx.unk7A[1];
|
|
} else {
|
|
dListIndex = 0;
|
|
alpha = 255;
|
|
}
|
|
|
|
if (alpha == 0) {
|
|
play->roomCtx.unk78 = 0;
|
|
} else {
|
|
OPEN_DISPS(play->state.gfxCtx);
|
|
|
|
play->roomCtx.unk78 = 1;
|
|
AnimatedMat_Draw(play, play->sceneMaterialAnims);
|
|
Scene_SetRenderModeXlu(play, dListIndex, 3);
|
|
gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 255, alpha);
|
|
gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, alpha);
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* SceneTableEntry Draw Config 7:
|
|
* This is a special draw config for Sakon's Hideout, as well as the Music Box House. Its step value is set manually
|
|
* rather than always animating like `Scene_DrawConfigMatAnim`.
|
|
*/
|
|
void Scene_DrawConfigMatAnimManualStep(PlayState* play) {
|
|
AnimatedMat_DrawStep(play, play->sceneMaterialAnims, play->roomCtx.unk7A[0]);
|
|
}
|
|
|
|
/**
|
|
* SceneTableEntry Draw Config 6:
|
|
* This is a special draw config for Great Bay Temple, which handles both material animations as well as setting the lod
|
|
* fraction to a certain value when certain flags are set, which are likely used for the pipes whenever they are
|
|
* activated.
|
|
*/
|
|
void Scene_DrawConfigGreatBayTemple(PlayState* play) {
|
|
static Gfx sGreatBayTempleColorSetDL[] = {
|
|
gsDPSetPrimColor(0, 255, 255, 255, 255, 255),
|
|
gsSPEndDisplayList(),
|
|
};
|
|
s32 lodFrac;
|
|
s32 i;
|
|
Gfx* gfx;
|
|
Gfx* gfxHead;
|
|
|
|
if (Flags_GetSwitch(play, 0x33) && Flags_GetSwitch(play, 0x34) && Flags_GetSwitch(play, 0x35) &&
|
|
Flags_GetSwitch(play, 0x36)) {
|
|
BgCheck_SetContextFlags(&play->colCtx, BGCHECK_FLAG_REVERSE_CONVEYOR_FLOW);
|
|
} else {
|
|
BgCheck_UnsetContextFlags(&play->colCtx, BGCHECK_FLAG_REVERSE_CONVEYOR_FLOW);
|
|
}
|
|
|
|
gfxHead = GRAPH_ALLOC(play->state.gfxCtx, 18 * sizeof(Gfx));
|
|
|
|
AnimatedMat_Draw(play, play->sceneMaterialAnims);
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
|
|
|
for (gfx = gfxHead, i = 0; i < 9; i++, gfx += 2) {
|
|
lodFrac = 0;
|
|
|
|
bcopy(sGreatBayTempleColorSetDL, gfx, sizeof(sGreatBayTempleColorSetDL));
|
|
|
|
switch (i) {
|
|
case 0:
|
|
if (Flags_GetSwitch(play, 0x33) && Flags_GetSwitch(play, 0x34) && Flags_GetSwitch(play, 0x35) &&
|
|
Flags_GetSwitch(play, 0x36)) {
|
|
lodFrac = 255;
|
|
}
|
|
break;
|
|
case 1:
|
|
if (Flags_GetSwitch(play, 0x37)) {
|
|
lodFrac = 68;
|
|
}
|
|
break;
|
|
case 2:
|
|
if (Flags_GetSwitch(play, 0x37) && Flags_GetSwitch(play, 0x38)) {
|
|
lodFrac = 68;
|
|
}
|
|
break;
|
|
case 3:
|
|
if (Flags_GetSwitch(play, 0x37) && Flags_GetSwitch(play, 0x38) && Flags_GetSwitch(play, 0x39)) {
|
|
lodFrac = 68;
|
|
}
|
|
break;
|
|
case 4:
|
|
if (!(Flags_GetSwitch(play, 0x33))) {
|
|
lodFrac = 68;
|
|
}
|
|
break;
|
|
case 5:
|
|
if (Flags_GetSwitch(play, 0x34)) {
|
|
lodFrac = 68;
|
|
}
|
|
break;
|
|
case 6:
|
|
if (Flags_GetSwitch(play, 0x34) && Flags_GetSwitch(play, 0x35)) {
|
|
lodFrac = 68;
|
|
}
|
|
break;
|
|
case 7:
|
|
if (Flags_GetSwitch(play, 0x34) && Flags_GetSwitch(play, 0x35) && Flags_GetSwitch(play, 0x36)) {
|
|
lodFrac = 68;
|
|
}
|
|
break;
|
|
case 8:
|
|
if (Flags_GetSwitch(play, 0x3A)) {
|
|
lodFrac = 68;
|
|
}
|
|
break;
|
|
}
|
|
|
|
gDPSetPrimColor(gfx, 0, lodFrac, 255, 255, 255, 255);
|
|
}
|
|
|
|
gSPSegment(POLY_OPA_DISP++, 0x06, gfxHead);
|
|
gSPSegment(POLY_XLU_DISP++, 0x06, gfxHead);
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
|
}
|