#include #include "constants.h" #include "game/game_006900.h" #include "game/bondgun.h" #include "game/tex.h" #include "game/savebuffer.h" #include "game/menugfx.h" #include "game/menu.h" #include "game/game_1531a0.h" #include "game/gfxmemory.h" #include "game/file.h" #include "game/utils.h" #include "bss.h" #include "lib/vi.h" #include "lib/main.h" #include "lib/rng.h" #include "lib/mtx.h" #include "data.h" #include "types.h" #define NUM_SUCCESS_PARTICLES 280 #define BLURIMG_WIDTH 40 #define BLURIMG_HEIGHT 30 #define SAMPLE_WIDTH 8 #define SAMPLE_HEIGHT 8 #define PXTOBYTES(val) ((val) * 2) /** * Blur the gameplay background for the pause menu. * * The blurred image is 30x40 pixels at 16 bits per pixel. At standard * resolution this is 1/8th the size of the framebuffer. * * This function reads the framebuffer in blocks of 8x8 pixels. Each block's * R/G/B components are averaged and used to set a pixel in the blurred buffer. * * If hi-res is being used, every second horizontal pixel on the framebuffer is * read instead. The blurred image is the same size regardless of hi-res. * * The transition effect when pausing and unpausing is implemented elsewhere. * It's a simple fade between the source framebuffer and the blurred image. * Only one blurred image is made. */ void menugfxCreateBlur(void) { u8 *fb = (u8 *) viGetFrontBuffer(); s32 dstx; s32 dsty; #if PAL s32 fbwidthinbytes = viGetWidth() * 2; f32 scale = viGetWidth() / 320.0f; #else s32 fbwidthinbytes = PXTOBYTES(viGetWidth()); #endif s32 srcx; s32 srcy; u32 r; u32 g; u32 b; u16 colour; static u32 cccc = 1; #if PAL g_ScaleX = 1; #else g_ScaleX = (g_ViRes == VIRES_HI) ? 2 : 1; #endif if (cccc == 1) { fb = (u8 *) viGetFrontBuffer(); } mainOverrideVariable("cccc", &cccc); for (dsty = 0; dsty < BLURIMG_HEIGHT; dsty++) { for (dstx = 0; dstx < BLURIMG_WIDTH; dstx++) { s32 dstindex = PXTOBYTES(dsty * BLURIMG_WIDTH) + PXTOBYTES(dstx); #if PAL s32 samplestartindex = (((s32) ((f32) dstx * 2 * 4 * 2 * scale) + (s32) (dsty * fbwidthinbytes * 8)) & 0xfffffffe); #else s32 samplestartindex = PXTOBYTES(dstx * SAMPLE_WIDTH) * g_ScaleX + dsty * fbwidthinbytes * SAMPLE_HEIGHT; #endif r = g = b = 0; for (srcx = 0; srcx < SAMPLE_WIDTH; srcx++) { for (srcy = 0; srcy < SAMPLE_HEIGHT; srcy++) { #if PAL s32 index = (samplestartindex + (s32) (PXTOBYTES((f32) srcx) * scale) + srcy * fbwidthinbytes) & 0xfffffffe; #else s32 index = samplestartindex + PXTOBYTES(srcx) * g_ScaleX + srcy * fbwidthinbytes; #endif colour = fb[index] << 8 | fb[index + 1]; r = r + (colour >> 11 & 0x1f); g = g + (colour >> 6 & 0x1f); b = b + (colour >> 1 & 0x1f); } } r /= SAMPLE_WIDTH * SAMPLE_HEIGHT; g /= SAMPLE_WIDTH * SAMPLE_HEIGHT; b /= SAMPLE_WIDTH * SAMPLE_HEIGHT; g_BlurBuffer[dstindex + 0] = ((r << 3) | (g >> 2)) & 0xffff; g_BlurBuffer[dstindex + 1] = ((g << 6) | ((b & 0x1f) << 1)) & 0xffff; } } g_ScaleX = 1; } Gfx *menugfxRenderBgBlur(Gfx *gdl, u32 colour, s16 arg2, s16 arg3) { u32 *colours; struct gfxvtx *vertices; #if VERSION >= VERSION_PAL_BETA s32 width; s32 height; #endif if (IS4MB()) { return menugfxRenderGradient(gdl, 0, 0, viGetWidth(), viGetHeight(), 0xff, 0xff, 0xff); } colours = gfxAllocateColours(1); vertices = gfxAllocateVertices(4); gDPPipeSync(gdl++); gSPTexture(gdl++, 0xffff, 0xffff, 0, G_TX_RENDERTILE, G_ON); gDPLoadTextureBlock(gdl++, g_BlurBuffer, G_IM_FMT_RGBA, G_IM_SIZ_16b, 40, 30, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); gDPPipeSync(gdl++); gDPSetCycleType(gdl++, G_CYC_1CYCLE); gDPSetAlphaCompare(gdl++, G_AC_NONE); gDPSetCombineMode(gdl++, G_CC_MODULATEI, G_CC_MODULATEI); gSPClearGeometryMode(gdl++, G_CULL_BOTH); gDPSetTextureFilter(gdl++, G_TF_BILERP); gDPSetRenderMode(gdl++, G_RM_XLU_SURF, G_RM_XLU_SURF2); #if VERSION >= VERSION_JPN_FINAL width = viGetWidth() * 10; height = viGetHeight() * 10; *(u16 *)&vertices[0].x = arg2; *(u16 *)&vertices[0].y = arg3; vertices[0].z = -10; *(u16 *)&vertices[1].x = arg2 + 320 * 10u + 40; *(u16 *)&vertices[1].y = arg3; vertices[1].z = -10; *(u16 *)&vertices[2].x = arg2 + 320 * 10u + 40; *(u16 *)&vertices[2].y = arg3 + 240 * 10u + 50; vertices[2].z = -10; *(u16 *)&vertices[3].x = arg2; *(u16 *)&vertices[3].y = arg3 + 240 * 10u + 50; vertices[3].z = -10; #elif PAL width = viGetWidth() * 10; height = viGetHeight() * 10; *(u16 *)&vertices[0].x = arg2; *(u16 *)&vertices[0].y = arg3; vertices[0].z = -10; *(u16 *)&vertices[1].x = (s32)width + arg2 + 40; *(u16 *)&vertices[1].y = arg3; vertices[1].z = -10; *(u16 *)&vertices[2].x = (s32)width + arg2 + 40; *(u16 *)&vertices[2].y = (s32)height + arg3 + 50; vertices[2].z = -10; *(u16 *)&vertices[3].x = arg2; *(u16 *)&vertices[3].y = (s32)height + arg3 + 50; vertices[3].z = -10; #else *(u16 *)&vertices[0].x = arg2; *(u16 *)&vertices[0].y = arg3; vertices[0].z = -10; *(u16 *)&vertices[1].x = arg2 + 320 * 10u + 40; *(u16 *)&vertices[1].y = arg3; vertices[1].z = -10; *(u16 *)&vertices[2].x = arg2 + 320 * 10u + 40; *(u16 *)&vertices[2].y = arg3 + 240 * 10u + 50; vertices[2].z = -10; *(u16 *)&vertices[3].x = arg2; *(u16 *)&vertices[3].y = arg3 + 240 * 10u + 50; vertices[3].z = -10; #endif vertices[0].s = 0; vertices[0].t = 0; vertices[1].s = 1280; vertices[1].t = 0; vertices[2].s = 1280; vertices[2].t = 960; vertices[3].s = 0; vertices[3].t = 960; vertices[0].colour = 0; vertices[1].colour = 0; vertices[2].colour = 0; vertices[3].colour = 0; colours[0] = colour; gDPSetColorArray(gdl++, osVirtualToPhysical(colours), 1); gDPSetVerticeArray(gdl++, osVirtualToPhysical(vertices), 4); gDPTri2(gdl++, 0, 1, 2, 2, 3, 0); return gdl; } void func0f0e0cbc(s32 arg0, s32 arg1, s16 arg2, s16 arg3, struct gfxvtx *vertex, Mtxf *arg5) { struct coord sp24; sp24.x = (arg2 - arg0 + 100) * 0.25f; sp24.y = (arg3 - arg1 + 100) * 0.25f; sp24.z = 0; vertex->x = arg2 * 10; vertex->y = arg3 * 10; vertex->z = -10; vertex->colour = 0; mtx4TransformVecInPlace(arg5, &sp24); vertex->s = sp24.x * 32; vertex->t = sp24.y * 32; } Gfx *menugfxRenderDialogBackground(Gfx *gdl, s32 x1, s32 y1, s32 x2, s32 y2, struct menudialog *dialog, u32 colour1, u32 colour2, f32 arg8) { u32 stack[1]; u32 leftcolour; u32 rightcolour; // Render the dialog's background fill gdl = textSetPrimColour(gdl, colour1); gDPFillRectangleScaled(gdl++, x1, y1, x2, y2); gdl = text0f153838(gdl); if (dialog->transitionfrac < 0.0f) { leftcolour = g_MenuColourPalettes[dialog->type].unk00; } else { leftcolour = colourBlend(g_MenuColourPalettes[dialog->type2].unk00, g_MenuColourPalettes[dialog->type].unk00, dialog->colourweight); } if (dialog->transitionfrac < 0.0f) { rightcolour = g_MenuColourPalettes[dialog->type].unk08; } else { rightcolour = colourBlend(g_MenuColourPalettes[dialog->type2].unk08, g_MenuColourPalettes[dialog->type].unk08, dialog->colourweight); } // Right, left, bottom border gdl = menugfxDrawDialogBorderLine(gdl, x2 - 1, y1, x2, y2, rightcolour, rightcolour); gdl = menugfxDrawDialogBorderLine(gdl, x1, y1, x1 + 1, y2, leftcolour, leftcolour); gdl = menugfxDrawDialogBorderLine(gdl, x1, y2 - 1, x2, y2, leftcolour, rightcolour); return gdl; } /** * This unused function renders an experimental menu background. * * The background consists of two layers of a green hazy texture. * Both layers spin slowly in opposite directions. */ Gfx *menugfxRenderBgGreenHaze(Gfx *gdl, s32 x1, s32 y1, s32 x2, s32 y2) { s32 i; u32 *colours; struct gfxvtx *vertices; u32 alphas[2]; s16 t5; s16 s0; s16 s2; s16 s3; f32 f20; f32 f22; f32 f24; f32 f26; f32 f0; f32 f2; u32 stack; colours = gfxAllocateColours(4); vertices = gfxAllocateVertices(8); gDPPipeSync(gdl++); gDPSetCycleType(gdl++, G_CYC_1CYCLE); gDPSetAlphaCompare(gdl++, G_AC_NONE); gDPSetCombineMode(gdl++, G_CC_MODULATEI, G_CC_MODULATEI); gSPClearGeometryMode(gdl++, G_CULL_BOTH); gDPSetTextureFilter(gdl++, G_TF_BILERP); texSelect(&gdl, &g_TexGeneralConfigs[6], 2, 0, 2, 1, NULL); gDPSetRenderMode(gdl++, G_RM_XLU_SURF, G_RM_XLU_SURF2); vertices[4].x = vertices[0].x = x1 * 10; vertices[4].y = vertices[0].y = y1 * 10; vertices[4].z = vertices[0].z = -10; vertices[5].x = vertices[1].x = x2 * 10; vertices[5].y = vertices[1].y = y1 * 10; vertices[5].z = vertices[1].z = -10; vertices[6].x = vertices[2].x = x2 * 10; vertices[6].y = vertices[2].y = y2 * 10; vertices[6].z = vertices[2].z = -10; vertices[7].x = vertices[3].x = x1 * 10; vertices[7].y = vertices[3].y = y2 * 10; vertices[7].z = vertices[3].z = -10; for (i = 0; i < 2; i++) { s16 tmp = i * 256; f0 = g_20SecIntervalFrac; f26 = M_BADTAU * g_20SecIntervalFrac; if (i == 1) { f26 = -f26; } if (i == 1) { f0 += 0.5f; } if (f0 > 1.0f) { f0 -= 1.0f; } f2 = 1.0f - f0; if (f0 < 0.2f) { alphas[i] = f0 / 0.2f * 127.0f; } else if (f0 > 0.9f) { alphas[i] = f2 / 0.1f * 127.0f; } else { alphas[i] = 0x7f; } f20 = (f2 + 0.1f) * 15.0f; f22 = (x2 - x1) / 2 * f20; f24 = (y2 - y1) / 2 * f20; s2 = sinf(f26) * f22; s3 = cosf(f26) * f24; s0 = cosf(f26) * f22; t5 = -sinf(f26) * f24; vertices[i * 4 + 0].s = tmp - s2 - s0; vertices[i * 4 + 0].t = tmp - s3 - t5; vertices[i * 4 + 1].s = tmp + s2 - s0; vertices[i * 4 + 1].t = tmp + s3 - t5; vertices[i * 4 + 2].s = tmp + s2 + s0; vertices[i * 4 + 2].t = tmp + s3 + t5; vertices[i * 4 + 3].s = tmp - s2 + s0; vertices[i * 4 + 3].t = tmp - s3 + t5; } vertices[0].colour = 0; vertices[1].colour = 0; vertices[2].colour = 4; vertices[3].colour = 4; vertices[4].colour = 12; vertices[5].colour = 12; vertices[6].colour = 8; vertices[7].colour = 8; colours[0] = 0x00af0000 | alphas[0]; colours[1] = 0xffff0000 | alphas[0]; colours[2] = 0x00af0000 | alphas[1]; colours[3] = 0xffff0000 | alphas[1]; gDPSetColorArray(gdl++, osVirtualToPhysical(colours), 4); gDPSetVerticeArray(gdl++, osVirtualToPhysical(vertices), 8); if (g_20SecIntervalFrac > 0.5f) { gDPTri4(gdl++, 4, 5, 6, 6, 7, 4, 0, 1, 2, 2, 3, 0); } else { gDPTri4(gdl++, 0, 1, 2, 2, 3, 0, 4, 5, 6, 6, 7, 4); } return gdl; } Gfx *menugfxDrawDropdownBackground(Gfx *gdl, s32 x1, s32 y1, s32 x2, s32 y2) { u32 *colours = gfxAllocateColours(3); struct gfxvtx *vertices = gfxAllocateVertices(6); u32 colour1; u32 colour2; gDPPipeSync(gdl++); gDPSetCycleType(gdl++, G_CYC_1CYCLE); gDPSetAlphaCompare(gdl++, G_AC_NONE); gDPSetCombineMode(gdl++, G_CC_MODULATEI, G_CC_MODULATEI); gSPClearGeometryMode(gdl++, G_CULL_BOTH); gDPSetTextureFilter(gdl++, G_TF_BILERP); texSelect(&gdl, NULL, 2, 0, 2, true, NULL); gDPSetRenderMode(gdl++, G_RM_XLU_SURF, G_RM_XLU_SURF2); vertices[0].x = x1 * 10; vertices[0].y = y1 * 10; vertices[0].z = -10; vertices[1].x = x2 * 10; vertices[1].y = y1 * 10; vertices[1].z = -10; vertices[2].x = x1 * 10; vertices[2].y = (y2 + y1) / 2 * 10; vertices[2].z = -10; vertices[3].x = x2 * 10; vertices[3].y = (y2 + y1) / 2 * 10; vertices[3].z = -10; vertices[4].x = x1 * 10; vertices[4].y = y2 * 10; vertices[4].z = -10; vertices[5].x = x2 * 10; vertices[5].y = y2 * 10; vertices[5].z = -10; vertices[0].colour = 0; vertices[1].colour = 0; vertices[2].colour = 4; vertices[3].colour = 4; vertices[4].colour = 8; vertices[5].colour = 8; colour1 = text0f1543ac((x1 + x2) / 2, (y2 + y1) / 2, 0xffffffff) & 0xff; colour2 = (text0f1543ac((x1 + x2) / 2, (y2 + y1) / 2, 0xffffff7f) & 0xff) | 0x00006f00; colours[0] = colour1 | 0x00006f00; colours[1] = colour2; colours[2] = colour1 | 0x00003f00; gDPSetColorArray(gdl++, osVirtualToPhysical(colours), 3); gDPSetVerticeArray(gdl++, osVirtualToPhysical(vertices), 6); gDPTri4(gdl++, 0, 1, 3, 3, 2, 0, 2, 3, 4, 4, 3, 5); return gdl; } #if VERSION >= VERSION_NTSC_1_0 // NTSC beta is non-matching, but a close match is shown here #if VERSION >= VERSION_NTSC_1_0 Gfx *menugfxDrawListGroupHeader(Gfx *gdl, s32 x1, s32 y1, s32 x2, s32 y2, s32 x3, u8 alpha) #else Gfx *menugfxDrawListGroupHeader(Gfx *gdl, s32 x1, s32 y1, s32 x2, s32 y2, s32 x3) #endif { u32 *colours = gfxAllocateColours(7); struct gfxvtx *vertices = gfxAllocateVertices(9); u32 alpha1; u32 alpha2; gDPPipeSync(gdl++); gDPSetCycleType(gdl++, G_CYC_1CYCLE); gDPSetAlphaCompare(gdl++, G_AC_NONE); gDPSetCombineMode(gdl++, G_CC_MODULATEI, G_CC_MODULATEI); gSPClearGeometryMode(gdl++, G_CULL_BOTH); gDPSetTextureFilter(gdl++, G_TF_BILERP); texSelect(&gdl, NULL, 2, 0, 2, 1, NULL); gDPSetRenderMode(gdl++, G_RM_XLU_SURF, G_RM_XLU_SURF2); vertices[0].x = x1 * 10; vertices[0].y = y1 * 10; vertices[0].z = -10; vertices[1].x = x2 * 10; vertices[1].y = y1 * 10; vertices[1].z = -10; vertices[2].x = x1 * 10; vertices[2].y = (y2 + y1) / 2 * 10; vertices[2].z = -10; vertices[3].x = x2 * 10; vertices[3].y = (y2 + y1) / 2 * 10; vertices[3].z = -10; vertices[4].x = x1 * 10; vertices[4].y = y2 * 10; vertices[4].z = -10; vertices[5].x = x2 * 10; vertices[5].y = y2 * 10; vertices[5].z = -10; vertices[6].x = x3 * 10; vertices[6].y = y1 * 10; vertices[6].z = -10; vertices[7].x = x3 * 10; vertices[7].y = (y2 + y1) / 2 * 10; vertices[7].z = -10; vertices[8].x = x3 * 10; vertices[8].y = y2 * 10; vertices[8].z = -10; vertices[0].colour = 0; vertices[1].colour = 24; vertices[2].colour = 4; vertices[3].colour = 4; vertices[4].colour = 8; vertices[5].colour = 8; vertices[6].colour = 12; vertices[7].colour = 16; vertices[8].colour = 20; #if VERSION >= VERSION_NTSC_1_0 alpha1 = alpha; alpha2 = alpha; #else alpha1 = text0f1543ac((x2 + x1) / 2, (y2 + y1) / 2, 0xffffffff) & 0xff; alpha2 = text0f1543ac((x2 + x1) / 2, (y2 + y1) / 2, 0xffffff7f) & 0xff; #endif colours[0] = 0x00006f00 | alpha1; colours[1] = 0x00006f00 | alpha2; colours[2] = 0x00003f00 | alpha2; colours[3] = 0xffffff00; colours[4] = (0x00006f00 | alpha2) & 0xffffff00; colours[5] = (0x00003f00 | alpha1) & 0xffffff00; colours[6] = 0x6f6f6f00 | alpha1; gDPSetColorArray(gdl++, osVirtualToPhysical(colours), 7); gDPSetVerticeArray(gdl++, osVirtualToPhysical(vertices), 9); gDPTri4(gdl++, 0, 1, 3, 3, 2, 0, 2, 3, 4, 4, 3, 5); gDPTri4(gdl++, 1, 6, 7, 7, 3, 1, 3, 7, 8, 8, 5, 3); gdl = menugfxDrawShimmer(gdl, x1, y1, x2, y1 + 1, (alpha1 & 0xff) >> 2, 1, 0x28, 0); gdl = menugfxDrawShimmer(gdl, x1, y2, x2, y2 + 1, (alpha1 & 0xff) >> 2, 0, 0x28, 1); return gdl; } #else GLOBAL_ASM( glabel menugfxDrawListGroupHeader /* f0ded8c: 27bdff70 */ addiu $sp,$sp,-144 /* f0ded90: afbf003c */ sw $ra,0x3c($sp) /* f0ded94: afa40090 */ sw $a0,0x90($sp) /* f0ded98: afb20038 */ sw $s2,0x38($sp) /* f0ded9c: afb10034 */ sw $s1,0x34($sp) /* f0deda0: afb00030 */ sw $s0,0x30($sp) /* f0deda4: afa50094 */ sw $a1,0x94($sp) /* f0deda8: afa60098 */ sw $a2,0x98($sp) /* f0dedac: afa7009c */ sw $a3,0x9c($sp) /* f0dedb0: 0fc588c3 */ jal gfxAllocateColours /* f0dedb4: 24040007 */ addiu $a0,$zero,0x7 /* f0dedb8: 00408825 */ or $s1,$v0,$zero /* f0dedbc: 0fc588a9 */ jal gfxAllocateVertices /* f0dedc0: 24040009 */ addiu $a0,$zero,0x9 /* f0dedc4: 8fae0090 */ lw $t6,0x90($sp) /* f0dedc8: 3c18e700 */ lui $t8,0xe700 /* f0dedcc: 00408025 */ or $s0,$v0,$zero /* f0dedd0: 25cf0008 */ addiu $t7,$t6,0x8 /* f0dedd4: afaf0090 */ sw $t7,0x90($sp) /* f0dedd8: adc00004 */ sw $zero,0x4($t6) /* f0deddc: add80000 */ sw $t8,0x0($t6) /* f0dede0: 8fb90090 */ lw $t9,0x90($sp) /* f0dede4: 3c0fba00 */ lui $t7,0xba00 /* f0dede8: 35ef1402 */ ori $t7,$t7,0x1402 /* f0dedec: 272e0008 */ addiu $t6,$t9,0x8 /* f0dedf0: afae0090 */ sw $t6,0x90($sp) /* f0dedf4: af200004 */ sw $zero,0x4($t9) /* f0dedf8: af2f0000 */ sw $t7,0x0($t9) /* f0dedfc: 8fb80090 */ lw $t8,0x90($sp) /* f0dee00: 3c0eb900 */ lui $t6,0xb900 /* f0dee04: 35ce0002 */ ori $t6,$t6,0x2 /* f0dee08: 27190008 */ addiu $t9,$t8,0x8 /* f0dee0c: afb90090 */ sw $t9,0x90($sp) /* f0dee10: af000004 */ sw $zero,0x4($t8) /* f0dee14: af0e0000 */ sw $t6,0x0($t8) /* f0dee18: 8faf0090 */ lw $t7,0x90($sp) /* f0dee1c: 3c19fc12 */ lui $t9,0xfc12 /* f0dee20: 37397e24 */ ori $t9,$t9,0x7e24 /* f0dee24: 25f80008 */ addiu $t8,$t7,0x8 /* f0dee28: afb80090 */ sw $t8,0x90($sp) /* f0dee2c: 240ef9fc */ addiu $t6,$zero,-1540 /* f0dee30: adee0004 */ sw $t6,0x4($t7) /* f0dee34: adf90000 */ sw $t9,0x0($t7) /* f0dee38: 8faf0090 */ lw $t7,0x90($sp) /* f0dee3c: 3c19b600 */ lui $t9,0xb600 /* f0dee40: 240e3000 */ addiu $t6,$zero,0x3000 /* f0dee44: 25f80008 */ addiu $t8,$t7,0x8 /* f0dee48: afb80090 */ sw $t8,0x90($sp) /* f0dee4c: adee0004 */ sw $t6,0x4($t7) /* f0dee50: adf90000 */ sw $t9,0x0($t7) /* f0dee54: 8faf0090 */ lw $t7,0x90($sp) /* f0dee58: 3c19ba00 */ lui $t9,0xba00 /* f0dee5c: 37390c02 */ ori $t9,$t9,0xc02 /* f0dee60: 25f80008 */ addiu $t8,$t7,0x8 /* f0dee64: afb80090 */ sw $t8,0x90($sp) /* f0dee68: 240e2000 */ addiu $t6,$zero,0x2000 /* f0dee6c: adee0004 */ sw $t6,0x4($t7) /* f0dee70: adf90000 */ sw $t9,0x0($t7) /* f0dee74: 240f0002 */ addiu $t7,$zero,0x2 /* f0dee78: 24180001 */ addiu $t8,$zero,0x1 /* f0dee7c: afb80014 */ sw $t8,0x14($sp) /* f0dee80: afaf0010 */ sw $t7,0x10($sp) /* f0dee84: afa00018 */ sw $zero,0x18($sp) /* f0dee88: 27a40090 */ addiu $a0,$sp,0x90 /* f0dee8c: 00002825 */ or $a1,$zero,$zero /* f0dee90: 24060002 */ addiu $a2,$zero,0x2 /* f0dee94: 0fc2c5c8 */ jal texSelect /* f0dee98: 00003825 */ or $a3,$zero,$zero /* f0dee9c: 8fab0094 */ lw $t3,0x94($sp) /* f0deea0: 2404000a */ addiu $a0,$zero,0xa /* f0deea4: 8fac0098 */ lw $t4,0x98($sp) /* f0deea8: 01640019 */ multu $t3,$a0 /* f0deeac: 8fad009c */ lw $t5,0x9c($sp) /* f0deeb0: 8fb90090 */ lw $t9,0x90($sp) /* f0deeb4: 8faa00a0 */ lw $t2,0xa0($sp) /* f0deeb8: 3c0fb900 */ lui $t7,0xb900 /* f0deebc: 272e0008 */ addiu $t6,$t9,0x8 /* f0deec0: afae0090 */ sw $t6,0x90($sp) /* f0deec4: 3c180050 */ lui $t8,0x50 /* f0deec8: 37184240 */ ori $t8,$t8,0x4240 /* f0deecc: 35ef031d */ ori $t7,$t7,0x31d /* f0deed0: 00002812 */ mflo $a1 /* f0deed4: af2f0000 */ sw $t7,0x0($t9) /* f0deed8: af380004 */ sw $t8,0x4($t9) /* f0deedc: 01840019 */ multu $t4,$a0 /* f0deee0: 03201825 */ or $v1,$t9,$zero /* f0deee4: 014c9021 */ addu $s2,$t2,$t4 /* f0deee8: 2402fff6 */ addiu $v0,$zero,-10 /* f0deeec: a6050000 */ sh $a1,0x0($s0) /* f0deef0: a6020004 */ sh $v0,0x4($s0) /* f0deef4: a6020010 */ sh $v0,0x10($s0) /* f0deef8: a6050018 */ sh $a1,0x18($s0) /* f0deefc: a602001c */ sh $v0,0x1c($s0) /* f0def00: a6020028 */ sh $v0,0x28($s0) /* f0def04: 00003012 */ mflo $a2 /* f0def08: a6060002 */ sh $a2,0x2($s0) /* f0def0c: a606000e */ sh $a2,0xe($s0) /* f0def10: 01a40019 */ multu $t5,$a0 /* f0def14: a6050030 */ sh $a1,0x30($s0) /* f0def18: a6020034 */ sh $v0,0x34($s0) /* f0def1c: a6020040 */ sh $v0,0x40($s0) /* f0def20: 240f0018 */ addiu $t7,$zero,0x18 /* f0def24: 24050008 */ addiu $a1,$zero,0x8 /* f0def28: 2418000c */ addiu $t8,$zero,0xc /* f0def2c: 00003812 */ mflo $a3 /* f0def30: a607000c */ sh $a3,0xc($s0) /* f0def34: 06410003 */ bgez $s2,.NB0f0def44 /* f0def38: 0012c843 */ sra $t9,$s2,0x1 /* f0def3c: 26410001 */ addiu $at,$s2,0x1 /* f0def40: 0001c843 */ sra $t9,$at,0x1 .NB0f0def44: /* f0def44: 03240019 */ multu $t9,$a0 /* f0def48: a6070024 */ sh $a3,0x24($s0) /* f0def4c: a607003c */ sh $a3,0x3c($s0) /* f0def50: 03209025 */ or $s2,$t9,$zero /* f0def54: 24190010 */ addiu $t9,$zero,0x10 /* f0def58: 00004012 */ mflo $t0 /* f0def5c: a608001a */ sh $t0,0x1a($s0) /* f0def60: a6080026 */ sh $t0,0x26($s0) /* f0def64: 01440019 */ multu $t2,$a0 /* f0def68: 00001812 */ mflo $v1 /* f0def6c: a6030032 */ sh $v1,0x32($s0) /* f0def70: a603003e */ sh $v1,0x3e($s0) /* f0def74: 8fae00a4 */ lw $t6,0xa4($sp) /* f0def78: a20f0013 */ sb $t7,0x13($s0) /* f0def7c: a606004a */ sh $a2,0x4a($s0) /* f0def80: 01c40019 */ multu $t6,$a0 /* f0def84: 24040004 */ addiu $a0,$zero,0x4 /* f0def88: a204001f */ sb $a0,0x1f($s0) /* f0def8c: a204002b */ sb $a0,0x2b($s0) /* f0def90: 016d2021 */ addu $a0,$t3,$t5 /* f0def94: a2050037 */ sb $a1,0x37($s0) /* f0def98: a2050043 */ sb $a1,0x43($s0) /* f0def9c: 240e0014 */ addiu $t6,$zero,0x14 /* f0defa0: a602004c */ sh $v0,0x4c($s0) /* f0defa4: a6080056 */ sh $t0,0x56($s0) /* f0defa8: 00004812 */ mflo $t1 /* f0defac: a6090048 */ sh $t1,0x48($s0) /* f0defb0: a6090054 */ sh $t1,0x54($s0) /* f0defb4: a6020058 */ sh $v0,0x58($s0) /* f0defb8: a6090060 */ sh $t1,0x60($s0) /* f0defbc: a6030062 */ sh $v1,0x62($s0) /* f0defc0: a6020064 */ sh $v0,0x64($s0) /* f0defc4: a2000007 */ sb $zero,0x7($s0) /* f0defc8: a218004f */ sb $t8,0x4f($s0) /* f0defcc: a219005b */ sb $t9,0x5b($s0) /* f0defd0: a20e0067 */ sb $t6,0x67($s0) /* f0defd4: 04810003 */ bgez $a0,.NB0f0defe4 /* f0defd8: 00047843 */ sra $t7,$a0,0x1 /* f0defdc: 24810001 */ addiu $at,$a0,0x1 /* f0defe0: 00017843 */ sra $t7,$at,0x1 .NB0f0defe4: /* f0defe4: 01e02025 */ or $a0,$t7,$zero /* f0defe8: afaf0050 */ sw $t7,0x50($sp) /* f0defec: afb20044 */ sw $s2,0x44($sp) /* f0deff0: 02402825 */ or $a1,$s2,$zero /* f0deff4: 0fc53a82 */ jal text0f1543ac /* f0deff8: 2406ffff */ addiu $a2,$zero,-1 /* f0deffc: 8fa40050 */ lw $a0,0x50($sp) /* f0df000: 305200ff */ andi $s2,$v0,0xff /* f0df004: 8fa50044 */ lw $a1,0x44($sp) /* f0df008: 0fc53a82 */ jal text0f1543ac /* f0df00c: 2406ff7f */ addiu $a2,$zero,-129 /* f0df010: 2406ff00 */ addiu $a2,$zero,-256 /* f0df014: 36586f00 */ ori $t8,$s2,0x6f00 /* f0df018: 304300ff */ andi $v1,$v0,0xff /* f0df01c: 3c016f6f */ lui $at,0x6f6f /* f0df020: ae380000 */ sw $t8,0x0($s1) /* f0df024: 34796f00 */ ori $t9,$v1,0x6f00 /* f0df028: 36453f00 */ ori $a1,$s2,0x3f00 /* f0df02c: 34216f00 */ ori $at,$at,0x6f00 /* f0df030: 03267024 */ and $t6,$t9,$a2 /* f0df034: 00a67824 */ and $t7,$a1,$a2 /* f0df038: 0241c025 */ or $t8,$s2,$at /* f0df03c: ae390004 */ sw $t9,0x4($s1) /* f0df040: ae250008 */ sw $a1,0x8($s1) /* f0df044: ae26000c */ sw $a2,0xc($s1) /* f0df048: ae2e0010 */ sw $t6,0x10($s1) /* f0df04c: ae2f0014 */ sw $t7,0x14($s1) /* f0df050: ae380018 */ sw $t8,0x18($s1) /* f0df054: 8fb90090 */ lw $t9,0x90($sp) /* f0df058: 3c0f0718 */ lui $t7,0x718 /* f0df05c: 35ef001c */ ori $t7,$t7,0x1c /* f0df060: 272e0008 */ addiu $t6,$t9,0x8 /* f0df064: afae0090 */ sw $t6,0x90($sp) /* f0df068: af2f0000 */ sw $t7,0x0($t9) /* f0df06c: 02202025 */ or $a0,$s1,$zero /* f0df070: 0c013100 */ jal osVirtualToPhysical /* f0df074: afb90060 */ sw $t9,0x60($sp) /* f0df078: 8fa70060 */ lw $a3,0x60($sp) /* f0df07c: 3c0e0480 */ lui $t6,0x480 /* f0df080: 35ce006c */ ori $t6,$t6,0x6c /* f0df084: ace20004 */ sw $v0,0x4($a3) /* f0df088: 8fb10090 */ lw $s1,0x90($sp) /* f0df08c: 02002025 */ or $a0,$s0,$zero /* f0df090: 26390008 */ addiu $t9,$s1,0x8 /* f0df094: afb90090 */ sw $t9,0x90($sp) /* f0df098: 0c013100 */ jal osVirtualToPhysical /* f0df09c: ae2e0000 */ sw $t6,0x0($s1) /* f0df0a0: ae220004 */ sw $v0,0x4($s1) /* f0df0a4: 8faf0090 */ lw $t7,0x90($sp) /* f0df0a8: 3c19b100 */ lui $t9,0xb100 /* f0df0ac: 3c0e3432 */ lui $t6,0x3432 /* f0df0b0: 25f80008 */ addiu $t8,$t7,0x8 /* f0df0b4: afb80090 */ sw $t8,0x90($sp) /* f0df0b8: 35ce2310 */ ori $t6,$t6,0x2310 /* f0df0bc: 37395403 */ ori $t9,$t9,0x5403 /* f0df0c0: adf90000 */ sw $t9,0x0($t7) /* f0df0c4: adee0004 */ sw $t6,0x4($t7) /* f0df0c8: 8faf0090 */ lw $t7,0x90($sp) /* f0df0cc: 3c0e5873 */ lui $t6,0x5873 /* f0df0d0: 3c19b100 */ lui $t9,0xb100 /* f0df0d4: 25f80008 */ addiu $t8,$t7,0x8 /* f0df0d8: afb80090 */ sw $t8,0x90($sp) /* f0df0dc: 37393817 */ ori $t9,$t9,0x3817 /* f0df0e0: 35ce3761 */ ori $t6,$t6,0x3761 /* f0df0e4: adee0004 */ sw $t6,0x4($t7) /* f0df0e8: adf90000 */ sw $t9,0x0($t7) /* f0df0ec: 8fa60098 */ lw $a2,0x98($sp) /* f0df0f0: 325000ff */ andi $s0,$s2,0xff /* f0df0f4: 0010c882 */ srl $t9,$s0,0x2 /* f0df0f8: 240f0028 */ addiu $t7,$zero,0x28 /* f0df0fc: 240e0001 */ addiu $t6,$zero,0x1 /* f0df100: 24d80001 */ addiu $t8,$a2,0x1 /* f0df104: afb80010 */ sw $t8,0x10($sp) /* f0df108: afae0018 */ sw $t6,0x18($sp) /* f0df10c: afaf001c */ sw $t7,0x1c($sp) /* f0df110: 03208025 */ or $s0,$t9,$zero /* f0df114: afb90014 */ sw $t9,0x14($sp) /* f0df118: afa00020 */ sw $zero,0x20($sp) /* f0df11c: 8fa7009c */ lw $a3,0x9c($sp) /* f0df120: 8fa50094 */ lw $a1,0x94($sp) /* f0df124: 0fc37fce */ jal menugfxDrawShimmer /* f0df128: 8fa40090 */ lw $a0,0x90($sp) /* f0df12c: 8fa600a0 */ lw $a2,0xa0($sp) /* f0df130: 24190028 */ addiu $t9,$zero,0x28 /* f0df134: 240e0001 */ addiu $t6,$zero,0x1 /* f0df138: 24d80001 */ addiu $t8,$a2,0x1 /* f0df13c: afa20090 */ sw $v0,0x90($sp) /* f0df140: afb80010 */ sw $t8,0x10($sp) /* f0df144: afae0020 */ sw $t6,0x20($sp) /* f0df148: afb9001c */ sw $t9,0x1c($sp) /* f0df14c: 00402025 */ or $a0,$v0,$zero /* f0df150: 8fa50094 */ lw $a1,0x94($sp) /* f0df154: 8fa7009c */ lw $a3,0x9c($sp) /* f0df158: afb00014 */ sw $s0,0x14($sp) /* f0df15c: 0fc37fce */ jal menugfxDrawShimmer /* f0df160: afa00018 */ sw $zero,0x18($sp) /* f0df164: 8fbf003c */ lw $ra,0x3c($sp) /* f0df168: 8fb00030 */ lw $s0,0x30($sp) /* f0df16c: 8fb10034 */ lw $s1,0x34($sp) /* f0df170: 8fb20038 */ lw $s2,0x38($sp) /* f0df174: 03e00008 */ jr $ra /* f0df178: 27bd0090 */ addiu $sp,$sp,0x90 ); #endif #if MATCHING GLOBAL_ASM( glabel menugfxRenderGradient /* f0e1ce8: 27bdffa0 */ addiu $sp,$sp,-96 /* f0e1cec: afbf002c */ sw $ra,0x2c($sp) /* f0e1cf0: afa40060 */ sw $a0,0x60($sp) /* f0e1cf4: afb10028 */ sw $s1,0x28($sp) /* f0e1cf8: afb00024 */ sw $s0,0x24($sp) /* f0e1cfc: afa50064 */ sw $a1,0x64($sp) /* f0e1d00: afa60068 */ sw $a2,0x68($sp) /* f0e1d04: afa7006c */ sw $a3,0x6c($sp) /* f0e1d08: 0fc59e73 */ jal gfxAllocateColours /* f0e1d0c: 24040003 */ addiu $a0,$zero,0x3 /* f0e1d10: 00408825 */ or $s1,$v0,$zero /* f0e1d14: 0fc59e59 */ jal gfxAllocateVertices /* f0e1d18: 24040006 */ addiu $a0,$zero,0x6 /* f0e1d1c: 8fae0060 */ lw $t6,0x60($sp) /* f0e1d20: 3c18e700 */ lui $t8,0xe700 /* f0e1d24: 00408025 */ or $s0,$v0,$zero /* f0e1d28: 25cf0008 */ addiu $t7,$t6,0x8 /* f0e1d2c: afaf0060 */ sw $t7,0x60($sp) /* f0e1d30: adc00004 */ sw $zero,0x4($t6) /* f0e1d34: add80000 */ sw $t8,0x0($t6) /* f0e1d38: 8fb90060 */ lw $t9,0x60($sp) /* f0e1d3c: 3c0eba00 */ lui $t6,0xba00 /* f0e1d40: 35ce1402 */ ori $t6,$t6,0x1402 /* f0e1d44: 272d0008 */ addiu $t5,$t9,0x8 /* f0e1d48: afad0060 */ sw $t5,0x60($sp) /* f0e1d4c: af200004 */ sw $zero,0x4($t9) /* f0e1d50: af2e0000 */ sw $t6,0x0($t9) /* f0e1d54: 8faf0060 */ lw $t7,0x60($sp) /* f0e1d58: 3c19b900 */ lui $t9,0xb900 /* f0e1d5c: 37390002 */ ori $t9,$t9,0x2 /* f0e1d60: 25f80008 */ addiu $t8,$t7,0x8 /* f0e1d64: afb80060 */ sw $t8,0x60($sp) /* f0e1d68: ade00004 */ sw $zero,0x4($t7) /* f0e1d6c: adf90000 */ sw $t9,0x0($t7) /* f0e1d70: 8fad0060 */ lw $t5,0x60($sp) /* f0e1d74: 3c0ffc12 */ lui $t7,0xfc12 /* f0e1d78: 35ef7e24 */ ori $t7,$t7,0x7e24 /* f0e1d7c: 25ae0008 */ addiu $t6,$t5,0x8 /* f0e1d80: afae0060 */ sw $t6,0x60($sp) /* f0e1d84: 2418f9fc */ addiu $t8,$zero,-1540 /* f0e1d88: adb80004 */ sw $t8,0x4($t5) /* f0e1d8c: adaf0000 */ sw $t7,0x0($t5) /* f0e1d90: 8fb90060 */ lw $t9,0x60($sp) /* f0e1d94: 240f3000 */ addiu $t7,$zero,0x3000 /* f0e1d98: 3c0eb600 */ lui $t6,0xb600 /* f0e1d9c: 272d0008 */ addiu $t5,$t9,0x8 /* f0e1da0: afad0060 */ sw $t5,0x60($sp) /* f0e1da4: af2f0004 */ sw $t7,0x4($t9) /* f0e1da8: af2e0000 */ sw $t6,0x0($t9) /* f0e1dac: 8fb80060 */ lw $t8,0x60($sp) /* f0e1db0: 3c0dba00 */ lui $t5,0xba00 /* f0e1db4: 35ad0c02 */ ori $t5,$t5,0xc02 /* f0e1db8: 27190008 */ addiu $t9,$t8,0x8 /* f0e1dbc: afb90060 */ sw $t9,0x60($sp) /* f0e1dc0: 240e2000 */ addiu $t6,$zero,0x2000 /* f0e1dc4: af0e0004 */ sw $t6,0x4($t8) /* f0e1dc8: af0d0000 */ sw $t5,0x0($t8) /* f0e1dcc: 24180001 */ addiu $t8,$zero,0x1 /* f0e1dd0: 240f0002 */ addiu $t7,$zero,0x2 /* f0e1dd4: afaf0010 */ sw $t7,0x10($sp) /* f0e1dd8: afb80014 */ sw $t8,0x14($sp) /* f0e1ddc: afa00018 */ sw $zero,0x18($sp) /* f0e1de0: 27a40060 */ addiu $a0,$sp,0x60 /* f0e1de4: 00002825 */ or $a1,$zero,$zero /* f0e1de8: 24060002 */ addiu $a2,$zero,0x2 /* f0e1dec: 0fc2ce70 */ jal texSelect /* f0e1df0: 00003825 */ or $a3,$zero,$zero /* f0e1df4: 8fb90060 */ lw $t9,0x60($sp) /* f0e1df8: 8fab0070 */ lw $t3,0x70($sp) /* f0e1dfc: 8fac0068 */ lw $t4,0x68($sp) /* f0e1e00: 8fa9006c */ lw $t1,0x6c($sp) /* f0e1e04: 8faa0064 */ lw $t2,0x64($sp) /* f0e1e08: 272d0008 */ addiu $t5,$t9,0x8 /* f0e1e0c: afad0060 */ sw $t5,0x60($sp) /* f0e1e10: 3c0eb900 */ lui $t6,0xb900 /* f0e1e14: 3c0f0050 */ lui $t7,0x50 /* f0e1e18: 018b4021 */ addu $t0,$t4,$t3 /* f0e1e1c: 35ef4240 */ ori $t7,$t7,0x4240 /* f0e1e20: 35ce031d */ ori $t6,$t6,0x31d /* f0e1e24: af2e0000 */ sw $t6,0x0($t9) /* f0e1e28: af2f0004 */ sw $t7,0x4($t9) /* f0e1e2c: 03201025 */ or $v0,$t9,$zero /* f0e1e30: 05010003 */ bgez $t0,.L0f0e1e40 /* f0e1e34: 0008c043 */ sra $t8,$t0,0x1 /* f0e1e38: 25010001 */ addiu $at,$t0,0x1 /* f0e1e3c: 0001c043 */ sra $t8,$at,0x1 .L0f0e1e40: /* f0e1e40: 0018c840 */ sll $t9,$t8,0x1 /* f0e1e44: 012a2023 */ subu $a0,$t1,$t2 /* f0e1e48: 0099082a */ slt $at,$a0,$t9 /* f0e1e4c: 10200001 */ beqz $at,.L0f0e1e54 /* f0e1e50: 03004025 */ or $t0,$t8,$zero .L0f0e1e54: /* f0e1e54: 2406000a */ addiu $a2,$zero,0xa /* f0e1e58: 01460019 */ multu $t2,$a2 /* f0e1e5c: 2407fff6 */ addiu $a3,$zero,-10 /* f0e1e60: a6070004 */ sh $a3,0x4($s0) /* f0e1e64: a6070010 */ sh $a3,0x10($s0) /* f0e1e68: a607001c */ sh $a3,0x1c($s0) /* f0e1e6c: a6070028 */ sh $a3,0x28($s0) /* f0e1e70: a6070034 */ sh $a3,0x34($s0) /* f0e1e74: a6070040 */ sh $a3,0x40($s0) /* f0e1e78: a2000007 */ sb $zero,0x7($s0) /* f0e1e7c: a2000013 */ sb $zero,0x13($s0) /* f0e1e80: 00001012 */ mflo $v0 /* f0e1e84: a6020000 */ sh $v0,0x0($s0) /* f0e1e88: a6020024 */ sh $v0,0x24($s0) /* f0e1e8c: 01860019 */ multu $t4,$a2 /* f0e1e90: 00001812 */ mflo $v1 /* f0e1e94: a6030002 */ sh $v1,0x2($s0) /* f0e1e98: a603000e */ sh $v1,0xe($s0) /* f0e1e9c: 01260019 */ multu $t1,$a2 /* f0e1ea0: 24030004 */ addiu $v1,$zero,0x4 /* f0e1ea4: a203001f */ sb $v1,0x1f($s0) /* f0e1ea8: a203002b */ sb $v1,0x2b($s0) /* f0e1eac: 00002012 */ mflo $a0 /* f0e1eb0: a604000c */ sh $a0,0xc($s0) /* f0e1eb4: a6040018 */ sh $a0,0x18($s0) /* f0e1eb8: 01660019 */ multu $t3,$a2 /* f0e1ebc: 24040008 */ addiu $a0,$zero,0x8 /* f0e1ec0: a2040037 */ sb $a0,0x37($s0) /* f0e1ec4: a2040043 */ sb $a0,0x43($s0) /* f0e1ec8: 02202025 */ or $a0,$s1,$zero /* f0e1ecc: 00002812 */ mflo $a1 /* f0e1ed0: a605001a */ sh $a1,0x1a($s0) /* f0e1ed4: a6050026 */ sh $a1,0x26($s0) /* f0e1ed8: 01460019 */ multu $t2,$a2 /* f0e1edc: 00006812 */ mflo $t5 /* f0e1ee0: a60d0030 */ sh $t5,0x30($s0) /* f0e1ee4: 00000000 */ nop /* f0e1ee8: 01060019 */ multu $t0,$a2 /* f0e1eec: 00001012 */ mflo $v0 /* f0e1ef0: a6020032 */ sh $v0,0x32($s0) /* f0e1ef4: a602003e */ sh $v0,0x3e($s0) /* f0e1ef8: 01260019 */ multu $t1,$a2 /* f0e1efc: 00007012 */ mflo $t6 /* f0e1f00: a60e003c */ sh $t6,0x3c($s0) /* f0e1f04: 8faf0074 */ lw $t7,0x74($sp) /* f0e1f08: ae2f0000 */ sw $t7,0x0($s1) /* f0e1f0c: 8fb80078 */ lw $t8,0x78($sp) /* f0e1f10: 3c0f0708 */ lui $t7,0x708 /* f0e1f14: 35ef000c */ ori $t7,$t7,0xc /* f0e1f18: ae380008 */ sw $t8,0x8($s1) /* f0e1f1c: 8fb9007c */ lw $t9,0x7c($sp) /* f0e1f20: ae390004 */ sw $t9,0x4($s1) /* f0e1f24: 8fad0060 */ lw $t5,0x60($sp) /* f0e1f28: 25ae0008 */ addiu $t6,$t5,0x8 /* f0e1f2c: afae0060 */ sw $t6,0x60($sp) /* f0e1f30: adaf0000 */ sw $t7,0x0($t5) /* f0e1f34: 0c012d20 */ jal osVirtualToPhysical /* f0e1f38: afad0034 */ sw $t5,0x34($sp) /* f0e1f3c: 8fa30034 */ lw $v1,0x34($sp) /* f0e1f40: 3c0d0450 */ lui $t5,0x450 /* f0e1f44: 35ad0048 */ ori $t5,$t5,0x48 /* f0e1f48: ac620004 */ sw $v0,0x4($v1) /* f0e1f4c: 8fb80060 */ lw $t8,0x60($sp) /* f0e1f50: 02002025 */ or $a0,$s0,$zero /* f0e1f54: 27190008 */ addiu $t9,$t8,0x8 /* f0e1f58: afb90060 */ sw $t9,0x60($sp) /* f0e1f5c: af0d0000 */ sw $t5,0x0($t8) /* f0e1f60: 0c012d20 */ jal osVirtualToPhysical /* f0e1f64: afb80030 */ sw $t8,0x30($sp) /* f0e1f68: 8fa50030 */ lw $a1,0x30($sp) /* f0e1f6c: 3c18b100 */ lui $t8,0xb100 /* f0e1f70: 3c195432 */ lui $t9,0x5432 /* f0e1f74: aca20004 */ sw $v0,0x4($a1) /* f0e1f78: 8fae0060 */ lw $t6,0x60($sp) /* f0e1f7c: 37394510 */ ori $t9,$t9,0x4510 /* f0e1f80: 37182405 */ ori $t8,$t8,0x2405 /* f0e1f84: 25cf0008 */ addiu $t7,$t6,0x8 /* f0e1f88: afaf0060 */ sw $t7,0x60($sp) /* f0e1f8c: add90004 */ sw $t9,0x4($t6) /* f0e1f90: add80000 */ sw $t8,0x0($t6) /* f0e1f94: 8fbf002c */ lw $ra,0x2c($sp) /* f0e1f98: 8fb10028 */ lw $s1,0x28($sp) /* f0e1f9c: 8fb00024 */ lw $s0,0x24($sp) /* f0e1fa0: 8fa20060 */ lw $v0,0x60($sp) /* f0e1fa4: 03e00008 */ jr $ra /* f0e1fa8: 27bd0060 */ addiu $sp,$sp,0x60 ); #else // Mismatch: Goal has the if statement with empty contents Gfx *menugfxRenderGradient(Gfx *gdl, s32 x1, s32 y1, s32 x2, s32 y2, u32 colourstart, u32 colourmid, u32 colourend) { u32 *colours = gfxAllocateColours(3); struct gfxvtx *vertices = gfxAllocateVertices(6); s32 ymid; gDPPipeSync(gdl++); gDPSetCycleType(gdl++, G_CYC_1CYCLE); gDPSetAlphaCompare(gdl++, G_AC_NONE); gDPSetCombineMode(gdl++, G_CC_MODULATEI, G_CC_MODULATEI); gSPClearGeometryMode(gdl++, G_CULL_BOTH); gDPSetTextureFilter(gdl++, G_TF_BILERP); texSelect(&gdl, NULL, 2, 0, 2, 1, NULL); gDPSetRenderMode(gdl++, G_RM_XLU_SURF, G_RM_XLU_SURF2); ymid = (y1 + y2) / 2; if (x2 - x1 < ymid * 2) { ymid <<= 0; } // 0 = top left // 1 = top right // 2 = bottom right // 3 = bottom left // 4 = mid left // 5 = mid right vertices[0].z = -10; vertices[1].z = -10; vertices[2].z = -10; vertices[3].z = -10; vertices[4].z = -10; vertices[5].z = -10; vertices[0].x = x1 * 10; vertices[0].y = y1 * 10; vertices[0].colour = 0; vertices[1].x = x2 * 10; vertices[1].y = y1 * 10; vertices[1].colour = 0; vertices[2].x = x2 * 10; vertices[2].y = y2 * 10; vertices[2].colour = 4; vertices[3].x = x1 * 10; vertices[3].y = y2 * 10; vertices[3].colour = 4; vertices[4].x = x1 * 10; vertices[4].y = ymid * 10; vertices[4].colour = 8; vertices[5].x = x2 * 10; vertices[5].y = ymid * 10; vertices[5].colour = 8; colours[0] = colourstart; colours[2] = colourmid; colours[1] = colourend; gDPSetColorArray(gdl++, osVirtualToPhysical(colours), 3); gDPSetVerticeArray(gdl++, osVirtualToPhysical(vertices), 6); gDPTri4(gdl++, 0, 1, 5, 5, 4, 0, 2, 3, 4, 4, 5, 2); return gdl; } #endif Gfx *menugfxRenderSlider(Gfx *gdl, s32 x1, s32 y1, s32 x2, s32 y2, s32 markerx, u32 colour) { u32 *colours = gfxAllocateColours(3); struct gfxvtx *vertices = gfxAllocateVertices(6); gDPPipeSync(gdl++); gDPSetCycleType(gdl++, G_CYC_1CYCLE); gDPSetAlphaCompare(gdl++, G_AC_NONE); gDPSetCombineMode(gdl++, G_CC_MODULATEI, G_CC_MODULATEI); gSPClearGeometryMode(gdl++, G_CULL_BOTH); gDPSetTextureFilter(gdl++, G_TF_BILERP); texSelect(&gdl, NULL, 2, 0, 2, 1, NULL); gDPSetRenderMode(gdl++, G_RM_AA_XLU_SURF, G_RM_AA_XLU_SURF2); gDPSetRenderMode(gdl++, G_RM_XLU_SURF, G_RM_XLU_SURF2); // Marker triangle vertices[0].x = markerx * 10 - 40; vertices[0].y = y2 * 10 - 80; vertices[0].z = -10; vertices[1].x = markerx * 10 + 40; vertices[1].y = y2 * 10 - 80; vertices[1].z = -10; vertices[2].x = markerx * 10; vertices[2].y = y2 * 10 + 10; vertices[2].z = -10; vertices[0].colour = 0; vertices[1].colour = 0; vertices[2].colour = 4; // Background triangle vertices[3].x = x1 * 10; vertices[3].y = y2 * 10; vertices[3].z = -10; vertices[4].x = (s16)(x2 * 10) - 40; vertices[4].y = y1 * 10; vertices[4].z = -10; vertices[5].x = x2 * 10; vertices[5].y = y2 * 10; vertices[5].z = -10; vertices[3].colour = 8; vertices[4].colour = 8; vertices[5].colour = 8; colours[0] = (colour & 0xffffff00) | 0x4f; colours[1] = 0xffffffff; colours[2] = 0x0000ff4f; gDPSetColorArray(gdl++, osVirtualToPhysical(colours), 3); gDPSetVerticeArray(gdl++, osVirtualToPhysical(vertices), 6); gDPTri1(gdl++, 3, 4, 5); gDPPipeSync(gdl++); gDPSetRenderMode(gdl++, G_RM_AA_XLU_SURF, G_RM_AA_XLU_SURF2); gDPTri1(gdl++, 0, 1, 2); gDPPipeSync(gdl++); gDPSetRenderMode(gdl++, G_RM_XLU_SURF, G_RM_XLU_SURF2); // Line to the left of the marker: blue -> white gradient gdl = menugfxDrawLine(gdl, x1, y2, markerx, y2 + 1, 0x0000ffff, 0xffffffff); // Line to the right of the marker: solid blue gdl = menugfxDrawLine(gdl, markerx, y2, x2, y2 + 1, 0x0000ffff, 0x0000ffff); return gdl; } Gfx *menugfx0f0e2348(Gfx *gdl) { gSPSetGeometryMode(gdl++, G_CULL_BACK); gDPSetCycleType(gdl++, G_CYC_1CYCLE); gDPPipelineMode(gdl++, G_PM_1PRIMITIVE); gDPSetTextureLOD(gdl++, G_TL_TILE); gDPSetTextureLUT(gdl++, G_TT_NONE); gDPSetTextureDetail(gdl++, G_TD_CLAMP); gDPSetTexturePersp(gdl++, G_TP_PERSP); gDPSetTextureFilter(gdl++, G_TF_BILERP); gDPSetTextureConvert(gdl++, G_TC_FILT); gDPSetCombineMode(gdl++, G_CC_SHADE, G_CC_SHADE); gDPSetCombineKey(gdl++, G_CK_NONE); gDPSetAlphaCompare(gdl++, G_AC_NONE); gDPSetRenderMode(gdl++, G_RM_ZB_OPA_SURF, G_RM_ZB_OPA_SURF2); gDPSetColorDither(gdl++, G_CD_MAGICSQ); gSPSetGeometryMode(gdl++, G_ZBUFFER); return gdl; } Gfx *menugfx0f0e2498(Gfx *gdl) { gDPPipeSync(gdl++); gDPSetCycleType(gdl++, G_CYC_1CYCLE); gDPSetAlphaCompare(gdl++, G_AC_NONE); gDPSetCombineMode(gdl++, G_CC_MODULATEI, G_CC_MODULATEI); gSPClearGeometryMode(gdl++, G_CULL_BOTH); texSelect(&gdl, 0, 2, 0, 2, 1, NULL); gDPSetRenderMode(gdl++, G_RM_XLU_SURF, G_RM_XLU_SURF2); return gdl; } Gfx *menugfxDrawTri2(Gfx *gdl, s32 x1, s32 y1, s32 x2, s32 y2, u32 colour1, u32 colour2, bool arg7) { struct gfxvtx *vertices; u32 *colours; colours = gfxAllocateColours(2); vertices = gfxAllocateVertices(4); vertices[0].x = x1 * 10; vertices[0].y = y1 * 10; vertices[0].z = -10; vertices[1].x = x2 * 10; vertices[1].y = y1 * 10; vertices[1].z = -10; vertices[2].x = x2 * 10; vertices[2].y = y2 * 10; vertices[2].z = -10; vertices[3].x = x1 * 10; vertices[3].y = y2 * 10; vertices[3].z = -10; if (!arg7) { vertices[0].colour = 0; vertices[1].colour = 4; vertices[2].colour = 4; vertices[3].colour = 0; } else { vertices[0].colour = 0; vertices[1].colour = 0; vertices[2].colour = 4; vertices[3].colour = 4; } colours[0] = colour1; colours[1] = colour2; gDPSetColorArray(gdl++, osVirtualToPhysical(colours), 2); gDPSetVerticeArray(gdl++, osVirtualToPhysical(vertices), 4); gDPTri2(gdl++, 0, 1, 2, 2, 3, 0); return gdl; } Gfx *menugfxDrawLine(Gfx *gdl, s32 x1, s32 y1, s32 x2, s32 y2, u32 colour1, u32 colour2) { gdl = menugfx0f0e2498(gdl); gdl = menugfxDrawTri2(gdl, x1, y1, x2, y2, colour1, colour2, false); return gdl; } Gfx *menugfxDrawProjectedLine(Gfx *gdl, s32 x1, s32 y1, s32 x2, s32 y2, u32 colour1, u32 colour2) { s32 numfullblocks; s32 i; u32 partcolourtop; u32 partcolourbottom; s32 partbottom; s32 parttop; u32 stack[2]; if (textHasDiagonalBlend()) { if (x2 - x1 < y2 - y1) { // Portrait numfullblocks = (y2 - y1) / 15; parttop = y1; partcolourtop = textApplyProjectionColour(x1, y1, colour1); for (i = 0; i < numfullblocks; i++) { partbottom = y1 + i * 15; if (y2 - partbottom < 3) { partbottom = y2; partcolourbottom = textApplyProjectionColour(x2, partbottom, colour2); } else { partcolourbottom = colourBlend(colour2, colour1, (partbottom - y1) * 255 / (y2 - y1)); // @bug: y1 should be x1 partcolourbottom = textApplyProjectionColour(y1, partbottom, partcolourbottom); } gdl = menugfxDrawTri2(gdl, x1, parttop, x2, partbottom, partcolourtop, partcolourbottom, false); parttop = partbottom; partcolourtop = partcolourbottom; } partcolourbottom = textApplyProjectionColour(x2, y2, colour2); gdl = menugfxDrawTri2(gdl, x1, parttop, x2, y2, partcolourtop, partcolourbottom, false); } else { // Landscape s32 numfullblocks; s32 i; u32 partcolourleft; u32 partcolourright; s32 partright; s32 partleft; u32 stack[2]; numfullblocks = (x2 - x1) / 15; partleft = x1; partcolourleft = textApplyProjectionColour(x1, y1, colour1); for (i = 0; i < numfullblocks; i++) { partright = x1 + i * 15; if (x2 - partright < 3) { partright = x2; partcolourright = textApplyProjectionColour(x2, y2, colour2); } else { partcolourright = colourBlend(colour2, colour1, (partright - x1) * 255 / (x2 - x1)); partcolourright = textApplyProjectionColour(partright, y1, partcolourright); } gdl = menugfxDrawTri2(gdl, partleft, y1, partright, y2, partcolourleft, partcolourright, false); partleft = partright; partcolourleft = partcolourright; } if (partcolourtop); partcolourright = textApplyProjectionColour(x2, y2, colour2); gdl = menugfxDrawTri2(gdl, partleft, y1, x2, y2, partcolourleft, partcolourright, false); } } else { gdl = menugfxDrawTri2(gdl, x1, y1, x2, y2, colour1, colour2, false); } return gdl; } /** * Consider rendering a shimmer effect along a line, based on timing. * * Also known as the white comets that travel along the dialog borders and * within some elements in the dialog. * * The given coordinates are the coordinates of the full line. Colour is the * natural colour of the line. * * The shimmer will go right to left or bottom to top unless the reverse * argument is set to true. */ Gfx *menugfxDrawShimmer(Gfx *gdl, s32 x1, s32 y1, s32 x2, s32 y2, u32 colour, bool arg6, s32 arg7, bool reverse) { s32 shimmerleft; s32 shimmertop; s32 shimmerright; s32 shimmerbottom; s32 v0; s32 alpha; s32 minalpha; u32 tailcolour; alpha = 0; minalpha = 0; if (reverse) { v0 = 6.0f * g_20SecIntervalFrac * 600.0f; } else { v0 = (1.0f - g_20SecIntervalFrac) * 6.0f * 600.0f; } if (y2 - y1 < x2 - x1) { // Horizontal v0 += (u32)(y1 + x1); v0 %= 600; shimmerleft = x1 + v0 - arg7; shimmerright = shimmerleft + arg7; if (shimmerleft < x1) { alpha = x1 - shimmerleft; shimmerleft = x1; } if (shimmerright > x2) { minalpha = shimmerright - x2; shimmerright = x2; } if (alpha < minalpha) { alpha = minalpha; } alpha = alpha * 255 / arg7; if (alpha > 255) { alpha = 255; } if (x1 <= shimmerright && x2 >= shimmerleft) { if (arg6) { gdl = menugfx0f0e2498(gdl); } tailcolour = ((((colour & 0xff) * (0xff - alpha)) / 255) & 0xff) | 0xffffff00; if (reverse) { // Left to right gdl = menugfxDrawTri2(gdl, shimmerleft, y1, shimmerright, y2, 0xffffff00, tailcolour, 0); } else { // Right to left gdl = menugfxDrawTri2(gdl, shimmerleft, y1, shimmerright, y2, tailcolour, 0xffffff00, 0); } } } else { // Vertical v0 += (u32)(y1 + x1); v0 %= 600; shimmertop = y1 + v0 - arg7; shimmerbottom = shimmertop + arg7; if (shimmertop < y1) { alpha = y1 - shimmertop; shimmertop = y1; } if (shimmerbottom > y2) { minalpha = shimmerbottom - y2; shimmerbottom = y2; } if (alpha < minalpha) { alpha = minalpha; } alpha = alpha * 255 / arg7; if (alpha > 255) { alpha = 255; } if (y1 <= shimmerbottom && y2 >= shimmertop) { if (arg6) { gdl = menugfx0f0e2498(gdl); } tailcolour = ((((colour & 0xff) * (0xff - alpha)) / 255) & 0xff) | 0xffffff00; if (reverse) { // Top to bottom gdl = menugfxDrawTri2(gdl, x1, shimmertop, x2, shimmerbottom, 0xffffff00, tailcolour, 1); } else { // Bottom to top gdl = menugfxDrawTri2(gdl, x1, shimmertop, x2, shimmerbottom, tailcolour, 0xffffff00, 1); } } } return gdl; } Gfx *menugfxDrawDialogBorderLine(Gfx *gdl, s32 x1, s32 y1, s32 x2, s32 y2, u32 colour1, u32 colour2) { gdl = menugfxDrawLine(gdl, x1, y1, x2, y2, colour1, colour2); gdl = menugfxDrawShimmer(gdl, x1, y1, x2, y2, colour1, 0, 10, false); return gdl; } Gfx *menugfxDrawFilledRect(Gfx *gdl, s32 x1, s32 y1, s32 x2, s32 y2, u32 colour1, u32 colour2) { gdl = menugfx0f0e2498(gdl); gdl = menugfxDrawProjectedLine(gdl, x1, y1, x2, y2, colour1, colour2); gdl = menugfxDrawShimmer(gdl, x1, y1, x2, y2, colour1, 0, 10, false); return gdl; } /** * Draw a chevron/arrow using a simple triangle. * * Used for the left/right arrows on the Combat Simulator head/body selectors. * * The x and y arguments refer to the apex of the chevron. Size is the distance * from the apex to the opposite side. */ Gfx *menugfxDrawCarouselChevron(Gfx *gdl, s32 x, s32 y, s32 size, s32 direction, u32 colour1, u32 colour2) { struct gfxvtx *vertices; u32 *colours; s16 halfwidth; s16 halfheight; s16 relx; s16 rely; relx = 0; rely = 0; halfwidth = 0; halfheight = 0; size *= 10; switch (direction) { case 0: // Down rely = -size; halfwidth = -size / 2; break; case 1: // Left relx = size; halfheight = -size / 2; break; case 2: // Up rely = size; halfwidth = size / 2; break; case 3: // Right relx = size * -1; halfheight = size / 2; break; } colours = gfxAllocateColours(2); vertices = gfxAllocateVertices(3); gDPPipeSync(gdl++); gDPSetCycleType(gdl++, G_CYC_1CYCLE); gDPSetAlphaCompare(gdl++, G_AC_NONE); gDPSetCombineMode(gdl++, G_CC_MODULATEI, G_CC_MODULATEI); gSPClearGeometryMode(gdl++, G_CULL_BOTH); texSelect(&gdl, NULL, 2, 0, 2, 1, NULL); gDPSetRenderMode(gdl++, G_RM_XLU_SURF, G_RM_XLU_SURF2); vertices[0].x = x * 10; vertices[0].y = y * 10; vertices[0].z = -10; vertices[1].x = x * 10 + relx + halfwidth; vertices[1].y = y * 10 + rely + halfheight; vertices[1].z = -10; vertices[2].x = x * 10 + relx - halfwidth; vertices[2].y = y * 10 + rely - halfheight; vertices[2].z = -10; vertices[0].colour = 0; vertices[1].colour = 4; vertices[2].colour = 4; colours[0] = colour1; colours[1] = colour2; gDPSetColorArray(gdl++, osVirtualToPhysical(colours), 2); gDPSetVerticeArray(gdl++, osVirtualToPhysical(vertices), 3); gDPTri1(gdl++, 0, 1, 2); return gdl; } /** * Draw a chevron/arrow for dialogs. * * These chevons are drawn with two triangles, and the middle rear vertex's * position can be adjusted on each frame to create an animated chevron. * * The x and y arguments refer to the apex of the chevron. Size is the distance * from the apex to the opposite side. */ Gfx *menugfxDrawDialogChevron(Gfx *gdl, s32 x, s32 y, s32 size, s32 direction, u32 colour1, u32 colour2, f32 arg7) { u32 stack; u32 *colours; struct gfxvtx *vertices; s16 halfwidth; s16 halfheight; s16 relx; s16 rely; relx = 0; rely = 0; halfwidth = 0; halfheight = 0; size *= 10; switch (direction) { case 0: // Down rely = -size; halfwidth = -((s32)(size * arg7 * 0.5f) + size) / 2; break; case 1: // Left relx = size; halfheight = -((s32)(size * arg7 * 0.5f) + size) / 2; break; case 2: // Up rely = size; halfwidth = ((s32)(size * arg7 * 0.5f) + size) / 2; break; case 3: // Right relx = -size; halfheight = ((s32)(size * arg7 * 0.5f) + size) / 2; break; } colours = gfxAllocateColours(2); vertices = gfxAllocateVertices(4); gDPPipeSync(gdl++); gDPSetCycleType(gdl++, G_CYC_1CYCLE); gDPSetAlphaCompare(gdl++, G_AC_NONE); gDPSetCombineMode(gdl++, G_CC_MODULATEI, G_CC_MODULATEI); gSPClearGeometryMode(gdl++, G_CULL_BOTH); texSelect(&gdl, NULL, 2, 0, 2, 1, NULL); gDPSetRenderMode(gdl++, G_RM_AA_XLU_SURF, G_RM_AA_XLU_SURF2); // Apex vertices[0].x = x * 10; vertices[0].y = y * 10; vertices[0].z = -10; vertices[1].x = x * 10 + relx + halfwidth; vertices[1].y = y * 10 + rely + halfheight; vertices[1].z = -10; vertices[2].x = x * 10 + relx - halfwidth; vertices[2].y = y * 10 + rely - halfheight; vertices[2].z = -10; relx = (relx / 3.0f + (relx * 1.5f * (1.0f - arg7)) / 3.0f); rely = rely / 3.0f + (rely * 1.5f * (1.0f - arg7)) / 3.0f; // Middle vertex vertices[3].x = x * 10 + relx; vertices[3].y = y * 10 + rely; vertices[3].z = -10; vertices[0].colour = 0; vertices[1].colour = 4; vertices[2].colour = 4; vertices[3].colour = 4; colours[0] = colour1; colours[1] = colour2; gDPSetColorArray(gdl++, osVirtualToPhysical(colours), 2); gDPSetVerticeArray(gdl++, osVirtualToPhysical(vertices), 4); gDPTri2(gdl++, 0, 1, 3, 3, 2, 0); return gdl; } Gfx *menugfxDrawCheckbox(Gfx *gdl, s32 x, s32 y, s32 size, bool fill, u32 bordercolour, u32 fillcolour) { if (fill) { gdl = textSetPrimColour(gdl, fillcolour); gDPFillRectangleScaled(gdl++, x, y, x + size, y + size); gdl = text0f153838(gdl); } gdl = textSetPrimColour(gdl, bordercolour); gDPFillRectangleScaled(gdl++, x, y, x + size + 1, y + 1); gDPFillRectangleScaled(gdl++, x, y + size, x + size + 1, y + size + 1); gDPFillRectangleScaled(gdl++, x, y + 1, x + 1, y + size); gDPFillRectangleScaled(gdl++, x + size, y + 1, x + size + 1, y + size); gdl = text0f153838(gdl); return gdl; } Gfx *menugfxRenderBgFailure(Gfx *gdl) { f32 spb4; s32 i; f32 angle; s32 s0; s32 s1; s32 s2; s32 s3; s32 s6; s32 s7; u32 alpha1; u32 alpha2; spb4 = M_TAU * g_20SecIntervalFrac; var8009de98 = var8009de9c = 0; gdl = func0f0d4a3c(gdl, 0); var8009de90 = -100000; var8009de94 = 100000; gdl = menugfxDrawPlane(gdl, -10000, 0, 10000, 0, 0x00007f7f, 0x00007f7f, MENUPLANE_04); gdl = menugfxDrawPlane(gdl, -10000, 300, 10000, 300, 0x00007f7f, 0x00007f7f, MENUPLANE_04); for (i = 0; i < 3; i++) { angle = (2.0f * i * M_PI) / 3.0f + spb4; s6 = sinf(angle) * 600.0f; s3 = cosf(angle) * 600.0f; angle += 0.52359879016876f; s2 = sinf(angle) * 600.0f; s0 = cosf(angle) * 600.0f; angle += 0.52359879016876f; s1 = sinf(angle) * 600.0f; s7 = cosf(angle) * 600.0f; s6 += 160; s2 += 160; s1 += 160; s3 += 120; s0 += 120; s7 += 120; gdl = menugfxDrawPlane(gdl, s6, s3, s2, s0, 0xff000040, 0xff00007f, MENUPLANE_02); gdl = menugfxDrawPlane(gdl, s2, s0, s1, s7, 0xff00007f, 0xff000040, MENUPLANE_03); angle = -2.0f * spb4 + (2.0f * i * M_PI) / 3.0f; s6 = sinf(angle) * 600.0f; s3 = cosf(angle) * 600.0f; angle += 0.17453293502331f; s2 = sinf(angle) * 600.0f; s0 = cosf(angle) * 600.0f; angle += 0.099733099341393f; s1 = sinf(angle) * 600.0f; s7 = cosf(angle) * 600.0f; s6 += 160; s2 += 160; s1 += 160; s3 += 120; s0 += 120; s7 += 120; alpha1 = menuGetCosOscFrac(4) * 127.0f; alpha2 = menuGetCosOscFrac(4) * 55.0f; gdl = menugfxDrawPlane(gdl, s6, s3, s2, s0, 0xffff0000 | alpha2, 0xffff0000 | alpha1, MENUPLANE_02); gdl = menugfxDrawPlane(gdl, s2, s0, s1, s7, 0xffff0000 | alpha1, 0xffff0000 | alpha2, MENUPLANE_03); angle = -2.0f * spb4 + (2.0f * i * M_PI) / 3.0f + M_PI; s6 = sinf(angle) * 600.0f; s3 = cosf(angle) * 600.0f; angle += 0.17453293502331f; s2 = sinf(angle) * 600.0f; s0 = cosf(angle) * 600.0f; angle += 0.099733099341393f; s1 = sinf(angle) * 600.0f; s7 = cosf(angle) * 600.0f; s6 += 160; s2 += 160; s1 += 160; s3 += 120; s0 += 120; s7 += 120; alpha1 = (1.0f - menuGetCosOscFrac(4)) * 99.0f; alpha2 = (1.0f - menuGetCosOscFrac(4)) * 33.0f; gdl = menugfxDrawPlane(gdl, s6, s3, s2, s0, 0xffffff00 | alpha2, 0xffffff00 | alpha1, MENUPLANE_02); gdl = menugfxDrawPlane(gdl, s2, s0, s1, s7, 0xffffff00 | alpha1, 0xffffff00 | alpha2, MENUPLANE_03); } gdl = func0f0d4c80(gdl); return gdl; } /** * Draw the background for the Combat Simulator menus. * * The background has two "cones" being projected into the camera's eye and * rotating in opposite directions. */ Gfx *menugfxRenderBgCone(Gfx *gdl) { f32 baseangle; f32 angle; s32 x1; s32 y1; s32 x2; s32 y2; s32 i; u32 colourupper; u32 colour; // Cone 1 baseangle = M_TAU * g_20SecIntervalFrac * 2.0f; colourupper = (u32) (menuGetSinOscFrac(1.0f) * 255.0f) << 16; gdl = func0f0d4a3c(gdl, 0); if (1); var8009de90 = -100000; var8009de94 = 100000; for (i = 0; i < 8; i++) { angle = baseangle + i * 2.0f * M_PI * 0.125f; x1 = 600.0f * sinf(angle); y1 = 600.0f * cosf(angle); x2 = 600.0f * sinf(angle + 0.78539818525314f); y2 = 600.0f * cosf(angle + 0.78539818525314f); x1 += 160; x2 += 160; y1 += 120; y2 += 120; colour = colourupper | 0xff00007f; gdl = menugfxDrawPlane(gdl, x1, y1, x2, y2, colour, colour, MENUPLANE_08); } // Cone 2 colourupper = (u32) (255.0f - menuGetCosOscFrac(1.0f) * 255.0f) << 16; baseangle = M_TAU * g_20SecIntervalFrac; if (1); for (i = 0; i < 8; i++) { if (gdl && gdl); angle = -baseangle + 2.0f * i * M_PI * 0.125f; x1 = 600.0f * sinf(angle); y1 = 600.0f * cosf(angle); x2 = 600.0f * sinf(angle + 0.78539818525314f); y2 = 600.0f * cosf(angle + 0.78539818525314f); x1 += 160; x2 += 160; y1 += 120; y2 += 120; colour = colourupper | 0xff00007f; gdl = menugfxDrawPlane(gdl, x1, y1, x2, y2, colour, colour, MENUPLANE_09); } gdl = func0f0d4c80(gdl); return gdl; } /** * Fill the framebuffer with a transparent green overlay. * * The amount of transparency varies from frame to frame. It's quite volatile. * * This function is not called. */ Gfx *func0f0e458c(Gfx *gdl) { var8009de98 = 0; var8009de9c = -20 - viGetHeight() / 2; gdl = func0f0d4a3c(gdl, 0); var8009de90 = -100000; var8009de94 = 100000; gdl = menugfxDrawPlane(gdl, -1000, viGetHeight() + 10, 2000, viGetHeight() + 10, 0x00ff00bf, 0x00ff00bf, MENUPLANE_06); gdl = menugfxDrawPlane(gdl, -1000, viGetHeight() + 10, 2000, viGetHeight() + 10, 0xffff00af, 0xffff00af, MENUPLANE_05); gdl = func0f0d4c80(gdl); var8009de98 = var8009de9c = 0; return gdl; } Gfx *func0f0e46b0(Gfx *gdl, f32 arg1) { s32 y1 = (var8009de9c + 120) + arg1 * (0.0f - (var8009de9c + 120)); s32 y2 = (var8009de9c + 120) + arg1 * (240.0f - (var8009de9c + 120)); gdl = func0f0d4a3c(gdl, 0); var8009de90 = -100000; var8009de94 = 100000; gdl = menugfxDrawPlane(gdl, -1000, y1, 2000, y1, 0xffff007f, 0xffff007f, MENUPLANE_05); gdl = menugfxDrawPlane(gdl, -1000, y1, 2000, y1, 0x00aa007f, 0x00aa007f, MENUPLANE_06); gdl = menugfxDrawPlane(gdl, -1000, y2, 2000, y2, 0xffff007f, 0xffff007f, MENUPLANE_05); gdl = menugfxDrawPlane(gdl, -1000, y2, 2000, y2, 0x00aa007f, 0x00aa007f, MENUPLANE_06); gdl = func0f0d4c80(gdl); return gdl; } /** * This is an exact copy of menugfxRenderBgFailure. */ Gfx *menugfxRenderBgFailureCopy(Gfx *gdl) { f32 spb4; s32 i; f32 angle; s32 s0; s32 s1; s32 s2; s32 s3; s32 s6; s32 s7; u32 alpha1; u32 alpha2; spb4 = M_TAU * g_20SecIntervalFrac; var8009de98 = var8009de9c = 0; gdl = func0f0d4a3c(gdl, 0); var8009de90 = -100000; var8009de94 = 100000; gdl = menugfxDrawPlane(gdl, -10000, 0, 10000, 0, 0x00007f7f, 0x00007f7f, MENUPLANE_04); gdl = menugfxDrawPlane(gdl, -10000, 300, 10000, 300, 0x00007f7f, 0x00007f7f, MENUPLANE_04); for (i = 0; i < 3; i++) { angle = (2.0f * i * M_PI) / 3.0f + spb4; s6 = sinf(angle) * 600.0f; s3 = cosf(angle) * 600.0f; angle += 0.52359879016876f; s2 = sinf(angle) * 600.0f; s0 = cosf(angle) * 600.0f; angle += 0.52359879016876f; s1 = sinf(angle) * 600.0f; s7 = cosf(angle) * 600.0f; s6 += 160; s2 += 160; s1 += 160; s3 += 120; s0 += 120; s7 += 120; gdl = menugfxDrawPlane(gdl, s6, s3, s2, s0, 0xff000040, 0xff00007f, MENUPLANE_02); gdl = menugfxDrawPlane(gdl, s2, s0, s1, s7, 0xff00007f, 0xff000040, MENUPLANE_03); angle = -2.0f * spb4 + (2.0f * i * M_PI) / 3.0f; s6 = sinf(angle) * 600.0f; s3 = cosf(angle) * 600.0f; angle += 0.17453293502331f; s2 = sinf(angle) * 600.0f; s0 = cosf(angle) * 600.0f; angle += 0.099733099341393f; s1 = sinf(angle) * 600.0f; s7 = cosf(angle) * 600.0f; s6 += 160; s2 += 160; s1 += 160; s3 += 120; s0 += 120; s7 += 120; alpha1 = menuGetCosOscFrac(4) * 127.0f; alpha2 = menuGetCosOscFrac(4) * 55.0f; gdl = menugfxDrawPlane(gdl, s6, s3, s2, s0, 0xffff0000 | alpha2, 0xffff0000 | alpha1, MENUPLANE_02); gdl = menugfxDrawPlane(gdl, s2, s0, s1, s7, 0xffff0000 | alpha1, 0xffff0000 | alpha2, MENUPLANE_03); angle = -2.0f * spb4 + (2.0f * i * M_PI) / 3.0f + M_PI; s6 = sinf(angle) * 600.0f; s3 = cosf(angle) * 600.0f; angle += 0.17453293502331f; s2 = sinf(angle) * 600.0f; s0 = cosf(angle) * 600.0f; angle += 0.099733099341393f; s1 = sinf(angle) * 600.0f; s7 = cosf(angle) * 600.0f; s6 += 160; s2 += 160; s1 += 160; s3 += 120; s0 += 120; s7 += 120; alpha1 = (1.0f - menuGetCosOscFrac(4)) * 99.0f; alpha2 = (1.0f - menuGetCosOscFrac(4)) * 33.0f; gdl = menugfxDrawPlane(gdl, s6, s3, s2, s0, 0xffffff00 | alpha2, 0xffffff00 | alpha1, MENUPLANE_02); gdl = menugfxDrawPlane(gdl, s2, s0, s1, s7, 0xffffff00 | alpha1, 0xffffff00 | alpha2, MENUPLANE_03); } gdl = func0f0d4c80(gdl); return gdl; } struct coord *g_MenuParticles = NULL; /** * Menu particles are stored in gunmem. Gunmem doesn't need to be freed because * the memory gets reused for other things, so all that needs to happen here is * clearing the pointer that the menugfx system maintains. */ void menugfxFreeParticles(void) { g_MenuParticles = NULL; } u32 menugfxGetParticleArraySize(void) { return align16(NUM_SUCCESS_PARTICLES * sizeof(struct coord)); } /** * Render the "success" background, which is used on the solo mission completed * endscreen. * * The endscreen features two haze layers, and a bunch of particles (stars?) * flying towards the camera. * * In the Defense stage, everything is gray and the particles move slower. */ Gfx *menugfxRenderBgSuccess(Gfx *gdl) { Mtxf sp110; Mtxf *modelmtx; u32 *colours; u32 *ptr; s32 i; s32 j; f32 f0; f32 speed = 5.0f; bool gray = false; if (g_StageIndex == STAGEINDEX_DEFENSE) { speed = 2.0f; gray = true; } // Initialise particles if they haven't been already if (g_MenuParticles == NULL) { g_MenuParticles = (struct coord *) bgunGetGunMem(); if (g_MenuParticles == NULL) { return gdl; } for (i = 0; i < NUM_SUCCESS_PARTICLES; i++) { do { g_MenuParticles[i].x = RANDOMFRAC() * 10000.0f - 5000.0f; g_MenuParticles[i].y = RANDOMFRAC() * 10000.0f - 5000.0f; } while (g_MenuParticles[i].x < 640.0f && g_MenuParticles[i].x > -640.0f && g_MenuParticles[i].y < 480.0f && g_MenuParticles[i].y > -480.0f); g_MenuParticles[i].z = -RANDOMFRAC() * 8000.0f; } } // Move the particles closer, and reset the ones which have gone behind the camera for (i = 0; i < NUM_SUCCESS_PARTICLES; i++) { s32 mult = (i % 5) + 1; #if VERSION >= VERSION_PAL_BETA g_MenuParticles[i].z += mult * g_Vars.diffframe240freal * speed; #else g_MenuParticles[i].z += mult * g_Vars.diffframe240f * speed; #endif if (g_MenuParticles[i].z > 0.0f) { do { g_MenuParticles[i].x = RANDOMFRAC() * 10000.0f - 5000.0f; g_MenuParticles[i].y = RANDOMFRAC() * 10000.0f - 5000.0f; } while (g_MenuParticles[i].x < 640.0f && g_MenuParticles[i].x > -640.0f && g_MenuParticles[i].y < 480.0f && g_MenuParticles[i].y > -480.0f); g_MenuParticles[i].z = -8000.0f - RANDOMFRAC() * 500.0f; } } f0 = menuGetLinearIntervalFrac(10.0f); // Draw the two haze layers var8009de98 = 0; var8009de9c = 0; gdl = func0f0d4a3c(gdl, 0); var8009de90 = -100000; var8009de94 = 100000; if (gray) { gdl = menugfxDrawPlane(gdl, -1000, -10, 2000, -10, 0x6060607f, 0x6060607f, MENUPLANE_05); gdl = menugfxDrawPlane(gdl, -1000, viGetHeight() + 10, 2000, viGetHeight() + 10, 0x9090907f, 0x9090907f, MENUPLANE_05); } else { gdl = menugfxDrawPlane(gdl, -1000, -10, 2000, -10, 0x0000947f, 0x0000947f, MENUPLANE_10); gdl = menugfxDrawPlane(gdl, -1000, viGetHeight() + 10, 2000, viGetHeight() + 10, 0x6200947f, 0x6200947f, MENUPLANE_06); } // Prepare stuff for drawing the particles gdl = func0f0d4c80(gdl); gdl = func0f0d49c8(gdl); texSelect(&gdl, &g_TexGeneralConfigs[1], 2, 1, 2, true, NULL); gDPSetCycleType(gdl++, G_CYC_1CYCLE); gDPSetColorDither(gdl++, G_CD_DISABLE); gDPSetRenderMode(gdl++, G_RM_AA_ZB_XLU_SURF, G_RM_AA_ZB_XLU_SURF2); gDPSetAlphaCompare(gdl++, G_AC_NONE); gDPSetTextureLOD(gdl++, G_TL_TILE); gDPSetTextureConvert(gdl++, G_TC_FILT); gDPSetCombineLERP(gdl++, 0, 0, 0, SHADE, TEXEL0, 0, SHADE, 0, 0, 0, 0, SHADE, TEXEL0, 0, SHADE, 0); gDPSetTextureFilter(gdl++, G_TF_BILERP); gDPSetTexturePersp(gdl++, G_TP_PERSP); mtx4LoadIdentity(&sp110); modelmtx = gfxAllocateMatrix(); mtx00016054(&sp110, modelmtx); gSPMatrix(gdl++, osVirtualToPhysical(modelmtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); colours = gfxAllocateColours(20); if (gray) { for (j = 0, ptr = colours; j < 5;) { ptr[0] = 0xffffff00 | ((5 - j) * 127u / 5); ptr += 4; j++; } for (j = 0, ptr = colours; j < 5;) { ptr[1] = 0xaaaaaa00 | ((5 - j) * 16u / 5); ptr += 4; j++; } for (j = 0, ptr = colours; j < 5;) { ptr[2] = 0xffffff00 | ((5 - j) * 127u / 5); ptr += 4; j++; } for (j = 0, ptr = colours; j < 5;) { ptr[3] = 0xaaaaaa00 | ((5 - j) * 16u / 5); ptr += 4; j++; } } else { for (j = 0, ptr = colours; j < 5;) { ptr[0] = 0xffffff00 | ((5 - j) * 127u / 5); ptr += 4; j++; } for (j = 0, ptr = colours; j < 5;) { ptr[1] = 0xaaaaff00 | ((5 - j) * 16u / 5); ptr += 4; j++; } for (j = 0, ptr = colours; j < 5;) { ptr[2] = 0xffffff00 | ((5 - j) * 127u / 5); ptr += 4; j++; } for (j = 0, ptr = colours; j < 5;) { if (colours); ptr[3] = 0xffaaff00 | ((5 - j) * 16u / 5); ptr += 4; j++; } } { struct coord pos; u32 stack[5]; gDPSetColorArray(gdl++, osVirtualToPhysical(colours), 20); // Draw the particles for (i = NUM_SUCCESS_PARTICLES - 1; i >= 0; i--) { s32 s3 = 0; f32 sine = sinf(f0 * M_BADTAU + M_BADTAU * (i / 15.0f)); f32 cosine = cosf(f0 * M_BADTAU + M_BADTAU * (i / 15.0f)); pos.x = g_MenuParticles[i].x; pos.y = g_MenuParticles[i].y; pos.z = g_MenuParticles[i].z; if (pos.z < -6600.0f) { s3 = -(pos.f[2] + 6600.0f) / 1400.0f * 5.0f; } if (pos.z); if (pos.z < 0.0f && s3 < 6) { f32 invsine2 = -sine; f32 invsine = -sine; f32 invcosine = -cosine; struct gfxvtx *vertices = gfxAllocateVertices(5); vertices[0].x = pos.f[0]; vertices[0].y = pos.f[1]; vertices[0].z = pos.f[2]; vertices[1].x = pos.f[0] + 25.0f * (sine + cosine); vertices[1].y = pos.f[1] + 25.0f * (cosine + invsine); vertices[1].z = pos.f[2]; vertices[2].x = pos.f[0] + 25.0f * (sine - cosine); vertices[2].y = pos.f[1] + 25.0f * (cosine - invsine); vertices[2].z = pos.f[2]; vertices[3].x = pos.f[0] + 25.0f * (invsine - cosine); vertices[3].y = pos.f[1] + 25.0f * (invcosine - invsine); vertices[3].z = pos.f[2]; vertices[4].x = pos.f[0] + 25.0f * (invsine2 + cosine); vertices[4].y = pos.f[1] + 25.0f * (invcosine + invsine); vertices[4].z = pos.f[2]; vertices[0].colour = (s3 * 4 + (i % 2) * 2) * 4; vertices[1].colour = (s3 * 4 + (i % 2) * 2 + 1) * 4; vertices[2].colour = (s3 * 4 + (i % 2) * 2 + 1) * 4; vertices[3].colour = (s3 * 4 + (i % 2) * 2 + 1) * 4; vertices[4].colour = (s3 * 4 + (i % 2) * 2 + 1) * 4; gDPSetVerticeArray(gdl++, osVirtualToPhysical(vertices), 5); gDPTri4(gdl++, 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 1); } } } gdl = func0f0d479c(gdl); return gdl; }