Skip to content

Commit

Permalink
Merge pull request #306 from roblabla/screen-effects
Browse files Browse the repository at this point in the history
Implement ScreenEffects
  • Loading branch information
roblabla authored Nov 5, 2024
2 parents d119c53 + c2c93ea commit 08ebd8b
Show file tree
Hide file tree
Showing 8 changed files with 308 additions and 15 deletions.
9 changes: 9 additions & 0 deletions config/implemented.csv
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,15 @@ th06::GameWindow::InitD3dDevice
th06::GameWindow::InitD3dRendering
th06::ScreenEffect::Clear
th06::ScreenEffect::SetViewport
th06::ScreenEffect::CalcFadeIn
th06::ScreenEffect::DrawSquare
th06::ScreenEffect::CalcFadeOut
th06::ScreenEffect::RegisterChain
th06::ScreenEffect::DrawFadeIn
th06::ScreenEffect::DrawFadeOut
th06::ScreenEffect::ShakeScreen
th06::ScreenEffect::AddedCallback
th06::ScreenEffect::DeletedCallback
th06::utils::AddNormalizeAngle
th06::utils::Rotate
th06::SoundPlayer::SoundPlayer
Expand Down
2 changes: 0 additions & 2 deletions config/stubbed.csv
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ th06::ResultScreen::HandleReplaySaveKeyboard
th06::ResultScreen::GetHighScore
th06::MusicRoom::RegisterChain
th06::ResultScreen::ReleaseScoreDat
th06::ScreenEffect::RegisterChain
th06::MainMenu::SelectRelated
th06::ScreenEffect::DrawSquare
th06::TextHelper::ReleaseTextBuffer
th06::Pbg3Archive::Pbg3Archive
12 changes: 6 additions & 6 deletions src/BombData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ void BombData::BombReimuACalc(Player *player)
player->bombInfo.bombRegionVelocities[i] / 100.0f; // ZUN moment

