diff --git a/patches/display_patches.c b/patches/display_patches.c index 2a61a37..090f760 100644 --- a/patches/display_patches.c +++ b/patches/display_patches.c @@ -961,23 +961,13 @@ RECOMP_PATCH void Aquas_BlueMarineReticle_Draw(void) { } #if 1 -u32 bolse_ult = 0, bolse_lrt = 63, bolse_uls = 0, bolse_lrs = 63; - RECOMP_PATCH void Bolse_BoBaseShield_Update(BoBaseShield* this) { D_i4_801A0530 = 0; Math_SmoothStepToF(&this->fwork[0], D_BO_801A03DC * 9.0f + 10.0f, 1.0f, 10.0f, 0.0f); // Lib_Texture_Scroll(aBoBaseShieldTex, 16, 16, 0); - bolse_ult = (bolse_ult - 4) & 0x3F; - bolse_lrt = (bolse_ult - 63) & 0xFFF; - bolse_lrt = (bolse_ult - 63) & 0xFFF; - // pointer to the SetTileSize cmd - Gfx* cmd = (Gfx*) SEGMENTED_TO_VIRTUAL((void*) ((Gfx*) (aBoBaseShieldDL + 2))); - // upper left coords - cmd->words.w0 = (G_SETTILESIZE << 24) | (bolse_uls << 12) | bolse_ult; - // lower right coords - cmd->words.w1 = (cmd->words.w1 & 0x07000000) | (bolse_lrs << 12) | bolse_lrt; + Gfx_Texture_UV_Scroll(aBoBaseShieldDL + 2, 16, 16, 0, 1); switch (this->state) { case 2: diff --git a/patches/effect_tagging.c b/patches/effect_tagging.c index 0575c41..8dfed89 100644 --- a/patches/effect_tagging.c +++ b/patches/effect_tagging.c @@ -65,7 +65,6 @@ RECOMP_PATCH void TexturedLine_Draw(void) { } } -u32 a6_ult = 0, a6_lrt = 63; extern Gfx D_A6_6012550[]; // extern int gUvOn; /* Debug */ @@ -167,11 +166,7 @@ RECOMP_PATCH void Effect_Effect395_Draw(Effect395* this) { if (gPlayState != PLAY_PAUSE) { // Lib_Texture_Scroll(D_A6_6012840, 16, 16, 0); // @Recomp use UV scrolling instead of CPU - a6_ult = (a6_ult - 4) & 0x3F; - a6_lrt = (a6_ult + 63) & 0xFFF; - Gfx* cmd = (Gfx*) SEGMENTED_TO_VIRTUAL((void*) ((Gfx*) (D_A6_6012550 + 6))); - cmd->words.w0 = (G_SETTILESIZE << 24) | a6_ult; - cmd->words.w1 = (cmd->words.w1 & 0x0703F000) | a6_lrt; + Gfx_Texture_UV_Scroll(D_A6_6012550 + 6, 16, 16, 0, 1); } RCP_SetupDL(&gMasterDisp, SETUPDL_53); Matrix_Scale(gGfxMatrix, this->orient.x, this->orient.y, this->orient.z, MTXF_APPLY); @@ -1506,15 +1501,10 @@ RECOMP_PATCH void Effect_ElectricArc_Draw(EffectElectricArc* this) { // Texture scrolling for explosions #if 1 -u32 e383_ult = 0, e383_lrt = 127; RECOMP_PATCH void Effect_Effect383_Update(Effect383* this) { // Lib_Texture_Scroll(D_10190C0, 16, 32, 0); // @Recomp use UV tex scrolling instead - e383_ult = (e383_ult - 4) & 0x7F; - e383_lrt = (e383_ult + 127) & 0xFFF; - Gfx* cmd = (Gfx*) SEGMENTED_TO_VIRTUAL((void*) ((Gfx*) (D_10182C0 + 6))); - cmd->words.w0 = (G_SETTILESIZE << 24) | e383_ult; - cmd->words.w1 = (cmd->words.w1 & 0x0703F000) | e383_lrt; + Gfx_Texture_UV_Scroll(D_10182C0 + 6, 16, 32, 0, 1); gGroundClipMode = 2; this->obj.rot.y += 1.0f; @@ -1548,21 +1538,13 @@ RECOMP_PATCH void Effect_Effect383_Update(Effect383* this) { #if 1 void Obj54_8006AA3C(f32 xPos, f32 yPos, f32 zPos); -u32 wf_ult = 0, wf_lrt = 127; - RECOMP_PATCH void CoWaterfall_Update(CoWaterfall* this) { Vec3f dest; Vec3f src; // Lib_Texture_Scroll(aCoWaterfallTex2, 32, 32, 1); // @Recomp use UV tex scrolling instead - wf_ult = (wf_ult + 4) & 0x7F; - wf_lrt = (wf_ult + 127) & 0xFFF; - Gfx* cmd1 = (Gfx*) SEGMENTED_TO_VIRTUAL((void*) ((Gfx*) (aCoWaterfallDL + 26))); - u32 words_w0 = (G_SETTILESIZE << 24) | wf_ult; - u32 words_w1 = (cmd1->words.w1 & 0x0707F000) | wf_lrt; - cmd1->words.w0 = words_w0; - cmd1->words.w1 = words_w1; + Gfx_Texture_UV_Scroll(aCoWaterfallDL + 26, 32, 32, 1, 1); if ((gGameFrameCount % 4) == 0) { Matrix_RotateY(gCalcMatrix, this->obj.rot.y * M_DTOR, MTXF_NEW); @@ -1581,7 +1563,6 @@ RECOMP_PATCH void CoWaterfall_Update(CoWaterfall* this) { #if 1 void func_tank_80043280(u16* text0, u16* text1, f32 zRot); void func_tank_80043B18(Player* player); -u32 lm6_ult = 0, lm6_lrt = 0; #if 0 extern int gUvOn; @@ -1724,33 +1705,11 @@ RECOMP_PATCH void func_tank_80044868(Player* player) { if (player->baseSpeed > 0.0f) { // Lib_Texture_Scroll(aLandmasterModelTex6, 32, 32, 0); // @recomp: UV Scrolling - lm6_ult = (lm6_ult - 4) & 0x7F; - lm6_lrt = (lm6_ult + 127) & 0xFFF; - // aLandmasterModelDL - // + 92 - // + 141 - // + 150 - // + 177 - Gfx* cmd = (Gfx*) SEGMENTED_TO_VIRTUAL((void*) ((Gfx*) (aLandmasterModelDL + 92))); - u32 cmd_words_w0, cmd_words_w1; - // upper left coords - cmd_words_w0 = (G_SETTILESIZE << 24) | lm6_ult; - // lower right coords - cmd_words_w1 = (cmd->words.w1 & 0x0707F000) | lm6_lrt; - cmd->words.w0 = cmd_words_w0; - cmd->words.w1 = cmd_words_w1; - - cmd = (Gfx*) SEGMENTED_TO_VIRTUAL((void*) ((Gfx*) (aLandmasterModelDL + 141))); - cmd->words.w0 = cmd_words_w0; - cmd->words.w1 = cmd_words_w1; - - cmd = (Gfx*) SEGMENTED_TO_VIRTUAL((void*) ((Gfx*) (aLandmasterModelDL + 150))); - cmd->words.w0 = cmd_words_w0; - cmd->words.w1 = cmd_words_w1; - - cmd = (Gfx*) SEGMENTED_TO_VIRTUAL((void*) ((Gfx*) (aLandmasterModelDL + 177))); - cmd->words.w0 = cmd_words_w0; - cmd->words.w1 = cmd_words_w1; + Gfx_Texture_UV_Scroll(aLandmasterModelDL + 92, 32, 32, 0, 1); + Gfx_Texture_UV_Scroll(aLandmasterModelDL + 141, 32, 32, 0, 1); + Gfx_Texture_UV_Scroll(aLandmasterModelDL + 150, 32, 32, 0, 1); + Gfx_Texture_UV_Scroll(aLandmasterModelDL + 177, 32, 32, 0, 1); + if ((gCurrentLevel == LEVEL_TITANIA) && !gBossActive) { func_tank_80043280(aLandmasterModelTex4, D_TI_6009BB8, gGameFrameCount * -55.0f); } @@ -1762,33 +1721,10 @@ RECOMP_PATCH void func_tank_80044868(Player* player) { if (player->baseSpeed > 10.0f) { // Lib_Texture_Scroll(aLandmasterModelTex6, 32, 32, 0); // @recomp: UV Scrolling - lm6_ult = (lm6_ult - 4) & 0x7F; - lm6_lrt = (lm6_ult + 127) & 0xFFF; - // aLandmasterModelDL - // + 92 - // + 141 - // + 150 - // + 177 - Gfx* cmd = (Gfx*) SEGMENTED_TO_VIRTUAL((void*) ((Gfx*) (aLandmasterModelDL + 92))); - u32 cmd_words_w0, cmd_words_w1; - // upper left coords - cmd_words_w0 = (G_SETTILESIZE << 24) | lm6_ult; - // lower right coords - cmd_words_w1 = (cmd->words.w1 & 0x0707F000) | lm6_lrt; - cmd->words.w0 = cmd_words_w0; - cmd->words.w1 = cmd_words_w1; - - cmd = (Gfx*) SEGMENTED_TO_VIRTUAL((void*) ((Gfx*) (aLandmasterModelDL + 141))); - cmd->words.w0 = cmd_words_w0; - cmd->words.w1 = cmd_words_w1; - - cmd = (Gfx*) SEGMENTED_TO_VIRTUAL((void*) ((Gfx*) (aLandmasterModelDL + 150))); - cmd->words.w0 = cmd_words_w0; - cmd->words.w1 = cmd_words_w1; - - cmd = (Gfx*) SEGMENTED_TO_VIRTUAL((void*) ((Gfx*) (aLandmasterModelDL + 177))); - cmd->words.w0 = cmd_words_w0; - cmd->words.w1 = cmd_words_w1; + Gfx_Texture_UV_Scroll(aLandmasterModelDL + 92, 32, 32, 0, 1); + Gfx_Texture_UV_Scroll(aLandmasterModelDL + 141, 32, 32, 0, 1); + Gfx_Texture_UV_Scroll(aLandmasterModelDL + 150, 32, 32, 0, 1); + Gfx_Texture_UV_Scroll(aLandmasterModelDL + 177, 32, 32, 0, 1); if ((gCurrentLevel == LEVEL_TITANIA) && !gBossActive) { func_tank_80043280(aLandmasterModelTex4, D_TI_6009BB8, gGameFrameCount * -55.0f); @@ -1805,8 +1741,6 @@ void Corneria_Garuda_HandleDamage(Actor* this); #if 1 s32 Corneria_CoGaruda1_CheckCollision(CoGaruda1* this); -u32 garuda1_ult = 0, garuda1_lrt = 63; - RECOMP_PATCH void Corneria_CoGaruda1_Update(CoGaruda1* this) { Vec3f frameTable[20]; f32 sin; @@ -1828,14 +1762,7 @@ RECOMP_PATCH void Corneria_CoGaruda1_Update(CoGaruda1* this) { // @recomp: UV texture scrolling // Lib_Texture_Scroll(aCoGarudaTracksTex, 16, 16, 1); - garuda1_ult = (garuda1_ult + 4) & 0x3F; - garuda1_lrt = (garuda1_ult + 63) & 0xFFF; - // gfx+59 - Gfx* cmd = (Gfx*) SEGMENTED_TO_VIRTUAL((void*) ((Gfx*) (ast_corneria_seg6_gfx_31ED0 + 59))); - // upper left coords - cmd->words.w0 = (G_SETTILESIZE << 24) | garuda1_ult; - // lower right coords - cmd->words.w1 = (cmd->words.w1 & 0x0703F000) | garuda1_lrt; + Gfx_Texture_UV_Scroll(ast_corneria_seg6_gfx_31ED0 + 59, 16, 16, 1, 1); this->animFrame = 0; @@ -1872,8 +1799,6 @@ RECOMP_PATCH void Corneria_CoGaruda1_Update(CoGaruda1* this) { #endif #if 1 -u32 garuda2_ult = 0, garuda2_lrt = 63; - RECOMP_PATCH void Corneria_CoGaruda2_Update(CoGaruda2* this) { Vec3f frameTable[20]; Vec3f src; @@ -1903,17 +1828,9 @@ RECOMP_PATCH void Corneria_CoGaruda2_Update(CoGaruda2* this) { case 1: this->fwork[0] = -10.0f; - { - // Lib_Texture_Scroll(aCoGarudaTracksTex, 16, 16, 1); - garuda2_ult = (garuda2_ult - 4) & 0x3F; - garuda2_lrt = (garuda2_ult + 63) & 0xFFF; - // gfx+59 - Gfx* cmd = (Gfx*) SEGMENTED_TO_VIRTUAL((void*) ((Gfx*) (ast_corneria_seg6_gfx_31ED0 + 59))); - // upper left coords - cmd->words.w0 = (G_SETTILESIZE << 24) | garuda2_ult; - // lower right coords - cmd->words.w1 = (cmd->words.w1 & 0x0703F000) | garuda2_lrt; - } + // @recomp: UV texture scrolling + // Lib_Texture_Scroll(aCoGarudaTracksTex, 16, 16, 1); + Gfx_Texture_UV_Scroll(ast_corneria_seg6_gfx_31ED0 + 59, 16, 16, 1, 1); if (this->timer_0BC == 0) { this->state = 2; @@ -1924,17 +1841,9 @@ RECOMP_PATCH void Corneria_CoGaruda2_Update(CoGaruda2* this) { case 2: this->fwork[0] = -10.0f; - { - // Lib_Texture_Scroll(aCoGarudaTracksTex, 16, 16, 1); - garuda2_ult = (garuda2_ult - 4) & 0x3F; - garuda2_lrt = (garuda2_ult + 63) & 0xFFF; - // gfx+59 - Gfx* cmd = (Gfx*) SEGMENTED_TO_VIRTUAL((void*) ((Gfx*) (ast_corneria_seg6_gfx_31ED0 + 59))); - // upper left coords - cmd->words.w0 = (G_SETTILESIZE << 24) | garuda2_ult; - // lower right coords - cmd->words.w1 = (cmd->words.w1 & 0x0703F000) | garuda2_lrt; - } + // @recomp: UV texture scrolling + // Lib_Texture_Scroll(aCoGarudaTracksTex, 16, 16, 1); + Gfx_Texture_UV_Scroll(ast_corneria_seg6_gfx_31ED0 + 59, 16, 16, 1, 1); this->animFrame++; @@ -1973,8 +1882,6 @@ RECOMP_PATCH void Corneria_CoGaruda2_Update(CoGaruda2* this) { #endif #if 1 -u32 garuda3_ult = 0, garuda3_lrt = 63; - RECOMP_PATCH void Corneria_CoGaruda3_Update(CoGaruda3* this) { s32 pad; Vec3f frameTable[20]; @@ -1998,17 +1905,11 @@ RECOMP_PATCH void Corneria_CoGaruda3_Update(CoGaruda3* this) { case 1: this->fwork[0] = 5.0f; this->fwork[1] += 5.0f; - { - // Lib_Texture_Scroll(aCoGarudaTracksTex, 16, 16, 1); - garuda3_ult = (garuda3_ult - 4) & 0x3F; - garuda3_lrt = (garuda3_ult + 63) & 0xFFF; - // gfx+59 - Gfx* cmd = (Gfx*) SEGMENTED_TO_VIRTUAL((void*) ((Gfx*) (ast_corneria_seg6_gfx_31ED0 + 59))); - // upper left coords - cmd->words.w0 = (G_SETTILESIZE << 24) | garuda3_ult; - // lower right coords - cmd->words.w1 = (cmd->words.w1 & 0x0703F000) | garuda3_lrt; - } + + // @recomp: UV texture scrolling + // Lib_Texture_Scroll(aCoGarudaTracksTex, 16, 16, 1); + Gfx_Texture_UV_Scroll(ast_corneria_seg6_gfx_31ED0 + 59, 16, 16, 1, 1); + this->animFrame++; if (this->animFrame >= Animation_GetFrameCount(&aCoGaruda3Anim)) { this->animFrame = 0; diff --git a/patches/ground.c b/patches/ground.c index 7a653f5..6278dc3 100644 --- a/patches/ground.c +++ b/patches/ground.c @@ -1332,10 +1332,6 @@ void Solar_SoFlare_Spawn3(f32, f32, f32, f32); extern Gfx aSoLava1DL_copy[]; extern Gfx aSoLava2DL_copy[]; -u32 cob1_uls = 0, cob1_lrs = 255; -u32 sol_ult = 0, sol_lrt = 127; -u32 met_ult = 0, met_lrt = 127; - // for Texture scroll debugging #if 0 extern int gUvOn; @@ -1403,11 +1399,7 @@ RECOMP_PATCH void Play_UpdateLevel(void) { case LEVEL_METEO: // @recomp: use UV Scrolling // Lib_Texture_Scroll(aMeteoWarpTex, 8, 8, 1); - met_ult = (met_ult + 4) & 0x1F; - met_lrt = (met_ult + 31) & 0xFFF; - Gfx* cmd = (Gfx*) SEGMENTED_TO_VIRTUAL((void*) ((Gfx*) (aMeteoWarpDL + 2))); - cmd->words.w0 = (G_SETTILESIZE << 24) | met_ult; - cmd->words.w1 = (cmd->words.w1 & 0x0701F000) | met_lrt; + Gfx_Texture_UV_Scroll(aMeteoWarpDL + 2, 8, 8, 1, 1); /* fallthrough */ case LEVEL_SECTOR_X: @@ -1432,19 +1424,17 @@ RECOMP_PATCH void Play_UpdateLevel(void) { break; case LEVEL_CORNERIA: + // Water waving effect HUD_Texture_Wave(D_CO_603EB38, D_CO_6028A60); - if ((gGameFrameCount % 2) != 0) { + + // @recomp: "GOODLUCK!" with UV scrolling #if 0 - // @recomp: "GOODLUCK!" with UV scrolling - cob1_uls = (cob1_uls - 4) & 0xFF; - cob1_lrs = (cob1_uls + 255) & 0xFFF; - Gfx* cmd = (Gfx*) SEGMENTED_TO_VIRTUAL((void*) ((Gfx*) (aCoBuilding1DL + 36))); - cmd->words.w0 = (G_SETTILESIZE << 24) | (cob1_uls << 12); - cmd->words.w1 = (cmd->words.w1 & 0x0700007F) | (cob1_lrs << 12); + Gfx_Texture_UV_Scroll(aCoBuilding1DL + 36, 64, 32, 3, 1); #else + if ((gGameFrameCount % 2) != 0) { Lib_Texture_Scroll(D_CO_600CBD8, 64, 32, 3); -#endif } +#endif break; case LEVEL_AQUAS: @@ -1456,35 +1446,18 @@ RECOMP_PATCH void Play_UpdateLevel(void) { // @recomp: Use UV texture scrolling for ((void) gPathTexScroll; gPathTexScroll >= 10.0f; gPathTexScroll -= 10.0f) { - sol_ult = (sol_ult + 4) & 0x7F; // Lib_Texture_Scroll(aSoLavaTex, 32, 32, 1); + Gfx_Texture_UV_Scroll(aSoLava1DL + 2, 32, 32, 1, 1); + Gfx_Texture_UV_Scroll(aSoLava2DL + 2, 32, 32, 1, 1); + Gfx_Texture_UV_Scroll(aSoLava1DL_copy + 2, 32, 32, 1, 0); + Gfx_Texture_UV_Scroll(aSoLava2DL_copy + 2, 32, 32, 1, 0); } if (gPlayer[0].state == PLAYERSTATE_NEXT) { - sol_ult = (sol_ult + 4) & 0x7F; // Lib_Texture_Scroll(aSoLavaTex, 32, 32, 1); - } - - { - sol_lrt = (sol_ult + 127) & 0xFFF; - Gfx* cmd1 = (Gfx*) SEGMENTED_TO_VIRTUAL((void*) ((Gfx*) (aSoLava1DL + 2))); - Gfx* cmd2 = (Gfx*) SEGMENTED_TO_VIRTUAL((void*) ((Gfx*) (aSoLava2DL + 2))); - u32 words_w0 = (G_SETTILESIZE << 24) | sol_ult; - u32 words_w1 = (cmd1->words.w1 & 0x0707F000) | sol_lrt; - cmd1->words.w0 = words_w0; - cmd1->words.w1 = words_w1; - cmd2->words.w0 = words_w0; - cmd2->words.w1 = words_w1; - } - { - sol_lrt = (sol_ult + 127) & 0xFFF; - Gfx* cmd1 = (Gfx*) ((void*) ((Gfx*) (aSoLava1DL_copy + 2))); - Gfx* cmd2 = (Gfx*) ((void*) ((Gfx*) (aSoLava2DL_copy + 2))); - u32 words_w0 = (G_SETTILESIZE << 24) | sol_ult; - u32 words_w1 = (cmd1->words.w1 & 0x0707F000) | sol_lrt; - cmd1->words.w0 = words_w0; - cmd1->words.w1 = words_w1; - cmd2->words.w0 = words_w0; - cmd2->words.w1 = words_w1; + Gfx_Texture_UV_Scroll(aSoLava1DL + 2, 32, 32, 1, 1); + Gfx_Texture_UV_Scroll(aSoLava2DL + 2, 32, 32, 1, 1); + Gfx_Texture_UV_Scroll(aSoLava1DL_copy + 2, 32, 32, 1, 0); + Gfx_Texture_UV_Scroll(aSoLava2DL_copy + 2, 32, 32, 1, 0); } Lib_Texture_Mottle(aSoBackdropTex, D_SO_6020F60, 3); @@ -1550,35 +1523,18 @@ RECOMP_PATCH void Play_UpdateLevel(void) { // @recomp: Use UV texture scrolling for ((void) gPathTexScroll; gPathTexScroll >= 20.0f; gPathTexScroll -= 20.0f) { - sol_ult = (sol_ult + 4) & 0x7F; // Lib_Texture_Scroll(D_ZO_602C2CC, 32, 32, 1); + Gfx_Texture_UV_Scroll(aZoWater1DL + 2, 32, 32, 1, 1); + Gfx_Texture_UV_Scroll(aZoWater2DL + 2, 32, 32, 1, 1); + Gfx_Texture_UV_Scroll(aZoWater1DL_copy + 2, 32, 32, 1, 0); + Gfx_Texture_UV_Scroll(aZoWater2DL_copy + 2, 32, 32, 1, 0); } if (gPlayer[0].state == PLAYERSTATE_NEXT) { - sol_ult = (sol_ult + 4) & 0x7F; // Lib_Texture_Scroll(D_ZO_602C2CC, 32, 32, 1); - } - - { - sol_lrt = (sol_ult + 127) & 0xFFF; - Gfx* cmd1 = (Gfx*) SEGMENTED_TO_VIRTUAL((void*) ((Gfx*) (aZoWater1DL + 2))); - Gfx* cmd2 = (Gfx*) SEGMENTED_TO_VIRTUAL((void*) ((Gfx*) (aZoWater2DL + 2))); - u32 words_w0 = (G_SETTILESIZE << 24) | sol_ult; - u32 words_w1 = (cmd1->words.w1 & 0x0707F000) | sol_lrt; - cmd1->words.w0 = words_w0; - cmd1->words.w1 = words_w1; - cmd2->words.w0 = words_w0; - cmd2->words.w1 = words_w1; - } - { - sol_lrt = (sol_ult + 127) & 0xFFF; - Gfx* cmd1 = (Gfx*) ((void*) ((Gfx*) (aZoWater1DL_copy + 2))); - Gfx* cmd2 = (Gfx*) ((void*) ((Gfx*) (aZoWater2DL_copy + 2))); - u32 words_w0 = (G_SETTILESIZE << 24) | sol_ult; - u32 words_w1 = (cmd1->words.w1 & 0x0707F000) | sol_lrt; - cmd1->words.w0 = words_w0; - cmd1->words.w1 = words_w1; - cmd2->words.w0 = words_w0; - cmd2->words.w1 = words_w1; + Gfx_Texture_UV_Scroll(aZoWater1DL + 2, 32, 32, 1, 1); + Gfx_Texture_UV_Scroll(aZoWater2DL + 2, 32, 32, 1, 1); + Gfx_Texture_UV_Scroll(aZoWater1DL_copy + 2, 32, 32, 1, 0); + Gfx_Texture_UV_Scroll(aZoWater2DL_copy + 2, 32, 32, 1, 0); } HUD_Texture_Wave(D_ZO_602C2CC, aZoWaterTex); diff --git a/patches/patches.h b/patches/patches.h index 3fa397d..f7500a4 100644 --- a/patches/patches.h +++ b/patches/patches.h @@ -145,6 +145,7 @@ f32 __sinf(f32); f32 __cosf(f32); float sqrtf(float f); void Game_InitFullViewport(void); +void Gfx_Texture_UV_Scroll(Gfx* displayList, u16 width, u16 height, s32 mode, bool segmented); void* memcpy2(void* dest, const void* src, size_t n); #define INCBIN(identifier, filename) \ diff --git a/patches/title.c b/patches/title.c index 18a4bac..59a97fc 100644 --- a/patches/title.c +++ b/patches/title.c @@ -10,9 +10,190 @@ void Title_SetCamUp(f32 xRot, f32 yRot); void Title_GetCamRot(f32* xRot, f32* yRot); void Title_CsTakeOff_Setup(void); void Title_GreatFoxDeckPlatform_Draw(void); +bool should_interpolate_perspective(Vec3f* eye, Vec3f* at); extern s32 F_80177D80; +typedef enum TitleCsStates { + /* 0 */ TITLE_SCREEN, // In the Title Screen. + /* 1 */ TITLE_GREAT_FOX_TRAVELING, // Close up to the Great Fox while it's traveling to corneria. + /* 2 */ TITLE_CS_TEAM_RUNNING, // Team is running in Great Fox's the passage way before take-off. + /* 3 */ TITLE_GREAT_FOX_CLOSE_UP, // Closing up to the Great Fox before take-off. + /* 4 */ TITLE_TAKE_OFF, // Take-off cutscene. + /* 5 */ TITLE_TAKE_OFF_SPACE, // Arwings coming out of the Great Fox out to space. + /* 7 */ TITLE_RANKING = 7 // Show ranking +} TitleCsStates; + +void Title_Ranking_Draw(void); +void Title_Screen_Draw(void); +void Title_StarfoxLogo_Draw(void); +void Title_CopyrightSymbol_Draw(void); +void Title_Copyright_Draw(void); +void Title_PressStart_Draw(void); +void Title_64Logo_Draw(void); +void Title_CsTeamRunning_Draw(void); +void Title_Logos_Draw(void); +void Title_SunGlare_Draw(void); +void Title_CsGreatFoxTraveling_Draw(void); +void Title_CsTakeOff_Draw(void); +void Title_CsGreatFoxCloseUp_Draw(void); +void Title_CsTakeOffSpace_Draw(void); +void Title_Matrix_Push(void); +void Title_TeamName_Draw(void); +void Title_TitleCard_Draw(void); + +extern bool D_menu_801B8348; +extern bool sDrawTeamName; +extern s32 D_menu_801B8298; +bool sSkipInterpolation = 0; + +#if 1 +RECOMP_PATCH void Title_Draw(void) { + static s32 camSkipTimes; + + if (sSkipInterpolation) { + // Skip interpolation for this frame. + gEXMatrixGroupSimple(gMasterDisp++, TAG_CAMERA_1, G_EX_NOPUSH, G_MTX_PROJECTION, G_EX_COMPONENT_SKIP, + G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, + G_EX_ORDER_LINEAR, G_EX_EDIT_NONE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP); + recomp_printf("CAMERA 1 SKIPED: %d\n", camSkipTimes++); + gCamera1Skipped = true; + sSkipInterpolation = 0; + } else { + // Simple interpolation works much better for cameras because they orbit around a focus. + gEXMatrixGroupSimple(gMasterDisp++, TAG_CAMERA_1, G_EX_NOPUSH, G_MTX_PROJECTION, G_EX_COMPONENT_INTERPOLATE, + G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, + G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, G_EX_EDIT_NONE, G_EX_COMPONENT_SKIP, + G_EX_COMPONENT_SKIP); + gCamera1Skipped = false; + } + + switch (sCutsceneState) { + case TITLE_RANKING: + Title_Ranking_Draw(); + break; + + case TITLE_SCREEN: + Title_Matrix_Push(); + Title_Screen_Draw(); + + Matrix_Pop(&gGfxMatrix); + + Title_StarfoxLogo_Draw(); + Title_CopyrightSymbol_Draw(); + Title_Copyright_Draw(); + Title_PressStart_Draw(); + Title_Matrix_Push(); + Title_64Logo_Draw(); + + Matrix_Pop(&gGfxMatrix); + break; + + case TITLE_GREAT_FOX_TRAVELING: + if (D_menu_801B8348) { + Title_Matrix_Push(); + Title_CsGreatFoxTraveling_Draw(); + + Matrix_Pop(&gGfxMatrix); + + Radio_Draw(); + Title_TitleCard_Draw(); + } + Title_SunGlare_Draw(); + Title_Logos_Draw(); + break; + + case TITLE_CS_TEAM_RUNNING: + Title_Matrix_Push(); + Title_CsTeamRunning_Draw(); + + Matrix_Pop(&gGfxMatrix); + + if (sDrawTeamName) { + Title_TeamName_Draw(); + } + break; + + case TITLE_GREAT_FOX_CLOSE_UP: + Title_Matrix_Push(); + + Title_CsGreatFoxCloseUp_Draw(); + + Matrix_Pop(&gGfxMatrix); + break; + + case TITLE_TAKE_OFF: + Title_Matrix_Push(); + Title_CsTakeOff_Draw(); + + Matrix_Pop(&gGfxMatrix); + + Title_TitleCard_Draw(); + break; + + case TITLE_TAKE_OFF_SPACE: + Title_Matrix_Push(); + + Title_CsTakeOffSpace_Draw(); + + Matrix_Pop(&gGfxMatrix); + break; + } + + if (sWipeHeight != 0) { + gFillScreenAlpha = 0; + gFillScreenRed = 0; + gFillScreenGreen = 0; + gFillScreenBlue = 0; + Wipe_Draw(WIPE_VERTICAL, sWipeHeight); + } + +// Debug prints for camera skipping +#if 0 + // Matrix_LookAt(gGfxMatrix, gCsCamEyeX, gCsCamEyeY, gCsCamEyeZ, gCsCamAtX, gCsCamAtY, gCsCamAtZ, sTitleCamUpX, + // sTitleCamUpY, sTitleCamUpZ, MTXF_APPLY); + + RCP_SetupDL(&gMasterDisp, SETUPDL_83); + gDPSetPrimColor(gMasterDisp++, 0, 0, 255, 255, 0, 255); + Graphics_DisplaySmallText(10, 10, 1.0f, 1.0f, "CSEYEX:"); + Graphics_DisplaySmallNumber(80, 10, (int) ABS(gCsCamEyeX)); + if (gCsCamEyeX < 0.0f) + Graphics_DisplaySmallText(70, 10, 1.0f, 1.0f, "-"); + + Graphics_DisplaySmallText(10, 20, 1.0f, 1.0f, "CSEYEY:"); + Graphics_DisplaySmallNumber(80, 20, (int) ABS(gCsCamEyeY)); + if (gCsCamEyeY < 0.0f) + Graphics_DisplaySmallText(70, 20, 1.0f, 1.0f, "-"); + + Graphics_DisplaySmallText(10, 30, 1.0f, 1.0f, "CSEYEZ:"); + Graphics_DisplaySmallNumber(80, 30, (int) ABS(gCsCamEyeZ)); + if (gCsCamEyeZ < 0.0f) + Graphics_DisplaySmallText(70, 30, 1.0f, 1.0f, "-"); + + Graphics_DisplaySmallText(10, 40, 1.0f, 1.0f, "CSATX:"); + Graphics_DisplaySmallNumber(80, 40, (int) ABS(gCsCamAtX)); + if (gCsCamAtX < 0.0f) + Graphics_DisplaySmallText(70, 40, 1.0f, 1.0f, "-"); + + Graphics_DisplaySmallText(10, 50, 1.0f, 1.0f, "CSATY:"); + Graphics_DisplaySmallNumber(80, 50, (int) ABS(gCsCamAtY)); + if (gCsCamAtY < 0.0f) + Graphics_DisplaySmallText(70, 50, 1.0f, 1.0f, "-"); + + Graphics_DisplaySmallText(10, 60, 1.0f, 1.0f, "CSATZ:"); + Graphics_DisplaySmallNumber(80, 60, (int) ABS(gCsCamAtZ)); + if (gCsCamAtZ < 0.0f) + Graphics_DisplaySmallText(70, 60, 1.0f, 1.0f, "-"); + + Graphics_DisplaySmallText(10, 70, 1.0f, 1.0f, "SCNSTATE:"); + Graphics_DisplaySmallNumber(80, 70, (int) ABS(sSceneState)); + + Graphics_DisplaySmallText(10, 80, 1.0f, 1.0f, "CSSTATE:"); + Graphics_DisplaySmallNumber(80, 80, (int) ABS(sCutsceneState)); +#endif +} +#endif + #if 1 // Hangar Widescreen fix RECOMP_PATCH void Title_GreatFoxDeck_Draw(void) { F_80177D80++; @@ -22,13 +203,19 @@ RECOMP_PATCH void Title_GreatFoxDeck_Draw(void) { gAmbientB); RCP_SetupDL(&gMasterDisp, SETUPDL_23); + if (gCamera1Skipped) { + // Skip + // @recomp Tag the transform + gEXMatrixGroupDecomposedSkipAll(gMasterDisp++, TAG_GREATFOXDECK, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); + } else { + // @recomp Tag the transform. + gEXMatrixGroupDecomposedNormal(gMasterDisp++, TAG_GREATFOXDECK, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW); + } + Matrix_Push(&gGfxMatrix); Matrix_Translate(gGfxMatrix, 0.0f, D_menu_801B9048, D_menu_801B904C, MTXF_APPLY); Matrix_Scale(gGfxMatrix, 0.4f, 0.4f, 0.4f, MTXF_APPLY); - // @recomp Tag the transform. - gEXMatrixGroupDecomposedNormal(gMasterDisp++, TAG_GREATFOXDECK, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW); - Matrix_SetGfxMtx(&gMasterDisp); // Draw the original display list @@ -52,21 +239,28 @@ RECOMP_PATCH void Title_GreatFoxDeck_Draw(void) { gSPClearGeometryMode(gMasterDisp++, G_CULL_FRONT); // Clear front-face culling (inverted) gSPSetGeometryMode(gMasterDisp++, G_CULL_BACK); // Re-enable normal backface culling - // @recomp Pop the transform id. - gEXPopMatrixGroup(gMasterDisp++, G_MTX_MODELVIEW); - Matrix_Pop(&gGfxMatrix); // Restore original matrix state Title_GreatFoxDeckPlatform_Draw(); Matrix_Pop(&gGfxMatrix); // Restore original transformation + + // @recomp Pop the transform id. + gEXPopMatrixGroup(gMasterDisp++, G_MTX_MODELVIEW); } #endif RECOMP_PATCH void Title_GreatFoxDeckPlatform_Draw(void) { - // @recomp Tag the transform. - gEXMatrixGroupDecomposedNormal(gMasterDisp++, TAG_GREATFOXDECK_PLATFORM, G_EX_PUSH, G_MTX_MODELVIEW, - G_EX_EDIT_ALLOW); + if (gCamera1Skipped) { + // Skip + // @recomp Tag the transform + gEXMatrixGroupDecomposedSkipAll(gMasterDisp++, TAG_GREATFOXDECK_PLATFORM, G_EX_PUSH, G_MTX_MODELVIEW, + G_EX_EDIT_NONE); + } else { + // @recomp Tag the transform. + gEXMatrixGroupDecomposedNormal(gMasterDisp++, TAG_GREATFOXDECK_PLATFORM, G_EX_PUSH, G_MTX_MODELVIEW, + G_EX_EDIT_ALLOW); + } gSPSetGeometryMode(gMasterDisp++, G_CULL_BACK); Matrix_Translate(gGfxMatrix, 400.0f, -250.0f, 0.0f, MTXF_APPLY); @@ -165,12 +359,13 @@ RECOMP_PATCH void Title_CorneriaExplosions_Draw(void) { for (i = 0; i < sMaxExplosions; i++) { // @recomp Tag the transform. - gEXMatrixGroupDecomposedSkipAll(gMasterDisp++, TAG_CORNERIA_EXPLOSIONS + i, G_EX_PUSH, G_MTX_MODELVIEW, - G_EX_EDIT_ALLOW); - // gEXMatrixGroupDecomposed(gMasterDisp++, TAG_CORNERIA_EXPLOSIONS + i, G_EX_PUSH, G_MTX_MODELVIEW, - // G_EX_COMPONENT_AUTO, G_EX_COMPONENT_AUTO, G_EX_COMPONENT_AUTO, - // G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, - // G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_AUTO, G_EX_EDIT_ALLOW); + // gEXMatrixGroupDecomposedSkipAll(gMasterDisp++, TAG_CORNERIA_EXPLOSIONS + i, G_EX_PUSH, G_MTX_MODELVIEW, + // G_EX_EDIT_ALLOW); + gEXMatrixGroupDecomposed(gMasterDisp++, TAG_CORNERIA_EXPLOSIONS + i, G_EX_PUSH, G_MTX_MODELVIEW, + G_EX_COMPONENT_AUTO, G_EX_COMPONENT_AUTO, G_EX_COMPONENT_AUTO, + G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, + G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_AUTO, G_EX_EDIT_ALLOW, G_EX_COMPONENT_SKIP, + G_EX_COMPONENT_SKIP); gDPSetPrimColor(gMasterDisp++, 0, 0, 255, 200, 200, D_menu_801B7CC8[i]); gDPSetEnvColor(gMasterDisp++, 255, 0, 0, D_menu_801B7CF0[i]); @@ -204,9 +399,16 @@ RECOMP_PATCH void Title_GreatFoxDeckLauncher_Draw(TitleTeam teamIdx) { Matrix_Translate(gGfxMatrix, sTitleArwing[teamIdx].pos.x, -12.8f, sTitleDeckLauncherZpos, MTXF_APPLY); Matrix_Scale(gGfxMatrix, 0.8f, 0.8f, 0.8f, MTXF_APPLY); - // @recomp Tag the transform. - gEXMatrixGroupDecomposedNormal(gMasterDisp++, TAG_GREATFOXDECK_LAUNCHER + teamIdx, G_EX_PUSH, G_MTX_MODELVIEW, - G_EX_EDIT_ALLOW); + if (gCamera1Skipped) { + // Skip + // @recomp Tag the transform + gEXMatrixGroupDecomposedSkipAll(gMasterDisp++, TAG_GREATFOXDECK_LAUNCHER + teamIdx, G_EX_PUSH, G_MTX_MODELVIEW, + G_EX_EDIT_NONE); + } else { + // @recomp Tag the transform. + gEXMatrixGroupDecomposedNormal(gMasterDisp++, TAG_GREATFOXDECK_LAUNCHER + teamIdx, G_EX_PUSH, G_MTX_MODELVIEW, + G_EX_EDIT_ALLOW); + } Matrix_SetGfxMtx(&gMasterDisp); @@ -263,9 +465,16 @@ RECOMP_PATCH void Title_Arwing_DrawEngineGlow(TitleTeam teamIdx) { gSPClearGeometryMode(gMasterDisp++, G_CULL_BACK); - // @recomp Tag the transform. - gEXMatrixGroupDecomposedNormal(gMasterDisp++, TAG_ARWING_ENGINE_GLOW + teamIdx, G_EX_PUSH, G_MTX_MODELVIEW, - G_EX_EDIT_ALLOW); + if (gCamera1Skipped) { + // Skip + // @recomp Tag the transform + gEXMatrixGroupDecomposedSkipAll(gMasterDisp++, TAG_ARWING_ENGINE_GLOW + teamIdx, G_EX_PUSH, G_MTX_MODELVIEW, + G_EX_EDIT_NONE); + } else { + // @recomp Tag the transform. + gEXMatrixGroupDecomposedNormal(gMasterDisp++, TAG_ARWING_ENGINE_GLOW + teamIdx, G_EX_PUSH, G_MTX_MODELVIEW, + G_EX_EDIT_ALLOW); + } gSPDisplayList(gMasterDisp++, aTitleArwingEngineGlowDL); @@ -347,9 +556,16 @@ RECOMP_PATCH void Title_EngineGlowParticles_Draw(TitleTeam teamIdx) { Matrix_SetGfxMtx(&gMasterDisp); - // @recomp Tag the transform. - gEXMatrixGroupDecomposedNormal(gMasterDisp++, TAG_ARWING_ENGINE_GLOW_PARTICLES + (teamIdx << 8) + i, G_EX_PUSH, - G_MTX_MODELVIEW, G_EX_EDIT_ALLOW); + if (gCamera1Skipped) { + // Skip + // @recomp Tag the transform + gEXMatrixGroupDecomposedSkipAll(gMasterDisp++, TAG_ARWING_ENGINE_GLOW_PARTICLES, G_EX_PUSH, G_MTX_MODELVIEW, + G_EX_EDIT_NONE); + } else { + // @recomp Tag the transform. + gEXMatrixGroupDecomposedNormal(gMasterDisp++, TAG_ARWING_ENGINE_GLOW_PARTICLES + (teamIdx << 8) + i, + G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW); + } gSPDisplayList(gMasterDisp++, aTitleArwingEngineGlowDL); @@ -368,9 +584,16 @@ RECOMP_PATCH void Title_ArwingShadow_Draw(s32 arg0) { Matrix_Scale(gGfxMatrix, 1.0f, 1.0f, 1.0f, MTXF_APPLY); Matrix_RotateY(gGfxMatrix, M_PI, MTXF_APPLY); - // @recomp Tag the transform. - gEXMatrixGroupDecomposedNormal(gMasterDisp++, TAG_ARWING_SHADOW + arg0, G_EX_PUSH, G_MTX_MODELVIEW, - G_EX_EDIT_ALLOW); + if (gCamera1Skipped) { + // Skip + // @recomp Tag the transform + gEXMatrixGroupDecomposedSkipAll(gMasterDisp++, TAG_ARWING_SHADOW + arg0, G_EX_PUSH, G_MTX_MODELVIEW, + G_EX_EDIT_NONE); + } else { + // @recomp Tag the transform. + gEXMatrixGroupDecomposedNormal(gMasterDisp++, TAG_ARWING_SHADOW + arg0, G_EX_PUSH, G_MTX_MODELVIEW, + G_EX_EDIT_ALLOW); + } Matrix_SetGfxMtx(&gMasterDisp); @@ -548,6 +771,7 @@ RECOMP_PATCH void Title_CsTakeOff_Update(void) __attribute__((optnone)) { gAmbientB = 46; sSceneState++; + sSkipInterpolation = 1; } sTimer3++; break; @@ -648,6 +872,7 @@ RECOMP_PATCH void Title_CsTakeOff_Update(void) __attribute__((optnone)) { Audio_SetEnvSfxReverb(0); sSceneState = 0; sCutsceneState = 5; // TITLE_TAKE_OFF_SPACE + sSkipInterpolation = 1; } sTimer3++; } diff --git a/patches/uv_scroll.c b/patches/uv_scroll.c new file mode 100644 index 0000000..36ecc3b --- /dev/null +++ b/patches/uv_scroll.c @@ -0,0 +1,70 @@ +#include "patches.h" + +#if 1 +void Gfx_Texture_UV_Scroll(Gfx* displayList, u16 width, u16 height, s32 mode, bool segmented) { + u32 ult = 0; + u32 lrt = 0; + u32 lrs = 0; + u32 uls = 0; + Gfx* cmd = NULL; + + if (displayList == NULL) { + return; + } + + if (segmented) { + cmd = SEGMENTED_TO_VIRTUAL(displayList); + } else { + cmd = displayList; + } + + switch (mode) { + case 0: // UP + ult = cmd->words.w0 & 0xFFF; + lrt = cmd->words.w1 & 0xFFF; + + ult = (ult - 4) & ((height * 4) - 1); + lrt = (ult + ((height * 4) - 1)) & 0x0FFF; + + cmd->words.w0 = (G_SETTILESIZE << 24) | ult; + cmd->words.w1 = (cmd->words.w1 & 0x0707F000) | lrt; + break; + + case 1: // DOWN + ult = cmd->words.w0 & 0xFFF; + lrt = cmd->words.w1 & 0xFFF; + + ult = (ult + 4) & ((height * 4) - 1); + lrt = (ult + ((height * 4) - 1)) & 0x0FFF; + + cmd->words.w0 = (G_SETTILESIZE << 24) | ult; + cmd->words.w1 = (cmd->words.w1 & 0x0707F000) | lrt; + break; + + case 2: // RIGHT + uls = (cmd->words.w0 >> 12) & 0xFFF; + lrs = (cmd->words.w1 >> 12) & 0xFFF; + + uls = (uls + 4) & ((width * 4) - 1); + lrs = (uls + ((width * 4) - 1)) & 0x0FFF; + + cmd->words.w0 = (G_SETTILESIZE << 24) | (uls << 12); + cmd->words.w1 = (cmd->words.w1 & 0x0700007F) | (lrs << 12); + break; + + case 3: // LEFT + uls = (cmd->words.w0 >> 12) & 0xFFF; + lrs = (cmd->words.w1 >> 12) & 0xFFF; + + uls = (uls - 4) & ((width * 4) - 1); + lrs = (uls + ((width * 4) - 1)) & 0x0FFF; + + cmd->words.w0 = (G_SETTILESIZE << 24) | (uls << 12); + cmd->words.w1 = (cmd->words.w1 & 0x0700007F) | (lrs << 12); + break; + + default: // INVALID MODE + break; + } +} +#endif \ No newline at end of file diff --git a/patches/widescreen_actors.c b/patches/widescreen_actors.c index 1cfb8f7..0c4a53f 100644 --- a/patches/widescreen_actors.c +++ b/patches/widescreen_actors.c @@ -711,7 +711,7 @@ RECOMP_PATCH void Corneria_LevelStart(Player* player) { peppy->state = 0; slippy->state = 0; falco->obj.pos.y = player->pos.y + 80.0f; - // @recomp: adjust Falco's position so he appears from further right + // @recomp: adjust Falco's position so he appears from farther right falco->obj.pos.z += 3.0f * 100.0f; } diff --git a/src/main/main.cpp b/src/main/main.cpp index d25b3c6..58c42b1 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -58,12 +58,11 @@ const std::string version_string = "1.0.3"; -template -void exit_error(const char* str, Ts ...args) { +template void exit_error(const char* str, Ts... args) { // TODO pop up an error - ((void)fprintf(stderr, str, args), ...); + ((void) fprintf(stderr, str, args), ...); assert(false); - + ultramodern::error_handling::quick_exit(__FILE__, __LINE__, __FUNCTION__); } @@ -87,11 +86,11 @@ ultramodern::gfx_callbacks_t::gfx_data_t create_gfx() { #if defined(__gnu_linux__) #include "icon_bytes.h" -bool SetImageAsIcon(const char* filename, SDL_Window* window) -{ +bool SetImageAsIcon(const char* filename, SDL_Window* window) { // Read data int width, height, bytesPerPixel; - void* data = stbi_load_from_memory(reinterpret_cast(icon_bytes), sizeof(icon_bytes), &width, &height, &bytesPerPixel, 4); + void* data = stbi_load_from_memory(reinterpret_cast(icon_bytes), sizeof(icon_bytes), &width, + &height, &bytesPerPixel, 4); // Calculate pitch int pitch; @@ -115,17 +114,16 @@ bool SetImageAsIcon(const char* filename, SDL_Window* window) SDL_Surface* surface = nullptr; if (data != nullptr) { - surface = SDL_CreateRGBSurfaceFrom(data, width, height, 32, pitch, Rmask, Gmask, - Bmask, Amask); + surface = SDL_CreateRGBSurfaceFrom(data, width, height, 32, pitch, Rmask, Gmask, Bmask, Amask); } - if (surface == nullptr) { + if (surface == nullptr) { if (data != nullptr) { stbi_image_free(data); } return false; - } else { - SDL_SetWindowIcon(window,surface); + } else { + SDL_SetWindowIcon(window, surface); SDL_FreeSurface(surface); stbi_image_free(data); return true; @@ -144,13 +142,16 @@ ultramodern::renderer::WindowHandle create_window(ultramodern::gfx_callbacks_t:: flags |= SDL_WINDOW_VULKAN; #endif - window = SDL_CreateWindow("Starfox 64: Recompiled", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1600, 960, flags); + window = + SDL_CreateWindow("Starfox 64: Recompiled", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1600, 960, flags); #if defined(__linux__) - SetImageAsIcon("icons/512.png",window); - if (ultramodern::renderer::get_graphics_config().wm_option == ultramodern::renderer::WindowMode::Fullscreen) { // TODO: Remove once RT64 gets native fullscreen support on Linux - SDL_SetWindowFullscreen(window,SDL_WINDOW_FULLSCREEN_DESKTOP); + SetImageAsIcon("icons/512.png", window); + if (ultramodern::renderer::get_graphics_config().wm_option == + ultramodern::renderer::WindowMode::Fullscreen) { // TODO: Remove once RT64 gets native fullscreen support on + // Linux + SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); } else { - SDL_SetWindowFullscreen(window,0); + SDL_SetWindowFullscreen(window, 0); } #endif @@ -168,7 +169,7 @@ ultramodern::renderer::WindowHandle create_window(ultramodern::gfx_callbacks_t:: return ultramodern::renderer::WindowHandle{ window }; #elif defined(__APPLE__) SDL_MetalView view = SDL_Metal_CreateView(window); - return ultramodern::renderer::WindowHandle{ wmInfo.info.cocoa.window, SDL_Metal_GetLayer(view) }; + return ultramodern::renderer::WindowHandle{ wmInfo.info.cocoa.window, SDL_Metal_GetLayer(view) }; #else static_assert(false && "Unimplemented"); #endif @@ -188,7 +189,8 @@ static uint32_t output_sample_rate = 48000; constexpr uint32_t input_channels = 2; static uint32_t output_channels = 2; -// Terminology: a frame is a collection of samples for each channel. e.g. 2 input samples is one input frame. This is unrelated to graphical frames. +// Terminology: a frame is a collection of samples for each channel. e.g. 2 input samples is one input frame. This is +// unrelated to graphical frames. // Number of frames to duplicate for fixing interpolation at the start and end of a chunk. constexpr uint32_t duplicated_input_frames = 4; @@ -203,13 +205,14 @@ void queue_samples(int16_t* audio_data, size_t sample_count) { static std::vector swap_buffer; static std::array duplicated_sample_buffer; - // Make sure the swap buffer is large enough to hold the audio data, including any extra space needed for resampling. + // Make sure the swap buffer is large enough to hold the audio data, including any extra space needed for + // resampling. size_t resampled_sample_count = sample_count + duplicated_input_frames * input_channels; size_t max_sample_count = std::max(resampled_sample_count, resampled_sample_count * audio_convert.len_mult); if (max_sample_count > swap_buffer.size()) { swap_buffer.resize(max_sample_count); } - + // Copy the duplicated frames from last chunk into this chunk for (size_t i = 0; i < duplicated_input_frames * input_channels; i++) { swap_buffer[i] = duplicated_sample_buffer[i]; @@ -219,10 +222,12 @@ void queue_samples(int16_t* audio_data, size_t sample_count) { // swap buffer to correct for the address xor caused by endianness handling. float cur_main_volume = zelda64::get_main_volume() / 100.0f; // Get the current main volume, normalized to 0.0-1.0. for (size_t i = 0; i < sample_count; i += input_channels) { - swap_buffer[i + 0 + duplicated_input_frames * input_channels] = audio_data[i + 1] * (1.0f / 32768.0f) * cur_main_volume; - swap_buffer[i + 1 + duplicated_input_frames * input_channels] = audio_data[i + 0] * (1.0f / 32768.0f) * cur_main_volume; + swap_buffer[i + 0 + duplicated_input_frames * input_channels] = + audio_data[i + 1] * (1.0f / 32768.0f) * cur_main_volume; + swap_buffer[i + 1 + duplicated_input_frames * input_channels] = + audio_data[i + 0] * (1.0f / 32768.0f) * cur_main_volume; } - + // TODO handle cases where a chunk is smaller than the duplicated frame count. assert(sample_count > duplicated_input_frames * input_channels); @@ -230,7 +235,7 @@ void queue_samples(int16_t* audio_data, size_t sample_count) { for (size_t i = 0; i < duplicated_input_frames * input_channels; i++) { duplicated_sample_buffer[i] = swap_buffer[i + sample_count]; } - + audio_convert.buf = reinterpret_cast(swap_buffer.data()); audio_convert.len = (sample_count + duplicated_input_frames * input_channels) * sizeof(swap_buffer[0]); @@ -241,12 +246,14 @@ void queue_samples(int16_t* audio_data, size_t sample_count) { throw std::runtime_error("Error using SDL audio converter"); } - uint64_t cur_queued_microseconds = uint64_t(SDL_GetQueuedAudioSize(audio_device)) / bytes_per_frame * 1000000 / sample_rate; - uint32_t num_bytes_to_queue = audio_convert.len_cvt - output_channels * discarded_output_frames * sizeof(swap_buffer[0]); + uint64_t cur_queued_microseconds = + uint64_t(SDL_GetQueuedAudioSize(audio_device)) / bytes_per_frame * 1000000 / sample_rate; + uint32_t num_bytes_to_queue = + audio_convert.len_cvt - output_channels * discarded_output_frames * sizeof(swap_buffer[0]); float* samples_to_queue = swap_buffer.data() + output_channels * discarded_output_frames / 2; - // Prevent audio latency from building up by skipping samples in incoming audio when too many samples are already queued. - // Skip samples based on how many microseconds of samples are queued already. + // Prevent audio latency from building up by skipping samples in incoming audio when too many samples are already + // queued. Skip samples based on how many microseconds of samples are queued already. uint32_t skip_factor = cur_queued_microseconds / 100000; if (skip_factor != 0) { uint32_t skip_ratio = 1 << skip_factor; @@ -258,7 +265,8 @@ void queue_samples(int16_t* audio_data, size_t sample_count) { } // Queue the swapped audio data. - // Offset the data start by only half the discarded frame count as the other half of the discarded frames are at the end of the buffer. + // Offset the data start by only half the discarded frame count as the other half of the discarded frames are at the + // end of the buffer. SDL_QueueAudio(audio_device, samples_to_queue, num_bytes_to_queue); } @@ -277,8 +285,7 @@ size_t get_frames_remaining() { uint32_t frames_per_vi = (sample_rate / 60); if (buffered_byte_count > (buffer_offset_frames * bytes_per_frame * frames_per_vi)) { buffered_byte_count -= (buffer_offset_frames * bytes_per_frame * frames_per_vi); - } - else { + } else { buffered_byte_count = 0; } // Convert from byte count to sample count. @@ -286,7 +293,8 @@ size_t get_frames_remaining() { } void update_audio_converter() { - int ret = SDL_BuildAudioCVT(&audio_convert, AUDIO_F32, input_channels, sample_rate, AUDIO_F32, output_channels, output_sample_rate); + int ret = SDL_BuildAudioCVT(&audio_convert, AUDIO_F32, input_channels, sample_rate, AUDIO_F32, output_channels, + output_sample_rate); if (ret < 0) { printf("Error creating SDL audio converter: %s\n", SDL_GetError()); @@ -299,23 +307,21 @@ void update_audio_converter() { void set_frequency(uint32_t freq) { sample_rate = freq; - + update_audio_converter(); } void reset_audio(uint32_t output_freq) { - SDL_AudioSpec spec_desired{ - .freq = (int)output_freq, - .format = AUDIO_F32, - .channels = (Uint8)output_channels, - .silence = 0, // calculated - .samples = 0x100, // Fairly small sample count to reduce the latency of internal buffering - .padding = 0, // unused - .size = 0, // calculated - .callback = nullptr, - .userdata = nullptr - }; - + SDL_AudioSpec spec_desired{ .freq = (int) output_freq, + .format = AUDIO_F32, + .channels = (Uint8) output_channels, + .silence = 0, // calculated + .samples = + 0x100, // Fairly small sample count to reduce the latency of internal buffering + .padding = 0, // unused + .size = 0, // calculated + .callback = nullptr, + .userdata = nullptr }; audio_device = SDL_OpenAudioDevice(nullptr, false, &spec_desired, nullptr, 0); if (audio_device == 0) { @@ -332,19 +338,19 @@ extern RspUcodeFunc aspMain; RspUcodeFunc* get_rsp_microcode(const OSTask* task) { switch (task->t.type) { - case M_AUDTASK: - return aspMain; + case M_AUDTASK: + return aspMain; - // case M_NJPEGTASK: - // return njpgdspMain; + // case M_NJPEGTASK: + // return njpgdspMain; - default: - fprintf(stderr, "Unknown task: %" PRIu32 "\n", task->t.type); - return nullptr; + default: + fprintf(stderr, "Unknown task: %" PRIu32 "\n", task->t.type); + return nullptr; } } -extern "C" void recomp_entrypoint(uint8_t * rdram, recomp_context * ctx); +extern "C" void recomp_entrypoint(uint8_t* rdram, recomp_context* ctx); gpr get_entrypoint_address(); // array of supported GameEntry objects @@ -365,86 +371,86 @@ std::vector supported_games = { // TODO: move somewhere else namespace zelda64 { - std::string get_game_thread_name(const OSThread* t) { - std::string name = "[Game] "; - - switch (t->id) { - case 0: - switch (t->priority) { - case 150: - name += "PIMGR"; - break; - - case 254: - name += "VIMGR"; - break; - - default: - name += std::to_string(t->id); - break; - } - break; - - case 1: - name += "IDLE"; - break; - - case 2: - switch (t->priority) { - case 5: - name += "SLOWLY"; - break; - - case 127: - name += "FAULT"; - break; - - default: - name += std::to_string(t->id); - break; - } - break; - - case 3: - name += "MAIN"; - break; - - case 4: - name += "GRAPH"; - break; - - case 5: - name += "SCHED"; - break; - - case 7: - name += "PADMGR"; - break; - - case 10: - name += "AUDIOMGR"; - break; - - case 13: - name += "FLASHROM"; - break; - - case 18: - name += "DMAMGR"; - break; - - case 19: - name += "IRQMGR"; - break; - - default: - name += std::to_string(t->id); - break; - } - - return name; +std::string get_game_thread_name(const OSThread* t) { + std::string name = "[Game] "; + + switch (t->id) { + case 0: + switch (t->priority) { + case 150: + name += "PIMGR"; + break; + + case 254: + name += "VIMGR"; + break; + + default: + name += std::to_string(t->id); + break; + } + break; + + case 1: + name += "IDLE"; + break; + + case 2: + switch (t->priority) { + case 5: + name += "SLOWLY"; + break; + + case 127: + name += "FAULT"; + break; + + default: + name += std::to_string(t->id); + break; + } + break; + + case 3: + name += "MAIN"; + break; + + case 4: + name += "GRAPH"; + break; + + case 5: + name += "SCHED"; + break; + + case 7: + name += "PADMGR"; + break; + + case 10: + name += "AUDIOMGR"; + break; + + case 13: + name += "FLASHROM"; + break; + + case 18: + name += "DMAMGR"; + break; + + case 19: + name += "IRQMGR"; + break; + + default: + name += std::to_string(t->id); + break; } + + return name; } +} // namespace zelda64 #ifdef _WIN32 @@ -459,7 +465,8 @@ bool preload_executable(PreloadContext& context) { wchar_t module_name[MAX_PATH]; GetModuleFileNameW(NULL, module_name, MAX_PATH); - context.handle = CreateFileW(module_name, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + context.handle = + CreateFileW(module_name, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); if (context.handle == INVALID_HANDLE_VALUE) { fprintf(stderr, "Failed to load executable into memory!"); context = {}; @@ -527,7 +534,7 @@ bool preload_executable(PreloadContext& context) { context = {}; return false; } - + return true; } @@ -540,9 +547,7 @@ void release_preload(PreloadContext& context) { #else -struct PreloadContext { - -}; +struct PreloadContext {}; // TODO implement on other platforms bool preload_executable(PreloadContext& context) { @@ -569,8 +574,8 @@ void reorder_texture_pack(recomp::mods::ModContext&) { #define REGISTER_FUNC(name) recomp::overlays::register_base_export(#name, name) int main(int argc, char** argv) { - (void)argc; - (void)argv; + (void) argc; + (void) argv; recomp::Version project_version{}; if (!recomp::Version::from_string(version_string, project_version)) { ultramodern::error_handling::message_box(("Invalid version string: " + version_string).c_str()); @@ -578,7 +583,8 @@ int main(int argc, char** argv) { } // Map this executable into memory and lock it, which should keep it in physical memory. This ensures - // that there are no stutters from the OS having to load new pages of the executable whenever a new code page is run. + // that there are no stutters from the OS having to load new pages of the executable whenever a new code page is + // run. PreloadContext preload_context; bool preloaded = preload_executable(preload_context); @@ -591,7 +597,20 @@ int main(int argc, char** argv) { timeBeginPeriod(1); // Process arguments. - + + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "--show-console") == 0) { + if (GetConsoleWindow() == nullptr) { + AllocConsole(); + freopen("CONIN$", "r", stdin); + freopen("CONOUT$", "w", stderr); + freopen("CONOUT$", "w", stdout); + } + + break; + } + } + // Set up console output to accept UTF-8 on windows SetConsoleOutputCP(CP_UTF8); @@ -629,7 +648,7 @@ int main(int argc, char** argv) { // Source controller mappings file std::u8string controller_db_path = (zelda64::get_program_path() / "recompcontrollerdb.txt").u8string(); - if (SDL_GameControllerAddMappingsFromFile(reinterpret_cast(controller_db_path.c_str())) < 0) { + if (SDL_GameControllerAddMappingsFromFile(reinterpret_cast(controller_db_path.c_str())) < 0) { fprintf(stderr, "Failed to load controller mappings: %s\n", SDL_GetError()); } @@ -640,9 +659,10 @@ int main(int argc, char** argv) { recomp::register_game(game); } - //recomp::mods::register_embedded_mod("mm_recomp_dpad_builtin", { (const uint8_t*)(mm_recomp_dpad_builtin), std::size(mm_recomp_dpad_builtin)}); + // recomp::mods::register_embedded_mod("mm_recomp_dpad_builtin", { (const uint8_t*)(mm_recomp_dpad_builtin), + // std::size(mm_recomp_dpad_builtin)}); - //REGISTER_FUNC(recomp_get_window_resolution); + // REGISTER_FUNC(recomp_get_window_resolution); REGISTER_FUNC(recomp_get_target_aspect_ratio); REGISTER_FUNC(recomp_get_target_framerate); REGISTER_FUNC(recomp_get_film_grain_enabled); @@ -738,11 +758,11 @@ int main(int argc, char** argv) { if (preloaded) { release_preload(preload_context); } - - #ifdef _WIN32 + +#ifdef _WIN32 // End high resolution timing period. timeEndPeriod(1); - #endif - +#endif + return EXIT_SUCCESS; }