From 62e9f4d1a6456f0f7ea60777e1d2e5b2c3d27b88 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Sat, 5 Oct 2024 22:32:13 +1000 Subject: [PATCH] Document artifacts --- src/game/artifact.c | 168 +++++++++++++++++++++++---------- src/game/bondgun.c | 2 +- src/game/game_0b2150.c | 22 ++--- src/game/sky.c | 17 ++-- src/game/zbuf.c | 73 ++++++++------ src/include/bss.h | 2 +- src/include/constants.h | 2 +- src/include/game/game_0b2150.h | 6 +- src/include/game/zbuf.h | 2 +- src/include/types.h | 15 ++- src/lib/sched.c | 32 +++---- 11 files changed, 206 insertions(+), 135 deletions(-) diff --git a/src/game/artifact.c b/src/game/artifact.c index 6fdc5326b..ce2ec7357 100644 --- a/src/game/artifact.c +++ b/src/game/artifact.c @@ -17,10 +17,71 @@ #include "data.h" #include "types.h" +/** + * Artifacts are points of interest in the z-buffer. + * + * They correspond to: + * - Individual circles in the lens flare effect from the sun. + * - Individual corners of each light fixture's box. + * + * The game needs to do line of sight checks to these points. The collision + * system would normally be used for line of sight checks, but it only works + * with basic geometric volumes and also doesn't take into account the player's + * gun. Instead, the checks are done by reading from the previous frame's + * z-buffer. + * + * Typically, the z-buffer would be read by the scheduler after a graphics frame + * is rendered, but this only works if the z-buffer is a complete image. + * PD draws the scene, then clears the z-buffer before drawing the player's gun, + * so the z-buffer at the end only contains the player's gun. To work around + * this, the GPU is given commands to read the z-buffer as a texture and copy + * depth values to a safe place before clearing it. Then once the frame is + * rendered, the scheduler compares the saved depths with the current z-buffer + * and updates the artifact, applying the minimum of the two depths. + * + * The scheduler maintains 3 arrays of artifacts, each referenced by indexes + * which rotate between them. + * - Artifacts are written by the main thread using the write index. + * The write and front indexes are then incremented. + * - The same artifacts are updated by the scheduler using the pending index. + * The pending index is then updated. + * - The artifacts are then rendered on a later frame using the front index. + * + * In each artifacts array, the first several slots are reserved for the sun + * flare artifacts. The quantity depends on the number of suns in the stage + * (Skedar Ruins has 3) and there are 8 artifacts per sun. The remaining slots + * are used for light fixture corners. The array is big enough to handle at + * least 90 lights on screen at a time. + * + * The initial state of the indexes are write=0, front=1, pending=0. + * These are set in sched_reset_artifacts. + * + * The detailed workflow is: + * - CPU: Light artifacts are determined and added to write artifacts (0) array + * - CPU: Constructs the gdl in this order: + * - Render scene + * - Copy relevant parts of z-buffer to write depths (0) array + * - Clear z-buffer and render gun + * - Render artifacts by reading from front artifacts (1) array + * - CPU: increments write (0 -> 1) and front (1 -> 2) indexes + * - GPU: Executes above task. g_ArtifactDepths0 now contains depths, and is + * pointed to by pending. + * - Scheduler: Reads the z-buffer, which at this point only contains the gun + * depth information, and updates the artifact with the minimum of the two + * - Scheduler: Increments pending (0 -> 1) + * + * It appears that the front index should be initialised to 2 instead, so that + * it's one frame behind the others rather than two frames behind. + * + * There's no doubt this went through several iterations before landing on this + * implementation. It's likely that this was implemented using a single and full + * z-buffer and it worked well until they decided to clear the z-buffer before + * rendering the gun. There is evidence in zbuf.c that they allocated a second + * z-buffer and swapped it. But when memory got too tight they had to change it + * to this texture read method. + */ + u8 *var800a41a0; -u32 var800a41a4; -u32 var800a41a8; -u32 var800a41ac; void artifacts_clear(void) { @@ -38,11 +99,11 @@ void artifacts_tick(void) sched_increment_front_artifacts(); } -u16 func0f13c574(f32 arg0) +u16 artifacts_calculate_unk04(f32 arg0) { u32 value = arg0 * 8.0f; u32 left; - u32 right = value; + u32 right; if (value > 0x3f800) { right = value & 0x7ff; @@ -78,10 +139,10 @@ u16 func0f13c574(f32 arg0) left = 0; } - return left << 13 | (right << 2); + return left << 13 | right << 2; } -s32 func0f13c710(f32 arg0) +s32 artifacts_float_to_int(f32 arg0) { if (arg0 > 0.0f) { if (arg0 > 2147483520.0f) { @@ -198,8 +259,8 @@ void artifacts_calculate_glares_for_room(s32 roomnum) if (spdc[3] > 0.0001f) { f20 = 1.0f / spdc[3]; - x = func0f13c710(viewleft + (1.0f + spdc[0] * f20) * (viewwidth * 0.5f)); - y = func0f13c710(viewtop + (1.0f - spdc[1] * f20) * (viewheight * 0.5f)); + x = artifacts_float_to_int(viewleft + (1.0f + spdc[0] * f20) * (viewwidth * 0.5f)); + y = artifacts_float_to_int(viewtop + (1.0f - spdc[1] * f20) * (viewheight * 0.5f)); f0 = (spdc[2] * f20 * 511.0f + 511.0f) * 32.0f; if (f0 < 32576.0f) { @@ -301,8 +362,8 @@ void artifacts_calculate_glares_for_room(s32 roomnum) f20 = -9999.0f; } - xi = func0f13c710(viewleft + (1.0f + spdc[0] * f20) * (viewwidth * 0.5f)); - yi = func0f13c710(viewtop + (1.0f - spdc[1] * f20) * (viewheight * 0.5f)); + xi = artifacts_float_to_int(viewleft + (1.0f + spdc[0] * f20) * (viewwidth * 0.5f)); + yi = artifacts_float_to_int(viewtop + (1.0f - spdc[1] * f20) * (viewheight * 0.5f)); f0 = (spdc[2] * f20 * 511.0f + 511.0f) * 32.0f; if (g_ZbufPtr1 @@ -322,12 +383,12 @@ void artifacts_calculate_glares_for_room(s32 roomnum) } if (index < MAX_ARTIFACTS) { - artifact->unk04 = func0f13c574(f0) >> 2; - artifact->unk08 = &g_ZbufPtr1[vi_get_width() * yi + xi]; + artifact->expecteddepth = artifacts_calculate_unk04(f0) >> 2; + artifact->zbufptr = &g_ZbufPtr1[vi_get_width() * yi + xi]; artifact->light = &roomlights[i]; artifact->type = ARTIFACTTYPE_GLARE; - artifact->unk0c.u16_2 = xi; - artifact->unk0c.u16_1 = yi; + artifact->screenx = xi; + artifact->screeny = yi; } } } @@ -338,17 +399,20 @@ void artifacts_calculate_glares_for_room(s32 roomnum) } } -u8 func0f13d3c4(u8 arg0, u8 arg1) +/** + * Clamp the given value to with 7 units of base. + */ +u8 artifacts_clamp(u8 base, u8 value) { - if (arg1 >= arg0 + 7) { - return arg0 + 7; + if (value >= base + 7) { + return base + 7; } - if (arg1 <= arg0 - 7) { - return arg0 - 7; + if (value <= base - 7) { + return base - 7; } - return arg1; + return value; } Gfx *artifacts_configure_for_glares(Gfx *gdl) @@ -386,18 +450,18 @@ Gfx *artifacts_render_glares_for_room(Gfx *gdl, s32 roomnum) u16 min; u16 max; f32 lightop_cur_frac; - s32 t2; + s32 numgood; struct light *light; u8 *s3; s32 k; s32 count; - u16 t4; + u16 actualdepth; f32 add; s32 l; f32 brightness; - s32 avg; + s32 tolerance; f32 f0; - s32 v1; + s32 difference; s32 r; s32 g; s32 b; @@ -405,8 +469,8 @@ Gfx *artifacts_render_glares_for_room(Gfx *gdl, s32 roomnum) u8 colour[4]; s16 lightroompos[3]; struct coord lightworldpos; - struct coord lightscreenpos; - f32 spdc[2]; + struct coord lightworlddiff; + f32 screenpos[2]; f32 spd4[2]; f32 f24; bool extra; @@ -433,48 +497,48 @@ Gfx *artifacts_render_glares_for_room(Gfx *gdl, s32 roomnum) if (roomnum == light->roomnum) { lightindex = ((uintptr_t)light - (uintptr_t)g_BgLightsFileData) / sizeof(struct light); s3 = &var800a41a0[lightindex * 3]; - t2 = 0; + numgood = 0; min = 0xffff; max = 0; for (k = i; k < i + count; k++) { - if (artifacts[k].unk04 > max) { - max = artifacts[k].unk04; + if (artifacts[k].expecteddepth > max) { + max = artifacts[k].expecteddepth; } - if (artifacts[k].unk04 < min) { - min = artifacts[k].unk04; + if (artifacts[k].expecteddepth < min) { + min = artifacts[k].expecteddepth; } } - avg = (max - min) >> 1; + tolerance = (max - min) >> 1; - if (avg < 25) { - avg = 25; + if (tolerance < 25) { + tolerance = 25; } for (k = i; k < i + count; k++) { - u16 tmp; - t4 = (artifacts[k].unk02 & 0xfffc) >> 2; - tmp = artifacts[k].unk04; + u16 expecteddepth; + actualdepth = (artifacts[k].actualdepth & 0xfffc) >> 2; + expecteddepth = artifacts[k].expecteddepth; - if (tmp < t4) { - v1 = t4 - tmp; + if (actualdepth > expecteddepth) { + difference = actualdepth - expecteddepth; } else { - v1 = tmp - t4; + difference = expecteddepth - actualdepth; } - if (avg >= v1) { - t2++; + if (difference <= tolerance) { + numgood++; } artifacts[k].type = ARTIFACTTYPE_FREE; } - s3[0] = func0f13d3c4(s3[0], t2 * 2); + s3[0] = artifacts_clamp(s3[0], numgood * 2); - if (t2 > 0) { - brightness = vi_get_fov_y() * 0.017453292f; + if (numgood > 0) { + brightness = vi_get_fov_y() * DTOR(1.0f); add = cosf(brightness) / sinf(brightness) * 14.6f; if (light_is_healthy(roomnum, lightindex - g_Rooms[roomnum].gfxdata->lightsindex)) { @@ -510,14 +574,14 @@ Gfx *artifacts_render_glares_for_room(Gfx *gdl, s32 roomnum) for (l = 0; l < 3; l++) { lightroompos[l] = (light->bbox[0].s[l] + light->bbox[1].s[l] + light->bbox[2].s[l] + light->bbox[3].s[l]) / 4; lightworldpos.f[l] = lightroompos[l] + g_BgRooms[roomnum].pos.f[l]; - lightscreenpos.f[l] = lightworldpos.f[l] - g_Vars.currentplayer->cam_pos.f[l]; + lightworlddiff.f[l] = lightworldpos.f[l] - g_Vars.currentplayer->cam_pos.f[l]; } - mtx4_rotate_vec_in_place(cam_get_world_to_screen_mtxf(), &lightscreenpos); + mtx4_rotate_vec_in_place(cam_get_world_to_screen_mtxf(), &lightworlddiff); - cam0f0b4d04(&lightscreenpos, spdc); + cam0f0b4d04(&lightworlddiff, screenpos); - brightness *= 27500.0f / (-lightscreenpos.z < 1.0f ? 1.0f : -lightscreenpos.z); + brightness *= 27500.0f / (-lightworlddiff.z < 1.0f ? 1.0f : -lightworlddiff.z); if (light->brightnessmult != 0) { brightness *= light->brightnessmult * (1.0f / 32.0f); @@ -568,7 +632,7 @@ Gfx *artifacts_render_glares_for_room(Gfx *gdl, s32 roomnum) spd4[0] = f24; spd4[1] = f26; - func0f0b2740(&gdl, spdc, spd4, 64, 64, false, false, false, 1); + func0f0b2740(&gdl, screenpos, spd4, 64, 64, false, false, false, 1); if (extra) { colour[0] = 0xff; @@ -582,7 +646,7 @@ Gfx *artifacts_render_glares_for_room(Gfx *gdl, s32 roomnum) spd4[0] = f24 * 0.4f; spd4[1] = f26 * 0.4f; - func0f0b2740(&gdl, spdc, spd4, 64, 64, false, false, false, 1); + func0f0b2740(&gdl, screenpos, spd4, 64, 64, false, false, false, 1); } } } diff --git a/src/game/bondgun.c b/src/game/bondgun.c index 67f9f1b1c..ab5b688dd 100644 --- a/src/game/bondgun.c +++ b/src/game/bondgun.c @@ -8195,7 +8195,7 @@ void bgun_render(Gfx **gdlptr) return; } - gdl = zbuf_draw_artifacts_offscreen(gdl); + gdl = zbuf_save_artifact_depths(gdl); gdl = vi_prepare_zbuf(gdl); gdl = vi0000b1d0(gdl); diff --git a/src/game/game_0b2150.c b/src/game/game_0b2150.c index f08b10bea..93160da32 100644 --- a/src/game/game_0b2150.c +++ b/src/game/game_0b2150.c @@ -10,7 +10,7 @@ * With this function stubbed, light glares do not render, * nor do suns or their lens flares. */ -void func0f0b2150(Gfx **gdlptr, f32 *arg1, f32 *arg2, s32 width, s32 height, s32 arg5, s32 arg6, s32 arg7, s32 arg8, s32 tile, s32 arg10) +void func0f0b2150(Gfx **gdlptr, f32 *arg1, f32 *arg2, s32 width, s32 height, bool flip, bool arg6, bool arg7, bool arg8, s32 tile, bool arg10) { if (arg2[0] > 0.0f && arg2[1] > 0.0f) { Gfx *gdl = *gdlptr; @@ -50,7 +50,7 @@ void func0f0b2150(Gfx **gdlptr, f32 *arg1, f32 *arg2, s32 width, s32 height, s32 } if (xl < 0) { - if (arg5) { + if (flip) { t += ((-xl * height) << 5) / (xh - xl); } else { s += ((-xl * width) << 5) / (xh - xl); @@ -60,7 +60,7 @@ void func0f0b2150(Gfx **gdlptr, f32 *arg1, f32 *arg2, s32 width, s32 height, s32 } if (yl < 0) { - if (arg5) { + if (flip) { s += ((-yl * width) << 5) / (yh - yl); } else { t += ((-yl * height) << 5) / (yh - yl); @@ -80,7 +80,7 @@ void func0f0b2150(Gfx **gdlptr, f32 *arg1, f32 *arg2, s32 width, s32 height, s32 yh = heightx4; } - if (arg5) { + if (flip) { dsdx = width / (2.0f * arg2[1]) * 1024.0f; dtdy = height / (2.0f * arg2[0]) * 1024.0f; } else { @@ -113,7 +113,7 @@ void func0f0b2150(Gfx **gdlptr, f32 *arg1, f32 *arg2, s32 width, s32 height, s32 } } - if (arg5) { + if (flip) { gSPTextureRectangleFlip(gdl++, xl, yl, xh, yh, tile, s, t, dsdx, dtdy); } else { gSPTextureRectangle(gdl++, xl, yl, xh, yh, tile, s, t, dsdx, dtdy); @@ -126,17 +126,17 @@ void func0f0b2150(Gfx **gdlptr, f32 *arg1, f32 *arg2, s32 width, s32 height, s32 } } -void func0f0b26f0(Gfx **gdl, f32 *arg1, f32 *arg2, s32 width, s32 height, bool arg5, bool arg6, bool arg7, bool arg8, s32 tile) +void func0f0b26f0(Gfx **gdl, f32 *arg1, f32 *arg2, s32 width, s32 height, bool flip, bool arg6, bool arg7, bool arg8, s32 tile) { - func0f0b2150(gdl, arg1, arg2, width, height, arg5, arg6, arg7, arg8, tile, false); + func0f0b2150(gdl, arg1, arg2, width, height, flip, arg6, arg7, arg8, tile, false); } -void func0f0b2740(Gfx **gdl, f32 *arg1, f32 *arg2, s32 width, s32 height, bool arg5, bool arg6, bool arg7, u32 arg8) +void func0f0b2740(Gfx **gdl, f32 *arg1, f32 *arg2, s32 width, s32 height, bool flip, bool arg6, bool arg7, bool arg8) { - func0f0b2150(gdl, arg1, arg2, width, height, arg5, arg6, arg7, arg8, G_TX_RENDERTILE, false); + func0f0b2150(gdl, arg1, arg2, width, height, flip, arg6, arg7, arg8, G_TX_RENDERTILE, false); } -void func0f0b278c(Gfx **gdlptr, f32 *arg1, f32 *arg2, s32 twidth, u32 theight, u32 arg5, u32 arg6, u32 arg7, u32 r, u32 g, u32 b, u32 alpha, u32 arg12, u32 arg13) +void func0f0b278c(Gfx **gdlptr, f32 *arg1, f32 *arg2, s32 twidth, u32 theight, bool flip, bool arg6, bool arg7, u32 r, u32 g, u32 b, u32 alpha, bool arg12, bool arg13) { if (arg2[0] > 0.0f && arg2[1] > 0.0f) { Gfx *gdl = *gdlptr; @@ -153,6 +153,6 @@ void func0f0b278c(Gfx **gdlptr, f32 *arg1, f32 *arg2, s32 twidth, u32 theight, u *gdlptr = gdl; - func0f0b2150(gdlptr, arg1, arg2, twidth, theight, arg5, arg6, arg7, false, G_TX_RENDERTILE, false); + func0f0b2150(gdlptr, arg1, arg2, twidth, theight, flip, arg6, arg7, false, G_TX_RENDERTILE, false); } } diff --git a/src/game/sky.c b/src/game/sky.c index 82e5f3b48..91348fc5f 100644 --- a/src/game/sky.c +++ b/src/game/sky.c @@ -2427,9 +2427,9 @@ void sky_create_sun_artifact(struct artifact *artifact, s32 x, s32 y) s32 viewheight = vi_get_view_height(); if (x >= viewleft && x < viewleft + viewwidth && y >= viewtop && y < viewtop + viewheight) { - artifact->unk08 = &g_ZbufPtr1[(s32)cam_get_screen_width() * y + x]; - artifact->unk0c.u16_2 = x; - artifact->unk0c.u16_1 = y; + artifact->zbufptr = &g_ZbufPtr1[(s32)cam_get_screen_width() * y + x]; + artifact->screenx = x; + artifact->screeny = y; artifact->type = ARTIFACTTYPE_CIRCLE; } } @@ -2440,7 +2440,7 @@ f32 sky_get_artifact_group_intensity_frac(struct artifact *artifacts) s32 i; for (i = 0; i < 8; i++) { - if (artifacts[i].type == ARTIFACTTYPE_CIRCLE && artifacts[i].unk02 == 0xfffc) { + if (artifacts[i].type == ARTIFACTTYPE_CIRCLE && artifacts[i].actualdepth == 0xfffc) { sum += 0.125f; } } @@ -2616,7 +2616,8 @@ Gfx *sky_render_suns(Gfx *gdl, bool xray) sp12c[0] = radius * 0.50f * xscale; sp12c[1] = radius * 0.50f; - func0f0b2150(&gdl, sp134, sp12c, g_TexLightGlareConfigs[TEX_LIGHT_05].width, g_TexLightGlareConfigs[TEX_LIGHT_05].height, 0, 1, 1, 1, 0, 1); + func0f0b2150(&gdl, sp134, sp12c, g_TexLightGlareConfigs[TEX_LIGHT_05].width, g_TexLightGlareConfigs[TEX_LIGHT_05].height, + false, true, true, true, 0, true); gDPPipeSync(gdl++); gDPSetColorDither(gdl++, G_CD_BAYER); @@ -2707,7 +2708,8 @@ Gfx *sky_render_flare(Gfx *gdl, f32 x, f32 y, f32 intensityfrac, f32 size, s32 f sp174[1] = f2 * 0.5f; sp174[0] = f2 * 0.5f * scale; - func0f0b2150(&gdl, sp17c, sp174, g_TexLightGlareConfigs[TEX_LIGHT_06].width, g_TexLightGlareConfigs[TEX_LIGHT_06].height, 0, 1, 1, 1, 0, 1); + func0f0b2150(&gdl, sp17c, sp174, g_TexLightGlareConfigs[TEX_LIGHT_06].width, g_TexLightGlareConfigs[TEX_LIGHT_06].height, + false, true, true, true, 0, true); // Render the other artifacts tex_select(&gdl, &g_TexLightGlareConfigs[TEX_LIGHT_01], 4, 0, 2, 1, NULL); @@ -2764,7 +2766,8 @@ Gfx *sky_render_flare(Gfx *gdl, f32 x, f32 y, f32 intensityfrac, f32 size, s32 f sp174[1] = tmp * 0.5f; sp174[0] = tmp * 0.5f * scale; - func0f0b2150(&gdl, sp17c, sp174, g_TexLightGlareConfigs[TEX_LIGHT_01].width, g_TexLightGlareConfigs[TEX_LIGHT_01].height, 0, 0, 0, 0, 0, 1); + func0f0b2150(&gdl, sp17c, sp174, g_TexLightGlareConfigs[TEX_LIGHT_01].width, g_TexLightGlareConfigs[TEX_LIGHT_01].height, + false, false, false, false, 0, true); } // Check if the source is close to the center of the screen and create the bloom effect if so diff --git a/src/game/zbuf.c b/src/game/zbuf.c index af162440d..c10e74850 100644 --- a/src/game/zbuf.c +++ b/src/game/zbuf.c @@ -13,9 +13,9 @@ u32 g_ZbufWidth; u32 g_ZbufHeight; -u16 g_ArtifactsCfb0[0x180]; -u16 g_ArtifactsCfb1[0x180]; -u16 g_ArtifactsCfb2[0x180]; +u16 g_ArtifactDepths0[384]; +u16 g_ArtifactDepths1[384]; +u16 g_ArtifactDepths2[384]; u16 *g_ZbufPtr1 = NULL; u16 *g_ZbufPtr2 = NULL; @@ -76,12 +76,17 @@ void zbuf_allocate(void) } /** - * Note: There is only one z-buffer, so there is nothing to swap. - * Both of these pointers always have the same value. + * In an older implementation, the game almost certainly had two z-buffers. + * It needs a fresh z-buffer after rendering the scene and before rendering the + * player's gun, but it also needs to read values off both z-buffers for + * lighting purposes. In this older implementation, two z-buffers would have + * been used and swapped. * - * We assume this is a swap function due to the context in which it's called. - * Perhaps the developers implemented two buffers with swapping before realising - * they only needed one. + * Due to memory limitations, this method was removed and an alternative + * solution was used to read this values. + * + * This function is still called but it does nothing. + * There is only one z-buffer, and both pointers always have the same value. */ void zbuf_swap(void) { @@ -154,20 +159,20 @@ Gfx *zbuf_clear(Gfx *gdl) return gdl; } -u16 *zbuf_get_artifacts_cfb(s32 index) +u16 *zbuf_get_artifacts_depth_samples(s32 index) { u16 *addr; if (index == 0) { - addr = g_ArtifactsCfb0; + addr = g_ArtifactDepths0; } if (index == 1) { - addr = g_ArtifactsCfb1; + addr = g_ArtifactDepths1; } if (index == 2) { - addr = g_ArtifactsCfb2; + addr = g_ArtifactDepths2; } addr = (u16 *) (((uintptr_t) addr + 0x3f) & ~0x3f); @@ -175,23 +180,29 @@ u16 *zbuf_get_artifacts_cfb(s32 index) return addr; } -Gfx *zbuf_draw_artifacts_offscreen(Gfx *gdl) +/** + * Append GDL commands which make the GPU read from the z-buffer as a texture + * and write it to the scheduler's write artifacts list. Only the individual + * pixels of interest are copied. + */ +Gfx *zbuf_save_artifact_depths(Gfx *gdl) { struct artifact *artifacts = sched_get_write_artifacts(); u32 stack; - u16 *sp4c = g_ZbufPtr1; - u32 s4 = 0; - u16 *sp44; - u16 *s2; - u16 *image; + u16 *zbuf = g_ZbufPtr1; + u32 numsamples = 0; + u16 *samples; + u16 *thissample; + u16 *zbufrow; s32 i; vi_get_back_buffer(); - sp44 = zbuf_get_artifacts_cfb(g_SchedWriteArtifactsIndex); - g_SchedSpecialArtifactIndexes[g_SchedWriteArtifactsIndex] = 1; + samples = zbuf_get_artifacts_depth_samples(g_SchedWriteArtifactsIndex); + + g_SchedArtifactsWithDualBuffers[g_SchedWriteArtifactsIndex] = true; gDPPipeSync(gdl++); - gDPSetColorImage(gdl++, G_IM_FMT_RGBA, G_IM_SIZ_16b, vi_get_buf_width(), OS_PHYSICAL_TO_K0(sp44)); + gDPSetColorImage(gdl++, G_IM_FMT_RGBA, G_IM_SIZ_16b, vi_get_buf_width(), OS_PHYSICAL_TO_K0(samples)); gDPSetScissor(gdl++, G_SC_NON_INTERLACE, 0, 0, SCREEN_320, SCREEN_240); gDPSetCycleType(gdl++, G_CYC_COPY); 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); @@ -218,24 +229,24 @@ Gfx *zbuf_draw_artifacts_offscreen(Gfx *gdl) if (1); if (artifacts[i].type != ARTIFACTTYPE_FREE) { - s2 = &sp44[s4]; - image = &sp4c[artifacts[i].unk0c.u16_1 * vi_get_width()]; + thissample = &samples[numsamples]; + zbufrow = &zbuf[artifacts[i].screeny * vi_get_width()]; gDPPipeSync(gdl++); - gDPSetTextureImage(gdl++, G_IM_FMT_RGBA, G_IM_SIZ_16b, SCREEN_320, image); + gDPSetTextureImage(gdl++, G_IM_FMT_RGBA, G_IM_SIZ_16b, SCREEN_320, zbufrow); gDPLoadSync(gdl++); gDPLoadBlock(gdl++, 5, 0, 0, vi_get_width() - 1, 0); gDPPipeSync(gdl++); gSPTextureRectangle(gdl++, - s4 << 2, 0, - (s4 + 3) << 2, 0, - G_TX_RENDERTILE, (artifacts[i].unk0c.u16_2 * 32) + 16, 0x0010, 0x1000, 0); + numsamples << 2, 0, + (numsamples + 3) << 2, 0, + G_TX_RENDERTILE, (artifacts[i].screenx * 32) + 16, 0x0010, 0x1000, 0); - artifacts[i].unk0c.u16p = s2; - s4++; + artifacts[i].depthptr = thissample; + numsamples++; - if (s2); + if (thissample); } } @@ -249,7 +260,7 @@ Gfx *zbuf_draw_artifacts_offscreen(Gfx *gdl) gDPSetTexturePersp(gdl++, G_TP_PERSP); gDPSetColorDither(gdl++, G_CD_BAYER); - if (sp44); + if (samples); return gdl; } diff --git a/src/include/bss.h b/src/include/bss.h index b2870806d..a4833d49c 100644 --- a/src/include/bss.h +++ b/src/include/bss.h @@ -12,7 +12,7 @@ extern OSViMode *var8008dd60[NUM_GFXTASKS]; extern s32 var8008de08; extern s32 g_ViCurVStart0; extern s32 g_ViCurVStart1; -extern u8 g_SchedSpecialArtifactIndexes[3]; +extern u8 g_SchedArtifactsWithDualBuffers[3]; extern s32 g_SchedWriteArtifactsIndex; extern OSPiHandle CartRomHandle; extern OSPiHandle LeoDiskHandle; diff --git a/src/include/constants.h b/src/include/constants.h index 63a7245d5..b20ff0da6 100644 --- a/src/include/constants.h +++ b/src/include/constants.h @@ -4651,7 +4651,7 @@ enum weaponnum { #define INVAIMFLAG_AUTOAIM 0x00000002 #define INVAIMFLAG_ACCURATESINGLESHOT 0x00000004 -#define WEAPONFLAG_THROWABLE 0x00000001 // Entire weapon is throwable (eg. grendes, mines, knives) +#define WEAPONFLAG_THROWABLE 0x00000001 // Entire weapon is throwable (eg. grenades, mines, knives) #define WEAPONFLAG_00000004 0x00000004 #define WEAPONFLAG_ONEHANDED 0x00000008 // Makes guards carry the gun with one hand #define WEAPONFLAG_AICANUSE 0x00000010 diff --git a/src/include/game/game_0b2150.h b/src/include/game/game_0b2150.h index 5d1902659..be5d12d64 100644 --- a/src/include/game/game_0b2150.h +++ b/src/include/game/game_0b2150.h @@ -4,8 +4,8 @@ #include "data.h" #include "types.h" -void func0f0b2150(Gfx **gdl, f32 *arg1, f32 *arg2, s32 width, s32 height, bool arg5, bool arg6, bool arg7, bool arg8, bool arg9, bool arg10); -void func0f0b2740(Gfx **gdl, f32 *arg1, f32 *arg2, s32 width, s32 height, bool arg5, bool arg6, bool arg7, u32 arg8); -void func0f0b278c(Gfx **gdl, f32 *arg1, f32 *arg2, s32 width, u32 height, u32 arg5, u32 arg6, u32 arg7, u32 r, u32 g, u32 b, u32 alpha, u32 arg12, u32 arg13); +void func0f0b2150(Gfx **gdl, f32 *arg1, f32 *arg2, s32 width, s32 height, bool flip, bool arg6, bool arg7, bool arg8, bool arg9, bool arg10); +void func0f0b2740(Gfx **gdl, f32 *arg1, f32 *arg2, s32 width, s32 height, bool flip, bool arg6, bool arg7, bool arg8); +void func0f0b278c(Gfx **gdl, f32 *arg1, f32 *arg2, s32 width, u32 height, bool flip, bool arg6, bool arg7, u32 r, u32 g, u32 b, u32 alpha, bool arg12, bool arg13); #endif diff --git a/src/include/game/zbuf.h b/src/include/game/zbuf.h index f0f7d3303..aa229721f 100644 --- a/src/include/game/zbuf.h +++ b/src/include/game/zbuf.h @@ -9,6 +9,6 @@ void zbuf_reset(s32 stagenum); void zbuf_swap(void); Gfx *zbuf_configure_rdp(Gfx *gdl); Gfx *zbuf_clear(Gfx *gdl); -Gfx *zbuf_draw_artifacts_offscreen(Gfx *gdl); +Gfx *zbuf_save_artifact_depths(Gfx *gdl); #endif diff --git a/src/include/types.h b/src/include/types.h index 91a96b332..82a2a7912 100644 --- a/src/include/types.h +++ b/src/include/types.h @@ -3447,17 +3447,16 @@ struct audioconfig { struct artifact { u16 type; - u16 unk02; - u16 unk04; - u16 unk06; - u16 *unk08; + u16 actualdepth; + u16 expecteddepth; + u16 *zbufptr; union { - u16 *u16p; + u16 *depthptr; struct { - u16 u16_1; - u16 u16_2; + u16 screeny; + u16 screenx; }; - } unk0c; + }; struct light *light; }; diff --git a/src/lib/sched.c b/src/lib/sched.c index a0f3d04c0..8a32c06c8 100644 --- a/src/lib/sched.c +++ b/src/lib/sched.c @@ -73,7 +73,7 @@ u32 var8008de14; OSTimer g_SchedRspTimer; u32 g_SchedDpCounters[4]; struct artifact g_ArtifactLists[3][120]; -u8 g_SchedSpecialArtifactIndexes[3]; +u8 g_SchedArtifactsWithDualBuffers[3]; s32 g_SchedWriteArtifactsIndex; s32 g_SchedFrontArtifactsIndex; s32 g_SchedPendingArtifactsIndex; @@ -479,7 +479,7 @@ void sched_init_artifacts(void) g_ArtifactLists[i][j].type = ARTIFACTTYPE_FREE; } - g_SchedSpecialArtifactIndexes[i] = 0; + g_SchedArtifactsWithDualBuffers[i] = false; } } @@ -494,19 +494,13 @@ struct artifact *sched_get_write_artifacts(void) /** * The front list is the artifact list that is currently being displayed on the - * screen. Rendering logic reads this list. The list may be re-used for multiple - * frames in a row during lag. + * screen. Rendering logic reads this list. */ struct artifact *sched_get_front_artifacts(void) { return g_ArtifactLists[g_SchedFrontArtifactsIndex]; } -/** - * The pending list is possibly misnamed. I'm not sure how this list works. - * - * @TODO: Investigate. - */ struct artifact *sched_get_pending_artifacts(void) { return g_ArtifactLists[g_SchedPendingArtifactsIndex]; @@ -543,25 +537,25 @@ void sched_update_pending_artifacts(void) struct artifact *artifact = &artifacts[i]; if (artifact->type != ARTIFACTTYPE_FREE) { - u16 *unk08 = artifact->unk08; - u16 value08 = unk08[0]; + u16 *currdepthptr = artifact->zbufptr; + u16 currdepth = *currdepthptr; - if (g_SchedSpecialArtifactIndexes[g_SchedPendingArtifactsIndex] == 1) { - u16 *unk0c = artifact->unk0c.u16p; - u16 value0c = unk0c[0]; + if (g_SchedArtifactsWithDualBuffers[g_SchedPendingArtifactsIndex] == true) { + u16 *prevdepthptr = artifact->depthptr; + u16 prevdepth = *prevdepthptr; - if (value0c > value08) { - artifact->unk02 = value08; + if (currdepth < prevdepth) { + artifact->actualdepth = currdepth; } else { - artifact->unk02 = value0c; + artifact->actualdepth = prevdepth; } } else { - artifact->unk02 = value08; + artifact->actualdepth = currdepth; } } } - g_SchedSpecialArtifactIndexes[g_SchedPendingArtifactsIndex] = 0; + g_SchedArtifactsWithDualBuffers[g_SchedPendingArtifactsIndex] = false; sched_increment_pending_artifacts(); }