1
0
Fork 0
mirror of https://github.com/zeldaret/oot.git synced 2024-11-25 09:45:02 +00:00

Documentation for skybox drawing (#1515)

This commit is contained in:
Tharo 2023-07-04 03:30:53 +01:00 committed by GitHub
parent d3c6836df7
commit 100576edc9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 425 additions and 319 deletions

View file

@ -41,14 +41,20 @@ typedef enum {
/* 0x27 */ SKYBOX_UNSET_27 = 39
} SkyboxId;
typedef enum {
/* 0 */ SKYBOX_DRAW_128, // 128x128 top/bottom faces, 128x64 side faces
/* 1 */ SKYBOX_DRAW_256_4FACE, // 256x256 all side faces with per-face palettes
/* 2 */ SKYBOX_DRAW_256_3FACE // 256x256 3/4 side faces with per-face palettes
} SkyboxDrawType;
typedef struct SkyboxContext {
/* 0x000 */ char unk_00[0x128];
/* 0x128 */ void* staticSegments[2];
/* 0x130 */ u16 (*palettes)[256];
/* 0x134 */ Gfx (*dListBuf)[150];
/* 0x138 */ Gfx* unk_138;
/* 0x138 */ Gfx* gfx;
/* 0x13C */ Vtx* roomVtx;
/* 0x140 */ s16 unk_140;
/* 0x140 */ s16 drawType;
/* 0x144 */ Vec3f rot;
/* 0x150 */ char unk_150[0x10];
} SkyboxContext; // size = 0x160

View file

@ -1151,7 +1151,7 @@ void Play_Draw(PlayState* this) {
Environment_UpdateSkybox(this->skyboxId, &this->envCtx, &this->skyboxCtx);
Skybox_Draw(&this->skyboxCtx, gfxCtx, this->skyboxId, this->envCtx.skyboxBlend,
this->view.eye.x, this->view.eye.y, this->view.eye.z);
} else if (this->skyboxCtx.unk_140 == 0) {
} else if (this->skyboxCtx.drawType == SKYBOX_DRAW_128) {
Skybox_Draw(&this->skyboxCtx, gfxCtx, this->skyboxId, 0, this->view.eye.x, this->view.eye.y,
this->view.eye.z);
}
@ -1193,7 +1193,8 @@ void Play_Draw(PlayState* this) {
}
if ((R_HREG_MODE != HREG_MODE_PLAY) || R_PLAY_DRAW_SKYBOX) {
if ((this->skyboxCtx.unk_140 != 0) && (GET_ACTIVE_CAM(this)->setting != CAM_SET_PREREND_FIXED)) {
if ((this->skyboxCtx.drawType != SKYBOX_DRAW_128) &&
(GET_ACTIVE_CAM(this)->setting != CAM_SET_PREREND_FIXED)) {
Vec3f quakeOffset;
Camera_GetQuakeOffset(&quakeOffset, GET_ACTIVE_CAM(this));

View file

@ -2,371 +2,452 @@
#include "terminal.h"
#include "z64environment.h"
u32 D_8012AC90[4] = {
0x00000000,
0x00010000,
0x00020000,
0x00030000,
};
u16 D_8012ACA0[2][0x20] = {
{ 0x00, 0x02, 0x0A, 0x0C, 0x02, 0x04, 0x0C, 0x0E, 0x0A, 0x0C, 0x14, 0x16, 0x0C, 0x0E, 0x16, 0x18,
0x01, 0x03, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0B, 0x0D, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x15, 0x17 },
{ 0x14, 0x16, 0x1E, 0x20, 0x16, 0x18, 0x20, 0x22, 0x1E, 0x20, 0x28, 0x2A, 0x20, 0x22, 0x2A, 0x2C,
0x15, 0x17, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1F, 0x21, 0x23, 0x24, 0x25, 0x26, 0x27, 0x29, 0x2B },
};
s16 D_8012AD20[5] = {
0x0000, 0x0FC0, 0x1F80, 0x2F40, 0x3F00,
};
s16 D_8012AD2C[9] = {
0x0000, 0x07C0, 0x0F80, 0x1740, 0x1F00, 0x26C0, 0x2E80, 0x3640, 0x3E00,
};
s16 D_8012AD40[0x40] = {
0x00, 0x10, 0x13, 0x12, 0x10, 0x01, 0x14, 0x13, 0x01, 0x11, 0x15, 0x14, 0x11, 0x05, 0x16, 0x15,
0x12, 0x13, 0x17, 0x02, 0x13, 0x14, 0x03, 0x17, 0x14, 0x15, 0x18, 0x03, 0x15, 0x16, 0x07, 0x18,
0x02, 0x17, 0x1A, 0x19, 0x17, 0x03, 0x1B, 0x1A, 0x03, 0x18, 0x1C, 0x1B, 0x18, 0x07, 0x1D, 0x1C,
0x19, 0x1A, 0x1E, 0x0A, 0x1A, 0x1B, 0x0B, 0x1E, 0x1B, 0x1C, 0x1F, 0x0B, 0x1C, 0x1D, 0x0F, 0x1F,
};
u32 D_8012ADC0[6] = {
0x00000000, 0x00002000, 0x00004000, 0x00006000, 0x00008000, 0x0000C000,
};
u16 D_8012ADD8[0x20] = {
0x00, 0x02, 0x0A, 0x0C, 0x02, 0x04, 0x0C, 0x0E, 0x0A, 0x0C, 0x14, 0x16, 0x0C, 0x0E, 0x16, 0x18,
0x01, 0x03, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0B, 0x0D, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x15, 0x17,
};
s16 D_8012AE18[5] = {
0x0000, 0x07C0, 0x0F80, 0x1740, 0x1F00,
};
s16 D_8012AE24[5] = {
0x0000, 0x07C0, 0x0F80, 0x1740, 0x1F00,
};
s16 D_8012AE30[5] = {
0x0000, 0x07C0, 0x0F80, 0x07C0, 0x0000,
};
s16 D_8012AE3C[0x40] = {
0x00, 0x10, 0x13, 0x12, 0x10, 0x01, 0x14, 0x13, 0x01, 0x11, 0x15, 0x14, 0x11, 0x05, 0x16, 0x15,
0x12, 0x13, 0x17, 0x02, 0x13, 0x14, 0x03, 0x17, 0x14, 0x15, 0x18, 0x03, 0x15, 0x16, 0x07, 0x18,
0x02, 0x17, 0x1A, 0x19, 0x17, 0x03, 0x1B, 0x1A, 0x03, 0x18, 0x1C, 0x1B, 0x18, 0x07, 0x1D, 0x1C,
0x19, 0x1A, 0x1E, 0x0A, 0x1A, 0x1B, 0x0B, 0x1E, 0x1B, 0x1C, 0x1F, 0x0B, 0x1C, 0x1D, 0x0F, 0x1F,
};
typedef struct {
/* 0x000 */ s32 unk_0;
/* 0x004 */ s32 unk_4;
/* 0x008 */ s32 unk_8;
/* 0x00C */ s32 unk_C;
/* 0x010 */ s32 unk_10;
} Struct_8012AF0C; // size = 0x14
/* 0x000 */ s32 xStart;
/* 0x004 */ s32 yStart;
/* 0x008 */ s32 zStart;
/* 0x00C */ s32 outerIncrVal;
/* 0x010 */ s32 innerIncrVal;
} SkyboxFaceParams; // size = 0x14
Struct_8012AF0C D_8012AEBC[4] = {
{ -0x7E, 0x7C, -0x7E, 0x3F, -0x1F },
{ 0x7E, 0x7C, -0x7E, 0x3F, -0x1F },
{ 0x7E, 0x7C, 0x7E, -0x3F, -0x1F },
{ -0x7E, 0x7C, 0x7E, -0x3F, -0x1F },
// Converts texture coordinate values to s10.5 fixed point
#define TC(x) ((s16)((x)*32))
// Texture offsets for each face in the static segment buffer
u32 sSkybox256TexOffsets[4] = {
256 * 256 * 0,
256 * 256 * 1,
256 * 256 * 2,
256 * 256 * 3,
};
Struct_8012AF0C D_8012AF0C[6] = {
{ -0x40, 0x40, -0x40, 0x20, -0x20 }, { 0x40, 0x40, 0x40, -0x20, -0x20 }, { -0x40, 0x40, 0x40, -0x20, -0x20 },
{ 0x40, 0x40, -0x40, 0x20, -0x20 }, { -0x40, 0x40, 0x40, 0x20, -0x20 }, { -0x40, -0x40, -0x40, 0x20, 0x20 },
// Maps vertex buffer index to coordinate buffer index
u16 sSkybox256VtxBufIndices[2][32] = {
{
0, 2, 10, 12, 2, 4, 12, 14, 10, 12, 20, 22, 12, 14, 22, 24,
1, 3, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17, 18, 19, 21, 23,
},
{
20, 22, 30, 32, 22, 24, 32, 34, 30, 32, 40, 42, 32, 34, 42, 44,
21, 23, 25, 26, 27, 28, 29, 31, 33, 35, 36, 37, 38, 39, 41, 43,
},
};
s32 func_800ADBB0(SkyboxContext* skyboxCtx, Vtx* roomVtx, s32 arg2, s32 arg3, s32 arg4, s32 arg5, s32 arg6, s32 arg7,
s32 arg8, s32 arg9) {
u32 pad42C;
s32 pad428;
s32 sp424;
// S coordinates for all faces
s16 sSkybox256TexSCoords[5] = {
TC(126 * 0), TC(126 * 1), TC(126 * 2), TC(126 * 3), TC(126 * 4),
};
// T coordinates for all faces
s16 sSkybox256TexTCoords[9] = {
TC(62 * 0), TC(62 * 1), TC(62 * 2), TC(62 * 3), TC(62 * 4), TC(62 * 5), TC(62 * 6), TC(62 * 7), TC(62 * 8),
};
// Maps vertex index to vertex buffer index
s16 sSkybox256VtxIndices[64] = {
0, 16, 19, 18, 16, 1, 20, 19, 1, 17, 21, 20, 17, 5, 22, 21, 18, 19, 23, 2, 19, 20,
3, 23, 20, 21, 24, 3, 21, 22, 7, 24, 2, 23, 26, 25, 23, 3, 27, 26, 3, 24, 28, 27,
24, 7, 29, 28, 25, 26, 30, 10, 26, 27, 11, 30, 27, 28, 31, 11, 28, 29, 15, 31,
};
/**
* Build the vertex and display list data for a skybox with 256x256 face textures.
*
* While the textures are nominally 256x256 the 4x8 tiles that cover it are only 63x31, therefore only a
* 253x249 area is ever sampled (253 = 4 * 63 + 1, the additional +1 accounts for bilinear filtering,
* similarly 249 = 8 * 31 + 1)
*
* Each texture dimension is padded to the next power of 2, resulting in a final size of 256x256.
*/
s32 Skybox_CalculateFace256(SkyboxContext* skyboxCtx, Vtx* roomVtx, s32 roomVtxStartIndex, s32 xStart, s32 yStart,
s32 zStart, s32 innerIncrVal, s32 outerIncrVal, s32 faceNum, s32 dlistBufStartIndex) {
u32 innerIncr;
s32 outerIncr;
s32 n;
s32 i;
s32 j;
s32 k;
u16 index;
s16 phi_t1;
s16 phi_a2_4;
s16 phi_a0_4;
s16 phi_t2_4;
s16 phi_ra;
s32 sp358[9 * 5];
s32 sp2A4[9 * 5];
s32 sp1F0[9 * 5];
s32 sp13C[9 * 5];
s32 sp88[9 * 5];
s16 m;
s16 ult;
s16 uls;
s16 vtxIdx;
s16 l;
s32 xPoints[9 * 5];
s32 yPoints[9 * 5];
s32 zPoints[9 * 5];
s32 tcS[9 * 5];
s32 tcT[9 * 5];
s32 pad;
switch (arg8) {
case 0:
// Collect all vertex positions for this face
switch (faceNum) {
case 0: // xy plane
case 2:
pad428 = arg4;
outerIncr = yStart;
for (i = 0, k = 0; k < 9 * 5; i++) {
innerIncr = xStart;
for (i = 0, k = 0; k < 45; i++) {
pad42C = arg3;
for (j = 0; j < 5; j++, k++) {
sp1F0[k] = arg5;
sp358[k] = pad42C;
sp2A4[k] = pad428;
sp13C[k] = D_8012AD20[j];
sp88[k] = D_8012AD2C[i];
pad42C += arg6;
zPoints[k] = zStart;
xPoints[k] = innerIncr;
yPoints[k] = outerIncr;
tcS[k] = sSkybox256TexSCoords[j];
tcT[k] = sSkybox256TexTCoords[i];
innerIncr += innerIncrVal;
}
pad428 += arg7;
outerIncr += outerIncrVal;
}
break;
case 1:
case 1: // yz plane
case 3:
pad428 = arg4;
outerIncr = yStart;
for (i = 0, k = 0; k < 9 * 5; i++) {
innerIncr = zStart;
for (i = 0, k = 0; k < 45; i++) {
pad42C = arg5;
for (j = 0; j < 5; j++, k++) {
sp358[k] = arg3;
sp2A4[k] = pad428;
sp1F0[k] = pad42C;
sp13C[k] = D_8012AD20[j];
sp88[k] = D_8012AD2C[i];
pad42C += arg6;
xPoints[k] = xStart;
yPoints[k] = outerIncr;
zPoints[k] = innerIncr;
tcS[k] = sSkybox256TexSCoords[j];
tcT[k] = sSkybox256TexTCoords[i];
innerIncr += innerIncrVal;
}
pad428 += arg7;
outerIncr += outerIncrVal;
}
break;
case 4:
case 4: // xz plane
case 5:
pad428 = arg5;
outerIncr = zStart;
for (i = 0, k = 0; k < 9 * 5; i++) {
innerIncr = xStart;
for (i = 0, k = 0; k < 45; i++) {
pad42C = arg3;
for (j = 0; j < 5; j++, k++) {
sp2A4[k] = arg4;
sp358[k] = pad42C;
sp1F0[k] = pad428;
sp13C[k] = D_8012AD20[j];
sp88[k] = D_8012AD2C[i];
pad42C += arg6;
yPoints[k] = yStart;
xPoints[k] = innerIncr;
zPoints[k] = outerIncr;
tcS[k] = sSkybox256TexSCoords[j];
tcT[k] = sSkybox256TexTCoords[i];
innerIncr += innerIncrVal;
}
pad428 += arg7;
outerIncr += outerIncrVal;
}
break;
}
for (phi_a2_4 = 0, sp424 = 0; sp424 < 2; sp424++) {
skyboxCtx->unk_138 = skyboxCtx->dListBuf[arg9 + sp424];
// For a 256x256 texture with 63x31 tiles there are 32 tiles which requires at least 45 vertices,
// 45 > 32 (the maximum number of vertices that can be loaded at once) so it is split into two passes
for (ult = 0, n = 0; n < 2; n++) {
// Each iteration is 16 tiles of the texture, first iteration is the top 16 tiles
for (i = 0; i < 0x20; i++) {
index = D_8012ACA0[sp424][i];
// Select gfx buffer
skyboxCtx->gfx = skyboxCtx->dListBuf[dlistBufStartIndex + n];
roomVtx[arg2 + i].v.ob[0] = sp358[index];
roomVtx[arg2 + i].v.ob[1] = sp2A4[index];
roomVtx[arg2 + i].v.ob[2] = sp1F0[index];
roomVtx[arg2 + i].v.flag = 0;
roomVtx[arg2 + i].v.tc[0] = sp13C[index];
roomVtx[arg2 + i].v.tc[1] = sp88[index];
roomVtx[arg2 + i].v.cn[1] = 0;
roomVtx[arg2 + i].v.cn[2] = 0;
roomVtx[arg2 + i].v.cn[0] = 255;
}
gSPVertex(skyboxCtx->unk_138++, &roomVtx[arg2], 32, 0);
arg2 += i;
gSPCullDisplayList(skyboxCtx->unk_138++, 0, 15);
// Generate and load Vertex structures
for (i = 0; i < 32; i++) {
index = sSkybox256VtxBufIndices[n][i];
for (phi_t2_4 = 0, phi_ra = 0; phi_ra < 4; phi_ra++, phi_a2_4 += 0x1F) {
for (phi_a0_4 = 0, phi_t1 = 0; phi_t1 < 4; phi_t1++, phi_a0_4 += 0x3F, phi_t2_4 += 4) {
gDPLoadTextureTile(skyboxCtx->unk_138++, (u32)skyboxCtx->staticSegments[0] + D_8012AC90[arg8],
G_IM_FMT_CI, G_IM_SIZ_8b, 256, 0, phi_a0_4, phi_a2_4, phi_a0_4 + 0x3F,
phi_a2_4 + 0x1F, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD);
gSP1Quadrangle(skyboxCtx->unk_138++, D_8012AD40[phi_t2_4 + 1], D_8012AD40[phi_t2_4 + 2],
D_8012AD40[phi_t2_4 + 3], D_8012AD40[phi_t2_4 + 0], 3);
}
}
gSPEndDisplayList(skyboxCtx->unk_138++);
}
return arg2;
roomVtx[roomVtxStartIndex + i].v.ob[0] = xPoints[index];
roomVtx[roomVtxStartIndex + i].v.ob[1] = yPoints[index];
roomVtx[roomVtxStartIndex + i].v.ob[2] = zPoints[index];
roomVtx[roomVtxStartIndex + i].v.flag = 0;
roomVtx[roomVtxStartIndex + i].v.tc[0] = tcS[index];
roomVtx[roomVtxStartIndex + i].v.tc[1] = tcT[index];
roomVtx[roomVtxStartIndex + i].v.cn[1] = 0;
roomVtx[roomVtxStartIndex + i].v.cn[2] = 0;
roomVtx[roomVtxStartIndex + i].v.cn[0] = 255;
}
gSPVertex(skyboxCtx->gfx++, &roomVtx[roomVtxStartIndex], 32, 0);
roomVtxStartIndex += i; // += 32
s32 func_800AE2C0(SkyboxContext* skyboxCtx, Vtx* roomVtx, s32 arg2, s32 arg3, s32 arg4, s32 arg5, s32 arg6, s32 arg7,
s32 arg8) {
s32 i;
s32 j;
s32 k;
s16 phi_a0_4;
s16 phi_t1;
s32 temp1;
u16 index;
s16 phi_a2_4;
s16 phi_ra;
s16 phi_t2_4;
s32 temp2;
s32 sp2B4[5 * 5];
s32 sp250[5 * 5];
s32 sp1EC[5 * 5];
s32 sp188[5 * 5];
s32 sp124[5 * 5];
s32 pad;
// Cull the face if not within the viewing volume
gSPCullDisplayList(skyboxCtx->gfx++, 0, 15);
switch (arg8) {
case 0:
case 1:
temp1 = arg4;
for (i = 0, k = 0; k < 25; i++) {
temp2 = arg3;
for (j = 0; j < 5; j++, k++) {
sp1EC[k] = arg5;
sp2B4[k] = temp2;
sp250[k] = temp1;
sp188[k] = D_8012AE18[j];
sp124[k] = D_8012AE30[i];
temp2 += arg6;
}
temp1 += arg7;
}
break;
case 2:
case 3:
temp1 = arg4;
for (i = 0, k = 0; k < 25; i++) {
temp2 = arg5;
for (j = 0; j < 5; j++, k++) {
sp2B4[k] = arg3;
sp250[k] = temp1;
sp1EC[k] = temp2;
sp188[k] = D_8012AE18[j];
sp124[k] = D_8012AE30[i];
temp2 += arg6;
}
temp1 += arg7;
}
break;
case 4:
case 5:
temp1 = arg5;
for (i = 0, k = 0; k < 25; i++) {
temp2 = arg3;
for (j = 0; j < 5; j++, k++) {
sp250[k] = arg4;
sp2B4[k] = temp2;
sp1EC[k] = temp1;
sp188[k] = D_8012AE18[j];
sp124[k] = D_8012AE24[i];
temp2 += arg6;
}
temp1 += arg7;
}
break;
}
skyboxCtx->unk_138 = &skyboxCtx->dListBuf[2 * arg8][0];
for (i = 0; i < 0x20; i++) {
index = D_8012ADD8[i];
roomVtx[arg2 + i].v.ob[0] = sp2B4[index];
roomVtx[arg2 + i].v.ob[1] = sp250[index];
roomVtx[arg2 + i].v.ob[2] = sp1EC[index];
roomVtx[arg2 + i].v.flag = 0;
roomVtx[arg2 + i].v.tc[0] = sp188[index];
roomVtx[arg2 + i].v.tc[1] = sp124[index];
roomVtx[arg2 + i].v.cn[1] = 0;
roomVtx[arg2 + i].v.cn[2] = 0;
roomVtx[arg2 + i].v.cn[0] = 255;
}
gSPVertex(skyboxCtx->unk_138++, &roomVtx[arg2], 32, 0);
arg2 += i;
gSPCullDisplayList(skyboxCtx->unk_138++, 0, 15);
if ((arg8 == 4) || (arg8 == 5)) {
phi_a2_4 = 0;
for (phi_t2_4 = 0, phi_ra = 0; phi_ra < 4; phi_ra++, phi_a2_4 += 0x1F) {
for (phi_a0_4 = 0, phi_t1 = 0; phi_t1 < 4; phi_t1++, phi_a0_4 += 0x1F, phi_t2_4 += 4) {
gDPLoadMultiTile(skyboxCtx->unk_138++, (u32)skyboxCtx->staticSegments[0] + D_8012ADC0[arg8], 0,
G_TX_RENDERTILE, G_IM_FMT_CI, G_IM_SIZ_8b, 128, 0, phi_a0_4, phi_a2_4, phi_a0_4 + 0x1F,
phi_a2_4 + 0x1F, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD);
gDPLoadMultiTile(skyboxCtx->unk_138++, (u32)skyboxCtx->staticSegments[1] + D_8012ADC0[arg8], 0x80, 1,
G_IM_FMT_CI, G_IM_SIZ_8b, 128, 0, phi_a0_4, phi_a2_4, phi_a0_4 + 0x1F, phi_a2_4 + 0x1F,
0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP,
// Draw face, load the texture in several tiles to work around TMEM size limitations
for (vtxIdx = 0, l = 0; l < 4; l++, ult += 31) {
for (uls = 0, m = 0; m < 4; m++, uls += 63, vtxIdx += 4) {
gDPLoadTextureTile(skyboxCtx->gfx++, (u32)skyboxCtx->staticSegments[0] + sSkybox256TexOffsets[faceNum],
G_IM_FMT_CI, G_IM_SIZ_8b, 256, 0, uls, ult, uls + 63, ult + 31, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP,
G_TX_NOMASK, G_TX_NOLOD);
gSP1Quadrangle(skyboxCtx->unk_138++, D_8012AE3C[phi_t2_4 + 1], D_8012AE3C[phi_t2_4 + 2],
D_8012AE3C[phi_t2_4 + 3], D_8012AE3C[phi_t2_4 + 0], 3);
gSP1Quadrangle(skyboxCtx->gfx++, sSkybox256VtxIndices[vtxIdx + 1], sSkybox256VtxIndices[vtxIdx + 2],
sSkybox256VtxIndices[vtxIdx + 3], sSkybox256VtxIndices[vtxIdx + 0], 3);
}
}
gSPEndDisplayList(skyboxCtx->gfx++);
}
return roomVtxStartIndex;
}
// Texture offsets for each face in the static segment buffer
u32 sSkybox128TexOffsets[6] = {
128 * 64 * 0, 128 * 64 * 1, 128 * 64 * 2, 128 * 64 * 3, 128 * 64 * 4, 128 * 64 * 4 + 128 * 128,
};
// Maps vertex buffer index to coordinate buffer index
u16 sSkybox128VtxBufIndices[32] = {
0, 2, 10, 12, 2, 4, 12, 14, 10, 12, 20, 22, 12, 14, 22, 24, 1, 3, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17, 18, 19, 21, 23,
};
// S coordinates for all faces
s16 sSkybox128TexSCoords[5] = {
TC(62 * 0), TC(62 * 1), TC(62 * 2), TC(62 * 3), TC(62 * 4),
};
// T coordinates for top and bottom faces
s16 sSkybox128TexTCoordsXZ[5] = {
TC(62 * 0), TC(62 * 1), TC(62 * 2), TC(62 * 3), TC(62 * 4),
};
// T coordinates for side faces
s16 sSkybox128TexTCoords[5] = {
TC(62 * 0), TC(62 * 1), TC(62 * 2), TC(62 * 1), TC(62 * 0),
};
// Maps vertex index to vertex buffer index
s16 sSkybox128VtxIndices[64] = {
0, 16, 19, 18, 16, 1, 20, 19, 1, 17, 21, 20, 17, 5, 22, 21, 18, 19, 23, 2, 19, 20,
3, 23, 20, 21, 24, 3, 21, 22, 7, 24, 2, 23, 26, 25, 23, 3, 27, 26, 3, 24, 28, 27,
24, 7, 29, 28, 25, 26, 30, 10, 26, 27, 11, 30, 27, 28, 31, 11, 28, 29, 15, 31,
};
/**
* Build the vertex and display list data for a skybox with 128x128 and 128x64 face textures.
*
* While the textures are nominally 128x128 (128x64) the 4x4 (4x2) tiles that cover it are only 31x31,
* therefore only a 125x125 (125x63) area is ever sampled (see `Skybox_CalculateFace256` for more details)
*
* Each texture dimension is padded to the next power of 2, resulting in a final size of 128x128 (128x64)
*/
s32 Skybox_CalculateFace128(SkyboxContext* skyboxCtx, Vtx* roomVtx, s32 roomVtxStartIndex, s32 xStart, s32 yStart,
s32 zStart, s32 innerIncrVal, s32 outerIncrVal, s32 faceNum) {
s32 i;
s32 j;
s32 k;
s16 uls;
s16 m;
s32 outerIncr;
u16 index;
s16 ult;
s16 l;
s16 vtxIdx;
s32 innerIncr;
s32 xPoints[5 * 5];
s32 yPoints[5 * 5];
s32 zPoints[5 * 5];
s32 tcS[5 * 5];
s32 tcT[5 * 5];
s32 pad;
// Collect all vertex positions for this face
switch (faceNum) {
case 0: // xy plane
case 1:
outerIncr = yStart;
for (i = 0, k = 0; k < 25; i++) {
innerIncr = xStart;
for (j = 0; j < 5; j++, k++) {
zPoints[k] = zStart;
xPoints[k] = innerIncr;
yPoints[k] = outerIncr;
tcS[k] = sSkybox128TexSCoords[j];
tcT[k] = sSkybox128TexTCoords[i];
innerIncr += innerIncrVal;
}
outerIncr += outerIncrVal;
}
break;
case 2: // yz plane
case 3:
outerIncr = yStart;
for (i = 0, k = 0; k < 25; i++) {
innerIncr = zStart;
for (j = 0; j < 5; j++, k++) {
xPoints[k] = xStart;
yPoints[k] = outerIncr;
zPoints[k] = innerIncr;
tcS[k] = sSkybox128TexSCoords[j];
tcT[k] = sSkybox128TexTCoords[i];
innerIncr += innerIncrVal;
}
outerIncr += outerIncrVal;
}
break;
case 4: // xz plane
case 5:
outerIncr = zStart;
for (i = 0, k = 0; k < 25; i++) {
innerIncr = xStart;
for (j = 0; j < 5; j++, k++) {
yPoints[k] = yStart;
xPoints[k] = innerIncr;
zPoints[k] = outerIncr;
tcS[k] = sSkybox128TexSCoords[j];
tcT[k] = sSkybox128TexTCoordsXZ[i];
innerIncr += innerIncrVal;
}
outerIncr += outerIncrVal;
}
break;
}
// Select gfx buffer
skyboxCtx->gfx = &skyboxCtx->dListBuf[2 * faceNum][0];
// Generate and load Vertex structures
for (i = 0; i < 32; i++) {
index = sSkybox128VtxBufIndices[i];
roomVtx[roomVtxStartIndex + i].v.ob[0] = xPoints[index];
roomVtx[roomVtxStartIndex + i].v.ob[1] = yPoints[index];
roomVtx[roomVtxStartIndex + i].v.ob[2] = zPoints[index];
roomVtx[roomVtxStartIndex + i].v.flag = 0;
roomVtx[roomVtxStartIndex + i].v.tc[0] = tcS[index];
roomVtx[roomVtxStartIndex + i].v.tc[1] = tcT[index];
roomVtx[roomVtxStartIndex + i].v.cn[1] = 0;
roomVtx[roomVtxStartIndex + i].v.cn[2] = 0;
roomVtx[roomVtxStartIndex + i].v.cn[0] = 255;
}
gSPVertex(skyboxCtx->gfx++, &roomVtx[roomVtxStartIndex], 32, 0);
roomVtxStartIndex += i;
// Cull the face if not within the viewing volume
gSPCullDisplayList(skyboxCtx->gfx++, 0, 15);
// Draw face, load the texture in several tiles to work around TMEM size limitations
if (faceNum == 4 || faceNum == 5) {
// top/bottom faces, 128x128 texture
ult = 0;
for (vtxIdx = 0, l = 0; l < 4; l++, ult += 31) {
for (uls = 0, m = 0; m < 4; m++, uls += 31, vtxIdx += 4) {
gDPLoadMultiTile(skyboxCtx->gfx++, (u32)skyboxCtx->staticSegments[0] + sSkybox128TexOffsets[faceNum], 0,
G_TX_RENDERTILE, G_IM_FMT_CI, G_IM_SIZ_8b, 128, 0, uls, ult, uls + 31, ult + 31, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP,
G_TX_NOMASK, G_TX_NOLOD);
gDPLoadMultiTile(skyboxCtx->gfx++, (u32)skyboxCtx->staticSegments[1] + sSkybox128TexOffsets[faceNum],
0x80, 1, G_IM_FMT_CI, G_IM_SIZ_8b, 128, 0, uls, ult, uls + 31, ult + 31, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP,
G_TX_NOMASK, G_TX_NOLOD);
gSP1Quadrangle(skyboxCtx->gfx++, sSkybox128VtxIndices[vtxIdx + 1], sSkybox128VtxIndices[vtxIdx + 2],
sSkybox128VtxIndices[vtxIdx + 3], sSkybox128VtxIndices[vtxIdx + 0], 3);
}
}
} else {
phi_a2_4 = 0;
for (phi_t2_4 = 0, phi_ra = 0; phi_ra < 2; phi_ra++, phi_a2_4 += 0x1F) {
for (phi_a0_4 = 0, phi_t1 = 0; phi_t1 < 4; phi_t1++, phi_a0_4 += 0x1F, phi_t2_4 += 4) {
gDPLoadMultiTile(skyboxCtx->unk_138++, (u32)skyboxCtx->staticSegments[0] + D_8012ADC0[arg8], 0,
G_TX_RENDERTILE, G_IM_FMT_CI, G_IM_SIZ_8b, 128, 0, phi_a0_4, phi_a2_4, phi_a0_4 + 0x1F,
phi_a2_4 + 0x1F, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD);
gDPLoadMultiTile(skyboxCtx->unk_138++, (u32)skyboxCtx->staticSegments[1] + D_8012ADC0[arg8], 0x80, 1,
G_IM_FMT_CI, G_IM_SIZ_8b, 128, 0, phi_a0_4, phi_a2_4, phi_a0_4 + 0x1F, phi_a2_4 + 0x1F,
0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP,
// other faces, 128x64 texture
ult = 0;
for (vtxIdx = 0, l = 0; l < 2; l++, ult += 31) {
for (uls = 0, m = 0; m < 4; m++, uls += 31, vtxIdx += 4) {
gDPLoadMultiTile(skyboxCtx->gfx++, (u32)skyboxCtx->staticSegments[0] + sSkybox128TexOffsets[faceNum], 0,
G_TX_RENDERTILE, G_IM_FMT_CI, G_IM_SIZ_8b, 128, 0, uls, ult, uls + 31, ult + 31, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP,
G_TX_NOMASK, G_TX_NOLOD);
gSP1Quadrangle(skyboxCtx->unk_138++, D_8012AE3C[phi_t2_4 + 1], D_8012AE3C[phi_t2_4 + 2],
D_8012AE3C[phi_t2_4 + 3], D_8012AE3C[phi_t2_4 + 0], 3);
}
}
phi_a2_4 -= 0x1F;
for (phi_ra = 0; phi_ra < 2; phi_ra++, phi_a2_4 -= 0x1F) {
for (phi_a0_4 = 0, phi_t1 = 0; phi_t1 < 4; phi_t1++, phi_a0_4 += 0x1F, phi_t2_4 += 4) {
gDPLoadMultiTile(skyboxCtx->unk_138++, (u32)skyboxCtx->staticSegments[0] + D_8012ADC0[arg8], 0,
G_TX_RENDERTILE, G_IM_FMT_CI, G_IM_SIZ_8b, 128, 0, phi_a0_4, phi_a2_4, phi_a0_4 + 0x1F,
phi_a2_4 + 0x1F, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD);
gDPLoadMultiTile(skyboxCtx->unk_138++, (u32)skyboxCtx->staticSegments[1] + D_8012ADC0[arg8], 0x80, 1,
G_IM_FMT_CI, G_IM_SIZ_8b, 128, 0, phi_a0_4, phi_a2_4, phi_a0_4 + 0x1F, phi_a2_4 + 0x1F,
0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP,
gDPLoadMultiTile(skyboxCtx->gfx++, (u32)skyboxCtx->staticSegments[1] + sSkybox128TexOffsets[faceNum],
0x80, 1, G_IM_FMT_CI, G_IM_SIZ_8b, 128, 0, uls, ult, uls + 31, ult + 31, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP,
G_TX_NOMASK, G_TX_NOLOD);
gSP1Quadrangle(skyboxCtx->unk_138++, D_8012AE3C[phi_t2_4 + 1], D_8012AE3C[phi_t2_4 + 2],
D_8012AE3C[phi_t2_4 + 3], D_8012AE3C[phi_t2_4 + 0], 3);
gSP1Quadrangle(skyboxCtx->gfx++, sSkybox128VtxIndices[vtxIdx + 1], sSkybox128VtxIndices[vtxIdx + 2],
sSkybox128VtxIndices[vtxIdx + 3], sSkybox128VtxIndices[vtxIdx + 0], 3);
}
}
ult -= 31;
for (l = 0; l < 2; l++, ult -= 31) {
for (uls = 0, m = 0; m < 4; m++, uls += 31, vtxIdx += 4) {
gDPLoadMultiTile(skyboxCtx->gfx++, (u32)skyboxCtx->staticSegments[0] + sSkybox128TexOffsets[faceNum], 0,
G_TX_RENDERTILE, G_IM_FMT_CI, G_IM_SIZ_8b, 128, 0, uls, ult, uls + 31, ult + 31, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP,
G_TX_NOMASK, G_TX_NOLOD);
gDPLoadMultiTile(skyboxCtx->gfx++, (u32)skyboxCtx->staticSegments[1] + sSkybox128TexOffsets[faceNum],
0x80, 1, G_IM_FMT_CI, G_IM_SIZ_8b, 128, 0, uls, ult, uls + 31, ult + 31, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP,
G_TX_NOMASK, G_TX_NOLOD);
gSP1Quadrangle(skyboxCtx->gfx++, sSkybox128VtxIndices[vtxIdx + 1], sSkybox128VtxIndices[vtxIdx + 2],
sSkybox128VtxIndices[vtxIdx + 3], sSkybox128VtxIndices[vtxIdx + 0], 3);
}
}
}
gSPEndDisplayList(skyboxCtx->unk_138++);
return arg2;
gSPEndDisplayList(skyboxCtx->gfx++);
return roomVtxStartIndex;
}
void func_800AEFC8(SkyboxContext* skyboxCtx, s16 skyboxId) {
s32 i;
s32 j;
s32 phi_s3 = 0;
SkyboxFaceParams sSkybox256FaceParams[4] = {
{ -126, 124, -126, 63, -31 },
{ 126, 124, -126, 63, -31 },
{ 126, 124, 126, -63, -31 },
{ -126, 124, 126, -63, -31 },
};
/**
* Computes the display list for a skybox where each face is a 256x256 CI8 texture.
* The number of faces is determined by the skybox id or from the drawType field in SkyboxContext.
*/
void Skybox_Calculate256(SkyboxContext* skyboxCtx, s16 skyboxId) {
s32 faceNum;
s32 dlistBufStartIndex;
s32 roomVtxStartIndex = 0;
if (skyboxId == SKYBOX_BAZAAR || (skyboxId > SKYBOX_HOUSE_KAKARIKO && skyboxId <= SKYBOX_BOMBCHU_SHOP)) {
for (j = 0, i = 0; i < 2; i++, j += 2) {
phi_s3 = func_800ADBB0(skyboxCtx, skyboxCtx->roomVtx, phi_s3, D_8012AEBC[i].unk_0, D_8012AEBC[i].unk_4,
D_8012AEBC[i].unk_8, D_8012AEBC[i].unk_C, D_8012AEBC[i].unk_10, i, j);
// 2 faces, one in xy plane and one in yz plane
for (dlistBufStartIndex = 0, faceNum = 0; faceNum < 2; faceNum++, dlistBufStartIndex += 2) {
roomVtxStartIndex = Skybox_CalculateFace256(
skyboxCtx, skyboxCtx->roomVtx, roomVtxStartIndex, sSkybox256FaceParams[faceNum].xStart,
sSkybox256FaceParams[faceNum].yStart, sSkybox256FaceParams[faceNum].zStart,
sSkybox256FaceParams[faceNum].outerIncrVal, sSkybox256FaceParams[faceNum].innerIncrVal, faceNum,
dlistBufStartIndex);
}
} else if (skyboxCtx->unk_140 == 2) {
for (j = 0, i = 0; i < 3; i++, j += 2) {
phi_s3 = func_800ADBB0(skyboxCtx, skyboxCtx->roomVtx, phi_s3, D_8012AEBC[i].unk_0, D_8012AEBC[i].unk_4,
D_8012AEBC[i].unk_8, D_8012AEBC[i].unk_C, D_8012AEBC[i].unk_10, i, j);
} else if (skyboxCtx->drawType == SKYBOX_DRAW_256_3FACE) {
// 3 faces, 2 in xy plane and 1 in yz plane
for (dlistBufStartIndex = 0, faceNum = 0; faceNum < 3; faceNum++, dlistBufStartIndex += 2) {
roomVtxStartIndex = Skybox_CalculateFace256(
skyboxCtx, skyboxCtx->roomVtx, roomVtxStartIndex, sSkybox256FaceParams[faceNum].xStart,
sSkybox256FaceParams[faceNum].yStart, sSkybox256FaceParams[faceNum].zStart,
sSkybox256FaceParams[faceNum].outerIncrVal, sSkybox256FaceParams[faceNum].innerIncrVal, faceNum,
dlistBufStartIndex);
}
} else {
for (j = 0, i = 0; i < 4; i++, j += 2) {
phi_s3 = func_800ADBB0(skyboxCtx, skyboxCtx->roomVtx, phi_s3, D_8012AEBC[i].unk_0, D_8012AEBC[i].unk_4,
D_8012AEBC[i].unk_8, D_8012AEBC[i].unk_C, D_8012AEBC[i].unk_10, i, j);
// 4 faces, 2 in xy plane and 2 in yz plane
for (dlistBufStartIndex = 0, faceNum = 0; faceNum < 4; faceNum++, dlistBufStartIndex += 2) {
roomVtxStartIndex = Skybox_CalculateFace256(
skyboxCtx, skyboxCtx->roomVtx, roomVtxStartIndex, sSkybox256FaceParams[faceNum].xStart,
sSkybox256FaceParams[faceNum].yStart, sSkybox256FaceParams[faceNum].zStart,
sSkybox256FaceParams[faceNum].outerIncrVal, sSkybox256FaceParams[faceNum].innerIncrVal, faceNum,
dlistBufStartIndex);
}
}
}
void func_800AF178(SkyboxContext* skyboxCtx, s32 arg1) {
s32 phi_s2 = 0;
s32 i;
SkyboxFaceParams sSkybox128FaceParams[6] = {
{ -64, 64, -64, 32, -32 }, { 64, 64, 64, -32, -32 }, { -64, 64, 64, -32, -32 },
{ 64, 64, -64, 32, -32 }, { -64, 64, 64, 32, -32 }, { -64, -64, -64, 32, 32 },
};
for (i = 0; i < arg1; i++) {
phi_s2 = func_800AE2C0(skyboxCtx, skyboxCtx->roomVtx, phi_s2, D_8012AF0C[i].unk_0, D_8012AF0C[i].unk_4,
D_8012AF0C[i].unk_8, D_8012AF0C[i].unk_C, D_8012AF0C[i].unk_10, i);
/**
* Computes the display list for a skybox with up to 6 faces, where the sides are 128x64 CI8 textures and the
* top/bottom faces are 128x128 CI8 textures.
*/
void Skybox_Calculate128(SkyboxContext* skyboxCtx, s32 nFaces) {
s32 roomVtxStartIndex = 0;
s32 faceNum;
for (faceNum = 0; faceNum < nFaces; faceNum++) {
roomVtxStartIndex = Skybox_CalculateFace128(
skyboxCtx, skyboxCtx->roomVtx, roomVtxStartIndex, sSkybox128FaceParams[faceNum].xStart,
sSkybox128FaceParams[faceNum].yStart, sSkybox128FaceParams[faceNum].zStart,
sSkybox128FaceParams[faceNum].outerIncrVal, sSkybox128FaceParams[faceNum].innerIncrVal, faceNum);
}
}
@ -447,7 +528,7 @@ void Skybox_Setup(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) {
break;
case SKYBOX_BAZAAR:
skyboxCtx->unk_140 = 1;
skyboxCtx->drawType = SKYBOX_DRAW_256_4FACE;
start = (uintptr_t)_vr_SP1a_staticSegmentRomStart;
size = (uintptr_t)_vr_SP1a_staticSegmentRomEnd - start;
@ -489,7 +570,7 @@ void Skybox_Setup(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) {
DmaMgr_RequestSyncDebug((u8*)skyboxCtx->palettes + size, start, size, "../z_vr_box.c", 1175);
break;
case SKYBOX_MARKET_ADULT:
skyboxCtx->unk_140 = 1;
skyboxCtx->drawType = SKYBOX_DRAW_256_4FACE;
start = (uintptr_t)_vr_RUVR_staticSegmentRomStart;
size = (uintptr_t)_vr_RUVR_staticSegmentRomEnd - start;
@ -535,7 +616,7 @@ void Skybox_Setup(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) {
size, "../z_vr_box.c", 1216);
break;
case SKYBOX_HOUSE_LINK:
skyboxCtx->unk_140 = 1;
skyboxCtx->drawType = SKYBOX_DRAW_256_4FACE;
start = (uintptr_t)_vr_LHVR_staticSegmentRomStart;
size = (uintptr_t)_vr_LHVR_staticSegmentRomEnd - start;
@ -553,7 +634,7 @@ void Skybox_Setup(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) {
DmaMgr_RequestSyncDebug(skyboxCtx->palettes, start, size, "../z_vr_box.c", 1233);
break;
case SKYBOX_MARKET_CHILD_DAY:
skyboxCtx->unk_140 = 1;
skyboxCtx->drawType = SKYBOX_DRAW_256_4FACE;
start = (uintptr_t)_vr_MDVR_staticSegmentRomStart;
size = (uintptr_t)_vr_MDVR_staticSegmentRomEnd - start;
@ -571,7 +652,7 @@ void Skybox_Setup(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) {
DmaMgr_RequestSyncDebug(skyboxCtx->palettes, start, size, "../z_vr_box.c", 1264);
break;
case SKYBOX_MARKET_CHILD_NIGHT:
skyboxCtx->unk_140 = 1;
skyboxCtx->drawType = SKYBOX_DRAW_256_4FACE;
start = (uintptr_t)_vr_MNVR_staticSegmentRomStart;
size = (uintptr_t)_vr_MNVR_staticSegmentRomEnd - start;
@ -591,7 +672,7 @@ void Skybox_Setup(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) {
DmaMgr_RequestSyncDebug(skyboxCtx->palettes, start, size, "../z_vr_box.c", 1279);
break;
case SKYBOX_HAPPY_MASK_SHOP:
skyboxCtx->unk_140 = 1;
skyboxCtx->drawType = SKYBOX_DRAW_256_4FACE;
start = (uintptr_t)_vr_FCVR_staticSegmentRomStart;
size = (uintptr_t)_vr_FCVR_staticSegmentRomEnd - start;
@ -610,7 +691,7 @@ void Skybox_Setup(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) {
skyboxCtx->rot.y = 0.8f;
break;
case SKYBOX_HOUSE_KNOW_IT_ALL_BROTHERS:
skyboxCtx->unk_140 = 1;
skyboxCtx->drawType = SKYBOX_DRAW_256_4FACE;
start = (uintptr_t)_vr_KHVR_staticSegmentRomStart;
size = (uintptr_t)_vr_KHVR_staticSegmentRomEnd - start;
@ -628,7 +709,7 @@ void Skybox_Setup(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) {
DmaMgr_RequestSyncDebug(skyboxCtx->palettes, start, size, "../z_vr_box.c", 1308);
break;
case SKYBOX_HOUSE_OF_TWINS:
skyboxCtx->unk_140 = 2;
skyboxCtx->drawType = SKYBOX_DRAW_256_3FACE;
start = (uintptr_t)_vr_K3VR_staticSegmentRomStart;
size = (uintptr_t)_vr_K3VR_staticSegmentRomEnd - start;
@ -646,7 +727,7 @@ void Skybox_Setup(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) {
DmaMgr_RequestSyncDebug(skyboxCtx->palettes, start, size, "../z_vr_box.c", 1338);
break;
case SKYBOX_STABLES:
skyboxCtx->unk_140 = 1;
skyboxCtx->drawType = SKYBOX_DRAW_256_4FACE;
start = (uintptr_t)_vr_MLVR_staticSegmentRomStart;
size = (uintptr_t)_vr_MLVR_staticSegmentRomEnd - start;
@ -664,7 +745,7 @@ void Skybox_Setup(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) {
DmaMgr_RequestSyncDebug(skyboxCtx->palettes, start, size, "../z_vr_box.c", 1352);
break;
case SKYBOX_HOUSE_KAKARIKO:
skyboxCtx->unk_140 = 1;
skyboxCtx->drawType = SKYBOX_DRAW_256_4FACE;
start = (uintptr_t)_vr_KKRVR_staticSegmentRomStart;
size = (uintptr_t)_vr_KKRVR_staticSegmentRomEnd - start;
@ -682,7 +763,7 @@ void Skybox_Setup(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) {
DmaMgr_RequestSyncDebug(skyboxCtx->palettes, start, size, "../z_vr_box.c", 1366);
break;
case SKYBOX_KOKIRI_SHOP:
skyboxCtx->unk_140 = 1;
skyboxCtx->drawType = SKYBOX_DRAW_256_4FACE;
start = (uintptr_t)_vr_KSVR_staticSegmentRomStart;
size = (uintptr_t)_vr_KSVR_staticSegmentRomEnd - start;
@ -701,7 +782,7 @@ void Skybox_Setup(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) {
skyboxCtx->rot.y = 0.8f;
break;
case SKYBOX_GORON_SHOP:
skyboxCtx->unk_140 = 1;
skyboxCtx->drawType = SKYBOX_DRAW_256_4FACE;
start = (uintptr_t)_vr_GLVR_staticSegmentRomStart;
size = (uintptr_t)_vr_GLVR_staticSegmentRomEnd - start;
@ -720,7 +801,7 @@ void Skybox_Setup(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) {
skyboxCtx->rot.y = 0.8f;
break;
case SKYBOX_ZORA_SHOP:
skyboxCtx->unk_140 = 1;
skyboxCtx->drawType = SKYBOX_DRAW_256_4FACE;
start = (uintptr_t)_vr_ZRVR_staticSegmentRomStart;
size = (uintptr_t)_vr_ZRVR_staticSegmentRomEnd - start;
@ -739,7 +820,7 @@ void Skybox_Setup(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) {
skyboxCtx->rot.y = 0.8f;
break;
case SKYBOX_POTION_SHOP_KAKARIKO:
skyboxCtx->unk_140 = 1;
skyboxCtx->drawType = SKYBOX_DRAW_256_4FACE;
start = (uintptr_t)_vr_DGVR_staticSegmentRomStart;
size = (uintptr_t)_vr_DGVR_staticSegmentRomEnd - start;
@ -758,7 +839,7 @@ void Skybox_Setup(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) {
skyboxCtx->rot.y = 0.8f;
break;
case SKYBOX_POTION_SHOP_MARKET:
skyboxCtx->unk_140 = 1;
skyboxCtx->drawType = SKYBOX_DRAW_256_4FACE;
start = (uintptr_t)_vr_ALVR_staticSegmentRomStart;
size = (uintptr_t)_vr_ALVR_staticSegmentRomEnd - start;
@ -777,7 +858,7 @@ void Skybox_Setup(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) {
skyboxCtx->rot.y = 0.8f;
break;
case SKYBOX_BOMBCHU_SHOP:
skyboxCtx->unk_140 = 1;
skyboxCtx->drawType = SKYBOX_DRAW_256_4FACE;
start = (uintptr_t)_vr_NSVR_staticSegmentRomStart;
size = (uintptr_t)_vr_NSVR_staticSegmentRomEnd - start;
@ -796,7 +877,7 @@ void Skybox_Setup(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) {
skyboxCtx->rot.y = 0.8f;
break;
case SKYBOX_HOUSE_RICHARD:
skyboxCtx->unk_140 = 1;
skyboxCtx->drawType = SKYBOX_DRAW_256_4FACE;
start = (uintptr_t)_vr_IPVR_staticSegmentRomStart;
size = (uintptr_t)_vr_IPVR_staticSegmentRomEnd - start;
@ -814,7 +895,7 @@ void Skybox_Setup(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) {
DmaMgr_RequestSyncDebug(skyboxCtx->palettes, start, size, "../z_vr_box.c", 1519);
break;
case SKYBOX_HOUSE_IMPA:
skyboxCtx->unk_140 = 1;
skyboxCtx->drawType = SKYBOX_DRAW_256_4FACE;
start = (uintptr_t)_vr_LBVR_staticSegmentRomStart;
size = (uintptr_t)_vr_LBVR_staticSegmentRomEnd - start;
@ -832,7 +913,7 @@ void Skybox_Setup(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) {
DmaMgr_RequestSyncDebug(skyboxCtx->palettes, start, size, "../z_vr_box.c", 1533);
break;
case SKYBOX_TENT:
skyboxCtx->unk_140 = 2;
skyboxCtx->drawType = SKYBOX_DRAW_256_3FACE;
start = (uintptr_t)_vr_TTVR_staticSegmentRomStart;
size = (uintptr_t)_vr_TTVR_staticSegmentRomEnd - start;
@ -850,7 +931,7 @@ void Skybox_Setup(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) {
DmaMgr_RequestSyncDebug(skyboxCtx->palettes, start, size, "../z_vr_box.c", 1547);
break;
case SKYBOX_HOUSE_MIDO:
skyboxCtx->unk_140 = 2;
skyboxCtx->drawType = SKYBOX_DRAW_256_3FACE;
start = (uintptr_t)_vr_K4VR_staticSegmentRomStart;
size = (uintptr_t)_vr_K4VR_staticSegmentRomEnd - start;
@ -868,7 +949,7 @@ void Skybox_Setup(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) {
DmaMgr_RequestSyncDebug(skyboxCtx->palettes, start, size, "../z_vr_box.c", 1567);
break;
case SKYBOX_HOUSE_SARIA:
skyboxCtx->unk_140 = 2;
skyboxCtx->drawType = SKYBOX_DRAW_256_3FACE;
start = (uintptr_t)_vr_K5VR_staticSegmentRomStart;
size = (uintptr_t)_vr_K5VR_staticSegmentRomEnd - start;
@ -886,7 +967,7 @@ void Skybox_Setup(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) {
DmaMgr_RequestSyncDebug(skyboxCtx->palettes, start, size, "../z_vr_box.c", 1581);
break;
case SKYBOX_HOUSE_ALLEY:
skyboxCtx->unk_140 = 2;
skyboxCtx->drawType = SKYBOX_DRAW_256_3FACE;
start = (uintptr_t)_vr_KR3VR_staticSegmentRomStart;
size = (uintptr_t)_vr_KR3VR_staticSegmentRomEnd - start;
@ -911,40 +992,42 @@ void Skybox_Setup(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) {
void Skybox_Init(GameState* state, SkyboxContext* skyboxCtx, s16 skyboxId) {
PlayState* play = (PlayState*)state;
skyboxCtx->unk_140 = 0;
skyboxCtx->drawType = SKYBOX_DRAW_128;
skyboxCtx->rot.x = skyboxCtx->rot.y = skyboxCtx->rot.z = 0.0f;
// DMA required assets based on skybox id
Skybox_Setup(play, skyboxCtx, skyboxId);
osSyncPrintf("\n\n\n\n\n\n"
"%d"
"\n\n\n\n\n\n",
skyboxId);
// Precompute vertices and display lists for drawing the skybox
if (skyboxId != SKYBOX_NONE) {
osSyncPrintf(VT_FGCOL(GREEN));
if (skyboxCtx->unk_140 != 0) {
if (skyboxCtx->drawType != SKYBOX_DRAW_128) {
skyboxCtx->dListBuf = GameState_Alloc(state, 8 * 150 * sizeof(Gfx), "../z_vr_box.c", 1636);
ASSERT(skyboxCtx->dListBuf != NULL, "vr_box->dpList != NULL", "../z_vr_box.c", 1637);
skyboxCtx->roomVtx = GameState_Alloc(state, 256 * sizeof(Vtx), "../z_vr_box.c", 1639);
skyboxCtx->roomVtx = GameState_Alloc(state, 8 * 32 * sizeof(Vtx), "../z_vr_box.c", 1639);
ASSERT(skyboxCtx->roomVtx != NULL, "vr_box->roomVtx != NULL", "../z_vr_box.c", 1640);
func_800AEFC8(skyboxCtx, skyboxId);
Skybox_Calculate256(skyboxCtx, skyboxId);
} else {
skyboxCtx->dListBuf = GameState_Alloc(state, 12 * 150 * sizeof(Gfx), "../z_vr_box.c", 1643);
ASSERT(skyboxCtx->dListBuf != NULL, "vr_box->dpList != NULL", "../z_vr_box.c", 1644);
if (skyboxId == SKYBOX_CUTSCENE_MAP) {
skyboxCtx->roomVtx = GameState_Alloc(state, 192 * sizeof(Vtx), "../z_vr_box.c", 1648);
skyboxCtx->roomVtx = GameState_Alloc(state, 6 * 32 * sizeof(Vtx), "../z_vr_box.c", 1648);
ASSERT(skyboxCtx->roomVtx != NULL, "vr_box->roomVtx != NULL", "../z_vr_box.c", 1649);
func_800AF178(skyboxCtx, 6);
Skybox_Calculate128(skyboxCtx, 6); // compute all 6 faces
} else {
skyboxCtx->roomVtx = GameState_Alloc(state, 160 * sizeof(Vtx), "../z_vr_box.c", 1653);
skyboxCtx->roomVtx = GameState_Alloc(state, 5 * 32 * sizeof(Vtx), "../z_vr_box.c", 1653);
ASSERT(skyboxCtx->roomVtx != NULL, "vr_box->roomVtx != NULL", "../z_vr_box.c", 1654);
func_800AF178(skyboxCtx, 5);
Skybox_Calculate128(skyboxCtx, 5); // compute 5 faces, excludes the bottom face
}
}
osSyncPrintf(VT_RST);

View file

@ -23,8 +23,8 @@ void Skybox_Draw(SkyboxContext* skyboxCtx, GraphicsContext* gfxCtx, s16 skyboxId
gDPSetPrimColor(POLY_OPA_DISP++, 0x00, 0x00, 0, 0, 0, blend);
gSPTexture(POLY_OPA_DISP++, 0x8000, 0x8000, 0, G_TX_RENDERTILE, G_ON);
// Prepare matrix
sSkyboxDrawMatrix = Graph_Alloc(gfxCtx, sizeof(Mtx));
Matrix_Translate(x, y, z, MTXMODE_NEW);
Matrix_Scale(1.0f, 1.0f, 1.0f, MTXMODE_APPLY);
Matrix_RotateX(skyboxCtx->rot.x, MTXMODE_APPLY);
@ -33,45 +33,61 @@ void Skybox_Draw(SkyboxContext* skyboxCtx, GraphicsContext* gfxCtx, s16 skyboxId
Matrix_ToMtx(sSkyboxDrawMatrix, "../z_vr_box_draw.c", 76);
gSPMatrix(POLY_OPA_DISP++, sSkyboxDrawMatrix, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
// Enable magic square RGB dithering and bilinear filtering
gDPSetColorDither(POLY_OPA_DISP++, G_CD_MAGICSQ);
gDPSetTextureFilter(POLY_OPA_DISP++, G_TF_BILERP);
// All skyboxes use CI8 textures with an RGBA16 palette
gDPLoadTLUT_pal256(POLY_OPA_DISP++, skyboxCtx->palettes[0]);
gDPSetTextureLUT(POLY_OPA_DISP++, G_TT_RGBA16);
// Enable texture filtering RDP pipeline stages for bilinear filtering
gDPSetTextureConvert(POLY_OPA_DISP++, G_TC_FILT);
if (skyboxCtx->unk_140) {
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[0]);
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[1]);
if (skyboxCtx->drawType != SKYBOX_DRAW_128) {
// 256x256 textures, per-face palettes
// 2, 3 or 4 faces
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[0]); // -z face upper
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[1]); // -z face lower
gDPPipeSync(POLY_OPA_DISP++);
gDPLoadTLUT_pal256(POLY_OPA_DISP++, skyboxCtx->palettes[1]);
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[2]);
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[3]);
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[2]); // +x face upper
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[3]); // +x face lower
if (skyboxId != SKYBOX_BAZAAR) {
if (skyboxId <= SKYBOX_HOUSE_KAKARIKO || skyboxId > SKYBOX_BOMBCHU_SHOP) {
gDPPipeSync(POLY_OPA_DISP++);
gDPLoadTLUT_pal256(POLY_OPA_DISP++, skyboxCtx->palettes[2]);
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[4]);
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[5]);
if (skyboxId < SKYBOX_KOKIRI_SHOP || skyboxId > SKYBOX_BOMBCHU_SHOP) {
// Skip remaining faces for most shop skyboxes
gDPPipeSync(POLY_OPA_DISP++);
if (skyboxCtx->unk_140 != 2) {
gDPLoadTLUT_pal256(POLY_OPA_DISP++, skyboxCtx->palettes[2]);
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[4]); // +z face upper
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[5]); // +z face lower
// Note this pipesync is slightly misplaced and would be better off inside the condition
gDPPipeSync(POLY_OPA_DISP++);
if (skyboxCtx->drawType != SKYBOX_DRAW_256_3FACE) {
gDPLoadTLUT_pal256(POLY_OPA_DISP++, skyboxCtx->palettes[3]);
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[6]);
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[7]);
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[6]); // -x face upper
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[7]); // -x face lower
}
}
}
} else {
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[0]);
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[2]);
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[4]);
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[6]);
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[8]);
// 128x128 and 128x64 textures
// 5 or 6 faces
// Draw each face
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[0]); // -z face
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[2]); // +z face
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[4]); // -x face
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[6]); // +x face
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[8]); // +y face
if (skyboxId == SKYBOX_CUTSCENE_MAP) {
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[10]);
// Skip the bottom face in the cutscene map
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[10]); // -y face
}
}