IR Goggle support for 4player and 1-2p draw fixes

- allocate memory for 4player's IR goggle scanlines
- fixes IR goggle alignment
- fixes IR lens for players 2 and 4
- fixes off-by-one rendering error for top two players (bottom of screen)
- fixes off-by-one rendering error for right-side players (right side of semicircle thing)
- fixes dark area flickering; use resolved shading for props if not wearing goggles
- port: fix IR goggle off-by-one draw issues
This commit is contained in:
Catherine Reprobate committed 2025-03-23 12:47:06 -07:00
1 parent 2ff8819265
commit 355f0ed0ee
2 files changed
+31 -4

No files matched your search

+29 -2
View File
@@ -31,7 +31,7 @@ char var800a41c0[26];
char var800a41c0[24];
#endif
u8 g_IrScanlines[2][480];
u8 g_IrScanlines[4][480];
#if VERSION < VERSION_NTSC_1_0
u8 var800a8b58nb[0x1c0];
@@ -2356,6 +2356,10 @@ Gfx *bviewDrawIrLens(Gfx *gdl)
gSPSetExtraGeometryModeEXT(gdl++, G_MODULATE_EXT);
#endif
// fixes off by one error w/ two top players
if (g_Vars.currentplayernum == 0 || g_Vars.currentplayernum == 1) {
scanbottom++;
}
for (i = scantop; i < scanbottom; i++) {
#if VERSION >= VERSION_NTSC_1_0
if (i & 1) {
@@ -2392,6 +2396,10 @@ Gfx *bviewDrawIrLens(Gfx *gdl)
s32 semicirclewidth = sqrtf(sqinnerradius - (s32) (f0 * f0)) * (viewwidth / (f32) SCREEN_WIDTH_LO);
s32 semicircleright = viewcentrex + semicirclewidth;
s32 rightsidewidth = viewwidth - semicircleright;
// if playernum is 1 or 3, shift to the right by viewwidth
if (g_Vars.currentplayernum == 1 || g_Vars.currentplayernum == 3) {
rightsidewidth += viewwidth;
}
#ifdef PLATFORM_N64
// Left and right of semicircle
@@ -2405,14 +2413,22 @@ Gfx *bviewDrawIrLens(Gfx *gdl)
gdl = bviewCopyPixels(gdl, fb, i, 5, i, 1.0f, viewleft, viewwidth);
}
#else
// Left and right of semicircle
// Scanlines to the left and right of the semicircle
gDPFillRectangle(gdl++, viewleft, i, viewcentrex, i + 1);
if (PLAYERCOUNT() <= 2 && g_Vars.currentplayernum == 0 && i == viewcentrey) {
semicircleright -= 1;
}
else if (PLAYERCOUNT() > 2 && (g_Vars.currentplayernum == 1 || g_Vars.currentplayernum == 3 ) && i == viewcentrey) {
semicircleright -= 1;
}
gDPFillRectangle(gdl++, semicircleright, i, semicircleright + rightsidewidth, i + 1);
// The semicircle itself has a static colour
gDPSetPrimColorViaWord(gdl++, 0, 0, 0xee0000ff);
gDPFillRectangle(gdl++, viewcentrex, i, viewcentrex + semicirclewidth, i + 1);
} else {
// scanlines above and below the semicircle
gDPFillRectangle(gdl++, viewleft, i, viewleft + viewwidth, i + 1);
}
#endif
@@ -2781,6 +2797,10 @@ Gfx *bviewDrawIrBinoculars(Gfx *gdl)
s32 viewleft = viGetViewLeft();
s32 viewright = viewleft + viewwidth;
s32 viewbottom = viewtop + viewheight;
// fixes off by one error w/ two top players
if (g_Vars.currentplayernum == 0 || g_Vars.currentplayernum == 1) {
viewbottom++;
}
s32 leftx = viewleft + viewwidth / 3;
s32 rightx = viewleft + (viewwidth * 2) / 3;
s32 centrey = (viewtop + viewbottom) / 2;
@@ -2798,6 +2818,13 @@ Gfx *bviewDrawIrBinoculars(Gfx *gdl)
for (y = viewtop; y < viewbottom; y++) {
s32 ytocentre = centrey - y;
s32 sqytocentre = ytocentre * ytocentre;
if (PLAYERCOUNT() <= 2) {
sqytocentre += 1;
} else if (PLAYERCOUNT() > 2) {
if (g_Vars.currentplayernum == 1 || g_Vars.currentplayernum == 3) {
sqytocentre += 1;
}
}
if (sqytocentre < sqradius) {
s32 xoffset = (viewwidth / (f32) SCREEN_WIDTH_LO) * sqrtf(sqradius - sqytocentre);
+2 -2
View File
@@ -1616,9 +1616,9 @@ void propCalculateShadeColour(struct prop *prop, u8 *nextcol, u16 floorcol)
{
s32 shade = func0f068fc8(prop, 0);
// fix props flickering in split screen when one of the players has night vision on
// fix props flickering in split screen when one of the players has night vision or IR Goggles on
if (prop->type != PROPTYPE_PLAYER || g_Vars.currentplayer->prop != prop) {
if (USINGDEVICE(DEVICE_NIGHTVISION)) {
if (USINGDEVICE(DEVICE_NIGHTVISION) || USINGDEVICE(DEVICE_IRSCANNER)) {
if (prop->rooms[0] >= 0) {
shade = g_Rooms[prop->rooms[0]].br_settled_regional;
}