Files
ss/src/egg/core/eggAsyncDisplay.cpp
T
2024-04-27 16:32:40 +02:00

233 lines
7.1 KiB
C++

#include <egg/core/eggAsyncDisplay.h>
#include <egg/math/eggMatrix.h>
#include <egg/core/eggXfbManager.h>
#include <rvl/GX/GXTexture.h>
#include <rvl/GX/GXHardware.h>
static EGG::AsyncDisplay *lbl_80576790[2];
// Hacks for float ordering
static f32 one() {
return 1.0f;
}
static f64 cast() {
return 4503599627370496.0;
}
static f32 zero() {
return 0.0f;
}
namespace EGG {
AsyncDisplay::AsyncDisplay(u8 maxRetrace): Display(maxRetrace) {
this->field_0x98 = 0;
this->field_0x9C = 1.0f;
this->field_0xA4 = 0;
this->field_0xA8 = 0;
this->field_0xAC = 0;
this->field_0xB8 = 0;
lbl_80576790[0] = this;
OSInitThreadQueue(&this->mThreadQueue);
OSInitMessageQueue(&this->mMesgQueue, this->mMesgBuf, 4);
}
f32 AsyncDisplay::calcS() {
f32 tmp = this->field_0x9C + this->field_0xA0;
this->field_0x9C = tmp;
if (!(tmp > 1.0f)) {
return tmp;
}
if (this->mScreenStateFlag.onBit(4)) {
this->field_0x9C = tmp - 1.0f;
this->mScreenStateFlag.resetBit(4);
} else {
this->field_0x9C = tmp - this->field_0xA0;
this->mScreenStateFlag.setBit(4);
}
return tmp;
}
inline void AsyncDisplay::waitForMsg(bool b) {
// This is really ugly but I couldn't find a different way
// to make the compiler use the registers
XfbManager *xfb;
while (!((xfb = BaseSystem::mConfigData->getXfbMgr(), 1 < xfb->mNumXfbs - this->field_0xAC) && (BaseSystem::mConfigData->getXfbMgr()->mToCopyXfb != nullptr || b))) {
OSReceiveMessage(&this->mMesgQueue, this->mMesgBuf, 1);
while (OSReceiveMessage(&this->mMesgQueue, this->mMesgBuf, 0)) {}
}
}
void AsyncDisplay::beginFrame() {
BaseSystem::mConfigData->getXfbMgr();
GXDrawDone();
if (this->mFlag.onBit(1)) {
OSSleepThread(&this->mThreadQueue);
}
bool b = false;
if (BaseSystem::mConfigData->getXfbMgr()->mNumXfbs == 1) {
s32 tick = OSGetTick();
s32 lastTick = this->mLastTick;
if (tick - lastTick > Display::sTickPeriod) {
VIWaitForRetrace();
}
} else {
b = false;
if (this->field_0x98 == 1 && this->mScreenStateFlag.onBit(6)) {
b = true;
}
this->waitForMsg(b);
}
if (b) {
this->clearEFB();
this->mScreenStateFlag.resetBit(6);
GXDrawDone();
} else {
this->copyEFBtoXFB();
}
if (this->field_0x98 == 1) {
this->calcS();
}
this->field_0xAC++;
this->mFrameCount++;
this->calcFrequency();
}
void AsyncDisplay::endFrame() {
if (this->mScreenStateFlag.onBit(4)) {
this->mScreenStateFlag.setBit(5);
}
}
void AsyncDisplay::endRender() {
if (this->mScreenStateFlag.onBit(5)) {
this->mScreenStateFlag.setBit(6);
this->mScreenStateFlag.resetBit(5);
}
}
void AsyncDisplay::preVRetrace() {
s32 tick = OSGetTick();
this->mLastTick = tick;
if (this->field_0x98 == 0) {
u32 a8 = ++this->field_0xA8;
if (a8 - this->field_0xA4 >= this->mMaxRetraces) {
this->field_0xA4 = a8;
this->mScreenStateFlag.setBit(3);
OSSendMessage(&this->mMesgQueue, this->mMesgBuf, 0);
if (this->field_0xAC > 0) {
this->field_0xAC--;
}
}
OSWakeupThread(&this->mThreadQueue);
}
if (this->mScreenStateFlag.onBit(3)) {
s32 count = VIGetRetraceCount();
if (count - this->mRetraceCount >= this->mMaxRetraces) {
if (this->mScreenStateFlag.onBit(0)) {
Video *video = BaseSystem::mConfigData->getVideo();
VISetBlack(video->mFlag.offBit(0));
if (video->mFlag.offBit(0)) {
video->mFlag.setBit(0);
} else {
video->mFlag.resetBit(0);
}
this->mScreenStateFlag.resetBit(0);
}
XfbManager *xfb = BaseSystem::mConfigData->getXfbMgr();
xfb->setNextFrameBuffer();
s32 newCount = VIGetRetraceCount();
this->mRetraceCount = newCount;
this->mScreenStateFlag.resetBit(3);
}
}
}
void AsyncDisplay::clearEFB() {
Video *video = BaseSystem::mConfigData->getVideo();
GXRenderModeObj const *renderMode = video->pRenderMode;
this->clearEFB(renderMode->fbWidth, renderMode->efbHeight, 0, 0, renderMode->fbWidth, renderMode->efbHeight, this->mClearColor);
}
u32 AsyncDisplay::getTickPerFrame() {
if (this->field_0x98 == 1) {
return Video::getTickPerVRetrace(0);
} else {
return Video::getTickPerVRetrace();
}
}
// TODO move
extern "C" {
extern GXTexObj lbl_80673B20, lbl_8056EB20;
extern Matrix34f lbl_80674C00;
}
void AsyncDisplay::clearEFB(u16 fbWidth, u16 fbHeight, u16 x, u16 y, u16 width, u16 height, nw4r::ut::Color color) {
GXInitTexObj(&lbl_80673B20, &lbl_8056EB20, 4, 4, GX_TF_Z24X8, GX_REPEAT, GX_REPEAT, 0);
GXInitTexObjLOD(&lbl_80673B20, GX_NEAR, GX_NEAR, 0.0, 0.0, 0.0, 0, 0, GX_ANISO_1);
Mtx44 mat;
C_MTXOrtho(mat, 0.0, fbHeight, 0.0, fbWidth, 0.0, 1.0f);
GXSetProjection(mat, GX_ORTHOGRAPHIC);
GXSetViewport(0.0, 0.0, fbWidth, fbHeight, 0.0, 1.0f);
GXSetScissor(0, 0, fbWidth, fbHeight);
lbl_80674C00.loadPosMtx(0);
GXSetCurrentMtx(0);
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGB, GX_RGBX8, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_RGB565, 0);
GXSetNumChans(0);
GXSetChanCtrl(GX_COLOR0A0, false, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE);
GXSetChanCtrl(GX_COLOR1A1, false, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE);
GXSetNumTexGens(1);
GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3c, false, 0x7d);
GXLoadTexObj(&lbl_80673B20, GX_TEXMAP0);
GXSetNumTevStages(1);
GXSetTevColor(GX_TEVREG0, color);
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_C0);
GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_TEV_SCALE_0, 1, GX_TEVPREV);
GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A0);
GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_TEV_SCALE_0, 1, GX_TEVPREV);
GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_OR, GX_ALWAYS, 0);
GXSetZTexture(2, GX_TF_Z24X8, 0);
GXSetZCompLoc(false);
GXSetBlendMode(GX_BM_NONE, GX_BL_ZERO, GX_BL_ZERO, GX_LO_NOOP);
GXSetAlphaUpdate(true);
GXSetDstAlpha(true, color.a);
GXSetZMode(true, GX_ALWAYS, true);
GXSetCullMode(GX_CULL_BACK);
GXBegin(GX_QUADS, GX_VTXFMT0, 4);
GXPosition2u16(x, y);
GXPosition2u8(0, 0);
u16 tmp = x + width;
GXPosition2u16(tmp, y);
GXPosition2u8(1, 0);
u16 tmp2 = y + height;
GXPosition2u16(tmp, tmp2);
GXPosition2u8(1, 1);
GXPosition2u16(x, tmp2);
GXPosition2u8(0, 1);
// GXEnd();
GXSetZTexture(0, GX_TF_Z24X8, 0);
GXSetZCompLoc(true);
GXSetDstAlpha(false, color.a);
}
} // namespace EGG