g_SoundPlayer.PlaySoundByIdx(SOUND_F, 0);
ScreenEffect::RegisterChain(SCREEN_EFFECT_UNK_1, 16, 8, 0, 0);
ScreenEffect::RegisterChain(SCREEN_EFFECT_SHAKE, 16, 8, 0, 0);
}
}
}
Expand Down Expand Up @@ -274,13 +274,13 @@ void BombData::BombReimuBCalc(Player *player)
player->bombInfo.bombRegionPositions[3].x = 192.0f;
player->bombInfo.bombRegionPositions[3].y = player->positionCenter.y;
player->bombInfo.bombRegionPositions[3].z = 0.405f;
ScreenEffect::RegisterChain(SCREEN_EFFECT_UNK_1, 60, 2, 6, 0);
ScreenEffect::RegisterChain(SCREEN_EFFECT_SHAKE, 60, 2, 6, 0);
}
else
{
if (player->bombInfo.timer == 60)
{
ScreenEffect::RegisterChain(SCREEN_EFFECT_UNK_1, 80, 20, 0, 0);
ScreenEffect::RegisterChain(SCREEN_EFFECT_SHAKE, 80, 20, 0, 0);
}

player->bombProjectiles[0].size.x = 62.0f;
Expand Down Expand Up @@ -372,7 +372,7 @@ void BombData::BombMarisaACalc(Player *player)
player->bombInfo.bombRegionVelocities[i].z = 0.0f;
}
g_SoundPlayer.PlaySoundByIdx(SOUND_BOMB_REIMARI, 0);
ScreenEffect::RegisterChain(SCREEN_EFFECT_UNK_1, 0x78, 4, 1, 0);
ScreenEffect::RegisterChain(SCREEN_EFFECT_SHAKE, 120, 4, 1, 0);
}
else
{
Expand Down Expand Up @@ -485,11 +485,11 @@ void BombData::BombMarisaBCalc(Player *player)

if (player->bombInfo.timer == 60)
{
ScreenEffect::RegisterChain(SCREEN_EFFECT_UNK_1, 60, 1, 7, 0);
ScreenEffect::RegisterChain(SCREEN_EFFECT_SHAKE, 60, 1, 7, 0);
}
else if (player->bombInfo.timer == 120)
{
ScreenEffect::RegisterChain(SCREEN_EFFECT_UNK_1, 200, 24, 0, 0);
ScreenEffect::RegisterChain(SCREEN_EFFECT_SHAKE, 200, 24, 0, 0);
}

if (player->bombInfo.timer.HasTicked() && player->bombInfo.timer.AsFrames() % 4 != 0)
Expand Down
2 changes: 2 additions & 0 deletions src/ChainPriorities.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#define TH_CHAIN_PRIO_CALC_BULLETMANAGER 11
#define TH_CHAIN_PRIO_CALC_GUI 12
#define TH_CHAIN_PRIO_CALC_RESULTSCREEN 13
#define TH_CHAIN_PRIO_CALC_SCREENEFFECT 14
#define TH_CHAIN_PRIO_CALC_REPLAYMANAGER 15
#define TH_CHAIN_PRIO_CALC_HIGH_PRIO_REPLAYMANAGER_DEMO 16

Expand All @@ -32,3 +33,4 @@
#define TH_CHAIN_PRIO_DRAW_REPLAYMANAGER 13
#define TH_CHAIN_PRIO_DRAW_SUPERVISOR 14
#define TH_CHAIN_PRIO_DRAW_ASCIIMANAGER_MENUS 15
#define TH_CHAIN_PRIO_DRAW_SCREENEFFECT 16
2 changes: 1 addition & 1 deletion src/GameManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ ChainCallbackResult GameManager::OnUpdate(GameManager *gameManager)
gameManager->demoFrames++;
if (gameManager->demoFrames == DEMO_FADEOUT_FRAMES)
{
ScreenEffect::RegisterChain(SCREEN_EFFECT_FADE_OUT, 0x78, 0, 0, 0);
ScreenEffect::RegisterChain(SCREEN_EFFECT_FADE_OUT, 120, 0x000000, 0, 0);
}
if (gameManager->demoFrames >= DEMO_FRAMES)
{
Expand Down
4 changes: 2 additions & 2 deletions src/MainMenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -680,11 +680,11 @@ ZunResult MainMenu::AddedCallback(MainMenu *m)
if (g_Supervisor.startupTimeBeforeMenuMusic == 0)
{
g_Supervisor.PlayAudio("bgm/th06_01.mid");
ScreenEffect::RegisterChain(SCREEN_EFFECT_UNK_0, 0x78, 0xffffff, 0, 0);
ScreenEffect::RegisterChain(SCREEN_EFFECT_FADE_IN, 120, 0xffffff, 0, 0);
}
else
{
ScreenEffect::RegisterChain(SCREEN_EFFECT_UNK_0, 200, 0xffffff, 0, 0);
ScreenEffect::RegisterChain(SCREEN_EFFECT_FADE_IN, 200, 0xffffff, 0, 0);
}
}
g_GameManager.demoMode = 0;
Expand Down
256 changes: 256 additions & 0 deletions src/ScreenEffect.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#include "ScreenEffect.hpp"
#include "AnmManager.hpp"
#include "ChainPriorities.hpp"
#include "GameWindow.hpp"
#include "Rng.hpp"
#include "Supervisor.hpp"

namespace th06
Expand Down Expand Up @@ -32,4 +35,257 @@ void ScreenEffect::SetViewport(D3DCOLOR color)
g_Supervisor.d3dDevice->SetViewport(&g_Supervisor.viewport);
ScreenEffect::Clear(color);
}

ChainCallbackResult ScreenEffect::CalcFadeIn(ScreenEffect *effect)
{
if (effect->effectLength != 0)
{
effect->fadeAlpha = 255.0f - ((effect->timer.AsFramesFloat() * 255.0f) / effect->effectLength);
if (effect->fadeAlpha < 0)
{
effect->fadeAlpha = 0;
}
}

if (effect->timer >= effect->effectLength)
{
return CHAIN_CALLBACK_RESULT_CONTINUE_AND_REMOVE_JOB;
}

effect->timer.Tick();
return CHAIN_CALLBACK_RESULT_CONTINUE;
}

