diff options
| author | engineer124 <engineer124engineer124@gmail.com> | 2023-10-26 21:19:22 +1100 |
|---|---|---|
| committer | engineer124 <engineer124engineer124@gmail.com> | 2023-10-26 21:19:22 +1100 |
| commit | e46a451acea09783e9d9526c937fa559a4b1b6c5 (patch) | |
| tree | ba0945a526819d8b1e14f4261f5aac34aff98251 /src/code | |
| parent | 986e34c03664274d29c0fc9af07636e78ad2d997 (diff) | |
| parent | c3b19739c6e9d8da8a6d24afa818cfdad8c0ff42 (diff) | |
merge main
Diffstat (limited to 'src/code')
| -rw-r--r-- | src/code/code_80140E80.c | 21 | ||||
| -rw-r--r-- | src/code/z_actor.c | 20 | ||||
| -rw-r--r-- | src/code/z_bgcheck.c | 1 | ||||
| -rw-r--r-- | src/code/z_camera.c | 1 | ||||
| -rw-r--r-- | src/code/z_collision_check.c | 1 | ||||
| -rw-r--r-- | src/code/z_demo.c | 43 | ||||
| -rw-r--r-- | src/code/z_eventmgr.c | 10 | ||||
| -rw-r--r-- | src/code/z_lifemeter.c | 1 | ||||
| -rw-r--r-- | src/code/z_message.c | 2 | ||||
| -rw-r--r-- | src/code/z_play.c | 37 | ||||
| -rw-r--r-- | src/code/z_player_lib.c | 6 | ||||
| -rw-r--r-- | src/code/z_visfbuf.c | 329 |
12 files changed, 381 insertions, 91 deletions
diff --git a/src/code/code_80140E80.c b/src/code/code_80140E80.c deleted file mode 100644 index 56fcb663c..000000000 --- a/src/code/code_80140E80.c +++ /dev/null @@ -1,21 +0,0 @@ -#include "global.h" - -#pragma GLOBAL_ASM("asm/non_matchings/code/code_80140E80/func_80140E80.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/code_80140E80/func_80140EA0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/code_80140E80/func_80140EAC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/code_80140E80/func_80141008.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/code_80140E80/func_8014116C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/code_80140E80/func_801411B4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/code_80140E80/func_80141200.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/code_80140E80/func_8014151C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/code_80140E80/func_80141678.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/code_80140E80/func_80141778.s") diff --git a/src/code/z_actor.c b/src/code/z_actor.c index 01a778227..70945722f 100644 --- a/src/code/z_actor.c +++ b/src/code/z_actor.c @@ -4,12 +4,14 @@ */ #include "z64actor.h" +#include "prevent_bss_reordering.h" #include "fault.h" #include "sys_cfb.h" #include "loadfragment.h" #include "z64horse.h" #include "z64quake.h" #include "z64rumble.h" + #include "overlays/actors/ovl_En_Horse/z_en_horse.h" #include "overlays/actors/ovl_En_Part/z_en_part.h" #include "overlays/actors/ovl_En_Box/z_en_box.h" @@ -1393,31 +1395,31 @@ void Actor_MountHorse(PlayState* play, Player* player, Actor* horse) { s32 func_800B7200(Player* player) { return (player->stateFlags1 & (PLAYER_STATE1_80 | PLAYER_STATE1_20000000)) || - (player->csMode != PLAYER_CSMODE_NONE); + (player->csAction != PLAYER_CSACTION_NONE); } void Actor_SpawnHorse(PlayState* play, Player* player) { Horse_Spawn(play, player); } -s32 func_800B724C(PlayState* play, Actor* actor, u8 csMode) { +s32 func_800B724C(PlayState* play, Actor* actor, u8 csAction) { Player* player = GET_PLAYER(play); - if ((player->csMode == PLAYER_CSMODE_5) || - ((csMode == PLAYER_CSMODE_END) && (player->csMode == PLAYER_CSMODE_NONE))) { + if ((player->csAction == PLAYER_CSACTION_5) || + ((csAction == PLAYER_CSACTION_END) && (player->csAction == PLAYER_CSACTION_NONE))) { return false; } - player->csMode = csMode; + player->csAction = csAction; player->csActor = actor; player->unk_3BA = false; return true; } -s32 func_800B7298(PlayState* play, Actor* actor, u8 csMode) { +s32 func_800B7298(PlayState* play, Actor* actor, u8 csAction) { Player* player = GET_PLAYER(play); - if (func_800B724C(play, actor, csMode)) { + if (func_800B724C(play, actor, csAction)) { player->unk_3BA = true; return true; } @@ -1939,8 +1941,8 @@ s32 Actor_ProcessTalkRequest(Actor* actor, GameState* gameState) { * - Positive values (`PLAYER_IA_NONE < exchangeItemAction < PLAYER_IA_MAX`): * Offers the ability to initiate the conversation with an item from the player. * Not all positive values are implemented properly for this to work. - * Working ones are PLAYER_IA_PICTO_BOX and PLAYER_IA_BOTTLE_MIN <= exchangeItemAction < PLAYER_IA_MASK_MIN - * Note: While PLAYER_IA_BEANS works, it is special cased to just plant the bean with no talking. + * Working ones are PLAYER_IA_PICTOGRAPH_BOX and PLAYER_IA_BOTTLE_MIN <= exchangeItemAction < PLAYER_IA_MASK_MIN + * Note: While PLAYER_IA_MAGIC_BEANS works, it is special cased to just plant the bean with no talking. * - `PLAYER_IA_NONE`: * Allows the player to speak to or check the actor (by pressing A). * - `PLAYER_IA_MINUS1`: diff --git a/src/code/z_bgcheck.c b/src/code/z_bgcheck.c index ef2b7ea6a..baa16a60d 100644 --- a/src/code/z_bgcheck.c +++ b/src/code/z_bgcheck.c @@ -1,3 +1,4 @@ +#include "prevent_bss_reordering.h" #include "global.h" #include "fault.h" #include "fixed_point.h" diff --git a/src/code/z_camera.c b/src/code/z_camera.c index cc5ad58ea..49c31864b 100644 --- a/src/code/z_camera.c +++ b/src/code/z_camera.c @@ -43,7 +43,6 @@ * */ -#include "prevent_bss_reordering.h" #include "global.h" #include "libc/string.h" #include "z64quake.h" diff --git a/src/code/z_collision_check.c b/src/code/z_collision_check.c index e8a3a9017..753f24bb5 100644 --- a/src/code/z_collision_check.c +++ b/src/code/z_collision_check.c @@ -1,3 +1,4 @@ +#include "prevent_bss_reordering.h" #include "global.h" #include "z64collision_check.h" diff --git a/src/code/z_demo.c b/src/code/z_demo.c index 1123d3dc1..fa0419de4 100644 --- a/src/code/z_demo.c +++ b/src/code/z_demo.c @@ -1,3 +1,6 @@ +#include "prevent_bss_reordering.h" +#include "prevent_bss_reordering2.h" + #include "PR/ultratypes.h" // Variables are put before most headers as a hacky way to bypass bss reordering @@ -8,37 +11,9 @@ struct CutsceneCamera sCutsceneCameraInfo; u16 sCueTypeList[10]; u8 D_801F4DDC; static s16 sBssPad; -u8 gDisablePlayerCsModeStartPos; +u8 gDisablePlayerCsActionStartPos; s16 gDungeonBossWarpSceneId; -#include "prevent_bss_reordering.h" -#include "prevent_bss_reordering2.h" -// clang-format off -// Partial structs taken from "prevent_bss_reordering.h" -struct Dummy200 { int x; }; -struct Dummy201 { int x; }; -struct Dummy202 { int x; }; -struct Dummy203 { int x; }; -struct Dummy204 { int x; }; -struct Dummy205 { int x; }; -struct Dummy206 { int x; }; -struct Dummy207 { int x; }; -struct Dummy208 { int x; }; -struct Dummy209 { int x; }; -struct Dummy210 { int x; }; -struct Dummy211 { int x; }; -struct Dummy212 { int x; }; -struct Dummy213 { int x; }; -struct Dummy214 { int x; }; -struct Dummy215 { int x; }; -struct Dummy216 { int x; }; -struct Dummy217 { int x; }; -struct Dummy218 { int x; }; -struct Dummy219 { int x; }; -struct Dummy220 { int x; }; -// clang-format on - -#include "global.h" #include "z64quake.h" #include "z64rumble.h" #include "z64shrink_window.h" @@ -72,7 +47,7 @@ void Cutscene_InitContext(PlayState* play, CutsceneContext* csCtx) { sCueTypeList[i] = 0; } - gDisablePlayerCsModeStartPos = false; + gDisablePlayerCsActionStartPos = false; Audio_SetCutsceneFlag(false); } @@ -364,12 +339,12 @@ void CutsceneCmd_Misc(PlayState* play, CutsceneContext* csCtx, CsCmdMisc* cmd) { gSaveContext.save.playerForm = sCutsceneStoredPlayerForm; break; - case CS_MISC_DISABLE_PLAYER_CSMODE_START_POS: - gDisablePlayerCsModeStartPos = true; + case CS_MISC_DISABLE_PLAYER_CSACTION_START_POS: + gDisablePlayerCsActionStartPos = true; break; - case CS_MISC_ENABLE_PLAYER_CSMODE_START_POS: - gDisablePlayerCsModeStartPos = false; + case CS_MISC_ENABLE_PLAYER_CSACTION_START_POS: + gDisablePlayerCsActionStartPos = false; break; case CS_MISC_SAVE_ENTER_CLOCK_TOWN: diff --git a/src/code/z_eventmgr.c b/src/code/z_eventmgr.c index fed5ec48c..9f08806f9 100644 --- a/src/code/z_eventmgr.c +++ b/src/code/z_eventmgr.c @@ -213,7 +213,7 @@ void CutsceneManager_End(void) { sCutsceneMgr.targetActor->flags &= ~ACTOR_FLAG_100000; // fallthrough case CS_START_1: - func_800B7298(sCutsceneMgr.play, NULL, PLAYER_CSMODE_END); + func_800B7298(sCutsceneMgr.play, NULL, PLAYER_CSACTION_END); sCutsceneMgr.startMethod = CS_START_0; break; @@ -338,13 +338,13 @@ s16 CutsceneManager_IsNext(s16 csId) { } /** - * Start an actor cutscene, activate Player Cutscene Mode "Wait" + * Start an actor cutscene, activate Player Cutscene Action "Wait" */ s16 CutsceneManager_StartWithPlayerCs(s16 csId, Actor* actor) { s16 startCsId = CutsceneManager_Start(csId, actor); if (startCsId >= 0) { - func_800B7298(sCutsceneMgr.play, NULL, PLAYER_CSMODE_WAIT); + func_800B7298(sCutsceneMgr.play, NULL, PLAYER_CSACTION_WAIT); if (sCutsceneMgr.length == 0) { CutsceneManager_Stop(sCutsceneMgr.csId); } @@ -354,13 +354,13 @@ s16 CutsceneManager_StartWithPlayerCs(s16 csId, Actor* actor) { } /** - * Start an actor cutscene, activate Player Cutscene Mode "Wait", turn on ACTOR_FLAG_100000 + * Start an actor cutscene, activate Player Cutscene Action "Wait", turn on ACTOR_FLAG_100000 */ s16 CutsceneManager_StartWithPlayerCsAndSetFlag(s16 csId, Actor* actor) { s16 startCsId = CutsceneManager_Start(csId, actor); if (startCsId >= 0) { - func_800B7298(sCutsceneMgr.play, NULL, PLAYER_CSMODE_WAIT); + func_800B7298(sCutsceneMgr.play, NULL, PLAYER_CSACTION_WAIT); if (sCutsceneMgr.length == 0) { CutsceneManager_Stop(sCutsceneMgr.csId); } diff --git a/src/code/z_lifemeter.c b/src/code/z_lifemeter.c index 5d1299bbf..d9abe151d 100644 --- a/src/code/z_lifemeter.c +++ b/src/code/z_lifemeter.c @@ -1,3 +1,4 @@ +#include "prevent_bss_reordering.h" #include "global.h" #include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h" #include "interface/parameter_static/parameter_static.h" diff --git a/src/code/z_message.c b/src/code/z_message.c index 3fb8f5bac..4d717d8df 100644 --- a/src/code/z_message.c +++ b/src/code/z_message.c @@ -5107,6 +5107,7 @@ void Message_Draw(PlayState* play) { GraphicsContext* gfxCtx = play->state.gfxCtx; OPEN_DISPS(gfxCtx); + polyOpa = POLY_OPA_DISP; nextDisplayList = Graph_GfxPlusOne(polyOpa); gSPDisplayList(OVERLAY_DISP++, nextDisplayList); @@ -5118,6 +5119,7 @@ void Message_Draw(PlayState* play) { gSPEndDisplayList(nextDisplayList++); Graph_BranchDlist(polyOpa, nextDisplayList); POLY_OPA_DISP = nextDisplayList; + CLOSE_DISPS(gfxCtx); } diff --git a/src/code/z_play.c b/src/code/z_play.c index 174dedd1c..89e3f34c9 100644 --- a/src/code/z_play.c +++ b/src/code/z_play.c @@ -3,6 +3,7 @@ #include "regs.h" #include "functions.h" #include "z64vismono.h" +#include "z64visfbuf.h" // Variables are put before most headers as a hacky way to bypass bss reordering s16 sTransitionFillTimer; @@ -11,8 +12,8 @@ TransitionTile sTransitionTile; s32 gTransitionTileState; VisMono sPlayVisMono; Color_RGBA8_u32 gVisMonoColor; -Struct_80140E80 D_801F6D38; -Struct_80140E80* D_801F6D4C; +VisFbuf sPlayVisFbuf; +VisFbuf* sPlayVisFbufInstance; BombersNotebook sBombersNotebook; u8 sBombersNotebookOpen; u8 sMotionBlurStatus; @@ -417,8 +418,8 @@ void Play_Destroy(GameState* thisx) { ShrinkWindow_Destroy(); TransitionFade_Destroy(&this->unk_18E48); VisMono_Destroy(&sPlayVisMono); - func_80140EA0(D_801F6D4C); - D_801F6D4C = NULL; + VisFbuf_Destroy(sPlayVisFbufInstance); + sPlayVisFbufInstance = NULL; if (CHECK_WEEKEVENTREG(WEEKEVENTREG_92_80)) { Actor_CleanupContext(&this->actorCtx, this); @@ -1110,7 +1111,7 @@ void Play_PostWorldDraw(PlayState* this) { Gfx* opa; GraphicsContext* gfxCtx = this->state.gfxCtx; - D_801F6D4C->scale = gSaveContext.screenScale / 1000.0f; + sPlayVisFbufInstance->scale = gSaveContext.screenScale / 1000.0f; OPEN_DISPS(gfxCtx); @@ -1118,7 +1119,7 @@ void Play_PostWorldDraw(PlayState* this) { nextOpa = Graph_GfxPlusOne(opa); gSPDisplayList(OVERLAY_DISP++, nextOpa); - func_80141778(D_801F6D4C, &nextOpa, this->unk_18E60, gfxCtx); + VisFbuf_Draw(sPlayVisFbufInstance, &nextOpa, this->unk_18E60); gSPEndDisplayList(nextOpa++); Graph_BranchDlist(opa, nextOpa); @@ -2311,18 +2312,18 @@ void Play_Init(GameState* thisx) { VisMono_Init(&sPlayVisMono); gVisMonoColor.a = 0; - D_801F6D4C = &D_801F6D38; - func_80140E80(D_801F6D4C); - D_801F6D4C->lodProportion = 0.0f; - D_801F6D4C->mode = 1; - D_801F6D4C->primColor.r = 0; - D_801F6D4C->primColor.g = 0; - D_801F6D4C->primColor.b = 0; - D_801F6D4C->primColor.a = 0; - D_801F6D4C->envColor.r = 0; - D_801F6D4C->envColor.g = 0; - D_801F6D4C->envColor.b = 0; - D_801F6D4C->envColor.a = 0; + sPlayVisFbufInstance = &sPlayVisFbuf; + VisFbuf_Init(sPlayVisFbufInstance); + sPlayVisFbufInstance->lodProportion = 0.0f; + sPlayVisFbufInstance->mode = VIS_FBUF_MODE_GENERAL; + sPlayVisFbufInstance->primColor.r = 0; + sPlayVisFbufInstance->primColor.g = 0; + sPlayVisFbufInstance->primColor.b = 0; + sPlayVisFbufInstance->primColor.a = 0; + sPlayVisFbufInstance->envColor.r = 0; + sPlayVisFbufInstance->envColor.g = 0; + sPlayVisFbufInstance->envColor.b = 0; + sPlayVisFbufInstance->envColor.a = 0; CutsceneFlags_UnsetAll(this); THA_GetRemaining(&this->state.tha); zAllocSize = THA_GetRemaining(&this->state.tha); diff --git a/src/code/z_player_lib.c b/src/code/z_player_lib.c index 6c33a5565..486abcbda 100644 --- a/src/code/z_player_lib.c +++ b/src/code/z_player_lib.c @@ -495,7 +495,7 @@ void func_80123140(PlayState* play, Player* player) { s32 Player_InBlockingCsMode(PlayState* play, Player* player) { return (player->stateFlags1 & (PLAYER_STATE1_80 | PLAYER_STATE1_200 | PLAYER_STATE1_20000000)) || - (player->csMode != PLAYER_CSMODE_NONE) || (play->transitionTrigger == TRANS_TRIGGER_START) || + (player->csAction != PLAYER_CSACTION_NONE) || (play->transitionTrigger == TRANS_TRIGGER_START) || (play->transitionMode != TRANS_MODE_OFF) || (player->stateFlags1 & PLAYER_STATE1_1) || (player->stateFlags3 & PLAYER_STATE3_80) || (play->actorCtx.unk268 != 0); } @@ -1297,9 +1297,9 @@ void func_80123C58(Player* player) { } void Player_SetEquipmentData(PlayState* play, Player* player) { - if (player->csMode != PLAYER_CSMODE_134) { + if (player->csAction != PLAYER_CSACTION_134) { player->currentShield = GET_CUR_EQUIP_VALUE(EQUIP_TYPE_SHIELD); - if ((player->transformation != PLAYER_FORM_ZORA) || (((player->currentBoots != PLAYER_BOOTS_ZORA_LAND)) && + if ((player->transformation != PLAYER_FORM_ZORA) || ((player->currentBoots != PLAYER_BOOTS_ZORA_LAND) && (player->currentBoots != PLAYER_BOOTS_ZORA_UNDERWATER))) { player->currentBoots = D_801BFF90[player->transformation]; } diff --git a/src/code/z_visfbuf.c b/src/code/z_visfbuf.c new file mode 100644 index 000000000..62242bcec --- /dev/null +++ b/src/code/z_visfbuf.c @@ -0,0 +1,329 @@ +/** + * @file z_visfbuf.c + * @brief Copies images between color images (generally framebuffers), possibly with filling, scaling, and colour + * interpolation. + * + * Used for several transition effects, and in z_play to shrink the screen at the end of the First and Second Days. + * + * @note to use the functions in this file, with the exception of VisFbuf_Draw(), it is necessary to load the S2DEX2 + * microcode first, and then re-load the 3D microcode afterwards for the rest of the drawing in the frame; see + * VisFbuf_Draw() for how to do this. + */ + +#include "global.h" +#include "z64visfbuf.h" +#include "sys_cfb.h" + +#define SCALE_MIN 0.032f +#define SCALE_MAX 1.0f //!< also unchanged scale + +void VisFbuf_Init(VisFbuf* this) { + bzero(this, sizeof(VisFbuf)); +} + +void VisFbuf_Destroy(VisFbuf* this) { +} + +// internal, only used in VisFbuf_SetBg +/** + * Draw a bg to the specified color image. + * + * @param[in,out] gfxP Pointer to current displaylist + * @param[in] bg BG object to draw + * @param[out] img Pointer to beginning of destination color image + * @param[in] width Output width in pixels + * @param[in] height Output height in pixels + * @param[in] cycleMode Which BG mode to use + */ +void VisFbuf_DrawBgToColorImage(Gfx** gfxP, uObjBg* bg, void* img, s32 width, s32 height, VisFbufBgMode cycleMode) { + Gfx* gfx = *gfxP; + + gDPPipeSync(gfx++); + // Set up color image to draw bg to + gDPSetColorImage(gfx++, G_IM_FMT_RGBA, G_IM_SIZ_16b, width, img); + gDPSetScissor(gfx++, 0, 0, 0, width, height); + + // Draw bg in appropriate type + gSPObjRenderMode(gfx++, G_OBJRM_ANTIALIAS | G_OBJRM_BILERP); + if (!!(cycleMode & VIS_FBUF_BG_CYC_COPY) != 0) { //! FAKE: may possibly be a better way + gSPBgRectCopy(gfx++, bg); + } else { + gSPBgRect1Cyc(gfx++, bg); + } + + gDPPipeSync(gfx++); + // Reset the color image and scissor to frame's defaults + gDPSetColorImage(gfx++, G_IM_FMT_RGBA, G_IM_SIZ_16b, gCfbWidth, D_0F000000); + gSPDisplayList(gfx++, D_0E000000.setScissor); + + *gfxP = gfx; +} + +// internal +/** + * Set up a BG from a specified source image and draw it to the specified color image with + * VisFbuf_DrawBgToColorImage(), using the BG's settings. Use VisFbuf_SetBgSimple() or + * VisFbuf_SetBgGeneral() + * + * @param[out] gfxP Pointer to current displaylist + * @param[in] source Pointer to beginning of source color image + * @param[out] img Pointer to beginning of destination color image + * @param[in] width Output width in pixels + * @param[in] height Output height in pixels + * @param[in] x Left of drawn output + * @param[in] y Top of drawn output + * @param[in] scaleX Amount to rescale the image, (dsdx). No effect if `cycleMode` is `VIS_FBUF_BG_CYC_COPY`. + * @param[in] scaleY Amount to rescale the image, (dtdy). No effect if `cycleMode` is `VIS_FBUF_BG_CYC_COPY`. + * @param[in] cycleMode Which BG mode to use + */ +void VisFbuf_SetBg(Gfx** gfxP, void* source, void* img, s32 width, s32 height, f32 x, f32 y, f32 scaleX, f32 scaleY, + VisFbufBgMode cycleMode) { + Gfx* gfx = *gfxP; + Gfx* gfxTemp; + uObjBg* bg; + + // Allocate for BG + gfxTemp = gfx; + bg = Graph_DlistAlloc(&gfxTemp, sizeof(uObjBg)); + gfx = gfxTemp; + + // Set up BG + bg->b.imageX = 0; + bg->b.imageW = width << 2; + bg->b.frameX = x * 4; + bg->b.frameW = width << 2; + bg->b.imageY = 0; + bg->b.imageH = height << 2; + bg->b.frameY = y * 4; + bg->b.frameH = height << 2; + bg->b.imageLoad = G_BGLT_LOADTILE; + bg->b.imageFmt = G_IM_FMT_RGBA; + bg->b.imageSiz = G_IM_SIZ_16b; + bg->b.imagePal = 0; + bg->b.imageFlip = 0; + bg->b.imagePtr = source; + + if (!!(cycleMode & VIS_FBUF_BG_CYC_COPY) != 0) { //! FAKE: may possibly be a better way + guS2DInitBg(bg); + } else { + bg->s.scaleW = (s32)((1 << 10) / scaleX); + bg->s.scaleH = (s32)((1 << 10) / scaleY); + bg->s.imageYorig = bg->b.imageY; + } + + // draw BG to `img` + VisFbuf_DrawBgToColorImage(&gfx, bg, img, width, height, cycleMode); + + *gfxP = gfx; +} + +// used in FbdemoWipe5 and internally +// "default settings" wrapper for VisFbuf_SetBg +/** + * Set up a BG from a specified source image and draw it to the specified color image with + * VisFbuf_DrawBgToColorImage(), using the BG's settings. Position uses the default (0,0), and no rescaling is done + * even if 1-cycle mode is enabled. + * + * @see VisFbuf_SetBg() for arguments. + */ +void VisFbuf_SetBgSimple(Gfx** gfxP, void* source, void* img, s32 width, s32 height, VisFbufBgMode cycleMode) { + VisFbuf_SetBg(gfxP, source, img, width, height, 0.0f, 0.0f, SCALE_MAX, SCALE_MAX, cycleMode); +} + +// wrapper for VisFbuf_SetBg with general arguments, used in VisFbuf_ApplyEffects +/** + * Set up a BG from a specified source image and draw it to the specified color image with + * VisFbuf_DrawBgToColorImage(). Fully general settings are available. + * + * @see VisFbuf_SetBg() for arguments. + */ +void VisFbuf_SetBgGeneral(Gfx** gfxP, void* source, void* img, s32 width, s32 height, f32 x, f32 y, f32 scaleX, + f32 scaleY, VisFbufBgMode cycleMode) { + VisFbuf_SetBg(gfxP, source, img, width, height, x, y, scaleX, scaleY, cycleMode); +} + +// internal, used in VisFbuf_DrawGeneral +/** + * Most general redrawing function. + * + * - Copies `source` to `img`, + * - fills the current framebuffer with `this->primColor`, + * - applies colour interpolation to `img`, + * - copies `img` back to `source`, with rescaling. + * + * @param[in] this + * @param[in,out] gfxP Pointer to current displaylist + * @param[in,out] source Pointer to beginning of in/out color image + * @param[out] img Pointer to beginning of destination color image + * @param[in] width Output width in pixels + * @param[in] height Output height in pixels + */ +void VisFbuf_ApplyEffects(VisFbuf* this, Gfx** gfxP, void* source, void* img, s32 width, s32 height) { + Gfx* gfx = *gfxP; + s32 pad[3]; + + gDPPipeSync(gfx++); + // copy source to img + gDPSetOtherMode(gfx++, + G_AD_PATTERN | G_CD_MAGICSQ | G_CK_NONE | G_TC_CONV | G_TF_POINT | G_TT_NONE | G_TL_TILE | + G_TD_CLAMP | G_TP_NONE | G_CYC_COPY | G_PM_NPRIMITIVE, + G_AC_NONE | G_ZS_PIXEL | G_RM_NOOP | G_RM_NOOP2); + VisFbuf_SetBgSimple(&gfx, source, img, width, height, VIS_FBUF_BG_CYC_COPY); + + gDPPipeSync(gfx++); + // fill framebuffer with primColor + gDPSetOtherMode(gfx++, + G_AD_PATTERN | G_CD_MAGICSQ | G_CK_NONE | G_TC_CONV | G_TF_POINT | G_TT_NONE | G_TL_TILE | + G_TD_CLAMP | G_TP_NONE | G_CYC_FILL | G_PM_NPRIMITIVE, + G_AC_NONE | G_ZS_PIXEL | G_RM_NOOP | G_RM_NOOP2); + { + s32 color = GPACK_RGBA5551(this->primColor.r, this->primColor.g, (u32)this->primColor.b, 1); + + gDPSetFillColor(gfx++, (color << 0x10) | color); + } + //! @bug VisFbuf_SetBgSimple() sets the current color image back to the frame's default framebuffer at the end, + //! so this will always fill in the default framebuffer, whatever are used as `source` and `img`. This does not + //! arise in-game since this function is always used with `source = D_0F000000`. + gDPFillRectangle(gfx++, 0, 0, width - 1, height - 1); + + gDPPipeSync(gfx++); + // Set lod and primColor from struct, perform interpolation, draw image with scaling (this is the most general + // alteration this system can carry out). + { + s32 lodFrac = this->lodProportion * 255; + + gDPSetLODColor(gfx++, G_SETPRIMCOLOR, 0, lodFrac, this->primColor.rgba); + } + if (this->envColor.a == 0) { + // Interpolate between primColor and texel color using lod (but with max alpha) + gDPSetOtherMode(gfx++, + G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_BILERP | G_TT_NONE | G_TL_TILE | + G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE, + G_AC_THRESHOLD | G_ZS_PIXEL | AA_EN | CVG_DST_CLAMP | ZMODE_OPA | CVG_X_ALPHA | ALPHA_CVG_SEL | + GBL_c1(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_BL, G_BL_1MA) | + GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_BL, G_BL_1MA)); + gDPSetCombineLERP(gfx++, PRIMITIVE, TEXEL0, PRIM_LOD_FRAC, TEXEL0, 0, 0, 0, 1, PRIMITIVE, TEXEL0, PRIM_LOD_FRAC, + TEXEL0, 0, 0, 0, 1); + } else { + // Interpolate between envColor (the new black) and primColor (the new white) + gDPSetOtherMode(gfx++, + G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_POINT | G_TT_NONE | G_TL_TILE | + G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE, + G_AC_NONE | G_ZS_PIXEL | G_RM_CLD_SURF | G_RM_NOOP2); + gDPSetColor(gfx++, G_SETENVCOLOR, this->envColor.rgba); + gDPSetCombineLERP(gfx++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, PRIMITIVE, ENVIRONMENT, TEXEL0, + ENVIRONMENT, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, PRIMITIVE, ENVIRONMENT, TEXEL0, + ENVIRONMENT); + } + + // Draw scaled image in centre of `width * height` rectangle in `source` + { + f32 scale = CLAMP_ALT(this->scale, SCALE_MIN, SCALE_MAX); + + VisFbuf_SetBgGeneral(&gfx, img, source, width, height, width * 0.5f * (1.0f - scale), + height * 0.5f * (1.0f - scale), scale, scale, VIS_FBUF_BG_CYC_1CYC); + } + + gDPPipeSync(gfx++); + + *gfxP = gfx; +} + +// internal, used in VisFbuf_Draw, VIS_FBUF_MODE_GENERAL +/** + * If scale is within `(SCALE_MIN, SCALE_MAX)`, apply VisFbuf_ApplyEffects(). + * If it is smaller than `SCALE_MIN`, fill the framebuffer with `this->primColor` + * + * @param[in] this + * @param[in,out] gfxP Pointer to current displaylist + * @param[in,out] source Pointer to beginning of source color image + * @param[in,out] img Pointer to beginning of destination color image + * @param[in] width Output width in pixels + * @param[in] height Output height in pixels + */ +void VisFbuf_DrawGeneral(VisFbuf* this, Gfx** gfxP, void* source, void* img, s32 width, s32 height) { + if (this->scale < SCALE_MAX) { + Gfx* gfx = *gfxP; + u32 color; + + if (this->scale > SCALE_MIN) { + VisFbuf_ApplyEffects(this, &gfx, source, img, width, height); + } else { + gDPPipeSync(gfx++); + // fill the framebuffer with this->primColor + gDPSetOtherMode(gfx++, + G_AD_PATTERN | G_CD_MAGICSQ | G_CK_NONE | G_TC_CONV | G_TF_POINT | G_TT_NONE | G_TL_TILE | + G_TD_CLAMP | G_TP_NONE | G_CYC_FILL | G_PM_NPRIMITIVE, + G_AC_NONE | G_ZS_PIXEL | G_RM_NOOP | G_RM_NOOP2); + color = GPACK_RGBA5551(this->primColor.r, this->primColor.g, (u32)this->primColor.b, 1); + gDPSetFillColor(gfx++, (color << 0x10) | color); + //! @bug See corresponding note in VisFbuf_ApplyEffects() + gDPFillRectangle(gfx++, 0, 0, width - 1, height - 1); + + gDPPipeSync(gfx++); + } + + *gfxP = gfx; + } +} + +/** + * Redraw `img` in-place, using texel color to interpolate between envColor (the new black) and primColor (the new + * white) + * + * @param[in] this + * @param[in,out] gfxP Pointer to current displaylist + * @param[in,out] img Pointer to beginning of color image to modify in-place + * @param[in] width width of img + * @param[in] height height of img + */ +void VisFbuf_DrawInterpolate(VisFbuf* this, Gfx** gfxP, void* img, s32 width, s32 height) { + Gfx* gfx = *gfxP; + + gDPPipeSync(gfx++); + + gDPSetOtherMode(gfx++, + G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_POINT | G_TT_NONE | G_TL_TILE | + G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE, + G_AC_NONE | G_ZS_PIXEL | G_RM_CLD_SURF | G_RM_NOOP2); + gDPSetColor(gfx++, G_SETPRIMCOLOR, this->primColor.rgba); + gDPSetColor(gfx++, G_SETENVCOLOR, this->envColor.rgba); + gDPSetCombineLERP(gfx++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, + PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT); + VisFbuf_SetBgSimple(&gfx, img, img, width, height, VIS_FBUF_BG_CYC_1CYC); + + gDPPipeSync(gfx++); + + *gfxP = gfx; +} + +// used in Play and FbdemoWipe4 +/** + * main drawing function in this file, draws depending on settings specified in `this`. + * + * @param[in] this + * @param[in,out] gfxP Pointer to current displaylist + * @param[in,out] img Pointer to beginning of destination color image + */ +void VisFbuf_Draw(VisFbuf* this, Gfx** gfxP, void* img) { + Gfx* gfx = *gfxP; + + gSPLoadUcodeL(gfx++, gspS2DEX2_fifo); + + switch (this->mode) { + case VIS_FBUF_MODE_GENERAL: + VisFbuf_DrawGeneral(this, &gfx, D_0F000000, img, gScreenWidth, gScreenHeight); + break; + + case VIS_FBUF_MODE_INTERPOLATE: + VisFbuf_DrawInterpolate(this, &gfx, D_0F000000, gScreenWidth, gScreenHeight); + break; + + default: + break; + } + + gSPLoadUcode(gfx++, SysUcode_GetUCode(), SysUcode_GetUCodeData()); + + *gfxP = gfx; +} |
