#include #include "constants.h" #include "game/dlights.h" #include "game/game_006900.h" #include "game/atan2f.h" #include "game/savebuffer.h" #include "game/sky.h" #include "game/bondview.h" #include "game/game_1531a0.h" #include "game/gfxmemory.h" #include "game/lang.h" #include "game/options.h" #include "bss.h" #include "lib/vi.h" #include "lib/joy.h" #include "lib/main.h" #include "lib/rng.h" #include "lib/str.h" #include "lib/mtx.h" #include "data.h" #include "types.h" #include "gbiex.h" #ifdef AVOID_UB char var800a41c0[26]; #else char var800a41c0[24]; #endif u8 g_IrScanlines[2][480]; #if VERSION < VERSION_NTSC_1_0 u8 var800a8b58nb[0x1c0]; #endif s32 var8007f840 = 0; u8 var8007f844 = 0; u8 var8007f848 = 0; s32 g_IrBinocularRadius = PAL ? 102 : 90; s32 var8007f850 = 3; u32 var8007f854 = 0x00000000; u32 var8007f858 = 0xb8000000; u32 var8007f85c = 0x00000000; #if VERSION < VERSION_NTSC_1_0 void func0f13c2d0nb(void) { mainOverrideVariable("fsrad", (u32 *)&g_IrBinocularRadius); mainOverrideVariable("fscs", (u32 *)&var8007f850); } #endif Gfx *bviewDrawIrRect(Gfx *gdl, s32 x1, s32 y1, s32 x2, s32 y2) { gDPFillRectangle(gdl++, x1, y1, x2, y2); return gdl; } Gfx *bview0f141864(Gfx *gdl, s32 arg1, s32 arg2, s32 arg3, s32 arg4, s32 arg5) { s32 value = viGetWidth() * arg2 + arg4; gDPPipeSync(gdl++); gDPSetTextureImage(gdl++, G_IM_FMT_I, G_IM_SIZ_8b, SCREEN_320, value * 2 + arg1); gDPLoadSync(gdl++); gDPLoadBlock(gdl++, arg3, 0, 0, arg5 - 1, 0); return gdl; } Gfx *bview0f141940(Gfx *gdl, s32 arg1, s32 arg2, s32 tile, s32 arg4, s32 width) { s32 value = viGetWidth() * arg2 + arg4; gDPPipeSync(gdl++); gDPSetTextureImage(gdl++, G_IM_FMT_RGBA, G_IM_SIZ_16b, width, value * 2 + arg1); gDPLoadSync(gdl++); gDPLoadBlock(gdl++, tile, 0, 0, width - 1, 0); return gdl; } Gfx *bview0f141a20(Gfx *gdl, s32 top, s32 height, s32 left, s32 width) { gDPPipeSync(gdl++); gSPTextureRectangle(gdl++, left << 2, top << 2, (left + width) << 2, (top + 1) << 2, G_TX_RENDERTILE, 0, 0, height * 1024, 1024); return gdl; } Gfx *bviewCopyPixels(Gfx *gdl, u16 *fb, s32 top, u32 tile, s32 arg4, f32 arg5, s32 left, s32 width) { #ifdef PLATFORM_N64 uintptr_t image; s32 width2; s32 numparts; s32 lrs[1]; if (width > SCREEN_WIDTH_LO) { numparts = 2; lrs[0] = width / numparts; image = (uintptr_t) &fb[viGetWidth() * top + left] & 0x00ffffff; gDPSetTextureImage(gdl++, G_IM_FMT_RGBA, G_IM_SIZ_16b, SCREEN_320, image); gDPLoadBlock(gdl++, tile, 0, 0, width / numparts - 1, 0); gSPTextureRectangle(gdl++, left << 2, arg4 << 2, ((s32) left + width / numparts) << 2, (arg4 + 1) << 2, G_TX_RENDERTILE, (s32) ((width - width / arg5) * 16.0f), 0, (s32) (1024.0f / arg5), 1024); left += lrs[0]; image = (uintptr_t) &fb[viGetWidth() * top + left] & 0x00ffffff; gDPSetTextureImage(gdl++, G_IM_FMT_RGBA, G_IM_SIZ_16b, SCREEN_320, image); gDPLoadBlock(gdl++, tile, 0, 0, lrs[0] - 1, 0); gSPTextureRectangle(gdl++, left << 2, arg4 << 2, (left + lrs[0]) << (0, 2), (arg4 + 1) << 2, G_TX_RENDERTILE, 0, 0, (s32) (1024.0f / arg5), 1024); } else { width2 = width; image = (uintptr_t) &fb[viGetWidth() * top + left] & 0x00ffffff; gDPSetTextureImage(gdl++, G_IM_FMT_RGBA, G_IM_SIZ_16b, SCREEN_320, image); gDPLoadBlock(gdl++, tile, 0, 0, width2 - 1, 0); numparts = (s32) (1024.0f / arg5); gSPTextureRectangle(gdl++, left << 2, arg4 << 2, (left + width2) << 2, (arg4 + 1) << 2, G_TX_RENDERTILE, (s32) ((width - width / arg5) * 16.0f), 0, numparts, 1024); } return gdl; #else // PLATFORM_N64 // TODO: add an extended GBI opcode for this return gdl; #endif // PLATFORM_N64 } Gfx *bviewDrawFisheyeRect(Gfx *gdl, s32 arg1, f32 arg2, s32 arg3, s32 arg4) { if (arg2 < 1) { f32 tmp = arg4 * 0.5f; f32 fVar4 = arg3 + tmp; f32 fVar7 = (s32)(arg2 * tmp); gDPFillRectangle(gdl++, arg3, arg1, fVar4 - fVar7, arg1 + 1); gDPFillRectangle(gdl++, fVar4 + fVar7, arg1, arg3 + arg4, arg1 + 1); } return gdl; } Gfx *bviewPrepareStaticRgba16(Gfx *gdl, u32 colour, u32 alpha) { static u32 envcol = 0xffffffff; static u32 primcol = 0x7f7f7fff; mainOverrideVariable("envcol", &envcol); mainOverrideVariable("primcol", &primcol); gDPPipeSync(gdl++); gDPSetTile(gdl++, G_IM_FMT_RGBA, G_IM_SIZ_16b, 0, 0x0000, 5, 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); gDPSetCycleType(gdl++, G_CYC_1CYCLE); gSPTexture(gdl++, 0xffff, 0xffff, 0, G_TX_RENDERTILE, G_ON); gDPSetTextureLOD(gdl++, G_TL_TILE); gDPSetTextureDetail(gdl++, G_TD_CLAMP); gDPSetTextureLUT(gdl++, G_TT_NONE); gDPSetTile(gdl++, G_IM_FMT_RGBA, G_IM_SIZ_16b, 160, 0, G_TX_RENDERTILE, 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); gDPSetTileSize(gdl++, G_TX_RENDERTILE, 0, 0, 0x0800, 0x0020); gDPSetTextureFilter(gdl++, G_TF_POINT); gDPSetColor(gdl++, G_SETENVCOLOR, (colour & 0xffffff00) | (alpha & 0xff)); gDPSetCombineLERP(gdl++, TEXEL0, 0, ENVIRONMENT, 0, 0, 0, 0, ENVIRONMENT, TEXEL0, 0, ENVIRONMENT, 0, 0, 0, 0, ENVIRONMENT); gDPSetTexturePersp(gdl++, G_TP_NONE); gDPSetColorDither(gdl++, G_CD_DISABLE); gDPSetAlphaDither(gdl++, G_AD_NOISE); gDPSetRenderMode(gdl++, G_RM_CLD_SURF, G_RM_NOOP2); return gdl; } Gfx *bviewPrepareStaticI8(Gfx *gdl, u32 colour, u32 alpha) { static u32 envcol = 0xffffffff; static u32 primcol = 0x7f7f7fff; mainOverrideVariable("envcol", &envcol); mainOverrideVariable("primcol", &primcol); gDPPipeSync(gdl++); gDPSetTile(gdl++, G_IM_FMT_RGBA, G_IM_SIZ_8b, 0, 0x0000, 5, 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); gDPSetCycleType(gdl++, G_CYC_1CYCLE); gSPTexture(gdl++, 0xffff, 0xffff, 0, G_TX_RENDERTILE, G_ON); gDPSetTextureLOD(gdl++, G_TL_TILE); gDPSetTextureDetail(gdl++, G_TD_CLAMP); gDPSetTextureLUT(gdl++, G_TT_NONE); gDPSetTile(gdl++, G_IM_FMT_I, G_IM_SIZ_8b, 160, 0, G_TX_RENDERTILE, 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); gDPSetTileSize(gdl++, G_TX_RENDERTILE, 0, 0, 0x0800, 0x0020); gDPSetTextureFilter(gdl++, G_TF_POINT); gDPSetColor(gdl++, G_SETENVCOLOR, (colour & 0xffffff00) | (alpha & 0xff)); gDPSetCombineLERP(gdl++, TEXEL0, 0, ENVIRONMENT, 0, 0, 0, 0, ENVIRONMENT, TEXEL0, 0, ENVIRONMENT, 0, 0, 0, 0, ENVIRONMENT); gDPSetTexturePersp(gdl++, G_TP_NONE); gDPSetColorDither(gdl++, G_CD_DISABLE); gDPSetAlphaDither(gdl++, G_AD_NOISE); gDPSetRenderMode(gdl++, G_RM_CLD_SURF, G_RM_NOOP2); return gdl; } Gfx *bviewDrawMotionBlur(Gfx *gdl, u32 colour, u32 alpha) { u16 *fb = viGetFrontBuffer(); s32 viewtop = viGetViewTop(); s32 viewheight = viGetViewHeight(); f32 fxxx; f32 fyyy; s32 viewwidth = viGetViewWidth(); s32 viewleft = viGetViewLeft(); f32 somefloat; s32 newalpha; s32 i; static u32 sfyyy = 1000; static u32 sfxxx = 1000; if (var8007f848) { return gdl; } var8007f848 = true; newalpha = alpha; newalpha += var8007f844; if (newalpha > 230) { newalpha = 230; } var8007f844 = 0; mainOverrideVariable("sfxxx", &sfxxx); fxxx = sfxxx / 1000.0f; mainOverrideVariable("sfyyy", &sfyyy); fyyy = sfyyy / 1000.0f; gDPPipeSync(gdl++); somefloat = (viewheight - viewheight / fyyy) * 0.5f; gdl = bviewPrepareStaticRgba16(gdl, colour, newalpha); for (i = viewtop; i < viewtop + viewheight; i++) { gdl = bviewCopyPixels(gdl, fb, viewtop + (s32)somefloat, 5, i, fxxx, viewleft, viewwidth); somefloat += 1.0f / fyyy; } return gdl; } /** * Draw static for the Infiltration intro cutscene and Slayer rockets. */ Gfx *bviewDrawStatic(Gfx *gdl, u32 arg1, s32 arg2) { u16 *fb = viGetFrontBuffer(); s32 viewtop = viGetViewTop(); s32 viewheight = viGetViewHeight(); s32 viewwidth = viGetViewWidth(); s32 viewleft = viGetViewLeft(); u16 *fb2 = (u16 *) PHYS_TO_K0(random() & 0xfff00); s32 y; gDPPipeSync(gdl++); gdl = bviewPrepareStaticI8(gdl, arg1, arg2); for (y = viewtop; y < viewtop + viewheight; y++) { gdl = bviewCopyPixels(gdl, fb2, random() % 240, 5, y, 1.0f, viewleft, viewwidth); } if (fb2) { // empty } return gdl; } /** * Draw the yellow interlace effect for Slayer rockets. */ Gfx *bviewDrawSlayerRocketInterlace(Gfx *gdl, u32 colour, u32 alpha) { u16 *fb = viGetBackBuffer(); s32 viewtop = viGetViewTop(); s32 viewheight = viGetViewHeight(); s32 viewwidth = viGetViewWidth(); s32 y; s32 viewleft = viGetViewLeft(); f32 angle = 0.52359879016876f; s32 offset = (s32)(g_20SecIntervalFrac * 600.0f) % 12; f32 increment; var8007f840++; if (var8007f840 >= 2) { return gdl; } strcpy(var800a41c0, "interlaceGfx"); gDPPipeSync(gdl++); increment = (2.6179938316345f - angle) / viewheight; gdl = bviewPrepareStaticRgba16(gdl, colour, alpha); for (y = viewtop; y < viewtop + viewheight; y++) { s32 offsety = y - offset; if ((offsety % 8) == 0 || y == viewtop) { if ((offsety % 16) < 8) { gDPSetEnvColor(gdl++, 0xff, 0xff, 0x00, 0xff); } else { gDPSetEnvColor(gdl++, 0xff, 0xff, 0xbf, 0xff); } } gdl = bviewCopyPixels(gdl, fb, y, 5, y, 2.0f - sinf(angle), viewleft, viewwidth); angle += increment; } return gdl; } /** * Draw the blue film interlace effect for the Infiltration intro cutscene. */ Gfx *bviewDrawFilmInterlace(Gfx *gdl, u32 colour, u32 alpha) { u16 *fb = viGetBackBuffer(); s32 viewtop = viGetViewTop(); s32 viewheight = viGetViewHeight(); s32 y; s32 viewwidth = viGetViewWidth(); s32 viewleft = viGetViewLeft(); s32 offset = (s32)(g_20SecIntervalFrac * 600.0f) % 12; u32 stack; var8007f840++; if (var8007f840 >= 2) { return gdl; } strcpy(var800a41c0, "BlueInterlaceGfx"); gDPPipeSync(gdl++); gdl = bviewPrepareStaticRgba16(gdl, colour, alpha); for (y = viewtop; y < viewtop + viewheight; y++) { s32 offsety = y - offset; s32 tmpy = y; if (offsety % 6 == 0 || y == viewtop) { if (offsety % 12 < 6) { gDPSetEnvColor(gdl++, 0x7f, 0xff, 0xff, 0xff); } else { gDPSetEnvColor(gdl++, 0x00, 0xaf, 0xff, 0xff); } } if (random() % 20 == 1) { tmpy = random() % 200; } gdl = bviewCopyPixels(gdl, fb, tmpy, 5, y, 1, viewleft, viewwidth); } return gdl; } /** * Draw a zoom in/out motion blur effect. * * Used when entering/exiting combat boosts and when entering/exiting xray mode. */ Gfx *bviewDrawZoomBlur(Gfx *gdl, u32 colour, s32 alpha, f32 arg3, f32 arg4) { u16 *fb = viGetFrontBuffer(); s32 viewtop = viGetViewTop(); s32 viewheight = viGetViewHeight(); s32 viewwidth = viGetViewWidth(); s32 viewleft = viGetViewLeft(); f32 somefloat; s32 i; var8007f840++; if (var8007f840 >= 2) { return gdl; } strcpy(var800a41c0, "stretchBlurGfx"); gDPPipeSync(gdl++); somefloat = (viewheight - viewheight / arg4) * 0.5f; gdl = bviewPrepareStaticRgba16(gdl, colour, alpha); for (i = viewtop; i < viewtop + viewheight; i++) { gdl = bviewCopyPixels(gdl, fb, (s32)somefloat + viewtop, 5, i, arg3, viewleft, viewwidth); somefloat += 1.0f / arg4; } return gdl; } f32 bview0f142d74(s32 arg0, f32 arg1, f32 arg2, f32 arg3) { f32 result; f32 value = arg2; if (arg0 < 0 || arg0 >= 0x80) { return 0.01f; } value += arg0 * arg1; if (arg3 > value * value) { result = sqrtf(arg3 - value * value) * 0.00625f; } else { result = 0.01f; } return result; } /** * Draw the fisheye curved effect when using an eyespy. * * PAL Beta adds padding above and below to compensate for the higher vertical * screen resolution, by adjusting the viewtop and viewheight variables and * drawing black filler at the end of the function. However the size of these * bars is static regardless of the screen layout and size being used. * * PAL Final improves on beta's mistake by checking the screen size, but there's * no check for a vertical split being used, and as a result the fisheye radius * is smaller than it should be when using a horizontal split. @bug */ Gfx *bviewDrawFisheye(Gfx *gdl, u32 colour, u32 alpha, s32 shuttertime60, s8 startuptimer60, u8 hit) { u16 *fb = viGetBackBuffer(); s32 viewtop; s32 viewheight; f32 f26; f32 halfheight; f32 sqhalfheight; s32 viewwidth; s32 viewleft; s32 s2; s32 i; s32 s3; u8 starting; s32 curradius; f32 startupfrac; f32 fullradius; s32 one = 1; s32 spec; u8 alpha2; #if VERSION >= VERSION_PAL_FINAL && PAL s32 vpadding; #endif f32 tmp; #if VERSION >= VERSION_PAL_FINAL viewtop = viGetViewTop(); viewheight = viGetViewHeight(); viewwidth = viGetViewWidth(); viewleft = viGetViewLeft(); startupfrac = 1.0f; s2 = 0; #if PAL if (PLAYERCOUNT() >= 2 || optionsGetEffectiveScreenSize() == SCREENSIZE_WIDE || optionsGetEffectiveScreenSize() == SCREENSIZE_CINEMA) { vpadding = 16; viewtop += vpadding; viewheight -= vpadding * 2; } else { vpadding = 23; viewtop += vpadding; viewheight -= vpadding * 2; } #endif halfheight = viewheight * 0.5f; sqhalfheight = halfheight * halfheight; f26 = -(halfheight + halfheight) / viewheight; #elif VERSION >= VERSION_PAL_BETA viewtop = viGetViewTop() + 16; viewheight = viGetViewHeight() - 32; halfheight = viewheight * 0.5f; sqhalfheight = halfheight * halfheight; f26 = -(halfheight + halfheight) / viewheight; viewwidth = viGetViewWidth(); viewleft = viGetViewLeft(); startupfrac = 1.0f; s2 = 0; #else viewtop = viGetViewTop(); viewheight = viGetViewHeight(); halfheight = viewheight * 0.5f; sqhalfheight = halfheight * halfheight; f26 = -(halfheight + halfheight) / viewheight; viewwidth = viGetViewWidth(); viewleft = viGetViewLeft(); startupfrac = 1.0f; s2 = 0; #endif starting = (startuptimer60 < TICKS(50)); var8007f840++; if (var8007f840 >= 2) { return gdl; } strcpy(var800a41c0, "blurGfxFisheye"); s3 = 1; if (starting) { fullradius = viewheight * 0.5f; startupfrac = startuptimer60 / (PAL ? 41.0f : 50.0f); curradius = fullradius * startupfrac; spec = startupfrac * 255.0f; if (spec > 255) { spec = 255; } } gDPPipeSync(gdl++); gdl = bviewPrepareStaticRgba16(gdl, colour, alpha); if (starting) { for (i = viewtop; i < viewtop + viewheight; i++) { if (i % 2) { if (i > viewtop + fullradius - curradius && i < viewtop + fullradius + curradius) { gDPSetEnvColorViaWord(gdl++, (colour & 0xffffff00) | (spec & 0xff)); tmp = bview0f142d74(s2, f26, halfheight, sqhalfheight) * startupfrac; gdl = bviewCopyPixels(gdl, fb, i, 5, i, tmp, viewleft, viewwidth); } } s2 += s3; if (s2 >= viewheight * 0.5f) { s2 = viewheight * 0.5f; s3 = -s3; } } } else { f32 f22 = 1.0f; for (i = viewtop; i < viewtop + viewheight; i++) { if (hit == EYESPYHIT_DAMAGE) { alpha2 = (random() % 120) + 120; colour = 0xff333300 | (alpha2 & 0xff); f22 = ((random() % 32) + (f32) FBALLOC_HEIGHT) * (1.0f / 256.0f); gDPSetEnvColorViaWord(gdl++, colour); } else { gDPSetEnvColorViaWord(gdl++, 0xffffffff); } tmp = bview0f142d74(s2, f26, halfheight, sqhalfheight) * f22; gdl = bviewCopyPixels(gdl, fb, i, 5, i, tmp, viewleft, viewwidth); if (hit == EYESPYHIT_DAMAGE) { gDPSetEnvColorViaWord(gdl++, 0xddaaaa99); tmp = bview0f142d74(s2, f26, halfheight, sqhalfheight) * 1.03f; gdl = bviewCopyPixels(gdl, fb, i, 5, i, tmp, viewleft, viewwidth); } s2 += s3; if ((i % 2) == 0) { gDPSetEnvColorViaWord(gdl++, 0x00000055); gDPFillRectangle(gdl++, viewleft, i, viewleft + viewwidth, i + 1); } if (s2 >= viewheight * 0.5f) { s2 = viewheight * 0.5f; s3 = -s3; } } } gDPPipeSync(gdl++); gDPSetCycleType(gdl++, G_CYC_1CYCLE); gDPSetRenderMode(gdl++, G_RM_XLU_SURF, G_RM_XLU_SURF2); gDPSetCombineMode(gdl++, G_CC_PRIMITIVE, G_CC_PRIMITIVE); gDPSetPrimColor(gdl++, 0, 0, 0x00, 0x00, 0x00, 0xff); s3 = 1; if (shuttertime60 != 0 || starting) { s32 s7; s32 spa8 = viewheight * 0.5f; f32 f20; if (!starting) { shuttertime60 -= TICKS(12); if (shuttertime60 < 0) { shuttertime60 = -shuttertime60; } s7 = spa8 * (shuttertime60 / TICKS(12.0f)); } else { s7 = curradius; } for (i = viewtop; i < viewtop + spa8 - s7; i++) { gdl = bviewDrawFisheyeRect(gdl, i, 0.0f, viewleft, viewwidth); gdl = bviewDrawFisheyeRect(gdl, viewtop + viewtop + viewheight - i, 0.0f, viewleft, viewwidth); } gDPSetPrimColorViaWord(gdl++, 0, 0, 0x000000ff); tmp = (f32) one * halfheight; f20 = halfheight; for (i = viewtop + spa8 - s7; i <= viewtop + spa8; i++) { f32 f2; if (sqhalfheight > f20 * f20) { f2 = sqrtf(sqhalfheight - f20 * f20) * (1.0f / 160.0f); } else { f2 = 0.01f; } f20 += -tmp / s7; gdl = bviewDrawFisheyeRect(gdl, i, f2 * startupfrac, viewleft, viewwidth); if (i != viewtop + viewtop + viewheight - i) { gdl = bviewDrawFisheyeRect(gdl, viewtop + viewtop + viewheight - i, f2 * startupfrac, viewleft, viewwidth); } } } else { s2 = 0; for (i = viewtop; i < viewtop + viewheight; i++) { tmp = bview0f142d74(s2, f26, halfheight, sqhalfheight); gdl = bviewDrawFisheyeRect(gdl, i, tmp, viewleft, viewwidth); s2 += s3; if (s2 >= viewheight * 0.5f) { s2 = viewheight * 0.5f; s3 = -s3; } } } #if PAL s3 = viGetViewTop(); #if VERSION >= VERSION_PAL_FINAL s2 = s3 + viGetViewHeight() - vpadding; #else s2 = s3 + viGetViewHeight() - 16; #endif #if VERSION >= VERSION_PAL_FINAL for (i = 0; i < vpadding; i++) #else for (i = 0; i < 16; i++) #endif { gDPFillRectangle(gdl++, viewleft, s3 , viewleft + viewwidth, s3 + 1); gDPFillRectangle(gdl++, viewleft, s2, viewleft + viewwidth, s2 + 1); s3++; s2++; } #endif return gdl; } /** * Draw a black rectangle to the side of the circular fisheye lens. * * These are each 1px high, and go from the edge of the circle to the edge of * the screen. There is one drawn on every row on both sides. */ Gfx *bviewDrawEyespySideRect(Gfx *gdl, s32 *points, u8 r, u8 g, u8 b, u8 alpha) { Vtx *vertices = gfxAllocateVertices(4); Col *colours = gfxAllocateColours(2); vertices[0].x = points[0] * 10.0f; vertices[0].y = points[1] * 10.0f; vertices[0].z = -10; vertices[1].x = points[2] * 10.0f; vertices[1].y = points[3] * 10.0f; vertices[1].z = -10; vertices[2].x = points[4] * 10.0f; vertices[2].y = points[5] * 10.0f; vertices[2].z = -10; vertices[3].x = points[6] * 10.0f; vertices[3].y = points[7] * 10.0f; vertices[3].z = -10; colours[0].word = PD_BE32(r << 0x18 | g << 0x10 | b << 8 | 0xff); colours[1].word = PD_BE32(r << 0x18 | g << 0x10 | b << 8 | alpha); vertices[0].colour = 0; vertices[1].colour = 0; vertices[2].colour = 4; vertices[3].colour = 4; gSPColor(gdl++, colours, 2); gSPVertex(gdl++, vertices, 4, 0); if (colours); gSPTri2(gdl++, 0, 1, 2, 0, 2, 3); return gdl; } /** * Renders the eyespy user interface, excluding the fisheye lens. The lens is * drawn first by another function, then this one is called to draw the outer * information. Care must be taken not to draw over the top of the fisheye lens. * * Note that the dimensions of the view can differ based on hi-res on/off, as * well as using coop mode in both the vertical and horizontal screen splits. * Some elements are omitted if a vertical split is being used, and to handle * hi-res a scale variable is used to multiply X values and widths where needed. * * @bug: Many of the X values and widths are not multiplied by the scale which * causes them to display incorrectly when using hi-res: * - Some of the horizontal lines don't touch the lens circle. * - The vertical lines are thinner and closer to the screen edges than intended. * - The speed and height bars are stretched. * - The device name and model are closer to the screen edge than intended. */ Gfx *bviewDrawEyespyMetrics(Gfx *gdl) { char text[256]; s32 viewleft = viGetViewLeft(); #if VERSION >= VERSION_PAL_FINAL s32 viewwidth = viGetViewWidth(); s32 viewtop = viGetViewTop(); s32 viewheight = viGetViewHeight(); #elif VERSION >= VERSION_PAL_BETA s32 viewwidth = viGetViewWidth(); s32 viewtop = viGetViewTop() + 16; s32 viewheight = viGetViewHeight() - 32; #else s32 viewtop = viGetViewTop(); s32 viewwidth = viGetViewWidth(); s32 viewheight = viGetViewHeight(); #endif s32 viewright = viewleft + viewwidth - 1; s32 viewbottom = viewtop + viewheight - 1; s32 x; s32 y; s32 textwidth; s32 textheight; s32 x2; s32 y2; struct chrdata *chr; s32 savedy; s32 movex; s32 movey; s32 movez; f32 movedist; f32 sqmovedist = 0.0f; u32 colourtextbright; u32 colourtextdull; u32 colourglow; #if PAL s32 scale = 1; f32 palscale = viewwidth > SCREEN_WIDTH_LO ? 1.4f : 1.0f; #else s32 scale = viewwidth > SCREEN_WIDTH_LO ? 2 : 1; #endif #if VERSION >= VERSION_NTSC_1_0 bool vsplit = false; #endif #if VERSION >= VERSION_PAL_FINAL #if PAL if (PLAYERCOUNT() >= 2 || optionsGetEffectiveScreenSize() == SCREENSIZE_WIDE || optionsGetEffectiveScreenSize() == SCREENSIZE_CINEMA) { viewtop += 16; viewheight -= 32; } else { viewtop += 23; viewheight -= 46; } #endif viewbottom = viewtop + viewheight - 1; #endif if (g_Vars.currentplayer->eyespy == NULL || g_Vars.currentplayer->eyespy->prop == NULL || g_Vars.currentplayer->eyespy->prop->chr == NULL) { return gdl; } chr = g_Vars.currentplayer->eyespy->prop->chr; #if VERSION >= VERSION_NTSC_1_0 if (optionsGetScreenSplit() == SCREENSPLIT_VERTICAL && PLAYERCOUNT() >= 2) { vsplit = true; } #endif #if VERSION >= VERSION_NTSC_1_0 movex = chr->prop->pos.x - chr->prevpos.x; movey = chr->prop->pos.y - chr->prevpos.y; movez = chr->prop->pos.z - chr->prevpos.z; if (movex != 0.0f || movey != 0.0f || movez != 0.0f) { sqmovedist = movex * movex + movey * movey + movez * movez; } if (sqmovedist > 0.001f) { movedist = sqrtf(sqmovedist); } else { movedist = 0.0f; } #else if (g_Vars.coopplayernum < 0 && g_Vars.antiplayernum < 0) { movex = chr->prop->pos.x - chr->prevpos.x; movey = chr->prop->pos.y - chr->prevpos.y; movez = chr->prop->pos.z - chr->prevpos.z; if (movex != 0.0f || movey != 0.0f || movez != 0.0f) { sqmovedist = movex * movex + movey * movey + movez * movez; } if (sqmovedist > 0.001f) { movedist = sqrtf(sqmovedist); } else { movedist = 0.0f; } } else { movedist = 0.0f; } #endif if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_CAMSPY) { gdl = textSetPrimColour(gdl, 0x00ff0028); } else if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_DRUGSPY) { gdl = textSetPrimColour(gdl, 0x2244ffa0); } else { gdl = textSetPrimColour(gdl, 0xff3300a0); } #if VERSION >= VERSION_NTSC_1_0 if (!vsplit) #endif { // Render borders/lines in background gDPFillRectangle(gdl++, viewleft + 25, viewtop + 55, viewleft + 26, viewbottom - 24); gDPFillRectangle(gdl++, viewleft + 31, viewtop + 55, viewleft + 32, viewbottom - 42); gDPFillRectangle(gdl++, viewleft + 25, viewbottom - 25, viewleft + 25 + viewwidth / 5.0f + 1, viewbottom - 24); gDPFillRectangle(gdl++, viewleft + 31, viewbottom - 43, viewleft + 25 + viewwidth / 7.0f + 1, viewbottom - 42); gDPFillRectangle(gdl++, viewright - 25, viewtop + 25, viewright - 24, viewbottom - 54); gDPFillRectangle(gdl++, viewright - 31, viewtop + 43, viewright - 30, viewbottom - 54); gDPFillRectangle(gdl++, viewright - 25 - viewwidth / 5.0f, viewtop + 25, viewright - 24, viewtop + 26); gDPFillRectangle(gdl++, viewright - 25 - viewwidth / 7.0f, viewtop + 43, viewright - 30, viewtop + 44); gDPFillRectangle(gdl++, viewleft, viewtop + 55, viewleft + viewwidth / 5.0f + 1, viewtop + 56); gDPFillRectangle(gdl++, viewright - viewwidth / 5.0f, viewbottom - 55, viewright + 1, viewbottom - 54); } if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_DRUGSPY) { // Render crosshair s32 x = viewleft + (viewwidth >> 1); s32 y = viewtop + (viewheight >> 1); gDPFillRectangle(gdl++, x + 2, y + 0, x + 7, y + 1); gDPFillRectangle(gdl++, x + 2, y + 0, x + 5, y + 1); gDPFillRectangle(gdl++, x - 6, y + 0, x - 1, y + 1); gDPFillRectangle(gdl++, x - 4, y + 0, x - 1, y + 1); gDPFillRectangle(gdl++, x + 0, y + 2, x + 1, y + 7); gDPFillRectangle(gdl++, x + 0, y + 2, x + 1, y + 5); gDPFillRectangle(gdl++, x + 0, y - 6, x + 1, y - 1); gDPFillRectangle(gdl++, x + 0, y - 4, x + 1, y - 1); } if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_CAMSPY) { colourtextbright = 0x00ff00a0; colourtextdull = 0x005000ff; colourglow = 0x000f00ff; } else if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_DRUGSPY) { colourtextbright = 0x2244ffff; colourtextdull = 0x2244ffff; colourglow = 0x00000fff; } else { colourtextbright = 0xff3300ff; colourtextdull = 0xff3300ff; colourglow = 0x0f0000ff; } // "S/MPS" sprintf(text, "%s %s%5.2f", langGet(L_MISC_073), "", movedist * 0.6f); savedy = viewtop + 14; textMeasure(&textheight, &textwidth, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0); x = viewleft + 25 * scale; y = savedy; x2 = x + textwidth; \ y2 = y + textheight; \ gdl = text0f153858(gdl, &x, &y, &x2, &y2); #if VERSION >= VERSION_JPN_FINAL gdl = func0f1574d0jf(gdl, &x, &y, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, colourtextbright, colourglow, viGetWidth(), viGetHeight(), 0, 0); #else gdl = textRender(gdl, &x, &y, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, colourtextbright, colourglow, viGetWidth(), viGetHeight(), 0, 0); #endif // "H/M" sprintf(text, "%s %s%4.2f", langGet(L_MISC_074), "", g_Vars.currentplayer->eyespy->height * 0.01f); savedy += 9; textMeasure(&textheight, &textwidth, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0); x = viewleft + 25 * scale; y = savedy; x2 = x + textwidth; \ y2 = y + textheight; \ gdl = text0f153858(gdl, &x, &y, &x2, &y2); #if VERSION >= VERSION_JPN_FINAL gdl = func0f1574d0jf(gdl, &x, &y, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, colourtextbright, colourglow, viGetWidth(), viGetHeight(), 0, 0); #else gdl = textRender(gdl, &x, &y, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, colourtextbright, colourglow, viGetWidth(), viGetHeight(), 0, 0); #endif // "Y/D" sprintf(text, "%s %d", langGet(L_MISC_075), (s32)g_Vars.currentplayer->eyespy->theta); savedy += 9; textMeasure(&textheight, &textwidth, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0); x = viewleft + 25 * scale; y = savedy; x2 = x + textwidth; \ y2 = y + textheight; \ gdl = text0f153858(gdl, &x, &y, &x2, &y2); #if VERSION >= VERSION_JPN_FINAL gdl = func0f1574d0jf(gdl, &x, &y, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, colourtextbright, colourglow, viGetWidth(), viGetHeight(), 0, 0); #else gdl = textRender(gdl, &x, &y, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, colourtextbright, colourglow, viGetWidth(), viGetHeight(), 0, 0); #endif // "P/D" sprintf(text, "%s %d", langGet(L_MISC_076), (s32)g_Vars.currentplayer->eyespy->verta); savedy += 9; textMeasure(&textheight, &textwidth, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0); x = viewleft + 25 * scale; y = savedy; x2 = x + textwidth; \ y2 = y + textheight; \ gdl = text0f153858(gdl, &x, &y, &x2, &y2); #if VERSION >= VERSION_JPN_FINAL gdl = func0f1574d0jf(gdl, &x, &y, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, colourtextbright, colourglow, viGetWidth(), viGetHeight(), 0, 0); #else gdl = textRender(gdl, &x, &y, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, colourtextbright, colourglow, viGetWidth(), viGetHeight(), 0, 0); #endif // "CI 2023" sprintf(text, "%s", langGet(L_MISC_077)); textMeasure(&textheight, &textwidth, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0); #if VERSION >= VERSION_NTSC_1_0 x = (vsplit ? -3 : 0) + viewleft + 25 * scale + 5; y = (vsplit ? 18 : 0) + viewbottom - 41; #else x = viewleft + 25 * scale + 5; y = viewbottom - 41; #endif x2 = x + textwidth; \ y2 = y + textheight; \ gdl = text0f153858(gdl, &x, &y, &x2, &y2); #if VERSION >= VERSION_JPN_FINAL gdl = func0f1574d0jf(gdl, &x, &y, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, colourtextdull, colourglow, viGetWidth(), viGetHeight(), 0, 0); #else gdl = textRender(gdl, &x, &y, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, colourtextdull, colourglow, viGetWidth(), viGetHeight(), 0, 0); #endif if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_CAMSPY) { sprintf(text, "%s", langGet(L_MISC_078)); // "YKK: 95935" } else if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_DRUGSPY) { sprintf(text, "%s", langGet(L_MISC_208)); // "JM: 201172" } else { sprintf(text, "%s", langGet(L_MISC_217)); // "BNC: 15877" } textMeasure(&textheight, &textwidth, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0); #if VERSION >= VERSION_NTSC_1_0 x = viewleft + 25 * scale + (vsplit ? -3 : 0) + 5; y = viewbottom + (vsplit ? 20 : 0) - 34; #else x = viewleft + 25 * scale + 5; y = viewbottom - 34; #endif x2 = x + textwidth; \ y2 = y + textheight; \ gdl = text0f153858(gdl, &x, &y, &x2, &y2); #if VERSION >= VERSION_JPN_FINAL gdl = func0f1574d0jf(gdl, &x, &y, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, colourtextdull, colourglow, viGetWidth(), viGetHeight(), 0, 0); #else gdl = textRender(gdl, &x, &y, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, colourtextdull, colourglow, viGetWidth(), viGetHeight(), 0, 0); #endif if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_CAMSPY) { // "CAMSPY" sprintf(text, " %s", langGet(L_MISC_079)); textMeasure(&textheight, &textwidth, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0); #if VERSION >= VERSION_PAL_FINAL x = viewright - textwidth - 27; #else x = viewright - scale * 53 - 25; #endif #if VERSION >= VERSION_NTSC_1_0 y = (vsplit ? -13 : 0) + viewtop + 27; #else y = viewtop + 27; #endif x2 = x + textwidth; \ y2 = y + textheight; \ gdl = text0f153858(gdl, &x, &y, &x2, &y2); #if VERSION >= VERSION_JPN_FINAL gdl = func0f1574d0jf(gdl, &x, &y, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, colourtextdull, colourglow, viGetWidth(), viGetHeight(), 0, 0); #else gdl = textRender(gdl, &x, &y, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, colourtextdull, colourglow, viGetWidth(), viGetHeight(), 0, 0); #endif } else if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_DRUGSPY) { // "DRUGSPY" sprintf(text, " %s", langGet(L_MISC_468)); textMeasure(&textheight, &textwidth, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0); #if VERSION >= VERSION_PAL_FINAL x = viewright - textwidth - 27; #else x = viewright - scale * 53 - 25; #endif #if VERSION >= VERSION_NTSC_1_0 y = (vsplit ? -13 : 0) + viewtop + 27; #else y = viewtop + 27; #endif x2 = x + textwidth; \ y2 = y + textheight; \ gdl = text0f153858(gdl, &x, &y, &x2, &y2); #if VERSION >= VERSION_JPN_FINAL gdl = func0f1574d0jf(gdl, &x, &y, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, colourtextdull, colourglow, viGetWidth(), viGetHeight(), 0, 0); #else gdl = textRender(gdl, &x, &y, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, colourtextdull, colourglow, viGetWidth(), viGetHeight(), 0, 0); #endif } else { // "BOMBSPY" sprintf(text, " %s", langGet(L_MISC_469)); textMeasure(&textheight, &textwidth, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0); #if VERSION >= VERSION_PAL_FINAL x = viewright - textwidth - 27; #else x = viewright - scale * 59 - 25; #endif #if VERSION >= VERSION_NTSC_1_0 y = (vsplit ? -13 : 0) + viewtop + 27; #else y = viewtop + 27; #endif x2 = x + textwidth; \ y2 = y + textheight; \ gdl = text0f153858(gdl, &x, &y, &x2, &y2); #if VERSION >= VERSION_JPN_FINAL gdl = func0f1574d0jf(gdl, &x, &y, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, colourtextdull, colourglow, viGetWidth(), viGetHeight(), 0, 0); #else gdl = textRender(gdl, &x, &y, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, colourtextdull, colourglow, viGetWidth(), viGetHeight(), 0, 0); #endif } // Model number if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_CAMSPY) { sprintf(text, "%s", langGet(L_MISC_080)); // "MODEL 1.2" } else if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_DRUGSPY) { sprintf(text, "%s", langGet(L_MISC_207)); // "MODEL 1.4" } else { sprintf(text, "%s", langGet(L_MISC_216)); // "MODEL 1.3" } textMeasure(&textheight, &textwidth, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0); #if VERSION >= VERSION_PAL_FINAL x = (vsplit ? 3 : 0) + viewright - textwidth - 27; y = (vsplit ? -11 : 0) + viewtop + 34; #elif VERSION >= VERSION_NTSC_1_0 x = (vsplit ? 3 : 0) + viewright - scale * 46 - 25; y = (vsplit ? -11 : 0) + viewtop + 34; #else x = viewright - scale * 46 - 25; y = viewtop + 34; #endif x2 = x + textwidth; \ y2 = y + textheight; \ gdl = text0f153858(gdl, &x, &y, &x2, &y2); #if VERSION >= VERSION_JPN_FINAL gdl = func0f1574d0jf(gdl, &x, &y, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, colourtextdull, colourglow, viGetWidth(), viGetHeight(), 0, 0); #else gdl = textRender(gdl, &x, &y, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, colourtextdull, colourglow, viGetWidth(), viGetHeight(), 0, 0); #endif // Gyrostat/dartammo text if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_CAMSPY || g_Vars.currentplayer->eyespy->mode == EYESPYMODE_BOMBSPY) { sprintf(text, "%s", langGet(L_MISC_081)); // "GYROSTAT" } else { sprintf(text, "%s", langGet(L_MISC_206)); // "DARTAMMO" } textMeasure(&textheight, &textwidth, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0); #if VERSION >= VERSION_PAL_FINAL x = viewright - textwidth - 27; y = (vsplit ? -2 : 0) + viewbottom - 12; #elif VERSION >= VERSION_NTSC_1_0 x = (vsplit ? -35 : 0) + (viewright - viewwidth / 5.0f - 3 - (scale * 5 - 5)); y = (vsplit ? -2 : 0) + viewbottom - 12; #else x = viewright - viewwidth / 5.0f - 3 - (scale * 5 - 5); y = viewbottom - 12; #endif if (1); x2 = x + textwidth; \ y2 = y + textheight; \ gdl = text0f153858(gdl, &x, &y, &x2, &y2); #if VERSION >= VERSION_JPN_FINAL gdl = func0f1574d0jf(gdl, &x, &y, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, colourtextdull, colourglow, viGetWidth(), viGetHeight(), 0, 0); #else gdl = textRender(gdl, &x, &y, text, g_CharsHandelGothicXs, g_FontHandelGothicXs, colourtextdull, colourglow, viGetWidth(), viGetHeight(), 0, 0); #endif gdl = text0f153838(gdl); { s8 contpadnum = optionsGetContpadNum1(g_Vars.currentplayerstats->mpindex); u16 buttonsdown = joyGetButtons(contpadnum, 0xffff); \ u16 buttonsthisframe = joyGetButtonsPressedThisFrame(contpadnum, 0xffff); s8 cstickx = joyGetStickX(contpadnum); \ s8 csticky = joyGetStickY(contpadnum); s32 xpos; s32 tmpval; u8 brightness; u8 brightness2; s32 points[8]; s32 r; s32 g; s32 b; gDPPipeSync(gdl++); \ gDPSetCycleType(gdl++, G_CYC_1CYCLE); \ gDPSetColorDither(gdl++, G_CD_DISABLE); \ gDPSetTexturePersp(gdl++, G_TP_NONE); \ gDPSetAlphaCompare(gdl++, G_AC_NONE); \ gDPSetTextureLOD(gdl++, G_TL_TILE); \ gDPSetTextureFilter(gdl++, G_TF_BILERP); \ gDPSetTextureConvert(gdl++, G_TC_FILT); \ gDPSetTextureLUT(gdl++, G_TT_NONE); \ gDPSetRenderMode(gdl++, G_RM_CLD_SURF, G_RM_CLD_SURF2); \ gDPSetCombineMode(gdl++, G_CC_PRIMITIVE, G_CC_PRIMITIVE); #if VERSION >= VERSION_NTSC_1_0 if (!vsplit) #endif { xpos = (scale == 2) ? -76 : -85; // Up if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_CAMSPY) { brightness = 20; \ if (buttonsdown & (U_JPAD | U_CBUTTONS)) { \ brightness += 20; \ } \ if (buttonsthisframe & (U_JPAD | U_CBUTTONS)) { \ brightness += 20; \ } \ gDPSetPrimColor(gdl++, 0, 0, 0, brightness, 0, 0xff); \ } else if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_DRUGSPY) { brightness = 127; if (buttonsdown & (U_JPAD | U_CBUTTONS)) { brightness += 63; } if (buttonsthisframe & (U_JPAD | U_CBUTTONS)) { brightness += 63; \ } \ gDPSetPrimColor(gdl++, 0, 0, 0x10, 0x20, brightness, 0xff); } else { brightness = 20; if (buttonsdown & (U_JPAD | U_CBUTTONS)) { brightness += 20; } if (buttonsthisframe & (U_JPAD | U_CBUTTONS)) { brightness += 20; \ } \ gDPSetPrimColor(gdl++, 0, 0, brightness, brightness >> 2, 0, 0xff); } gDPFillRectangle(gdl++, xpos * scale + viewright, viewtop + 10, (xpos + 8) * scale + viewright, viewtop + 18); xpos += 10; // Down if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_CAMSPY) { brightness = 20; if (buttonsdown & (D_JPAD | D_CBUTTONS)) { \ brightness += 20; \ } \ if (buttonsthisframe & (D_JPAD | D_CBUTTONS)) { brightness += 20; } gDPSetPrimColor(gdl++, 0, 0, 0, brightness, 0, 0xff); } else if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_DRUGSPY) { brightness = 127; if (buttonsdown & (D_JPAD | D_CBUTTONS)) { brightness += 63; } if (buttonsthisframe & (D_JPAD | D_CBUTTONS)) { brightness += 63; } gDPSetPrimColor(gdl++, 0, 0, 0x10, 0x20, brightness, 0xff); } else { brightness = 20; if (buttonsdown & (D_JPAD | D_CBUTTONS)) { brightness += 20; } if (buttonsthisframe & (D_JPAD | D_CBUTTONS)) { brightness += 20; } gDPSetPrimColor(gdl++, 0, 0, brightness, brightness >> 2, 0, 0xff); } gDPFillRectangle(gdl++, xpos * scale + viewright, viewtop + 10, (xpos + 8) * scale + viewright, viewtop + 18); xpos += 10; // Left if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_CAMSPY) { brightness = 20; if (buttonsdown & (L_JPAD | L_CBUTTONS)) { \ brightness += 20; \ } \ if (buttonsthisframe & (L_JPAD | L_CBUTTONS)) { brightness += 20; } gDPSetPrimColor(gdl++, 0, 0, 0, brightness, 0, 0xff); } else if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_DRUGSPY) { brightness = 127; if (buttonsdown & (L_JPAD | L_CBUTTONS)) { brightness += 63; } if (buttonsthisframe & (L_JPAD | L_CBUTTONS)) { brightness += 63; } gDPSetPrimColor(gdl++, 0, 0, 0x10, 0x20, brightness, 0xff); } else { brightness = 20; if (buttonsdown & (L_JPAD | L_CBUTTONS)) { brightness += 20; } if (buttonsthisframe & (L_JPAD | L_CBUTTONS)) { brightness += 20; } gDPSetPrimColor(gdl++, 0, 0, brightness, brightness >> 2, 0, 0xff); } gDPFillRectangle(gdl++, xpos * scale + viewright, viewtop + 10, (xpos + 8) * scale + viewright, viewtop + 18); xpos += 10; // Right if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_CAMSPY) { brightness = 20; if (buttonsdown & (R_JPAD | R_CBUTTONS)) { \ brightness += 20; \ } \ if (buttonsthisframe & (R_JPAD | R_CBUTTONS)) { brightness += 20; } gDPSetPrimColor(gdl++, 0, 0, 0, brightness, 0, 0xff); } else if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_DRUGSPY) { brightness = 127; if (buttonsdown & (R_JPAD | R_CBUTTONS)) { brightness += 63; } if (buttonsthisframe & (R_JPAD | R_CBUTTONS)) { brightness += 63; } gDPSetPrimColor(gdl++, 0, 0, 0x10, 0x20, brightness, 0xff); } else { brightness = 20; if (buttonsdown & (R_JPAD | R_CBUTTONS)) { brightness += 20; } if (buttonsthisframe & (R_JPAD | R_CBUTTONS)) { brightness += 20; } gDPSetPrimColor(gdl++, 0, 0, brightness, brightness >> 2, 0, 0xff); } gDPFillRectangle(gdl++, xpos * scale + viewright, viewtop + 10, (xpos + 8) * scale + viewright, viewtop + 18); xpos += 10; // Shoulder buttons if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_CAMSPY) { brightness = 20; if (buttonsdown & (L_TRIG | R_TRIG)) { \ brightness += 20; \ } \ if (buttonsthisframe & (L_TRIG | R_TRIG)) { brightness += 20; } gDPSetPrimColor(gdl++, 0, 0, 0, brightness, 0, 0xff); } else if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_DRUGSPY) { brightness = 127; if (buttonsdown & (L_TRIG | R_TRIG)) { brightness += 63; } if (buttonsthisframe & (L_TRIG | R_TRIG)) { brightness += 63; } gDPSetPrimColor(gdl++, 0, 0, 0x10, 0x20, brightness, 0xff); } else { brightness = 20; if (buttonsdown & (L_TRIG | R_TRIG)) { brightness += 20; } if (buttonsthisframe & (L_TRIG | R_TRIG)) { brightness += 20; } gDPSetPrimColor(gdl++, 0, 0, brightness, brightness >> 2, 0, 0xff); } gDPFillRectangle(gdl++, xpos * scale + viewright, viewtop + 10, (xpos + 8) * scale + viewright, viewtop + 18); xpos += 10; // Z button if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_CAMSPY) { brightness = 20; if (buttonsdown & Z_TRIG) { \ brightness += 20; \ } \ if (buttonsthisframe & Z_TRIG) { brightness += 20; } gDPSetPrimColor(gdl++, 0, 0, 0, brightness, 0, 0xff); } else if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_DRUGSPY) { brightness = 127; if (buttonsdown & Z_TRIG) { brightness += 63; } if (buttonsthisframe & Z_TRIG) { brightness += 63; } gDPSetPrimColor(gdl++, 0, 0, 0x10, 0x20, brightness, 0xff); } else { brightness = 20; if (buttonsdown & Z_TRIG) { brightness += 20; } if (buttonsthisframe & Z_TRIG) { brightness += 20; } gDPSetPrimColor(gdl++, 0, 0, brightness, brightness >> 2, 0, 0xff); } gDPFillRectangle(gdl++, xpos * scale + viewright, viewtop + 10, (xpos + 8) * scale + viewright, viewtop + 18); } xpos = (scale == 2) ? -48 : -55; // Stick X tmpval = cstickx * 96.0f / 80.0f; brightness = tmpval < 0 ? -tmpval : tmpval; if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_CAMSPY) { gDPSetPrimColor(gdl++, 0, 0, 0, brightness, 0, 0xff); } else if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_DRUGSPY) { r = brightness / 96.0f * 16.0f; g = brightness / 96.0f * 32.0f; b = brightness * 2.5f; gDPSetPrimColor(gdl++, 0, 0, r, g, b, 0xff); } else { gDPSetPrimColor(gdl++, 0, 0, brightness, brightness >> 2, 0, 0xff); } #if VERSION >= VERSION_NTSC_1_0 if (!vsplit) #endif { tmpval = cstickx * 28.0f / 80.0f; if (cstickx > 0) { gDPFillRectangle(gdl++, xpos * scale + viewright, viewtop + 19, (tmpval + xpos) * scale + viewright, viewtop + 21); } else { gDPFillRectangle(gdl++, (tmpval + xpos) * scale + viewright, viewtop + 19, xpos * scale + viewright, viewtop + 21); } } // Stick Y tmpval = csticky * 96.0f / 80.0f; brightness = tmpval < 0 ? -tmpval : tmpval; if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_CAMSPY) { gDPSetPrimColor(gdl++, 0, 0, 0, brightness, 0, 0xff); } else if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_DRUGSPY) { r = brightness / 96.0f * 16.0f; g = brightness / 96.0f * 32.0f; b = brightness * 2.5f; gDPSetPrimColor(gdl++, 0, 0, r, g, b, 0xff); } else { gDPSetPrimColor(gdl++, 0, 0, brightness, brightness >> 2, 0, 0xff); } #if VERSION >= VERSION_NTSC_1_0 if (!vsplit) #endif { tmpval = csticky * 28.0f / 80.0f; if (csticky > 0) { gDPFillRectangle(gdl++, xpos * scale + viewright, viewtop + 22, (tmpval + xpos) * scale + viewright, viewtop + 24); } else { gDPFillRectangle(gdl++, (tmpval + xpos) * scale + viewright, viewtop + 22, xpos * scale + viewright, viewtop + 24); } } if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_CAMSPY) { #if VERSION >= VERSION_NTSC_1_0 if (!vsplit) #endif { // Camspy gyrobar 1 x = viewright - viewwidth / 5.0f; y = viewbottom - 13; tmpval = g_Vars.currentplayer->eyespy->theta * 96.0f / 360.0f; textheight = g_Vars.currentplayer->eyespy->theta * 35.0f / 360.0f; brightness = tmpval < 0 ? -tmpval : tmpval; \ gDPSetPrimColor(gdl++, 0, 0, 0, brightness, 0, 0xff); gDPFillRectangle(gdl++, x, y - textheight, x + scale * 5, y); // Camspy gyrobar 2 x += scale * 2 + scale * 5; tmpval = (g_Vars.currentplayer->eyespy->costheta + 1.0f) * 96.0f * 0.5f; textheight = (g_Vars.currentplayer->eyespy->costheta + 1.0f) * 35.0f * 0.5f; brightness = tmpval < 0 ? -tmpval : tmpval; gDPSetPrimColor(gdl++, 0, 0, 0, brightness, 0, 0xff); gDPFillRectangle(gdl++, x, y - textheight, x + scale * 5, y); // Camspy gyrobar 3 x += scale * 2 + scale * 5; tmpval = (g_Vars.currentplayer->eyespy->sintheta + 1.0f) * 96.0f * 0.5f; textheight = (g_Vars.currentplayer->eyespy->sintheta + 1.0f) * 35.0f * 0.5f; brightness = tmpval < 0 ? -tmpval : tmpval; gDPSetPrimColor(gdl++, 0, 0, 0, brightness, 0, 0xff); gDPFillRectangle(gdl++, x, y - textheight, x + scale * 5, y); // Camspy gyrobar 4 x += scale * 2 + scale * 5; tmpval = g_Vars.currentplayer->eyespy->verta * 96.0f / 360.0f; textheight = g_Vars.currentplayer->eyespy->verta * 35.0f / 360.0f; brightness = tmpval < 0 ? -tmpval : tmpval; gDPSetPrimColor(gdl++, 0, 0, 0, brightness, 0, 0xff); gDPFillRectangle(gdl++, x, y - textheight, x + scale * 5, y); // Camspy gyrobar 5 x += scale * 2 + scale * 5; tmpval = (g_Vars.currentplayer->eyespy->cosverta + 1.0f) * 96.0f * 0.5f; textheight = (g_Vars.currentplayer->eyespy->cosverta + 1.0f) * 35.0f * 0.5f; brightness = tmpval < 0 ? -tmpval : tmpval; gDPSetPrimColor(gdl++, 0, 0, 0, brightness, 0, 0xff); gDPFillRectangle(gdl++, x, y - textheight, x + scale * 5, y); // Camspy gyrobar 6 x += scale * 2 + scale * 5; tmpval = (g_Vars.currentplayer->eyespy->sinverta + 1.0f) * 96.0f * 0.5f; textheight = (g_Vars.currentplayer->eyespy->sinverta + 1.0f) * 35.0f * 0.5f; brightness = tmpval < 0 ? -tmpval : tmpval; gDPSetPrimColor(gdl++, 0, 0, 0, brightness, 0, 0xff); gDPFillRectangle(gdl++, x, y - textheight, x + scale * 5, y); x += scale * 2 + scale * 5; } } else if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_BOMBSPY) { #if VERSION >= VERSION_NTSC_1_0 if (!vsplit) #endif { // Bombspy gyrobar 1 x = viewright - viewwidth / 5.0f; y = viewbottom - 13; tmpval = g_Vars.currentplayer->eyespy->theta * 96.0f / 360.0f; textheight = g_Vars.currentplayer->eyespy->theta * 35.0f / 360.0f; brightness = tmpval < 0 ? -tmpval : tmpval; gDPSetPrimColor(gdl++, 0, 0, brightness, brightness >> 2, 0, 0xff); gDPFillRectangle(gdl++, x, y - textheight, x + scale * 5, y); // Bombspy gyrobar 2 x += scale * 2 + scale * 5; tmpval = (g_Vars.currentplayer->eyespy->costheta + 1.0f) * 96.0f * 0.5f; textheight = (g_Vars.currentplayer->eyespy->costheta + 1.0f) * 35.0f * 0.5f; brightness = tmpval < 0 ? -tmpval : tmpval; gDPSetPrimColor(gdl++, 0, 0, brightness, brightness >> 2, 0, 0xff); gDPFillRectangle(gdl++, x, y - textheight, x + scale * 5, y); // Bombspy gyrobar 3 x += scale * 2 + scale * 5; tmpval = (g_Vars.currentplayer->eyespy->sintheta + 1.0f) * 96.0f * 0.5f; textheight = (g_Vars.currentplayer->eyespy->sintheta + 1.0f) * 35.0f * 0.5f; brightness = tmpval < 0 ? -tmpval : tmpval; gDPSetPrimColor(gdl++, 0, 0, brightness, brightness >> 2, 0, 0xff); gDPFillRectangle(gdl++, x, y - textheight, x + scale * 5, y); // Bombspy gyrobar 4 x += scale * 2 + scale * 5; tmpval = g_Vars.currentplayer->eyespy->verta * 96.0f / 360.0f; textheight = g_Vars.currentplayer->eyespy->verta * 35.0f / 360.0f; brightness = tmpval < 0 ? -tmpval : tmpval; gDPSetPrimColor(gdl++, 0, 0, brightness, brightness >> 2, 0, 0xff); gDPFillRectangle(gdl++, x, y - textheight, x + scale * 5, y); // Bombspy gyrobar 5 x += scale * 2 + scale * 5; tmpval = (g_Vars.currentplayer->eyespy->cosverta + 1.0f) * 96.0f * 0.5f; textheight = (g_Vars.currentplayer->eyespy->cosverta + 1.0f) * 35.0f * 0.5f; brightness = tmpval < 0 ? -tmpval : tmpval; gDPSetPrimColor(gdl++, 0, 0, brightness, brightness >> 2, 0, 0xff); gDPFillRectangle(gdl++, x, y - textheight, x + scale * 5, y); // Bombspy gyrobar 6 x += scale * 2 + scale * 5; tmpval = (g_Vars.currentplayer->eyespy->sinverta + 1.0f) * 96.0f * 0.5f; textheight = (g_Vars.currentplayer->eyespy->sinverta + 1.0f) * 35.0f * 0.5f; brightness = tmpval < 0 ? -tmpval : tmpval; gDPSetPrimColor(gdl++, 0, 0, brightness, brightness >> 2, 0, 0xff); gDPFillRectangle(gdl++, x, y - textheight, x + scale * 5, y); x += scale * 2 + scale * 5; } } else { // Drugspy ammo s32 i; #if VERSION >= VERSION_NTSC_1_0 s32 width; #endif brightness2 = 255; #if VERSION >= VERSION_NTSC_1_0 width = scale * 30; #endif y = viewbottom - 13; x = viewright - viewwidth / 5.0f + 5; #if VERSION >= VERSION_NTSC_1_0 if (vsplit) { x -= 12; y -= 3; width = 15; } #endif for (i = 0; i < MAX_EYESPYDARTS; i++) { if (i >= g_Vars.currentplayer->eyespydarts) { brightness2 = 0x88; } gDPSetPrimColor(gdl++, 0, 0, 0x10, 0x20, brightness2, 0xff); #if VERSION >= VERSION_NTSC_1_0 gDPFillRectangle(gdl++, x, y - 4, x + width, y); #else gDPFillRectangle(gdl++, x, y - 4, x + 30 * scale, y); #endif y -= 5; } } gDPPipeSync(gdl++); \ gDPSetColorDither(gdl++, G_CD_BAYER); \ gDPSetTexturePersp(gdl++, G_TP_PERSP); \ gDPSetTextureLOD(gdl++, G_TL_LOD); if (g_Vars.coopplayernum < 0 && g_Vars.antiplayernum < 0) { s32 barheight = (viewbottom - viewtop - 103) / 17.0f - 1; s32 centrey = viewheight / 2.0f; s32 sqcentrey = centrey * centrey; s32 ypos; u8 alpha; u32 stack; u32 stack2; s8 yoffset; s32 value; s32 i; #if VERSION == VERSION_PAL_BETA if (centrey); #endif value = 17.0f * movedist / 25.0f; if (value > 17) { value = 17; } value = 17 - value; if (viewheight == FBALLOC_HEIGHT) { yoffset = 10; } else if (viewheight == 180) { // screen size: wide barheight--; yoffset = -8; } else { yoffset = 0; } gdl = func0f0d479c(gdl); gSPClearGeometryMode(gdl++, G_CULL_BOTH); gSPSetGeometryMode(gdl++, G_SHADE | G_SHADING_SMOOTH); gDPSetCombineMode(gdl++, G_CC_SHADE, G_CC_SHADE); gDPSetTextureFilter(gdl++, G_TF_BILERP); gDPSetCycleType(gdl++, G_CYC_1CYCLE); gDPSetRenderMode(gdl++, G_RM_AA_XLU_SURF, G_RM_AA_XLU_SURF2); // Speed bars (left side) y = viewtop + 58; if (viewheight == 180) { // screen size: wide y += 5; } ypos = centrey - y + 10; #if VERSION == VERSION_PAL_BETA ypos += 16; #endif #if VERSION == VERSION_PAL_FINAL if (PLAYERCOUNT() >= 2 || optionsGetEffectiveScreenSize() == SCREENSIZE_WIDE || optionsGetEffectiveScreenSize() == SCREENSIZE_CINEMA) { ypos += 16; } else { ypos += 23; } #endif for (i = 0; i < 17; i++) { brightness = i < value ? 40 : 80; alpha = i < value ? 0x22 : 0x56; points[0] = x = viewleft + 34; points[1] = y; points[2] = x = viewleft + 34; points[3] = y + barheight; #if PAL points[6] = x = viewwidth / 2.0f - sqrtf(sqcentrey - (ypos - yoffset) * (ypos - yoffset)) * palscale - 5.0f; #else points[6] = x = viewwidth / 2.0f - sqrtf(sqcentrey - (ypos - yoffset) * (ypos - yoffset)) * scale - 5.0f; #endif points[5] = y + barheight; ypos -= barheight; #if PAL points[4] = x = viewwidth / 2.0f - sqrtf(sqcentrey - (ypos - yoffset) * (ypos - yoffset)) * palscale - 5.0f; #else points[4] = x = viewwidth / 2.0f - sqrtf(sqcentrey - (ypos - yoffset) * (ypos - yoffset)) * scale - 5.0f; #endif points[7] = y; ypos -= 2; if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_CAMSPY) { gdl = bviewDrawEyespySideRect(gdl, points, 0, brightness, 0, alpha); } else if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_DRUGSPY) { gdl = bviewDrawEyespySideRect(gdl, points, 0x10, brightness, brightness * 3, alpha); } else { gdl = bviewDrawEyespySideRect(gdl, points, brightness, brightness >> 2, 0, alpha); } y += barheight; y += 2; } // Height bars (right side) value = g_Vars.currentplayer->eyespy->height * 17.0f * (1.0f / 160.0f); if (value > 17) { value = 17; } value = 17 - value; y = viewtop + 46; if (viewheight == 180) { // screen size: wide y += 5; } ypos = centrey - y + 10; #if VERSION == VERSION_PAL_BETA ypos += 16; #endif #if VERSION == VERSION_PAL_FINAL if (PLAYERCOUNT() >= 2 || optionsGetEffectiveScreenSize() == SCREENSIZE_WIDE || optionsGetEffectiveScreenSize() == SCREENSIZE_CINEMA) { ypos += 16; } else { ypos += 23; } #endif for (i = 0; i < 17; i++) { brightness = i < value ? 40 : 80; alpha = i < value ? 0x22 : 0x56; points[0] = x = viewright - 34; points[1] = y; points[3] = y + barheight; points[2] = x = viewright - 34; #if PAL points[6] = x = viewwidth / 2.0f + sqrtf(sqcentrey - (ypos - yoffset) * (ypos - yoffset)) * palscale + 5.0f; #else points[6] = x = viewwidth / 2.0f + sqrtf(sqcentrey - (ypos - yoffset) * (ypos - yoffset)) * scale + 5.0f; #endif points[5] = y + barheight; ypos -= barheight; #if PAL points[4] = x = viewwidth / 2.0f + sqrtf(sqcentrey - (ypos - yoffset) * (ypos - yoffset)) * palscale + 5.0f; #else points[4] = x = viewwidth / 2.0f + sqrtf(sqcentrey - (ypos - yoffset) * (ypos - yoffset)) * scale + 5.0f; #endif points[7] = y; ypos -= 2; if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_CAMSPY) { gdl = bviewDrawEyespySideRect(gdl, points, 0, brightness, 0, alpha); } else if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_DRUGSPY) { gdl = bviewDrawEyespySideRect(gdl, points, 0x10, brightness, brightness * 3U, alpha); } else { gdl = bviewDrawEyespySideRect(gdl, points, brightness, brightness >> 2, 0, alpha); } y += barheight; y += 2; } } gdl = func0f0d49c8(gdl); } return gdl; } void bview0f1572f8(void) { // empty } u8 var8007f878 = 0; Gfx *bviewDrawNvLens(Gfx *gdl) { u16 *fb = viGetBackBuffer(); s32 viewheight = viGetViewHeight(); s32 viewwidth = viGetViewWidth(); s32 viewtop = viGetViewTop(); s32 viewleft = viGetViewLeft(); s32 viewbottom = viewtop + viewheight; s32 brightness; s32 y; var8007f840++; if (var8007f840 >= 2) { return gdl; } strcpy(var800a41c0, "Fullscreen_DrawFaultScope"); var8009caec = 0xbc; var8009caef = 0xbe; var8009caf0 = 0xde; var8009caed = 0x50; var8009caee = 0xc0; brightness = roomGetFinalBrightness(g_Vars.currentplayer->prop->rooms[0]); if (brightness > 128) { skySetOverexposure(brightness, brightness, brightness); } if (g_Menus[g_Vars.currentplayerstats->mpindex].curdialog == NULL) { gdl = bviewDrawMotionBlur(gdl, 0x00ff0000, 0x60); } gDPPipeSync(gdl++); gdl = bviewPrepareStaticRgba16(gdl, 0xffffffff, 0xff); var8007f878++; for (y = viewtop; y < viewbottom; y++) { u8 green; if (((var8007f878 & 1) != (y & 1)) != 0) { u8 tmp = random() % 12; green = 0xff - tmp; } else { green = 0x94; } gDPSetColor(gdl++, G_SETENVCOLOR, (green << 16) + 0xff); gdl = bviewCopyPixels(gdl, fb, y, 5, y, 1, viewleft, viewwidth); } return gdl; } /** * Night vision doesn't have binoculars. */ Gfx *bviewDrawNvBinoculars(Gfx *gdl) { return gdl; } Gfx *bviewDrawIrLens(Gfx *gdl) { s32 i; s32 fadeincrement; u16 *fb = viGetBackBuffer(); s32 viewheight = viGetViewHeight(); s32 viewwidth = viGetViewWidth(); s32 viewtop = viGetViewTop(); s32 viewleft = viGetViewLeft(); s32 viewright; s32 viewbottom; s32 viewcentrex; s32 sqinnerradius; s32 stack[3]; s32 scanincrement; s32 scantop; s32 scanbottom; s32 scanrate = 4; s32 faderate = 2; u32 red; s32 outerradius; s32 innerradius; s32 viewcentrey; f32 viewheightf; s32 a0; #if VERSION < VERSION_NTSC_1_0 static s32 fsscanline = 0; static s32 fslastradius = -1; #endif viewright = viewleft + viewwidth; viewcentrex = (viewleft + viewright) / 2; outerradius = g_IrBinocularRadius; innerradius = g_IrBinocularRadius / var8007f850; var8007f840++; if (var8007f840 >= 2) { return gdl; } strcpy(var800a41c0, "Fullscreen_DrawFaultScope"); #if VERSION < VERSION_NTSC_1_0 osSyncPrintf("Fault Scope is active\n"); func0f13c2d0nb(); #endif viewbottom = viewtop + viewheight; viewcentrey = (viewtop + viewbottom) / 2; scantop = viewcentrey - outerradius; scanbottom = viewcentrey + outerradius; i = viewheight; if (scantop > viewbottom) { scantop = viewbottom; } #if VERSION >= VERSION_NTSC_1_0 if (scanbottom > viewbottom) { scanbottom = viewbottom; } #else if (scantop > viewbottom) { scantop = viewbottom; } #endif if (scantop < viewtop) { scantop = viewtop; } if (scanbottom < viewtop) { scanbottom = viewtop; } scanincrement = (f32) scanrate * i / 240.0f; fadeincrement = (f32) faderate * i / 240.0f; // This code runs on the first frame of IR use (90 != 0), // and in debug versions developers could change the radius at runtime. #if VERSION >= VERSION_NTSC_1_0 if (g_Vars.currentplayer->fslastradius != outerradius) { for (i = 0; i < 480; i++) { g_IrScanlines[g_Vars.currentplayernum][i] = 0xff; } g_Vars.currentplayer->fsscanline = 0; g_Vars.currentplayer->fslastradius = outerradius; } #else if (fslastradius != outerradius) { for (i = 0; i < 480; i++) { g_IrScanlines[0][i] = 0xff; } fsscanline = 0; fslastradius = outerradius; } #endif // Increment the scanline #if VERSION >= VERSION_NTSC_1_0 for (i = 0; i < scanincrement; i++) { if (g_Vars.currentplayer->fsscanline >= scanbottom) { g_Vars.currentplayer->fsscanline = scantop; } g_IrScanlines[g_Vars.currentplayernum][g_Vars.currentplayer->fsscanline] = 0xff - i; g_Vars.currentplayer->fsscanline++; } #else for (i = 0; i < scanincrement; i++, fsscanline++) { if (fsscanline == scanbottom) { fsscanline = scantop; } g_IrScanlines[0][fsscanline] = 0xff - i; } #endif var8009caec = 0xff; var8009caef = 0xde; var8009caf0 = 0xde; gDPPipeSync(gdl++); gdl = bviewPrepareStaticRgba16(gdl, 0xffffffff, 255); sqinnerradius = innerradius * innerradius; for (i = scantop; i < scanbottom; i++) { #if VERSION >= VERSION_NTSC_1_0 if (i & 1) { red = g_IrScanlines[g_Vars.currentplayernum][i]; } else { red = g_IrScanlines[g_Vars.currentplayernum][i] * 2 / 3; } #else if (i & 1) { red = g_IrScanlines[0][i]; } else { red = g_IrScanlines[0][i] * 2 / 3; } #endif red += random() % 8; if (red > 255) { red = 255; } gDPSetEnvColorViaWord(gdl++, (red << 24) + 0xff); a0 = viewcentrey - i; if (a0 * a0 < sqinnerradius) { // Rendering a line that overlaps the semicircle // in the middle of the screen f32 f0 = a0; s32 semicirclewidth = sqrtf(sqinnerradius - (s32) (f0 * f0)) * (viewwidth / (f32) SCREEN_WIDTH_LO); s32 semicircleright = viewcentrex + semicirclewidth; s32 rightsidewidth = viewwidth - semicircleright; // Left and right of semicircle gdl = bviewCopyPixels(gdl, fb, i, 5, i, 1.0f, viewleft, viewcentrex); gdl = bviewCopyPixels(gdl, fb, i, 5, i, 1.0f, semicircleright, rightsidewidth); // The semicircle itself has a static colour gDPSetEnvColorViaWord(gdl++, 0xee0000ff); gdl = bviewCopyPixels(gdl, fb, i, 5, i, 1.0f, viewcentrex, semicirclewidth); } else { gdl = bviewCopyPixels(gdl, fb, i, 5, i, 1.0f, viewleft, viewwidth); } #if VERSION >= VERSION_NTSC_1_0 if (g_IrScanlines[g_Vars.currentplayernum][i] > fadeincrement) { g_IrScanlines[g_Vars.currentplayernum][i] -= fadeincrement; } #else if (g_IrScanlines[0][i] > fadeincrement) { g_IrScanlines[0][i] -= fadeincrement; } #endif } if (g_Menus[g_Vars.currentplayerstats->mpindex].curdialog == NULL) { gdl = bviewDrawMotionBlur(gdl, 0xff000000, 0x40); } return gdl; } /** * Draw a horizontal blur/sretch effect. Unused. * * The term "Intro" used in the string suggests that was made for an older * version of the title screen, similar to bviewDrawIntroText. */ Gfx *bviewDrawIntroFaderBlur(Gfx *gdl, s32 arg1) { u16 *fb = viGetBackBuffer(); s32 viewtop = viGetViewTop(); s32 viewheight = viGetViewHeight(); s32 viewwidth = viGetViewWidth(); s32 viewleft = viGetViewLeft(); f32 halfheight; f32 extra; s32 y; var8007f840++; if (var8007f840 >= 2) { return gdl; } strcpy(var800a41c0, "IntroFaderBlurGfx"); gDPPipeSync(gdl++); gdl = bviewPrepareStaticRgba16(gdl, 0xffffffff, 255); halfheight = viewheight * 0.5f; extra = 0.5f; extra += 0.5f; for (y = viewtop; y < viewtop + viewheight; y++) { f32 frac = (y - viewtop - halfheight) / halfheight; if (frac < 0.0f) { frac = -frac; } frac += extra; if (frac > 1.0f) { frac = 1.0f; } gdl = bviewCopyPixels(gdl, fb, y, 5, y, RANDOMFRAC() * frac + 1.0f, viewleft, viewwidth); } return gdl; } /** * Called from the title screen's "Rare Presents" mode, which is unused. */ Gfx *bviewDrawIntroText(Gfx *gdl) { u16 *fb = viGetBackBuffer(); s32 viewtop = viGetViewTop(); s32 viewheight = viGetViewHeight(); s32 viewwidth = viGetViewWidth(); s32 viewleft = viGetViewLeft(); s32 y; var8007f840++; if (var8007f840 >= 2) { return gdl; } strcpy(var800a41c0, "IntroTextInterfereGfx"); gDPPipeSync(gdl++); gdl = bviewPrepareStaticRgba16(gdl, 0x8f8f8f8f, 255); for (y = viewtop; y < viewtop + viewheight; y += 2) { gdl = bviewCopyPixels(gdl, fb, y, 5, y, 1.0f, viewleft, viewwidth); } return gdl; } Gfx *bviewDrawHorizonScanner(Gfx *gdl) { u16 *fb = viGetBackBuffer(); s32 viewtop = viGetViewTop(); s32 viewheight = viGetViewHeight(); s32 viewwidth = viGetViewWidth(); s32 viewleft = viGetViewLeft(); char directiontext[32]; char hertztext[24]; char zoomtext[24]; #if VERSION >= VERSION_NTSC_1_0 char nametext[52]; #endif f32 lookx = g_Vars.currentplayer->cam_look.x; f32 lookz = g_Vars.currentplayer->cam_look.z; s32 x; s32 y; char directions[][3] = { {'n', '\0', '\0'}, {'n', 'e', '\0'}, {'e', '\0', '\0'}, {'s', 'e', '\0'}, {'s', '\0', '\0'}, {'s', 'w', '\0'}, {'w', '\0', '\0'}, {'n', 'w', '\0'}, {'n', '\0', '\0'}, }; s32 turnangle = atan2f(-lookx, lookz) * 180.0f / M_PI; f32 fovy; char arrows[12]; s32 tmplensheight = 130; s32 lenstop; s32 lensheight; s32 liney; s32 scale = 1; s32 vsplit = false; u32 colour; f32 range; var8007f840++; if (var8007f840 >= 2) { return gdl; } strcpy(var800a41c0, "BinocularViewGfx"); if (!PAL && g_ViRes == VIRES_HI) { scale = 2; } if (optionsGetScreenSplit() == SCREENSPLIT_VERTICAL && PLAYERCOUNT() >= 2) { vsplit = true; } if (tmplensheight > viewheight - 30) { tmplensheight = viewheight - 30; } if (((s32)(g_20SecIntervalFrac * 30.0f) & 1) == 1) { sprintf(arrows, ">> "); } else { sprintf(arrows, " >>"); } lensheight = tmplensheight; lenstop = viewtop + (viewheight / 2) - (lensheight / 2); // Black out areas above and below lens gdl = textSetPrimColour(gdl, 0x000000ff); gDPFillRectangle(gdl++, viewleft, viewtop, viewleft + viewwidth, lenstop); gDPFillRectangle(gdl++, viewleft, lenstop + lensheight, viewleft + viewwidth, viewtop + viewheight); gdl = text0f153838(gdl); // Prepare text buffers sprintf(directiontext, "%s %s:%03d", arrows, &directions[(turnangle + 22) / 45], turnangle); sprintf(hertztext, "%s %s%s%4.2fh", arrows, "", "", menuGetCosOscFrac(4) * 4.6f + 917.4f); fovy = viGetFovY(); if (fovy == 0 || fovy == 60.0f) { fovy = 1; } else { fovy = 60.0f / fovy + 1; } sprintf(zoomtext, "%s %s%s%4.2fX", arrows, "", "", fovy); gdl = text0f153628(gdl); // Arrows left of product name if (vsplit) { x = viewleft + 15 * scale; } else { x = viewleft + 25 * scale; } y = lenstop - 7; gdl = textRenderProjected(gdl, &x, &y, arrows, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0xffffff7f, viGetWidth(), viGetHeight(), 0, 0); // Product name #if VERSION >= VERSION_NTSC_1_0 strcpy(nametext, " JMBC"); if (!vsplit) { strcat(nametext, " WIDE BAND"); } strcat(nametext, " SCANNER\n"); gdl = textRenderProjected(gdl, &x, &y, nametext, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0xffffff7f, viGetWidth(), viGetHeight(), 0, 0); #else gdl = textRenderProjected(gdl, &x, &y, " JMBC WIDE BAND SCANNER\n", g_CharsHandelGothicXs, g_FontHandelGothicXs, 0xffffff7f, viGetWidth(), viGetHeight(), 0, 0); #endif // Hertz x = viewleft + 75 * scale; y = lenstop + lensheight + 1; gdl = textRenderProjected(gdl, &x, &y, hertztext, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0xffffff7f, viGetWidth(), viGetHeight(), 0, 0); // Zoom level if (vsplit) { x = viewleft + 75 * scale; y = lenstop + lensheight + 8; } else { x = viewleft + 150 * scale; y = lenstop + lensheight + 1; } gdl = textRenderProjected(gdl, &x, &y, zoomtext, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0xffffff7f, viGetWidth(), viGetHeight(), 0, 0); // Direction if (vsplit) { x = viewleft + 75 * scale; y = lenstop + lensheight + 15; } else { x = viewleft + 225 * scale; y = lenstop + lensheight + 1; } gdl = textRenderProjected(gdl, &x, &y, directiontext, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0xffffff7f, viGetWidth(), viGetHeight(), 0, 0); gdl = text0f153780(gdl); gDPPipeSync(gdl++); gdl = bviewPrepareStaticRgba16(gdl, 0xffffffff, 255); if (vsplit) { vsplit = 14; } // Iterate horizontal lines down the lens with a bit extra on top and bottom for (liney = lenstop - 9; liney < lenstop + lensheight + vsplit + 9; liney++) { if (liney < lenstop + lensheight && liney >= lenstop) { // Inside the lens if ((liney % 2) == 0) { colour = 0x00ffffff; } else { colour = 0x7fffffff; } range = (liney - lenstop - lensheight * 0.5f) / (lensheight * 0.5f); if (range < 0) { range = -range; } if (range > 1) { range = 0; } range = (range - 0.75f) * 4.0f; if (range < 0) { range = 0; } if (range > 0) { colour = colourBlend(0x000000ff, colour, range * 255.0f); } } else { // Outside of the lens if ((liney % 2) == 0) { colour = 0x007f7fff; } else { colour = 0x7fffffff; } range = 0; } // Different coloured lines at 1/4 and 3/4 marks in the lens if (liney == lenstop + lensheight / 4 || liney == lenstop + lensheight - lensheight / 4) { colour = 0xffffffff; } gDPSetColor(gdl++, G_SETENVCOLOR, colour); gdl = bviewCopyPixels(gdl, fb, liney, 5, liney, RANDOMFRAC() * range + 1, viewleft, viewwidth); } return gdl; } /** * Draws the black part of the IR scanner, which obscures the edges of the * screen and creates the binocular effect. * * The two circles are "placed" at the 1/3 and 2/3 marks horizontally. The * screen is then iterated top to bottom, one line at a time, and draws * black rectangles on each line to fill in the area outside the circles. */ Gfx *bviewDrawIrBinoculars(Gfx *gdl) { s32 viewheight = viGetViewHeight(); s32 viewwidth = viGetViewWidth(); s32 viewtop = viGetViewTop(); s32 viewleft = viGetViewLeft(); s32 viewright = viewleft + viewwidth; s32 viewbottom = viewtop + viewheight; s32 leftx = viewleft + viewwidth / 3; s32 rightx = viewleft + (viewwidth * 2) / 3; s32 centrey = (viewtop + viewbottom) / 2; s32 radius = g_IrBinocularRadius; s32 sqradius = radius * radius; s32 y; u32 stack[2]; gDPPipeSync(gdl++); gDPSetCycleType(gdl++, G_CYC_1CYCLE); gDPSetRenderMode(gdl++, G_RM_XLU_SURF, G_RM_XLU_SURF2); gDPSetCombineMode(gdl++, G_CC_PRIMITIVE, G_CC_PRIMITIVE); gDPSetPrimColor(gdl++, 0, 0, 0x00, 0x00, 0x00, 0xff); for (y = viewtop; y < viewbottom; y++) { s32 ytocentre = centrey - y; s32 sqytocentre = ytocentre * ytocentre; if (sqytocentre < sqradius) { s32 xoffset = (viewwidth / (f32) SCREEN_WIDTH_LO) * sqrtf(sqradius - sqytocentre); // Left side if (leftx - xoffset > viewleft) { gdl = bviewDrawIrRect(gdl, viewleft, y, leftx - xoffset, y + 1); } // Middle (top and bottom) if (leftx + xoffset < rightx - xoffset) { gdl = bviewDrawIrRect(gdl, leftx + xoffset, y, rightx - xoffset, y + 1); } // Right side if (rightx + xoffset < viewright) { gdl = bviewDrawIrRect(gdl, rightx + xoffset, y, viewright, y + 1); } } else { // Very top or bottom - whole line is black #if VERSION >= VERSION_NTSC_1_0 gdl = bviewDrawIrRect(gdl, viewleft, y, viewright, y + 1); #else gdl = bviewDrawIrRect(gdl, viewleft, y, viewright - 1, y + 1); #endif } } return gdl; } Gfx *bview0f148b38(Gfx *gdl) { return gdl; } void bviewSetMotionBlur(u32 bluramount) { var8007f840 = 0; var8007f848 = 0; var8007f844 = (bluramount << 1) / 3; } void bviewClearMotionBlur(void) { var8007f844 = 0; }