From b1ba2b39975408eda82352bb696c4ab9c795d079 Mon Sep 17 00:00:00 2001 From: Tharo Date: Thu, 16 Apr 2026 21:33:07 +0100 Subject: [PATCH] Macro-ify access to pauseCtx->playerSegment regions (#2693) * Macro-ify access to pauseCtx->playerSegment regions. Using macros to indicate which region in the player segment is being accessed makes the memory layout more obvious and indicates the intended level of memory ownership, particularly in the case of the texture image at the start of the segment. * Add clarifications for gameplay_keep details * Uniform macro name for the render texture * Comment --- include/pause.h | 26 ++++++++++++++++- src/code/z_player_lib.c | 29 ++++++++++--------- .../ovl_kaleido_scope/z_kaleido_equipment.c | 9 +++--- .../misc/ovl_kaleido_scope/z_kaleido_scope.c | 4 +-- 4 files changed, 47 insertions(+), 21 deletions(-) diff --git a/include/pause.h b/include/pause.h index d5f348a03c..694ab91d73 100644 --- a/include/pause.h +++ b/include/pause.h @@ -53,9 +53,33 @@ typedef enum PauseMenuPage { #define PAUSE_EQUIP_PLAYER_FRAG_HEIGHT (TMEM_SIZE / (PAUSE_EQUIP_PLAYER_WIDTH * G_IM_SIZ_16b_BYTES)) #define PAUSE_EQUIP_PLAYER_FRAG_NUM (((PAUSE_EQUIP_PLAYER_HEIGHT - 1) / PAUSE_EQUIP_PLAYER_FRAG_HEIGHT) + 1) -#define PAUSE_EQUIP_BUFFER_SIZE sizeof(u16[PAUSE_EQUIP_PLAYER_HEIGHT][PAUSE_EQUIP_PLAYER_WIDTH]) +// The pause player segment consists of: +// PAUSE_PLAYER_SEGMENT_RENDER_TEXTURE_SIZE RGBA16 texture / framebuffer for rendering the player into +// PAUSE_PLAYER_SEGMENT_GAMEPLAY_KEEP_BUFFER_SIZE First bytes of gameplay_keep for accessing player-related data +// sizeof(link object) Link object +// sizeof(Vec3s[PLAYER_LIMB_BUF_COUNT])) Joint table + +#define PAUSE_PLAYER_SEGMENT_RENDER_TEXTURE_SIZE sizeof(u16[PAUSE_EQUIP_PLAYER_HEIGHT][PAUSE_EQUIP_PLAYER_WIDTH]) #define PAUSE_PLAYER_SEGMENT_GAMEPLAY_KEEP_BUFFER_SIZE 0x5000 +#define PAUSE_PLAYER_SEGMENT_RENDER_TEXTURE(playerSegment) \ + (playerSegment) + +// Note that only the first chunk of gameplay_keep is loaded, the data relevant to rendering the player +// is expected to be within this first chunk. The size of this first chunk is determined by +// PAUSE_PLAYER_SEGMENT_GAMEPLAY_KEEP_BUFFER_SIZE. +#define PAUSE_PLAYER_SEGMENT_GAMEPLAY_KEEP_START(playerSegment) \ + ((playerSegment) + PAUSE_PLAYER_SEGMENT_RENDER_TEXTURE_SIZE) + +#define PAUSE_PLAYER_SEGMENT_LINK_OBJECT(playerSegment) \ + ((playerSegment) + PAUSE_PLAYER_SEGMENT_RENDER_TEXTURE_SIZE + PAUSE_PLAYER_SEGMENT_GAMEPLAY_KEEP_BUFFER_SIZE) + +#define PAUSE_PLAYER_SEGMENT_TOTAL_SIZE(linkObjectSize) \ + (PAUSE_PLAYER_SEGMENT_RENDER_TEXTURE_SIZE + \ + PAUSE_PLAYER_SEGMENT_GAMEPLAY_KEEP_BUFFER_SIZE + \ + (linkObjectSize) + \ + sizeof(Vec3s[PLAYER_LIMB_BUF_COUNT])) + typedef enum PauseState { /* 0 */ PAUSE_STATE_OFF, /* 1 */ PAUSE_STATE_WAIT_LETTERBOX, // Request no letterboxing and wait for it. diff --git a/src/code/z_player_lib.c b/src/code/z_player_lib.c index 49948f8562..c701f379db 100644 --- a/src/code/z_player_lib.c +++ b/src/code/z_player_lib.c @@ -1890,25 +1890,27 @@ u32 Player_InitPauseDrawData(PlayState* play, u8* segment, SkelAnime* skelAnime) u32 size; void* ptr; + // Note that since gameplay_keep is typically a compressed segment and due to constraints in the DMA manager, + // the entire segment is loaded even when only the first bytes up to PAUSE_PLAYER_SEGMENT_GAMEPLAY_KEEP_BUFFER_SIZE + // are kept for later use. size = gObjectTable[OBJECT_GAMEPLAY_KEEP].vromEnd - gObjectTable[OBJECT_GAMEPLAY_KEEP].vromStart; - ptr = segment + PAUSE_EQUIP_BUFFER_SIZE; + ptr = PAUSE_PLAYER_SEGMENT_GAMEPLAY_KEEP_START(segment); DMA_REQUEST_SYNC(ptr, gObjectTable[OBJECT_GAMEPLAY_KEEP].vromStart, size, "../z_player_lib.c", 2982); size = gObjectTable[linkObjectId].vromEnd - gObjectTable[linkObjectId].vromStart; - ptr = segment + PAUSE_EQUIP_BUFFER_SIZE + PAUSE_PLAYER_SEGMENT_GAMEPLAY_KEEP_BUFFER_SIZE; + ptr = PAUSE_PLAYER_SEGMENT_LINK_OBJECT(segment); DMA_REQUEST_SYNC(ptr, gObjectTable[linkObjectId].vromStart, size, "../z_player_lib.c", 2988); + // Joint tables are placed after the link object ptr = (void*)ALIGN16((uintptr_t)ptr + size); - gSegments[4] = OS_K0_TO_PHYSICAL(segment + PAUSE_EQUIP_BUFFER_SIZE); - gSegments[6] = - OS_K0_TO_PHYSICAL(segment + PAUSE_EQUIP_BUFFER_SIZE + PAUSE_PLAYER_SEGMENT_GAMEPLAY_KEEP_BUFFER_SIZE); + gSegments[4] = OS_K0_TO_PHYSICAL(PAUSE_PLAYER_SEGMENT_GAMEPLAY_KEEP_START(segment)); + gSegments[6] = OS_K0_TO_PHYSICAL(PAUSE_PLAYER_SEGMENT_LINK_OBJECT(segment)); SkelAnime_InitLink(play, skelAnime, gPlayerSkelHeaders[(void)0, gSaveContext.save.linkAge], &gPlayerAnim_link_normal_wait, 9, ptr, ptr, PLAYER_LIMB_MAX); - return PAUSE_EQUIP_BUFFER_SIZE + PAUSE_PLAYER_SEGMENT_GAMEPLAY_KEEP_BUFFER_SIZE + size + - sizeof(Vec3s[PLAYER_LIMB_BUF_COUNT]); + return PAUSE_PLAYER_SEGMENT_TOTAL_SIZE(size); } u8 sPauseModelGroupBySword[] = { @@ -2078,9 +2080,8 @@ void Player_DrawPause(PlayState* play, u8* segment, SkelAnime* skelAnime, Vec3f* Vec3s* srcTable; s32 i; - gSegments[4] = OS_K0_TO_PHYSICAL(segment + PAUSE_EQUIP_BUFFER_SIZE); - gSegments[6] = - OS_K0_TO_PHYSICAL(segment + PAUSE_EQUIP_BUFFER_SIZE + PAUSE_PLAYER_SEGMENT_GAMEPLAY_KEEP_BUFFER_SIZE); + gSegments[4] = OS_K0_TO_PHYSICAL(PAUSE_PLAYER_SEGMENT_GAMEPLAY_KEEP_START(segment)); + gSegments[6] = OS_K0_TO_PHYSICAL(PAUSE_PLAYER_SEGMENT_LINK_OBJECT(segment)); if (!LINK_IS_ADULT) { if (shield == PLAYER_SHIELD_DEKU) { @@ -2104,9 +2105,9 @@ void Player_DrawPause(PlayState* play, u8* segment, SkelAnime* skelAnime, Vec3f* *destTable++ = *srcTable++; } - Player_DrawPauseImpl(play, segment + PAUSE_EQUIP_BUFFER_SIZE, - segment + PAUSE_EQUIP_BUFFER_SIZE + PAUSE_PLAYER_SEGMENT_GAMEPLAY_KEEP_BUFFER_SIZE, skelAnime, - pos, rot, scale, sword, tunic, shield, boots, PAUSE_EQUIP_PLAYER_WIDTH, - PAUSE_EQUIP_PLAYER_HEIGHT, &eye, &at, 60.0f, play->state.gfxCtx->curFrameBuffer, + Player_DrawPauseImpl(play, PAUSE_PLAYER_SEGMENT_GAMEPLAY_KEEP_START(segment), + PAUSE_PLAYER_SEGMENT_LINK_OBJECT(segment), skelAnime, pos, rot, scale, sword, tunic, shield, + boots, PAUSE_EQUIP_PLAYER_WIDTH, PAUSE_EQUIP_PLAYER_HEIGHT, &eye, &at, 60.0f, + play->state.gfxCtx->curFrameBuffer, play->state.gfxCtx->curFrameBuffer + (PAUSE_EQUIP_PLAYER_WIDTH * PAUSE_EQUIP_PLAYER_HEIGHT)); } diff --git a/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c b/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c index 1ac3237125..1761c64750 100644 --- a/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c +++ b/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c @@ -70,7 +70,7 @@ static u8 sEquipmentItemOffsets[] = { ITEM_BOOTS_HOVER - ITEM_SWORD_KOKIRI, // EQUIP_VALUE_BOOTS_HOVER }; -void KaleidoScope_DrawEquipmentImage(PlayState* play, void* source, u32 width, u32 height) { +void KaleidoScope_DrawEquipmentImage(PlayState* play, void* texture, u32 width, u32 height) { PauseContext* pauseCtx = &play->pauseCtx; u8* curTexture; s32 vtxIndex; @@ -88,7 +88,7 @@ void KaleidoScope_DrawEquipmentImage(PlayState* play, void* source, u32 width, u gDPSetTextureFilter(POLY_OPA_DISP++, G_TF_POINT); gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha); - curTexture = source; + curTexture = texture; remainingSize = width * height * G_IM_SIZ_16b_BYTES; textureHeight = TMEM_SIZE / (width * G_IM_SIZ_16b_BYTES); textureSize = width * textureHeight * G_IM_SIZ_16b_BYTES; @@ -697,7 +697,7 @@ void KaleidoScope_DrawEquipment(PlayState* play) { #endif } - gSPSegment(POLY_OPA_DISP++, 0x07, pauseCtx->playerSegment); + gSPSegment(POLY_OPA_DISP++, 0x07, PAUSE_PLAYER_SEGMENT_RENDER_TEXTURE(pauseCtx->playerSegment)); gSPSegment(POLY_OPA_DISP++, 0x08, pauseCtx->iconItemSegment); gSPSegment(POLY_OPA_DISP++, 0x09, pauseCtx->iconItem24Segment); gSPSegment(POLY_OPA_DISP++, 0x0A, pauseCtx->nameSegment); @@ -707,7 +707,8 @@ void KaleidoScope_DrawEquipment(PlayState* play) { // Draw player prerender onto the equip page Gfx_SetupDL_42Opa(play->state.gfxCtx); - KaleidoScope_DrawEquipmentImage(play, pauseCtx->playerSegment, PAUSE_EQUIP_PLAYER_WIDTH, PAUSE_EQUIP_PLAYER_HEIGHT); + KaleidoScope_DrawEquipmentImage(play, PAUSE_PLAYER_SEGMENT_RENDER_TEXTURE(pauseCtx->playerSegment), + PAUSE_EQUIP_PLAYER_WIDTH, PAUSE_EQUIP_PLAYER_HEIGHT); CLOSE_DISPS(play->state.gfxCtx, "../z_kaleido_equipment.c", 609); } diff --git a/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.c b/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.c index f43b3d627c..ba66f0ca06 100644 --- a/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.c +++ b/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.c @@ -3431,7 +3431,7 @@ void KaleidoScope_Draw(PlayState* play) { pauseCtx->stickAdjY = input->rel.stick_y; gSPSegment(POLY_OPA_DISP++, 0x02, interfaceCtx->parameterSegment); - gSPSegment(POLY_OPA_DISP++, 0x07, pauseCtx->playerSegment); + gSPSegment(POLY_OPA_DISP++, 0x07, PAUSE_PLAYER_SEGMENT_RENDER_TEXTURE(pauseCtx->playerSegment)); gSPSegment(POLY_OPA_DISP++, 0x08, pauseCtx->iconItemSegment); gSPSegment(POLY_OPA_DISP++, 0x09, pauseCtx->iconItem24Segment); gSPSegment(POLY_OPA_DISP++, 0x0A, pauseCtx->nameSegment); @@ -3881,7 +3881,7 @@ void KaleidoScope_Update(PlayState* play) { PreRender_Init(&sPlayerPreRender); PreRender_SetValuesSave(&sPlayerPreRender, PAUSE_EQUIP_PLAYER_WIDTH, PAUSE_EQUIP_PLAYER_HEIGHT, - pauseCtx->playerSegment, NULL, sPreRenderCvg); + PAUSE_PLAYER_SEGMENT_RENDER_TEXTURE(pauseCtx->playerSegment), NULL, sPreRenderCvg); KaleidoScope_DrawPlayerWork(play); KaleidoScope_SetupPlayerPreRender(play);