void ScreenEffect::DrawSquare(ZunRect *rect, D3DCOLOR rectColor)
{
VertexDiffuseXyzrwh vertices[4];

// In the original code, VertexDiffuseXyzrwh almost certainly is a vec3 with a trailing w, which would make these
// simple vec3 assigns
memcpy(&vertices[0].position, &D3DXVECTOR3(rect->left, rect->top, 0.0f), sizeof(D3DXVECTOR3));
memcpy(&vertices[1].position, &D3DXVECTOR3(rect->right, rect->top, 0.0f), sizeof(D3DXVECTOR3));
memcpy(&vertices[2].position, &D3DXVECTOR3(rect->left, rect->bottom, 0.0f), sizeof(D3DXVECTOR3));
memcpy(&vertices[3].position, &D3DXVECTOR3(rect->right, rect->bottom, 0.0f), sizeof(D3DXVECTOR3));
vertices[0].position.w = vertices[1].position.w = vertices[2].position.w = vertices[3].position.w = 1.00f;
vertices[0].diffuse = vertices[1].diffuse = vertices[2].diffuse = vertices[3].diffuse = rectColor;

if (((g_Supervisor.cfg.opts >> GCOS_NO_COLOR_COMP) & 0x01) == 0)
{
g_Supervisor.d3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
g_Supervisor.d3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
}
g_Supervisor.d3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
g_Supervisor.d3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
if (((g_Supervisor.cfg.opts >> GCOS_TURN_OFF_DEPTH_TEST) & 0x01) == 0)
{
g_Supervisor.d3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
g_Supervisor.d3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
}

g_Supervisor.d3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
g_Supervisor.d3dDevice->SetVertexShader(D3DFVF_DIFFUSE | D3DFVF_XYZRHW);
g_Supervisor.d3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertices, sizeof(*vertices));
g_AnmManager->SetCurrentVertexShader(0xff);
g_AnmManager->SetCurrentSprite(NULL);
g_AnmManager->SetCurrentTexture(NULL);
g_AnmManager->SetCurrentColorOp(0xff);
g_AnmManager->SetCurrentBlendMode(0xff);
g_AnmManager->SetCurrentZWriteDisable(0xff);

if (((g_Supervisor.cfg.opts >> GCOS_NO_COLOR_COMP) & 0x01) == 0)
{
g_Supervisor.d3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
g_Supervisor.d3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
}
g_Supervisor.d3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
g_Supervisor.d3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_Supervisor.d3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
}

ChainCallbackResult ScreenEffect::CalcFadeOut(ScreenEffect *effect)
{
if (effect->effectLength != 0)
{
effect->fadeAlpha = (effect->timer.AsFramesFloat() * 255.0f) / effect->effectLength;
if (effect->fadeAlpha < 0)
{
effect->fadeAlpha = 0;
}
}

if (effect->timer >= effect->effectLength)
{
return CHAIN_CALLBACK_RESULT_CONTINUE_AND_REMOVE_JOB;
}

effect->timer.Tick();
return CHAIN_CALLBACK_RESULT_CONTINUE;
}

#pragma var_order(calcChainElem, drawChainElem, createdEffect)
ScreenEffect *ScreenEffect::RegisterChain(i32 effect, u32 ticks, u32 effectParam1, u32 effectParam2,
u32 unusedEffectParam)
{
ChainElem *calcChainElem;
ScreenEffect *createdEffect;
ChainElem *drawChainElem;

calcChainElem = NULL;
drawChainElem = NULL;

createdEffect = new ScreenEffect;

if (createdEffect == NULL)
{
return NULL;
}

memset(createdEffect, 0, sizeof(*createdEffect));

switch (effect)
{
case SCREEN_EFFECT_FADE_IN:
calcChainElem = g_Chain.CreateElem((ChainCallback)ScreenEffect::CalcFadeIn);
drawChainElem = g_Chain.CreateElem((ChainCallback)ScreenEffect::DrawFadeIn);
break;
case SCREEN_EFFECT_SHAKE:
calcChainElem = g_Chain.CreateElem((ChainCallback)ScreenEffect::ShakeScreen);
break;
case SCREEN_EFFECT_FADE_OUT:
calcChainElem = g_Chain.CreateElem((ChainCallback)ScreenEffect::CalcFadeOut);
drawChainElem = g_Chain.CreateElem((ChainCallback)ScreenEffect::DrawFadeOut);
}

calcChainElem->addedCallback = (ChainAddedCallback)ScreenEffect::AddedCallback;
calcChainElem->deletedCallback = (ChainAddedCallback)ScreenEffect::DeletedCallback;
calcChainElem->arg = createdEffect;
createdEffect->usedEffect = (ScreenEffects)effect;
createdEffect->effectLength = ticks;
createdEffect->genericParam = effectParam1;
createdEffect->shakinessParam = effectParam2;
createdEffect->unusedParam = unusedEffectParam;

if (g_Chain.AddToCalcChain(calcChainElem, TH_CHAIN_PRIO_CALC_SCREENEFFECT) != 0)
{
return NULL;
}

if (drawChainElem != NULL)
{
drawChainElem->arg = createdEffect;
g_Chain.AddToDrawChain(drawChainElem, TH_CHAIN_PRIO_DRAW_SCREENEFFECT);
}

createdEffect->calcChainElement = calcChainElem;
createdEffect->drawChainElement = drawChainElem;
return createdEffect;
}

