Files
Luke StreetandGitHub 484417b243 CEnvFxManager 95% + some GX macros (#50)
* CEnvFxManager 95% + some GX macros

* Use regular GXVert functions in CElementGen::RenderModels
2026-03-23 12:23:49 -06:00

349 lines
14 KiB
C++

#ifndef _CGX_IMPL
#define _CGX_IMPL
#include "CGX.hpp"
#include "Kyoto/Alloc/CMemory.hpp"
#include "Kyoto/Graphics/CTexture.hpp"
#include "dolphin/gx/GXDispList.h"
#include "dolphin/gx/GXGeometry.h"
#include "dolphin/gx/GXLighting.h"
#include "dolphin/gx/GXTev.h"
#ifndef CGX_INLINE
#define CGX_INLINE inline
#endif
CGX_INLINE void CGX::SetNumChans(uchar num) {
sGXState.x4e_numChans = num;
sGXState.x4c_flags.numDirty = sGXState.x4e_numChans != sGXState.x4d_prevNumChans;
}
CGX_INLINE void CGX::SetNumTexGens(uchar num) {
if (num != sGXState.x4f_numTexGens) {
sGXState.x4f_numTexGens = num;
GXSetNumTexGens(num);
}
}
CGX_INLINE void CGX::SetChanAmbColor(EChannelId channel, const GXColor& color) {
if (!CompareGXColors(color, sGXState.x38_chanAmbColors[channel])) {
CopyGXColor(sGXState.x38_chanAmbColors[channel], color);
GXSetChanAmbColor(static_cast< GXChannelID >(GX_COLOR0A0 + channel), color);
}
}
CGX_INLINE GXColor CGX::GetChanAmbColor(EChannelId channel) {
return sGXState.x38_chanAmbColors[channel];
}
CGX_INLINE void CGX::SetChanMatColor(EChannelId channel, const GXColor& color) {
if (!CompareGXColors(color, sGXState.x40_chanMatColors[channel])) {
CopyGXColor(sGXState.x40_chanMatColors[channel], color);
GXSetChanMatColor(static_cast< GXChannelID >(GX_COLOR0A0 + channel), color);
}
}
CGX_INLINE void CGX::SetChanCtrl(EChannelId channel, GXBool enable, GXColorSrc ambSrc,
GXColorSrc matSrc, GXLightID lights, GXDiffuseFn diffFn,
GXAttnFn attnFn) {
ushort& state = sGXState.x34_chanCtrls[channel];
ushort prevFlags = sGXState.x30_prevChanCtrls[channel];
if (lights == GX_LIGHT_NULL) {
enable = GX_FALSE;
}
uint flags = MaskAndShiftLeft(enable, 1, 0) | MaskAndShiftLeft(ambSrc, 1, 1) |
MaskAndShiftLeft(matSrc, 1, 2) | MaskAndShiftLeft(lights, 0xFF, 3) |
MaskAndShiftLeft(diffFn, 3, 11) | MaskAndShiftLeft(attnFn, 3, 13);
state = flags;
sGXState.x4c_chanFlags =
((flags != prevFlags) << (channel + 1)) | (sGXState.x4c_chanFlags & ~(1 << (channel + 1)));
}
CGX_INLINE void CGX::SetChanCtrl_Compressed(EChannelId channel, int lights, uint ctrl) {
ushort& state = sGXState.x34_chanCtrls[channel];
ushort prevFlags = sGXState.x30_prevChanCtrls[channel];
uint flags = ctrl & ~1;
if (lights != 0) {
flags = ctrl | MaskAndShiftLeft(lights, 0xFF, 3);
}
state = flags;
sGXState.x4c_chanFlags =
((flags != prevFlags) << (channel + 1)) | (sGXState.x4c_chanFlags & ~(1 << (channel + 1)));
}
CGX_INLINE void CGX::SetNumTevStages(uchar num) {
if (sGXState.x50_numTevStages != num) {
sGXState.x50_numTevStages = num;
GXSetNumTevStages(num);
}
}
CGX_INLINE void CGX::SetTevKColor(GXTevKColorID id, const GXColor& color) {
if (!CompareGXColors(sGXState.x58_kColors[id], color)) {
CopyGXColor(sGXState.x58_kColors[id], color);
GXSetTevKColor(id, color);
}
}
CGX_INLINE void CGX::SetTevColorIn(GXTevStageID stageId, GXTevColorArg a, GXTevColorArg b,
GXTevColorArg c, GXTevColorArg d) {
const uint flags = MaskAndShiftLeft(a, 0x1F, 0) | MaskAndShiftLeft(b, 0x1F, 5) |
MaskAndShiftLeft(c, 0x1F, 10) | MaskAndShiftLeft(d, 0x1F, 15);
STevState& state = sGXState.x68_tevStates[stageId];
if (flags != state.x0_colorInArgs) {
state.x0_colorInArgs = flags;
GXSetTevColorIn(stageId, a, b, c, d);
}
}
CGX_INLINE void CGX::SetTevColorIn_Compressed(GXTevStageID stageId, uint flags) {
STevState& state = sGXState.x68_tevStates[stageId];
if (flags != state.x0_colorInArgs) {
state.x0_colorInArgs = flags;
GXSetTevColorIn(stageId, static_cast< GXTevColorArg >(ShiftRightAndMask(flags, 0x1F, 0)),
static_cast< GXTevColorArg >(ShiftRightAndMask(flags, 0x1F, 5)),
static_cast< GXTevColorArg >(ShiftRightAndMask(flags, 0x1F, 10)),
static_cast< GXTevColorArg >(ShiftRightAndMask(flags, 0x1F, 15)));
}
}
CGX_INLINE void CGX::SetTevAlphaIn(GXTevStageID stageId, GXTevAlphaArg a, GXTevAlphaArg b,
GXTevAlphaArg c, GXTevAlphaArg d) {
uint flags = MaskAndShiftLeft(a, 0x1F, 0) | MaskAndShiftLeft(b, 0x1F, 5) |
MaskAndShiftLeft(c, 0x1F, 10) | MaskAndShiftLeft(d, 0x1F, 15);
STevState& state = sGXState.x68_tevStates[stageId];
if (flags != state.x4_alphaInArgs) {
state.x4_alphaInArgs = flags;
GXSetTevAlphaIn(stageId, a, b, c, d);
}
}
CGX_INLINE void CGX::SetTevAlphaIn_Compressed(GXTevStageID stageId, uint flags) {
STevState& state = sGXState.x68_tevStates[stageId];
if (flags != state.x4_alphaInArgs) {
state.x4_alphaInArgs = flags;
GXSetTevAlphaIn(stageId, static_cast< GXTevAlphaArg >(ShiftRightAndMask(flags, 0x1F, 0)),
static_cast< GXTevAlphaArg >(ShiftRightAndMask(flags, 0x1F, 5)),
static_cast< GXTevAlphaArg >(ShiftRightAndMask(flags, 0x1F, 10)),
static_cast< GXTevAlphaArg >(ShiftRightAndMask(flags, 0x1F, 15)));
}
}
CGX_INLINE void CGX::SetTevColorOp(GXTevStageID stageId, GXTevOp op, GXTevBias bias,
GXTevScale scale, GXBool clamp, GXTevRegID outReg) {
const uint flags = MaskAndShiftLeft(op, 0xF, 0) | MaskAndShiftLeft(bias, 3, 4) |
MaskAndShiftLeft(scale, 3, 6) | MaskAndShiftLeft(clamp, 1, 8) |
MaskAndShiftLeft(outReg, 3, 9);
STevState& state = sGXState.x68_tevStates[stageId];
if (flags != state.x8_colorOps) {
state.x8_colorOps = flags;
GXSetTevColorOp(stageId, op, bias, scale, clamp, outReg);
}
}
CGX_INLINE void CGX::SetTevColorOp_Compressed(GXTevStageID stageId, uint flags) {
STevState& state = sGXState.x68_tevStates[stageId];
if (flags != state.x8_colorOps) {
state.x8_colorOps = flags;
GXSetTevColorOp(stageId, static_cast< GXTevOp >(ShiftRightAndMask(flags, 0xF, 0)),
static_cast< GXTevBias >(ShiftRightAndMask(flags, 3, 4)),
static_cast< GXTevScale >(ShiftRightAndMask(flags, 3, 6)),
static_cast< GXBool >(ShiftRightAndMask(flags, 1, 8)),
static_cast< GXTevRegID >(ShiftRightAndMask(flags, 3, 9)));
}
}
CGX_INLINE void CGX::SetTevAlphaOp(GXTevStageID stageId, GXTevOp op, GXTevBias bias,
GXTevScale scale, GXBool clamp, GXTevRegID outReg) {
uint flags = MaskAndShiftLeft(op, 0xF, 0) | MaskAndShiftLeft(bias, 3, 4) |
MaskAndShiftLeft(scale, 3, 6) | MaskAndShiftLeft(clamp, 1, 8) |
MaskAndShiftLeft(outReg, 3, 9);
STevState& state = sGXState.x68_tevStates[stageId];
if (flags != state.xc_alphaOps) {
state.xc_alphaOps = flags;
GXSetTevAlphaOp(stageId, op, bias, scale, clamp, outReg);
}
}
CGX_INLINE void CGX::SetTevAlphaOp_Compressed(GXTevStageID stageId, uint flags) {
STevState& state = sGXState.x68_tevStates[stageId];
if (flags != state.xc_alphaOps) {
state.xc_alphaOps = flags;
GXSetTevAlphaOp(stageId, static_cast< GXTevOp >(ShiftRightAndMask(flags, 0xF, 0)),
static_cast< GXTevBias >(ShiftRightAndMask(flags, 3, 4)),
static_cast< GXTevScale >(ShiftRightAndMask(flags, 3, 6)),
static_cast< GXBool >(ShiftRightAndMask(flags, 1, 8)),
static_cast< GXTevRegID >(ShiftRightAndMask(flags, 3, 9)));
}
}
CGX_INLINE void CGX::SetTevKColorSel(GXTevStageID stageId, GXTevKColorSel sel) {
STevState& state = sGXState.x68_tevStates[stageId];
if (sel != state.x18_kColorSel) {
state.x18_kColorSel = sel;
GXSetTevKColorSel(stageId, sel);
}
}
CGX_INLINE void CGX::SetTevKAlphaSel(GXTevStageID stageId, GXTevKAlphaSel sel) {
STevState& state = sGXState.x68_tevStates[stageId];
if (sel != state.x19_kAlphaSel) {
state.x19_kAlphaSel = sel;
GXSetTevKAlphaSel(stageId, sel);
}
}
CGX_INLINE void CGX::SetTevOrder(GXTevStageID stageId, GXTexCoordID texCoord, GXTexMapID texMap,
GXChannelID color) {
STevState& state = sGXState.x68_tevStates[stageId];
uint flags = MaskAndShiftLeft(texCoord, 0xFF, 0) | MaskAndShiftLeft(texMap, 0xFF, 8) |
MaskAndShiftLeft(color, 0xFF, 16);
if (state.x14_tevOrderFlags != flags) {
state.x14_tevOrderFlags = flags;
GXSetTevOrder(stageId, texCoord, texMap, color);
}
}
CGX_INLINE void CGX::SetBlendMode(GXBlendMode mode, GXBlendFactor srcFac, GXBlendFactor dstFac,
GXLogicOp op) {
uint flags = MaskAndShiftLeft(mode, 3, 0) | MaskAndShiftLeft(srcFac, 7, 2) |
MaskAndShiftLeft(dstFac, 7, 5) | MaskAndShiftLeft(op, 0xF, 8);
if (flags != sGXState.x56_blendMode) {
update_fog(flags);
sGXState.x56_blendMode = flags;
GXSetBlendMode(mode, srcFac, dstFac, op);
}
}
CGX_INLINE void CGX::SetZMode(const GXBool compareEnable, GXCompare func,
const GXBool updateEnable) {
uchar flags = MaskAndShiftLeft(compareEnable, 0xFF, 0) | MaskAndShiftLeft(updateEnable, 0xFF, 1) |
MaskAndShiftLeft(func, 0xFF, 2);
if (flags != sGXState.x52_zmode) {
sGXState.x52_zmode = flags;
GXSetZMode(compareEnable, func, updateEnable);
}
}
CGX_INLINE void CGX::SetAlphaCompare(GXCompare comp0, uchar ref0, GXAlphaOp op, GXCompare comp1,
uchar ref1) {
uint flags = MaskAndShiftLeft(comp0, 7, 0) | MaskAndShiftLeft(ref0, 0xFF, 3) |
MaskAndShiftLeft(op, 7, 11) | MaskAndShiftLeft(comp1, 7, 14) |
MaskAndShiftLeft(ref1, 0xFF, 17);
if (sGXState.x248_alphaCompare != flags) {
sGXState.x248_alphaCompare = flags;
GXSetAlphaCompare(comp0, ref0, op, comp1, ref1);
GXSetZCompLoc(comp0 == GX_ALWAYS);
}
}
CGX_INLINE void CGX::SetTevIndirect(GXTevStageID stageId, GXIndTexStageID indStage,
GXIndTexFormat fmt, GXIndTexBiasSel biasSel,
GXIndTexMtxID mtxSel, GXIndTexWrap wrapS, GXIndTexWrap wrapT,
GXBool addPrev, GXBool indLod, GXIndTexAlphaSel alphaSel) {
STevState& state = sGXState.x68_tevStates[stageId];
uint flags = MaskAndShiftLeft(indStage, 3, 0) | MaskAndShiftLeft(fmt, 3, 2) |
MaskAndShiftLeft(biasSel, 7, 4) | MaskAndShiftLeft(mtxSel, 15, 7) |
MaskAndShiftLeft(wrapS, 7, 11) | MaskAndShiftLeft(wrapT, 7, 14) |
MaskAndShiftLeft(addPrev, 1, 17) | MaskAndShiftLeft(indLod, 1, 18) |
MaskAndShiftLeft(alphaSel, 3, 19);
if (state.x10_indFlags != flags) {
state.x10_indFlags = flags;
GXSetTevIndirect(stageId, indStage, fmt, biasSel, mtxSel, wrapS, wrapT, addPrev, indLod,
alphaSel);
}
}
CGX_INLINE void CGX::SetTevDirect(GXTevStageID stageId) {
STevState& state = sGXState.x68_tevStates[stageId];
if (state.x10_indFlags != 0) {
state.x10_indFlags = 0;
GXSetTevDirect(stageId);
}
}
CGX_INLINE void CGX::SetTexCoordGen(GXTexCoordID dstCoord, GXTexGenType fn, GXTexGenSrc src,
GXTexMtx mtx, GXBool normalize, GXPTTexMtx postMtx) {
STexState& state = sGXState.x228_texStates[dstCoord];
uint vm = (mtx - GX_TEXMTX0) / 3;
uint vp = postMtx - GX_PTTEXMTX0;
#if NONMATCHING
// Similarly to GXTexMtx, this should also be divided by 3
vp /= 3;
#endif
uint flags = MaskAndShiftLeft(fn, 0xF, 0) | MaskAndShiftLeft(src, 0x1F, 4) |
MaskAndShiftLeft(vm, 0x1F, 9) | MaskAndShiftLeft(normalize, 1, 14) |
MaskAndShiftLeft(vp, 0x3F, 15);
if (state.x0_coordGen != flags) {
state.x0_coordGen = flags;
GXSetTexCoordGen2(dstCoord, fn, src, mtx, normalize, postMtx);
}
}
CGX_INLINE void CGX::SetTexCoordGen_Compressed(GXTexCoordID dstCoord, uint flags) {
STexState& state = sGXState.x228_texStates[dstCoord];
if (state.x0_coordGen != flags) {
state.x0_coordGen = flags;
GXSetTexCoordGen2(dstCoord, static_cast< GXTexGenType >(flags & 0xF),
static_cast< GXTexGenSrc >(flags >> 4 & 0x1F),
static_cast< GXTexMtx >((flags >> 9 & 0x1F) * 3 + GX_TEXMTX0),
static_cast< GXBool >(flags >> 14 & 1),
static_cast< GXPTTexMtx >(flags >> 15 & 0x3F));
}
}
CGX_INLINE void CGX::SetNumIndStages(uchar num) {
if (sGXState.x51_numIndStages != num) {
sGXState.x51_numIndStages = num;
GXSetNumIndStages(num);
}
}
CGX_INLINE void CGX::SetArray(GXAttr attr, const void* data, uchar stride) {
uint idx = attr - GX_VA_POS;
if (data == nullptr || sGXState.x0_arrayPtrs[idx] == data) {
return;
}
sGXState.x0_arrayPtrs[idx] = data;
GXSetArray(attr, data, stride);
}
CGX_INLINE void CGX::CallDisplayList(const void* ptr, size_t size) {
if (sGXState.x4c_chanFlags != 0) {
FlushState();
}
GXCallDisplayList(ptr, size);
}
CGX_INLINE void CGX::Begin(GXPrimitive prim, GXVtxFmt fmt, ushort numVtx) {
if (sGXState.x4c_chanFlags != 0) {
FlushState();
}
GXBegin(prim, fmt, numVtx);
}
CGX_INLINE void CGX::End() {}
CGX_INLINE void CGX::SetFog(GXFogType type, float startZ, float endZ, float nearZ, float farZ,
const GXColor& color) {
sGXState.x53_fogType = type;
sGXState.x24c_fogParams.x0_fogStartZ = startZ;
sGXState.x24c_fogParams.x4_fogEndZ = endZ;
sGXState.x24c_fogParams.x8_fogNearZ = nearZ;
sGXState.x24c_fogParams.xc_fogFarZ = farZ;
CopyGXColor(sGXState.x24c_fogParams.x10_fogColor, color);
apply_fog();
}
CGX_INLINE void CGX::SetLineWidth(uchar width, GXTexOffset offset) {
ushort flags = width | offset << 8;
if (flags != sGXState.x54_lineWidthAndOffset) {
sGXState.x54_lineWidthAndOffset = flags;
GXSetLineWidth(width, offset);
}
}
#endif // _CGX_IMPL