ChainCallbackResult ScreenEffect::DrawFadeIn(ScreenEffect *effect)
{
ZunRect fadeRect;

fadeRect.left = 0.0f;
fadeRect.top = 0.0f;
fadeRect.right = 640.0f;
fadeRect.bottom = 480.0f;
g_Supervisor.viewport.X = 0;
g_Supervisor.viewport.Y = 0;
g_Supervisor.viewport.Width = 640;
g_Supervisor.viewport.Height = 480;
g_Supervisor.d3dDevice->SetViewport(&g_Supervisor.viewport);
ScreenEffect::DrawSquare(&fadeRect, (effect->fadeAlpha << 24) | effect->genericParam);
return CHAIN_CALLBACK_RESULT_CONTINUE;
}

ChainCallbackResult ScreenEffect::DrawFadeOut(ScreenEffect *effect)
{
ZunRect fadeRect;

fadeRect.left = 32.0f;
fadeRect.top = 16.0f;
fadeRect.right = 416.0f;
fadeRect.bottom = 464.0f;
ScreenEffect::DrawSquare(&fadeRect, (effect->fadeAlpha << 24) | effect->genericParam);
return CHAIN_CALLBACK_RESULT_CONTINUE;
}

ChainCallbackResult ScreenEffect::ShakeScreen(ScreenEffect *effect)
{
f32 screenOffset;

if (g_GameManager.isTimeStopped)
{
g_GameManager.arcadeRegionTopLeftPos.x = 32.0f;
g_GameManager.arcadeRegionTopLeftPos.y = 16.0f;
g_GameManager.arcadeRegionSize.x = 384.0f;
g_GameManager.arcadeRegionSize.y = 448.0f;
return CHAIN_CALLBACK_RESULT_CONTINUE;
}

effect->timer.Tick();
if (effect->timer >= effect->effectLength)
{
g_GameManager.arcadeRegionTopLeftPos.x = 32.0f;
g_GameManager.arcadeRegionTopLeftPos.y = 16.0f;
g_GameManager.arcadeRegionSize.x = 384.0f;
g_GameManager.arcadeRegionSize.y = 448.0f;
return CHAIN_CALLBACK_RESULT_CONTINUE_AND_REMOVE_JOB;
}

screenOffset =
((effect->timer.AsFramesFloat() * (effect->shakinessParam - effect->genericParam)) / effect->effectLength) +
effect->genericParam;

switch (g_Rng.GetRandomU32InRange(3))
{
case 0:
g_GameManager.arcadeRegionTopLeftPos.x = 32.0f;
g_GameManager.arcadeRegionSize.x = 384.0f;
break;
case 1:
g_GameManager.arcadeRegionTopLeftPos.x = 32.0f + screenOffset;
g_GameManager.arcadeRegionSize.x = 384.0f - screenOffset;
break;
case 2:
g_GameManager.arcadeRegionTopLeftPos.x = 32.0f;
g_GameManager.arcadeRegionSize.x = 384.0f - screenOffset;
break;
}

switch (g_Rng.GetRandomU32InRange(3))
{
case 0:
g_GameManager.arcadeRegionTopLeftPos.y = 16.0f;
g_GameManager.arcadeRegionSize.y = 448.0f;
break;
case 1:
g_GameManager.arcadeRegionTopLeftPos.y = 16.0f + screenOffset;
g_GameManager.arcadeRegionSize.y = 448.0f - screenOffset;
break;
case 2:
g_GameManager.arcadeRegionTopLeftPos.y = 16.0f;
g_GameManager.arcadeRegionSize.y = 448.0f - screenOffset;
break;
}

return CHAIN_CALLBACK_RESULT_CONTINUE;
}

ZunResult ScreenEffect::AddedCallback(ScreenEffect *effect)
{
effect->timer.InitializeForPopup();
return ZUN_SUCCESS;
}

ZunResult ScreenEffect::DeletedCallback(ScreenEffect *effect)
{
effect->calcChainElement->deletedCallback = NULL;
g_Chain.Cut(effect->drawChainElement);
effect->drawChainElement = NULL;
delete effect;
effect = NULL;

return ZUN_SUCCESS;
}
}; // namespace th06
Loading

0 comments on commit 08ebd8b

Please sign in to comment.