//
// Generated by dtk
// Translation Unit: d_drawlist.cpp
//

#include "d/dolzel.h" // IWYU pragma: keep
#include "d/d_drawlist.h"
#include "d/d_com_inf_game.h"
#include "d/d_kankyo_rain.h"
#include "d/actor/d_a_sea.h"
#include "dolphin/gf/GF.h"
#include "f_op/f_op_camera.h"
#include "m_Do/m_Do_graphic.h"
#include "m_Do/m_Do_lib.h"
#include "m_Do/m_Do_mtx.h"
#include "JSystem/JUtility/JUTAssert.h"
#include "JSystem/J2DGraph/J2DOrthoGraph.h"
#include "SSystem/SComponent/c_rnd.h"
#include "SSystem/SComponent/c_bg_s_shdw_draw.h"
#include "global.h"

GXTexObj dDlst_shadowControl_c::mSimpleTexObj;

/* 800804A4-800804C0       .text setViewPort__14dDlst_window_cFffffff */
void dDlst_window_c::setViewPort(f32 x, f32 y, f32 w, f32 h, f32 n, f32 f) {
    mViewport.mXOrig = x;
    mViewport.mYOrig = y;
    mViewport.mWidth = w;
    mViewport.mHeight = h;
    mViewport.mNearZ = n;
    mViewport.mFarZ = f;
}

/* 800804C0-800804D4       .text setScissor__14dDlst_window_cFffff */
void dDlst_window_c::setScissor(f32 x, f32 y, f32 w, f32 h) {
    mViewport.mScissor.mXOrig = x;
    mViewport.mScissor.mYOrig = y;
    mViewport.mScissor.mWidth = w;
    mViewport.mScissor.mHeight = h;
}

/* 800804D4-80080694       .text draw__13dDlst_2DTri_cFv */
void dDlst_2DTri_c::draw() {
    f32 cosR = JMASCos(mRot);
    f32 sinR = JMASSin(mRot);

    s16 px[3];
    s16 py[3];
    s16 angle = 0;
    for (int i = 0; i < 3; i++) {
        f32 x = mScaleX * JMASSin(angle);
        f32 y = mScaleY * JMASCos(angle);
        px[i] = mX + (s32)(x * cosR + y * sinR);
        py[i] = mY + (s32)(y * cosR - x * sinR);
        angle -= 0xFFFF / 3;
    }

    GXClearVtxDesc();
    GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
    GXSetNumChans(1);
    GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_REG, GX_SRC_REG, 0, GX_DF_NONE, GX_AF_NONE);
    GXSetChanMatColor(GX_COLOR0A0, mColor);
    GXSetNumTexGens(0);
    GXSetNumTevStages(1);
    GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
    GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
    GXSetBlendMode(GX_BM_BLEND, GX_BL_SRC_ALPHA, GX_BL_INV_SRC_ALPHA, GX_LO_SET);
    GXBegin(GX_TRIANGLES, GX_VTXFMT0, 3);
    GXPosition3s16(px[0], py[0], 0);
    GXPosition3s16(px[1], py[1], 0);
    GXPosition3s16(px[2], py[2], 0);
    GXEnd();
}

/* 80080694-80080784       .text draw__15dDlst_2DPoint_cFv */
void dDlst_2DPoint_c::draw() {
    GXClearVtxDesc();
    GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
    GXSetNumChans(1);
    GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_REG, GX_SRC_REG, 0, GX_DF_NONE, GX_AF_NONE);
    GXSetChanMatColor(GX_COLOR0A0, mColor);
    GXSetNumTexGens(0);
    GXSetNumTevStages(1);
    GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
    GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
    GXSetBlendMode(GX_BM_BLEND, GX_BL_SRC_ALPHA, GX_BL_INV_SRC_ALPHA, GX_LO_SET);
    GXSetPointSize(mPointSize, GX_TO_ZERO);
    GXBegin(GX_POINTS, GX_VTXFMT0, 1);
    GXPosition3s16(mPosX, mPosY, 0);
    GXEnd();
}

/* 80080784-80080A50       .text draw__11dDlst_2DT_cFv */
void dDlst_2DT_c::draw() {
    f32 texW = mTexW;
    f32 texH = mTexH;
    f32 xo = ((mX1 - mX0) * 0.5f) / mScaleX;
    f32 yo = ((mY1 - mY0) * 0.5f) / mScaleY;
    u16 s0 = ((mCenterX - xo) / texW) * 0x8000;
    u16 t0 = ((mCenterY - yo) / texH) * 0x8000;
    u16 s1 = ((mCenterX + xo) / texW) * 0x8000;
    u16 t1 = ((mCenterY + yo) / texH) * 0x8000;

    GXTexObj texObj;
    GXInitTexObj(&texObj, mpTexData, mTexW, mTexH, (GXTexFmt)mTexFmt, GX_CLAMP, GX_CLAMP, GX_FALSE);
    GXInitTexObjLOD(&texObj, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE, GX_ANISO_1);
    GXLoadTexObj(&texObj, GX_TEXMAP0);

    GXClearVtxDesc();
    GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
    GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
    GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
    GXSetNumChans(1);
    GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_REG, GX_SRC_REG, 0, GX_DF_NONE, GX_AF_NONE);

    static GXColor l_color = { 0xFF, 0xFF, 0xFF, 0xE0 };
    l_color.a = mAlpha;

    GXSetChanMatColor(GX_COLOR0A0, l_color);
    GXSetNumTexGens(1);
    GXSetNumTevStages(1);
    GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
    GXSetTevOp(GX_TEVSTAGE0, GX_MODULATE);
    GXSetBlendMode(GX_BM_NONE, GX_BL_ZERO, GX_BL_ZERO, GX_LO_SET);
    GXBegin(GX_QUADS, GX_VTXFMT0, 4);

    GXPosition3s16((s32)mX0, (s32)mY0, 0);
    GXColor1u32(0xFFFFFFFF);
    GXTexCoord2u16(s0, t0);

    GXPosition3s16((s32)mX1, (s32)mY0, 0);
    GXColor1u32(0xFFFFFFFF);
    GXTexCoord2u16(s1, t0);

    GXPosition3s16((s32)mX1, (s32)mY1, 0);
    GXColor1u32(0xFFFFFFFF);
    GXTexCoord2u16(s1, t1);

    GXPosition3s16((s32)mX0, (s32)mY1, 0);
    GXColor1u32(0xFFFFFFFF);
    GXTexCoord2u16(s0, t1);

    GXEnd();
}

/* 80080A50-800811E8       .text draw__12dDlst_2DT2_cFv */
void dDlst_2DT2_c::draw() {
    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_F32, 0);
    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
    GXClearVtxDesc();
    GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
    GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
    GXLoadTexObj(&mTex, GX_TEXMAP0);
    GXSetNumChans(0);
    GXSetTevColor(GX_TEVREG0, mColor);
    GXSetNumTexGens(1);
    GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
    GXSetNumTevStages(1);
    GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
    GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_C0, GX_CC_TEXC, GX_CC_ZERO);
    GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
    if (mAlpha)
        GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A0);
    else
        GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_A0, GX_CA_TEXA, GX_CA_ZERO);
    GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
    GXSetZCompLoc(0);
    GXSetZMode(GX_FALSE, GX_ALWAYS, GX_FALSE);
    GXSetBlendMode(GX_BM_NONE, GX_BL_SRC_ALPHA, GX_BL_INV_SRC_ALPHA, GX_LO_CLEAR);
    GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_OR, GX_GREATER, 0);
    GXSetFog(GX_FOG_NONE, 0.0f, 0.0f, 0.0f, 0.0f, g_clearColor);
    GXSetCullMode(GX_CULL_NONE);
    GXSetDither(GX_TRUE);
    GXSetClipMode(GX_CLIP_DISABLE);
    GXLoadPosMtxImm(cMtx_getIdentity(), GX_PNMTX0);
    GXSetCurrentMtx(GX_PNMTX0);

    f32 x0 = mX, x1 = x0 + mW;
    f32 y0 = mY, y1 = y0 + mH;

    if (mMirrorS && mMirrorT) {
        f32 xH = mX + mW * 0.5f;
        f32 yH = mY + mH * 0.5f;

        f32 s0, s1, t0, t1;

        if (mScrollS == 0.0f) {
            s0 = 0.0f;
            s1 = 0.0f;
        } else {
            s0 = 1.0f - 1.0f / mScrollS;
            s1 = 1.0f;
        }

        if (mScrollT == 0.0f) {
            t0 = 0.0f;
            t1 = 0.0f;
        } else {
            t0 = 1.0f - 1.0f / mScrollT;
            t1 = 1.0f;
        }

        GXBegin(GX_QUADS, GX_VTXFMT0, 16);

        // TL
        GXPosition2f32(mX, mY);
        GXTexCoord2f32(s0, t0);
        GXPosition2f32(xH, mY);
        GXTexCoord2f32(s1, t0);
        GXPosition2f32(xH, yH);
        GXTexCoord2f32(s1, t1);
        GXPosition2f32(mX, yH);
        GXTexCoord2f32(s0, t1);

        // TR
        GXPosition2f32(xH, mY);
        GXTexCoord2f32(s1, t0);
        GXPosition2f32(x1, mY);
        GXTexCoord2f32(s0, t0);
        GXPosition2f32(x1, yH);
        GXTexCoord2f32(s0, t1);
        GXPosition2f32(xH, yH);
        GXTexCoord2f32(s1, t1);

        // BL
        GXPosition2f32(mX, yH);
        GXTexCoord2f32(s0, t1);
        GXPosition2f32(xH, yH);
        GXTexCoord2f32(s1, t1);
        GXPosition2f32(xH, y1);
        GXTexCoord2f32(s1, t0);
        GXPosition2f32(mX, y1);
        GXTexCoord2f32(s0, t0);

        // BR
        GXPosition2f32(xH, yH);
        GXTexCoord2f32(s1, t1);
        GXPosition2f32(x1, yH);
        GXTexCoord2f32(s0, t1);
        GXPosition2f32(x1, y1);
        GXTexCoord2f32(s0, t0);
        GXPosition2f32(xH, y1);
        GXTexCoord2f32(s1, t0);

        GXEnd();
    } else if (mMirrorS) {
        f32 xH = mX + mW * 0.5f;

        f32 s0, s1, t0;

        if (mScrollS == 0.0f) {
            s0 = 0.0f;
            s1 = 0.0f;
        } else {
            s0 = 1.0f - 1.0f / mScrollS;
            s1 = 1.0f;
        }

        if (mScrollT == 0.0f) {
            t0 = 1.0f;
        } else {
            f32 h = (1.0f / mScrollT) * 0.5f;
            t0 = 0.5f - h;
        }

        GXBegin(GX_QUADS, GX_VTXFMT0, 8);

        // L
        GXPosition2f32(mX, mY);
        GXTexCoord2f32(s0, t0);
        GXPosition2f32(xH, mY);
        GXTexCoord2f32(s1, t0);
        GXPosition2f32(xH, y1);
        GXTexCoord2f32(s1, 1.0f);
        GXPosition2f32(mX, y1);
        GXTexCoord2f32(s0, 1.0f);

        // R
        GXPosition2f32(xH, mY);
        GXTexCoord2f32(s1, t0);
        GXPosition2f32(x1, mY);
        GXTexCoord2f32(s0, t0);
        GXPosition2f32(x1, y1);
        GXTexCoord2f32(s0, 1.0f);
        GXPosition2f32(xH, y1);
        GXTexCoord2f32(s1, 1.0f);

        GXEnd();
    } else if (mMirrorT) {
        f32 yH = mY + mH * 0.5f;

        f32 s0, s1, t0, t1;

        if (mScrollS == 0.0f) {
            s0 = 1.0f;
            s1 = 1.0f;
        } else {
            f32 h = (1.0f / mScrollS) * 0.5f;
            s0 = 0.5f - h;
            s1 = 0.5f + h;
        }

        if (mScrollT == 0.0f) {
            t0 = 0.0f;
            t1 = 0.0f;
        } else {
            t0 = 1.0f - 1.0f / mScrollT;
            t1 = 1.0f;
        }

        GXBegin(GX_QUADS, GX_VTXFMT0, 8);

        // T
        GXPosition2f32(mX, mY);
        GXTexCoord2f32(s0, t0);
        GXPosition2f32(x1, mY);
        GXTexCoord2f32(s1, t0);
        GXPosition2f32(x1, yH);
        GXTexCoord2f32(s1, t1);
        GXPosition2f32(mX, yH);
        GXTexCoord2f32(s0, t1);

        // B
        GXPosition2f32(mX, yH);
        GXTexCoord2f32(s0, t1);
        GXPosition2f32(x1, yH);
        GXTexCoord2f32(s1, t1);
        GXPosition2f32(x1, y1);
        GXTexCoord2f32(s1, t0);
        GXPosition2f32(mX, y1);
        GXTexCoord2f32(s0, t0);

        GXEnd();
    } else {
        f32 s0, s1, t0, t1;

        if (mScrollS == 0.0f) {
            s0 = 0.0f;
            s1 = 0.0f;
        } else {
            f32 h = (1.0f / mScrollS) * 0.5f;
            s0 = 0.5f - h;
            s1 = 0.5f + h;
        }

        if (mScrollT == 0.0f) {
            t0 = 0.0f;
            t1 = 0.0f;
        } else {
            f32 h = (1.0f / mScrollT) * 0.5f;
            t0 = 0.5f - h;
            t1 = 0.5f + h;
        }

        GXBegin(GX_QUADS, GX_VTXFMT0, 4);
        GXPosition2f32(mX, mY);
        GXTexCoord2f32(s0, t0);
        GXPosition2f32(x1, mY);
        GXTexCoord2f32(s1, t0);
        GXPosition2f32(x1, y1);
        GXTexCoord2f32(s1, t1);
        GXPosition2f32(mX, y1);
        GXTexCoord2f32(s0, t1);
        GXEnd();
    }

    GXSetClipMode(GX_CLIP_ENABLE);
    dComIfGp_getCurrentGrafPort()->setup2D();
}

/* 800811E8-800812F4       .text init__12dDlst_2DT2_cFP7ResTIMGffffUcUcUcff */
void dDlst_2DT2_c::init(ResTIMG* tex, f32 x, f32 y, f32 w, f32 h, u8 p0, u8 p1, u8 p2, f32 f0, f32 f1) {
    mDoLib_setResTimgObj(tex, &mTex, 0, NULL);
    mX = x;
    mY = y;
    mW = w;
    mH = h;
    mScrollS = f0;
    mScrollT = f1;
    GXColor black = { 0x00, 0x00, 0x00, 0xFF };
    mColor = black;

    mMirrorS = p1;
    if (mMirrorS && GXGetTexObjWrapS(&mTex) == GX_MIRROR)
        mMirrorS = 0;
    mMirrorT = p2;
    if (mMirrorT && GXGetTexObjWrapT(&mTex) == GX_MIRROR)
        mMirrorT = 0;
    mAlpha = p0;
}

/* 800812F4-800817CC       .text draw__11dDlst_2DM_cFv */
void dDlst_2DM_c::draw() {
    GXVtxAttrFmtList fmtList[GX_VA_MAX_ATTR + 1];

    s16 tex0_s0 = mTex[0].mScrollX;
    s16 tex0_t0 = mTex[0].mScrollY;
    s16 tex0_s1 = (tex0_s0 + 256.0f);
    s16 tex0_t1 = (tex0_t0 + 256.0f);

    f32 scaleX = 256.0f / mTex[1].mWidth;
    f32 scaleY = 256.0f / mTex[1].mHeight;

    s16 tex1_s0 = mTex[1].mScrollX * scaleX;
    s16 tex1_t0 = mTex[1].mScrollY * scaleY;
    s16 tex1_s1 = tex1_s0 + (s16)(mTex[0].mWidth * scaleX);
    s16 tex1_t1 = tex1_t0 + (s16)(mTex[0].mHeight * scaleY);

    GXGetVtxAttrFmtv(GX_VTXFMT0, fmtList);

    GXTexObj texObj[2];
    GXInitTexObj(&texObj[0], mTex[0].mpData, mTex[0].mWidth, mTex[0].mHeight, (GXTexFmt)mTex[0].mFormat, GX_CLAMP, GX_CLAMP, GX_FALSE);
    GXInitTexObjLOD(&texObj[0], GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE, GX_ANISO_1);
    GXTexWrapMode wrap1 = mTex1Wrap ? GX_REPEAT : GX_CLAMP;
    GXInitTexObj(&texObj[1], mTex[1].mpData, mTex[1].mWidth, mTex[1].mHeight, (GXTexFmt)mTex[1].mFormat, wrap1, wrap1, GX_FALSE);
    GXInitTexObjLOD(&texObj[1], GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE, GX_ANISO_1);
    GXLoadTexObj(&texObj[0], GX_TEXMAP0);
    GXLoadTexObj(&texObj[1], GX_TEXMAP1);

    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0);
    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S16, 8);
    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX1, GX_TEX_ST, GX_S16, 8);
    GXClearVtxDesc();
    GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
    GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
    GXSetVtxDesc(GX_VA_TEX1, GX_DIRECT);

    GXSetNumChans(0);
    GXSetTevColor(GX_TEVREG0, mC0);
    GXSetTevColor(GX_TEVREG1, mC1);

    GXSetNumTexGens(2);
    GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
    GXSetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX1, GX_IDENTITY);

    GXSetNumTevStages(2);

    GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
    GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_C1, GX_CC_C0, GX_CC_TEXC, GX_CC_ZERO);
    GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
    GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_A1, GX_CA_A0, GX_CA_TEXA, GX_CA_ZERO);
    GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);

    GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR_NULL);
    GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_TEXC, GX_CC_CPREV, GX_CC_ZERO);
    GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
    GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_TEXA, GX_CA_APREV, GX_CA_ZERO);
    GXSetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);

    GXSetBlendMode(GX_BM_BLEND, GX_BL_SRC_ALPHA, GX_BL_INV_SRC_ALPHA, GX_LO_SET);

    GXBegin(GX_QUADS, GX_VTXFMT0, 4);
    GXPosition3s16((s32)mX0, (s32)mY0, 0);
    GXTexCoord2s16(tex0_s0, tex0_t0);
    GXTexCoord2s16(tex1_s0, tex1_t0);

    GXPosition3s16((s32)mX1, (s32)mY0, 0);
    GXTexCoord2s16(tex0_s1, tex0_t0);
    GXTexCoord2s16(tex1_s1, tex1_t0);

    GXPosition3s16((s32)mX1, (s32)mY1, 0);
    GXTexCoord2s16(tex0_s1, tex0_t1);
    GXTexCoord2s16(tex1_s1, tex1_t1);

    GXPosition3s16((s32)mX0, (s32)mY1, 0);
    GXTexCoord2s16(tex0_s0, tex0_t1);
    GXTexCoord2s16(tex1_s0, tex1_t1);
    GXEnd();

    GXSetVtxAttrFmtv(GX_VTXFMT0, fmtList);
}

/* 800817CC-80081850       .text init__11dDlst_2Dm_cFP7ResTIMGP7ResTIMGff */
void dDlst_2Dm_c::init(ResTIMG* t0, ResTIMG* t1, f32 sx, f32 sy) {
    mTex[0].mbHasTlut = mDoLib_setResTimgObj(t0, &mTex[0].mTexObj, 0, &mTex[0].mTlutObj);
    mTex[1].mbHasTlut = mDoLib_setResTimgObj(t1, &mTex[1].mTexObj, 1, &mTex[1].mTlutObj);
    mScaleX = sx;
    mScaleY = sy;
}

/* 80081850-80081864       .text setPos__11dDlst_2Dm_cFssss */
void dDlst_2Dm_c::setPos(s16 x0, s16 y0, s16 x1, s16 y1) {
    mX0 = x0;
    mY0 = y0;
    mX1 = x1;
    mY1 = y1;
}

/* 80081864-80081870       .text setScale__11dDlst_2Dm_cFff */
void dDlst_2Dm_c::setScale(f32 sx, f32 sy) {
    mScaleX = sx;
    mScaleY = sy;
}

/* 80081870-80081888       .text setScroll__11dDlst_2Dm_cFiss */
void dDlst_2Dm_c::setScroll(int idx, s16 x, s16 y) {
    TexEntry * pTex = &mTex[idx];
    pTex->mScrollX = x;
    pTex->mScrollY = y;
}

/* 80081888-80081DA4       .text draw__11dDlst_2Dm_cFv */
void dDlst_2Dm_c::draw() {
    GXVtxAttrFmtList fmtList[GX_VA_MAX_ATTR + 1];

    s16 tex0_s0 = mTex[0].mScrollX;
    s16 tex0_t0 = mTex[0].mScrollY;
    s16 tex0_s1 = (tex0_s0 + 256.0f);
    s16 tex0_t1 = (tex0_t0 + 256.0f);

    f32 scaleX = (mScaleX * 256.0f) / GXGetTexObjWidth(&mTex[1].mTexObj);
    f32 scaleY = (mScaleY * 256.0f) / GXGetTexObjHeight(&mTex[1].mTexObj);

    s16 tex1_s0 = mTex[1].mScrollX * scaleX;
    s16 tex1_t0 = mTex[1].mScrollY * scaleY;
    s16 tex1_s1 = tex1_s0 + (s16)(scaleX * GXGetTexObjWidth(&mTex[0].mTexObj));
    s16 tex1_t1 = tex1_t0 + (s16)(scaleY * GXGetTexObjHeight(&mTex[0].mTexObj));

    GXGetVtxAttrFmtv(GX_VTXFMT0, fmtList);

    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0);
    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S16, 8);
    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX1, GX_TEX_ST, GX_S16, 8);
    GXClearVtxDesc();
    GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
    GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
    GXSetVtxDesc(GX_VA_TEX1, GX_DIRECT);
    GXLoadTexObj(&mTex[0].mTexObj, GX_TEXMAP0);
    if (mTex[0].mbHasTlut)
        GXLoadTlut(&mTex[0].mTlutObj, GXGetTexObjTlut(&mTex[0].mTexObj));
    GXLoadTexObj(&mTex[1].mTexObj, GX_TEXMAP1);
    if (mTex[1].mbHasTlut != 0)
        GXLoadTlut(&mTex[1].mTlutObj, GXGetTexObjTlut(&mTex[1].mTexObj));

    GXSetNumChans(0);
    GXSetTevColor(GX_TEVREG0, mBlack);
    GXSetTevColor(GX_TEVREG1, mWhite);

    GXSetNumTexGens(2);
    GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
    GXSetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX1, GX_IDENTITY);

    GXSetNumTevStages(2);

    GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
    GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_C1, GX_CC_C0, GX_CC_TEXC, GX_CC_ZERO);
    GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
    GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_A1, GX_CA_A0, GX_CA_TEXA, GX_CA_ZERO);
    GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);

    GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR_NULL);
    GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_TEXC, GX_CC_CPREV, GX_CC_ZERO);
    GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
    GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_TEXA, GX_CA_APREV, GX_CA_ZERO);
    GXSetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);

    GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_OR, GX_GREATER, 0);
    GXSetBlendMode(GX_BM_BLEND, GX_BL_SRC_ALPHA, GX_BL_INV_SRC_ALPHA, GX_LO_SET);
    GXLoadPosMtxImm(cMtx_getIdentity(), GX_PNMTX0);
    GXSetCurrentMtx(GX_PNMTX0);

    GXBegin(GX_QUADS, GX_VTXFMT0, 4);
    GXPosition3s16((s32)mX0, (s32)mY0, 0);
    GXTexCoord2s16(tex0_s0, tex0_t0);
    GXTexCoord2s16(tex1_s0, tex1_t0);

    GXPosition3s16((s32)mX1, (s32)mY0, 0);
    GXTexCoord2s16(tex0_s1, tex0_t0);
    GXTexCoord2s16(tex1_s1, tex1_t0);

    GXPosition3s16((s32)mX1, (s32)mY1, 0);
    GXTexCoord2s16(tex0_s1, tex0_t1);
    GXTexCoord2s16(tex1_s1, tex1_t1);

    GXPosition3s16((s32)mX0, (s32)mY1, 0);
    GXTexCoord2s16(tex0_s0, tex0_t1);
    GXTexCoord2s16(tex1_s0, tex1_t1);
    GXEnd();

    GXSetVtxAttrFmtv(GX_VTXFMT0, fmtList);
}

/* 80081DA4-80082130       .text draw__12dDlst_2DMt_cFv */
void dDlst_2DMt_c::draw() {
    GXVtxAttrFmtList fmtList[GX_VA_MAX_ATTR + 1];

    GXGetVtxAttrFmtv(GX_VTXFMT0, fmtList);
    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0);
    GXClearVtxDesc();
    GXSetVtxDesc(GX_VA_POS, GX_DIRECT);

    dDlst_2DMt_tex_c* pTex = &mTex[0];
    s32 texIdx = 0;
    for (s32 i = 0; i < mTexNum; pTex++, i++) {
        if (!pTex->check())
            continue;

        if (pTex->getCI())
            GXLoadTlut(pTex->getTlutObj(), i);

        GXLoadTexObj(pTex->getTexObj(), (GXTexMapID)texIdx);
        GXSetVtxAttrFmt(GX_VTXFMT0, (GXAttr)((u32)GX_VA_TEX0 + texIdx), GX_TEX_ST, GX_F32, 0);
        GXSetVtxDesc((GXAttr)((u32)GX_VA_TEX0 + texIdx), GX_DIRECT);
        GXSetTevColor((GXTevRegID)((u32)GX_TEVREG0 + texIdx), pTex->getColor());
        GXSetTexCoordGen((GXTexCoordID)texIdx, GX_TG_MTX2x4, (GXTexGenSrc)((u32)GX_TG_TEX0 + texIdx), GX_IDENTITY);
        GXSetTevOrder((GXTevStageID)texIdx, (GXTexCoordID)texIdx, (GXTexMapID)texIdx, GX_COLOR_NULL);
        GXSetTevColorIn((GXTevStageID)texIdx, GX_CC_ZERO, (GXTevColorArg)((u32)GX_CC_C0 + texIdx * 2), GX_CC_TEXC, (texIdx != 0) ? GX_CC_CPREV : GX_CC_ZERO);
        GXSetTevColorOp((GXTevStageID)texIdx, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
        GXSetTevAlphaIn((GXTevStageID)texIdx, GX_CA_ZERO, (GXTevAlphaArg)((u32)GX_CA_A0 + texIdx), GX_CA_TEXA, (texIdx != 0) ? GX_CA_APREV : GX_CA_ZERO);
        GXSetTevAlphaOp((GXTevStageID)texIdx, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
        texIdx++;

        if (texIdx >= 3)
            break;
    }

    if (texIdx != 0) {
        GXSetNumChans(0);
        GXSetNumTexGens(texIdx);
        GXSetNumTevStages(texIdx);
        GXSetBlendMode(GX_BM_BLEND, GX_BL_SRC_ALPHA, GX_BL_INV_SRC_ALPHA, GX_LO_SET);
        GXBegin(GX_QUADS, GX_VTXFMT0, 4);

        GXPosition3s16(mX0, mY0, 0);
        pTex = &mTex[0];
        for (s32 i = 0; i < mTexNum; pTex++, i++)
            if (pTex->check())
                GXTexCoord2f32(pTex->getS(), pTex->getT());

        GXPosition3s16(mX1, mY0, 0);
        pTex = &mTex[0];
        for (s32 i = 0; i < mTexNum; pTex++, i++)
            if (pTex->check())
                GXTexCoord2f32(pTex->getS() + pTex->getSw(), pTex->getT());

        GXPosition3s16(mX1, mY1, 0);
        pTex = &mTex[0];
        for (s32 i = 0; i < mTexNum; pTex++, i++)
            if (pTex->check())
                GXTexCoord2f32(pTex->getS() + pTex->getSw(), pTex->getT() + pTex->getTw());

        GXPosition3s16(mX0, mY1, 0);
        pTex = &mTex[0];
        for (s32 i = 0; i < mTexNum; pTex++, i++)
            if (pTex->check())
                GXTexCoord2f32(pTex->getS(), pTex->getT() + pTex->getTw());

        GXEnd();

        GXSetVtxAttrFmtv(GX_VTXFMT0, fmtList);
    }
}

/* 80082130-800821B0       .text __ct__10dDlst_2D_cFP7ResTIMGssUc */
dDlst_2D_c::dDlst_2D_c(ResTIMG* timg, s16 x, s16 y, u8 alpha) {
    mPicture.initiate(timg, NULL);
    mX = x;
    mY = y;
    mAlpha = alpha;
}

/* 800821B0-80082264       .text draw__10dDlst_2D_cFv */
void dDlst_2D_c::draw() {
    mPicture.setAlpha(mAlpha);
    mPicture.draw(mX, mY, false, false, false);
}

/* 80082264-80082274       .text init__8cM_rnd_cFiii */
void cM_rnd_c::init(int a, int b, int c) {
    m0 = a;
    m4 = b;
    m8 = c;
}

/* 80082274-80082368       .text get__8cM_rnd_cFv */
f32 cM_rnd_c::get() {
    m0 = (m0 * 171) % 30269;
    m4 = (m4 * 172) % 30307;
    m8 = (m8 * 170) % 30323;
    return std::fabsf(std::fmodf((m0 / 30269.0f) + (m4 / 30307.0f) + (m8 / 30323.0f), 1.0f));
}

/* 80082368-800823A0       .text getF__8cM_rnd_cFf */
f32 cM_rnd_c::getF(f32 m) {
    return get() * m;
}

/* 800823A0-800823E8       .text getFX__8cM_rnd_cFf */
f32 cM_rnd_c::getFX(f32 m) {
    return m * (get() - 0.5f) * 2.0f;
}

/* 800823E8-80082424       .text getValue__8cM_rnd_cFff */
f32 cM_rnd_c::getValue(f32 min, f32 range) {
    return min + getF(range);
}

/* 80082424-80082794       .text draw__18dDlst_effectLine_cFv */
void dDlst_effectLine_c::draw() {
    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
    GXClearVtxDesc();
    GXSetVtxDesc(GX_VA_POS, GX_DIRECT);

    GXSetNumChans(1);
    GXSetChanCtrl(GX_COLOR0, GX_FALSE, GX_SRC_REG, GX_SRC_REG, 0, GX_DF_CLAMP, GX_AF_NONE);
    GXSetNumTexGens(0);
    GXSetNumTevStages(1);
    GXSetTevColor(GX_TEVREG0, mColor);
    GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
    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_CS_SCALE_1, GX_TRUE, 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_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
    GXSetZMode(GX_FALSE, GX_LEQUAL, GX_FALSE);
    GXSetBlendMode(GX_BM_BLEND, GX_BL_SRC_ALPHA, GX_BL_INV_SRC_ALPHA, GX_LO_CLEAR);
    GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_OR, GX_ALWAYS, 0);
    GXSetCullMode(GX_CULL_NONE);
    GXSetClipMode(GX_CLIP_ENABLE);
    GXLoadPosMtxImm(j3dSys.getViewMtx(), GX_PNMTX0);
    GXSetCurrentMtx(GX_PNMTX0);

    s32 numSegments = (s32)mRnd.getValue(field_0x20, field_0x22);
    for (s32 i = 0; i < numSegments; i++) {
        cXyz pt0, pt1;

        s16 angle = mRnd.getFX(0x7FFF);

        f32 rad0 = mRnd.getValue(field_0x28, field_0x2C);
        pt0.x = mPos.x + rad0 * cM_ssin(angle);
        pt0.y = mPos.y + rad0 * cM_scos(angle);
        pt0.z = mPos.z;

        f32 rad1 = mRnd.getValue(field_0x30, field_0x34);
        pt1.x = pt0.x + rad1 * cM_ssin(angle);
        pt1.y = pt0.y + rad1 * cM_scos(angle);
        pt1.z = mPos.z;

        mDoMtx_multVec(dComIfGd_getInvViewMtx(), &pt0, &pt0);
        mDoMtx_multVec(dComIfGd_getInvViewMtx(), &pt1, &pt1);

        f32 lineWidth = mRnd.getValue(field_0x24, field_0x26);
        GXSetLineWidth(lineWidth, GX_TO_ZERO);

        GXBegin(GX_LINES, GX_VTXFMT0, 2);
        GXPosition3f32(pt0.x, pt0.y, pt0.z);
        GXPosition3f32(pt1.x, pt1.y, pt1.z);
        GXEnd();
    }
}

/* 80082794-80082828       .text update__18dDlst_effectLine_cFR4cXyzR8_GXColorUsUsUsUsffff */
void dDlst_effectLine_c::update(cXyz& pos, GXColor& color, u16 s0, u16 s1, u16 s2, u16 s3, f32 f0, f32 f1, f32 f2, f32 f3) {
    mPos = pos;
    mColor = color;
    field_0x20 = s0;
    field_0x22 = s1;
    field_0x24 = s2;
    field_0x26 = s3;
    field_0x28 = f0;
    field_0x2C = f1;
    field_0x30 = f2;
    field_0x34 = f3;
    dComIfGd_set2DOpa(this);
}

/* 80082828-80082838       .text set__22dDlst_alphaModelData_cFUcPA4_fUc */
void dDlst_alphaModelData_c::set(u8 type, Mtx mtx, u8 alpha) {
    mType = type;
    mpMtx = mtx;
    mAlpha = alpha;
}

#include "assets/l_backRevZMat.h"
#include "assets/l_frontZMat.h"
#include "assets/l_frontNoZSubMat.h"

#include "assets/l_bonboriPos__d_drawlist.h"

#include "assets/l_bonboriDL.h"

#include "assets/l_s_beam_checkPos__d_drawlist.h"

#include "assets/l_s_beam_checkDL.h"

#include "assets/l_cubePos__d_drawlist.h"

#include "assets/l_cubeDL.h"

#include "assets/l_bonbori2Pos__d_drawlist.h"

#include "assets/l_bonbori2DL.h"

/* 80082838-80082E44       .text draw__22dDlst_alphaModelData_cFPA4_f */
void dDlst_alphaModelData_c::draw(Mtx viewMtx) {
    Mtx mtx;
    MTXConcat(viewMtx, mpMtx, mtx);
    GFLoadPosMtxImm(mtx, GX_PNMTX0);
    GFSetCurrentMtx(GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY);

    GXColor color;
    color.a = mAlpha * 4;
    GFSetChanMatColor(GX_ALPHA0, color);

    if (mType == 0) {
        /* Bonbori */
        GFSetArray(GX_VA_POS, l_bonboriPos, sizeof(*l_bonboriPos));
        GXCallDisplayList(l_backRevZMat, 0x40);
        GXCallDisplayList(l_bonboriDL, 0xa0);
        GXCallDisplayList(l_frontZMat, 0x20);
        GXCallDisplayList(l_bonboriDL, 0xa0);
        GXCallDisplayList(l_frontNoZSubMat, 0x20);
        GXCallDisplayList(l_bonboriDL, 0xa0);
    } else if (mType == 1) {
        /* Bonborix2 */
        GFSetArray(GX_VA_POS, l_bonboriPos, sizeof(*l_bonboriPos));
        Mtx tmp;
        MTXScale(tmp, 0.8f, 0.8f, 0.8f);
        MTXConcat(mtx, tmp, tmp);
        GFLoadPosMtxImm(tmp, GX_PNMTX1);

        GXCallDisplayList(l_backRevZMat, 0x40);
        GXCallDisplayList(l_bonboriDL, 0xa0);
        GFSetCurrentMtx(GX_PNMTX1, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY);
        GXCallDisplayList(l_bonboriDL, 0xa0);

        GXCallDisplayList(l_frontZMat, 0x20);
        GFSetCurrentMtx(GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY);
        GXCallDisplayList(l_bonboriDL, 0xa0);
        GFSetCurrentMtx(GX_PNMTX1, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY);
        GXCallDisplayList(l_bonboriDL, 0xa0);

        GXCallDisplayList(l_frontNoZSubMat, 0x20);
        GFSetCurrentMtx(GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY);
        GXCallDisplayList(l_bonboriDL, 0xa0);
        GFSetCurrentMtx(GX_PNMTX1, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY);
        GXCallDisplayList(l_bonboriDL, 0xa0);
    } else if (mType == 5) {
        /* Bonborix3 */
        GFSetArray(GX_VA_POS, l_bonboriPos, sizeof(*l_bonboriPos));
        Mtx tmp;
        MTXScale(tmp, 0.8f, 0.8f, 0.8f);
        MTXConcat(mtx, tmp, tmp);
        GFLoadPosMtxImm(tmp, GX_PNMTX1);

        MTXScale(tmp, 0.6f, 0.6f, 0.6f);
        MTXConcat(mtx, tmp, tmp);
        GFLoadPosMtxImm(tmp, GX_PNMTX2);

        GXCallDisplayList(l_backRevZMat, 0x40);
        GXCallDisplayList(l_bonboriDL, 0xa0);
        GFSetCurrentMtx(GX_PNMTX1, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY);
        GXCallDisplayList(l_bonboriDL, 0xa0);
        GFSetCurrentMtx(GX_PNMTX2, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY);
        GXCallDisplayList(l_bonboriDL, 0xa0);

        GXCallDisplayList(l_frontZMat, 0x20);
        GFSetCurrentMtx(GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY);
        GXCallDisplayList(l_bonboriDL, 0xa0);
        GFSetCurrentMtx(GX_PNMTX1, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY);
        GXCallDisplayList(l_bonboriDL, 0xa0);
        GFSetCurrentMtx(GX_PNMTX2, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY);
        GXCallDisplayList(l_bonboriDL, 0xa0);

        GXCallDisplayList(l_frontNoZSubMat, 0x20);
        GFSetCurrentMtx(GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY);
        GXCallDisplayList(l_bonboriDL, 0xa0);
        GFSetCurrentMtx(GX_PNMTX1, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY);
        GXCallDisplayList(l_bonboriDL, 0xa0);
        GFSetCurrentMtx(GX_PNMTX2, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY);
        GXCallDisplayList(l_bonboriDL, 0xa0);
    } else if (mType == 2) {
        /* BeamCheck */
        GFSetArray(GX_VA_POS, l_s_beam_checkPos, sizeof(*l_s_beam_checkPos));
        GXCallDisplayList(l_backRevZMat, 0x40);
        GXCallDisplayList(l_s_beam_checkDL, 0xe0);
        GXCallDisplayList(l_frontZMat, 0x20);
        GXCallDisplayList(l_s_beam_checkDL, 0xe0);
        GXCallDisplayList(l_frontNoZSubMat, 0x20);
        GXCallDisplayList(l_s_beam_checkDL, 0xe0);
    } else if (mType == 3) {
        /* Cube */
        /* BeamCheck */
        GFSetArray(GX_VA_POS, l_cubePos, sizeof(*l_cubePos));
        GXCallDisplayList(l_backRevZMat, 0x40);
        GXCallDisplayList(l_frontZMat, 0x20);
        GXCallDisplayList(l_cubeDL, 0x40);
    } else if (mType == 4) {
        /* Bonbori2 */
        GFSetArray(GX_VA_POS, l_bonbori2Pos, sizeof(*l_bonbori2Pos));
        GXCallDisplayList(l_backRevZMat, 0x40);
        GXCallDisplayList(l_bonbori2DL, 0x2a0);
        GXCallDisplayList(l_frontZMat, 0x20);
        GXCallDisplayList(l_bonbori2DL, 0x2a0);
        GXCallDisplayList(l_frontNoZSubMat, 0x20);
        GXCallDisplayList(l_bonbori2DL, 0x2a0);
    }
}

/* 80082E44-80082E58       .text __ct__18dDlst_alphaModel_cFv */
dDlst_alphaModel_c::dDlst_alphaModel_c() {
    mCapacity = 0;
    mpData = NULL;
    mNum = 0;
}

/* 80082E58-80082EFC       .text create__18dDlst_alphaModel_cFi */
dDlst_alphaModel_c * dDlst_alphaModel_c::create(int num) {
    dDlst_alphaModel_c * i_this = new dDlst_alphaModel_c();
    if (i_this != NULL) {
        dDlst_alphaModelData_c * pData = new dDlst_alphaModelData_c[num];
        if (pData != NULL) {
            i_this->mpData = pData;
            i_this->mCapacity = num;
            return i_this;
        }

        if (i_this != NULL)
            delete i_this;
    }
    return NULL;
}

/* 80082EFC-80082F38       .text __dt__22dDlst_alphaModelData_cFv */
dDlst_alphaModelData_c::~dDlst_alphaModelData_c() {
}

/* 80082F38-80082F3C       .text __ct__22dDlst_alphaModelData_cFv */
dDlst_alphaModelData_c::dDlst_alphaModelData_c() {
}

/* 80082F3C-80082F9C       .text set__18dDlst_alphaModel_cFUcPA4_fUc */
BOOL dDlst_alphaModel_c::set(u8 type, Mtx mtx, u8 alpha) {
    if (mNum >= mCapacity)
        return FALSE;

    mpData[mNum].set(type, mtx, alpha);
    mNum++;
    return TRUE;
}

/* 80082F9C-80083064       .text draw__18dDlst_alphaModel_cFPA4_f */
BOOL dDlst_alphaModel_c::draw(Mtx mtx) {
    if (mNum == 0)
        return FALSE;

    #include "assets/l_matDL__draw__18dDlst_alphaModel_cFPA4_f.h"

    static GXVtxDescList l_vtxDescList[] = {
        {GX_VA_POS, GX_INDEX8},
        {GX_VA_NULL, GX_NONE},
    };

    static GXVtxAttrFmtList l_vtxAttrFmtList[] = {
        {GX_VA_POS, GX_POS_XYZ, GX_F32, 0x00},
        {GX_VA_NULL, GX_POS_XYZ, GX_F32, 0x00},
    };

    GXCallDisplayList(l_matDL, 0x60);
    GFSetVtxDescv(l_vtxDescList);
    GFSetVtxAttrFmtv(GX_VTXFMT0, l_vtxAttrFmtList);
    GXSetClipMode(GX_CLIP_ENABLE);

    dDlst_alphaModelData_c * pData = &mpData[0];
    for (s32 i = 0; i < mNum; pData++, i++)
        pData->draw(mtx);

    GFSetBlendModeEtc(GX_BM_NONE, GX_BL_ZERO, GX_BL_ZERO, GX_LO_CLEAR, 1, 0, 1);
    return TRUE;
}

#include "assets/l_shadowVolPos__d_drawlist.h"

#include "assets/l_shadowVolDL.h"
#include "assets/l_shadowProjMat.h"
#include "assets/l_shadowVolMat.h"
#include "assets/l_clearMat.h"
#include "assets/l_frontMat.h"
#include "assets/l_backSubMat.h"

#include "assets/l_simpleShadowPos__d_drawlist.h"

#include "assets/l_shadowVolumeDL.h"

/* 80083064-800832C4       .text draw__22dDlst_alphaModelPacketFv */
void dDlst_alphaModelPacket::draw() {
    GXSetNumChans(1);
    GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_REG, GX_SRC_REG, 0, GX_DF_NONE, GX_AF_NONE);
    GXSetChanMatColor(GX_COLOR0A0, mColor);
    GXSetNumTexGens(0);
    GXSetNumTevStages(1);
    GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
    GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC);
    GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
    GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA);
    GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
    GXSetZCompLoc(GX_TRUE);
    GXSetZMode(GX_TRUE, GX_LEQUAL, GX_FALSE);
    GXSetBlendMode(GX_BM_BLEND, GX_BL_SRC_ALPHA, GX_BL_INV_SRC_ALPHA, GX_LO_CLEAR);
    GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_OR, GX_GREATER, 0);
    GXSetFog(GX_FOG_NONE, 0.0f, 0.0f, 0.0f, 0.0f, g_clearColor);
    GXSetCullMode(GX_CULL_FRONT);
    GXClearVtxDesc();
    GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
    Mtx mtx;
    MTXConcat(j3dSys.getViewMtx(), *mMtxP, mtx);
    GXLoadPosMtxImm(mtx, GX_PNMTX0);
    GXSetCurrentMtx(GX_PNMTX0);

    if (mType == 0) {
        GXSetArray(GX_VA_POS, l_bonboriPos, sizeof(*l_bonboriPos));
        GXCallDisplayList(l_bonboriDL, 0xa0);
    } else if (mType == 1) {
        GXSetArray(GX_VA_POS, l_bonboriPos, sizeof(*l_bonboriPos));
        GXCallDisplayList(l_bonboriDL, 0xa0);
    } else if (mType == 2) {
        GXSetArray(GX_VA_POS, l_s_beam_checkPos, sizeof(*l_s_beam_checkPos));
        GXCallDisplayList(l_s_beam_checkDL, 0xe0);
    } else if (mType == 3) {
        GXSetArray(GX_VA_POS, l_cubePos, sizeof(*l_cubePos));
        GXCallDisplayList(l_cubeDL, 0x40);
    }
}

/* 800832C4-800833CC       .text set__18dDlst_shadowPoly_cFP10cBgD_Vtx_tUsUsUsP8cM3dGPla */
int dDlst_shadowPoly_c::set(cBgD_Vtx_t* vtx, u16 a, u16 b, u16 c, cM3dGPla* plane) {
    if (mCount >= getTriMax())
        return false;

    dDlst_shadowTri_c* tri = &getTri()[mCount];
    cXyz nrm = *plane->GetNP() * 2.0f;
    VECAdd(&vtx[a], &nrm, &tri->mPos[0]);
    VECAdd(&vtx[b], &nrm, &tri->mPos[1]);
    VECAdd(&vtx[c], &nrm, &tri->mPos[2]);
    mCount++;
    return true;
}

/* 800833CC-800834A4       .text set__18dDlst_shadowPoly_cFR4cXyzR4cXyzR4cXyz */
int dDlst_shadowPoly_c::set(cXyz& a, cXyz& b, cXyz& c) {
    if (mCount >= getTriMax())
        return false;

    dDlst_shadowTri_c* tri = &getTri()[mCount];
    tri->mPos[0].set(a);
    tri->mPos[1].set(b);
    tri->mPos[2].set(c);
    mCount++;
    return true;
}

/* 800834A4-80083568       .text draw__18dDlst_shadowPoly_cFv */
void dDlst_shadowPoly_c::draw() {
    dDlst_shadowTri_c* tri = getTri();
    GXBegin(GX_TRIANGLES, GX_VTXFMT0, mCount * 3);
    for (s32 i = 0; i < mCount; tri++, i++) {
        GXPosition3f32(tri->mPos[2].x, tri->mPos[2].y, tri->mPos[2].z);
        GXPosition3f32(tri->mPos[1].x, tri->mPos[1].y, tri->mPos[1].z);
        GXPosition3f32(tri->mPos[0].x, tri->mPos[0].y, tri->mPos[0].z);
    }
    GXEnd();
}

static void dummy() {
    // Fakematch to fix the vtable order and weak destructor order of dDlst_shadowReal_c and dDlst_shadowTri_c.
    struct {
        dDlst_shadowReal_c temp[1];
    }* temp = NULL;
    delete temp;
}

/* 80083668-800836E0       .text J3DDrawBuffer__create__FUl */
static J3DDrawBuffer * J3DDrawBuffer__create(u32 size) {
    J3DDrawBuffer * buffer = new J3DDrawBuffer();
    if (buffer != NULL) {
        if (buffer->allocBuffer(size) == 0)
            return buffer;
        delete buffer;
    }
    return NULL;
}

/* 800836E0-800837F0       .text init__18dDlst_shadowReal_cFv */
void dDlst_shadowReal_c::init() {
    u32 texDataSize = GXGetTexBufferSize(0x80, 0x80, GX_TF_I4, GX_FALSE, 0);
    mpTexData = new(0x20) u8[texDataSize];

    GXInitTexObj(&mTexObj, mpTexData, 0x80, 0x80, GX_TF_I4, GX_CLAMP, GX_CLAMP, GX_FALSE);
    GXInitTexObjLOD(&mTexObj, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_ANISO_1);

    mpCallBack = new J3DCallBackPacket();
    mpDrawBuffer = new J3DDrawBuffer(0x20);
    mpDrawBuffer->setInvalidSort();
}

/* 800837F0-80083850       .text reset__18dDlst_shadowReal_cFv */
void dDlst_shadowReal_c::reset() {
    if (mState == 1) {
        mState = 2;
    } else {
        mState = 0;
        field_0x1 = -1;
    }

    mpDrawBuffer->frameInit();
    mModelNum = 0;
}

/* 80083850-8008398C       .text imageDraw__18dDlst_shadowReal_cFPA4_f */
void dDlst_shadowReal_c::imageDraw(Mtx drawMtx) {
    if (mState != 1)
        return;

    GXSetProjection(mRenderProjMtx, GX_ORTHOGRAPHIC);
    if (mModelNum == 0) {
        j3dSys.setViewMtx(mViewMtx);
        mpDrawBuffer->draw();
    } else {
        J3DModel** modelP = mpModels;
        J3DShape::resetVcdVatCache();
        for (u8 i = 0; i < mModelNum; i++) {
            (*modelP)->viewCalc();
            J3DModelData* modelData = (*modelP)->getModelData();
            modelData->getShapeNodePointer(0)->loadPreDrawSetting();
            for (u16 j = 0; j < modelData->getShapeNum(); j++) {
                if (!modelData->getShapeNodePointer(j)->checkFlag(J3DShpFlag_Hide)) {
                    J3DShapePacket* packet = (*modelP)->getShapePacket(j);
                    packet->setBaseMtxPtr(&mViewMtx);
                    packet->drawFast();
                    packet->setBaseMtxPtr((Mtx*)drawMtx);
                }
            }
            modelP++;
        }
        J3DShape::resetVcdVatCache();
    }

    GXCopyTex(mpTexData, GX_TRUE);
    GXPixModeSync();
}

/* 8008398C-80083B8C       .text draw__18dDlst_shadowReal_cFv */
void dDlst_shadowReal_c::draw() {
    if (mState != 1)
        return;

    static GXColor l_color = { 0x00, 0x00, 0x00, 0x40 };
    l_color.a = (mAlpha >> 2) & ~3;

    GXSetTevColor(GX_TEVREG0, l_color);
    GXCallDisplayList(l_shadowVolMat, 0x40);

    GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
    GXClearVtxDesc();
    GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
    mDoMtx_stack_c::copy(mViewMtx);
    mDoMtx_stack_c::inverse();

    Mtx mtx;
    mDoMtx_inverse(mRenderProjMtx, mtx);
    mtx[2][3] = 0.0f;
    mDoMtx_stack_c::concat(mtx);
    mDoMtx_stack_c::scaleM(1.0f, 1.0f, -0.003f);
    mDoMtx_concat(j3dSys.getViewMtx(), mDoMtx_stack_c::get(), mtx);
    GXLoadPosMtxImm(mtx, GX_PNMTX1);
    GXSetCurrentMtx(GX_PNMTX1);
    GXCallDisplayList(l_shadowVolDL, 0x40);
    GXCallDisplayList(l_frontZMat, 0x20);
    GXCallDisplayList(l_shadowVolDL, 0x40);
    GXCallDisplayList(l_frontNoZSubMat, 0x20);
    GXCallDisplayList(l_shadowVolDL, 0x40);
    GXCallDisplayList(l_shadowProjMat, 0x40);

    GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
    GXLoadTexObj(&mTexObj, GX_TEXMAP0);
    GXClearVtxDesc();
    GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
    GXSetCurrentMtx(GX_PNMTX0);
    GXLoadTexMtxImm(mReceiverProjMtx, GX_TEXMTX0, GX_MTX3x4);
    mShadowRealPoly.draw();
    GXCallDisplayList(l_clearMat, 0x40);
    GXClearVtxDesc();
    GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
    GXSetCurrentMtx(GX_PNMTX1);
    GXCallDisplayList(l_shadowVolDL, 0x40);
}

/* 80083B8C-80083DA0       .text psdRealCallBack__FP13cBgS_ShdwDrawP10cBgD_Vtx_tiiiP8cM3dGPla */
int psdRealCallBack(cBgS_ShdwDraw* shdw, cBgD_Vtx_t* pVtx, int v0, int v1, int v2, cM3dGPla* tri) {
    ShdwDrawPoly_c* shdwDrawPoly = (ShdwDrawPoly_c*)shdw;
    const cXyz* normal = tri->GetNP();
    if (shdwDrawPoly->getLightVec()->inprod(*normal) < -0.2f) {
        cXyz* center = shdwDrawPoly->getCenter();
        if (normal->x * center->x + normal->y * center->y + normal->z * center->z + tri->GetD() > -50.f) {
            const cXyz* min = shdwDrawPoly->GetBndP()->GetMinP();
            const cXyz* max = shdwDrawPoly->GetBndP()->GetMaxP();
            cBgD_Vtx_t* vert1 = pVtx + v0;
            cBgD_Vtx_t* vert2 = pVtx + v1;
            cBgD_Vtx_t* vert3 = pVtx + v2;
            if ((normal->y <= 0.0f && (vert1->y < min->y || vert2->y < min->y || vert3->y < min->y)) ||
                (normal->y > 0.0f && (vert1->y < min->y && vert2->y < min->y && vert3->y < min->y)) ||
                (vert1->y > max->y && vert2->y > max->y && vert3->y > max->y) ||
                (vert1->x < min->x && vert2->x < min->x && vert3->x < min->x) ||
                (vert1->x > max->x && vert2->x > max->x && vert3->x > max->x) ||
                (vert1->z < min->z && vert2->z < min->z && vert3->z < min->z) ||
                (vert1->z > max->z && vert2->z > max->z && vert3->z > max->z)
            ) {
                return 1;
            } else {
                return shdwDrawPoly->getPoly()->set(pVtx, v0, v1, v2, tri);
            }
        }
    }
    return 1;
}

/* 80083DA0-80083E18       .text seaRealCallBack__FPvR4cXyzR4cXyzR4cXyz */
void seaRealCallBack(void* user, cXyz& v0, cXyz& v1, cXyz& v2) {
    ShdwDrawPoly_c* poly = (ShdwDrawPoly_c*)user;
    const cXyz* min = poly->GetBndP()->GetMinP();
    const cXyz* max = poly->GetBndP()->GetMaxP();
    if ((v0.y < min->y && v1.y < min->y && v2.y < min->y) || (v0.y > max->y && v1.y > max->y && v2.y > max->y)) {
        return;
    } else {
        poly->getPoly()->set(v0, v1, v2);
    }
}

/* 80083E18-800840B0       .text realPolygonCheck__FP4cXyzffP4cXyzP18dDlst_shadowPoly_c */
BOOL realPolygonCheck(cXyz* param_0, f32 casterRadius, f32 heightAgl, cXyz* lightDir, dDlst_shadowPoly_c* shadowPoly) {
    ShdwDrawPoly_c shdwDrawPoly;
    
    // Compute a bounding box around the shadow receiver based on its position, size, and light direction
    cXyz bbMin;
    cXyz bbMax;
    f32 tmp1 = casterRadius * casterRadius * 0.002f;
    f32 tmp2 = cLib_maxLimit(tmp1, 120.0f);
    f32 var1 = casterRadius + heightAgl - tmp2;
    bbMin.y = param_0->y - var1;
    bbMax.y = param_0->y + casterRadius * 0.4f;
    bbMax.x = param_0->x + lightDir->x * var1;
    if (bbMax.x < param_0->x) {
        bbMin.x = bbMax.x;
        bbMax.x = param_0->x;
    } else {
        bbMin.x = param_0->x;
    }
    bbMin.x -= casterRadius;
    bbMax.x += casterRadius;
    var1 = param_0->z + lightDir->z * var1;
    bbMax.z = var1;
    if (var1 < param_0->z) {
        bbMin.z = bbMax.z;
        bbMax.z = param_0->z;
    } else {
        bbMin.z = param_0->z;
    }
    bbMin.z -= casterRadius;
    bbMax.z += casterRadius;

    mDoLib_clipper::changeFar(mDoLib_clipper::getFovyRate() * 3000.0f);
    BOOL clip = mDoLib_clipper::clip(j3dSys.getViewMtx(), &bbMax, &bbMin);
    mDoLib_clipper::resetFar();
    if (clip) {
        return FALSE;
    }

    // Gather a list of polygons from the bg geometry (dBgS) or the sea (daSea) that will act as shadow receivers
    // ShdwDrawPoly_c is a transient object for collecting the triangles, which are stored permanently in dDlst_shadowPoly_c
    shdwDrawPoly.Set(bbMin, bbMax);
    shdwDrawPoly.SetCallback(psdRealCallBack);
    shdwDrawPoly.setCenter(param_0);
    shdwDrawPoly.setLightVec(lightDir);
    shdwDrawPoly.setPoly(shadowPoly);
    dComIfG_Bgsp()->ShdwDraw(&shdwDrawPoly);
    daSea_GetPoly(&shdwDrawPoly, seaRealCallBack, bbMin, bbMax);
    return TRUE;
}

/* 800841B0-8008450C       .text setShadowRealMtx__FPA4_fPA4_fPA4_fP4cXyzP4cXyzffP18dDlst_shadowPoly_cf */
u8 setShadowRealMtx(Mtx viewMtx, Mtx renderProjMtx, Mtx receiverProjMtx, cXyz* lightPos, cXyz* pos, f32 casterSize, f32 heightAgl, dDlst_shadowPoly_c* shadowPoly, f32 heightFade) {
    shadowPoly->reset();
    if (heightFade >= 1.0f) {
        return 0;
    }
    f32 opacity = 1.0f - heightFade;
    if (opacity > 1.0f) {
        opacity = 1.0f;
    }
    int alpha = 200.0f * opacity;
    cXyz lightVec = *lightPos - *pos;
    
    // The higher off the ground a shadow caster is, the weaker the shadow's horizontal components become
    // This cheats the light vec to be more vertical when the caster is high up, a la platforming drop shadows
    // At 50 units above ground, the shadow is fully vertical
    lightVec.y += heightAgl;
    f32 tmp = 0.02f * (50.0f - heightAgl);
    if (tmp < 0.0f) {
        lightVec.x = 0.0f;
        lightVec.z = 0.0f;
    } else if (tmp < 1.0f) {
        lightVec.x *= tmp;
        lightVec.z *= tmp;
    }

    f32 lightDist = std::sqrtf(lightVec.abs2());
    if (lightDist != 0.0f) {
        f32 tmp3 = (lightVec.y / lightDist);
        if (tmp3 < 1.5f) {
            lightVec.y = 1.5f * lightDist;
            lightDist = lightVec.abs2();
            lightDist = std::sqrtf(lightDist);
        }
        lightDist = (casterSize * 0.5f) / lightDist;
    }
    lightVec *= lightDist;
    lightVec += *pos;

    f32 casterRadius = casterSize * 0.4f;
    cXyz rayDir = *pos - lightVec;
    if (rayDir.isZero()) {
        rayDir.y = -1.0f;
        lightVec.y = pos->y + 1.0f;
    } else {
        rayDir.normalize();
    }

    if (!realPolygonCheck(pos, casterRadius, heightAgl, &rayDir, shadowPoly)) {
        return 0;
    }
    cMtx_lookAt(viewMtx, &lightVec, pos, 0);
    C_MTXOrtho(renderProjMtx, casterRadius, -casterRadius, -casterRadius, casterRadius, 1.0f, 10000.0f);
    C_MTXLightOrtho(receiverProjMtx, casterRadius, -casterRadius, -casterRadius, casterRadius, 0.5f, -0.5f, 0.5f, 0.5f);
    cMtx_concat(receiverProjMtx, viewMtx, receiverProjMtx);
    return alpha;
}

/* 8008450C-800846C8       .text set__18dDlst_shadowReal_cFUlScP8J3DModelP4cXyzffP12dKy_tevstr_c */
u32 dDlst_shadowReal_c::set(u32 key, s8 shouldFade, J3DModel* model, cXyz* pos, f32 casterSize, f32 heightAboveGround, dKy_tevstr_c* tevstr) {
    if (mState != 1 || key != mKey) {
        cXyz lightPos = dKy_plight_near_pos();
        if (tevstr) {
            lightPos = tevstr->mLightPosWorld;
        }
        mAlpha = setShadowRealMtx(
            mViewMtx, mRenderProjMtx, mReceiverProjMtx, &lightPos, pos, casterSize, heightAboveGround, &mShadowRealPoly,
            shouldFade == 0 ? 0.0f : heightAboveGround * 0.0007f
        );
        if (mAlpha == 0) {
            return 0;
        }
        mState = 1;
        mKey = key;
        field_0x1 = shouldFade;
        mpDrawBuffer->setCallBackPacket(mpCallBack);
        mModelNum = 0;
    }

    J3DDrawBuffer* buffer0 = j3dSys.getDrawBuffer(0);
    J3DDrawBuffer* buffer1 = j3dSys.getDrawBuffer(1);
    j3dSys.setViewMtx(mViewMtx);
    j3dSys.setDrawBuffer(mpDrawBuffer, 0);
    j3dSys.setDrawBuffer(mpDrawBuffer, 1);
    model->entry();
    model->lock();
    model->viewCalc();
    j3dSys.setViewMtx(dComIfGd_getView()->mViewMtx);
    j3dSys.setDrawBuffer(buffer0, 0);
    j3dSys.setDrawBuffer(buffer1, 1);
    return mKey;
}

/* 800846C8-80084844       .text set2__18dDlst_shadowReal_cFUlScP8J3DModelP4cXyzffP12dKy_tevstr_c */
u32 dDlst_shadowReal_c::set2(u32 key, s8 shouldFade, J3DModel* model, cXyz* pos, f32 casterSize, f32 heightAboveGround, dKy_tevstr_c* tevstr) {
    if (mModelNum == 0) {
        cXyz lightPos = dKy_plight_near_pos();
        if (tevstr) {
            lightPos = tevstr->mLightPosWorld;
        }
        mAlpha = setShadowRealMtx(
            mViewMtx, mRenderProjMtx, mReceiverProjMtx, &lightPos, pos, casterSize, heightAboveGround, &mShadowRealPoly,
            shouldFade == 0 ? 0.0f : heightAboveGround * 0.00025f
        );
        if (mAlpha == 0) {
            return 0;
        }
        mState = 1;
        mKey = key;
        field_0x1 = shouldFade;
        mModelNum = 0;
    }

    JUT_ASSERT(3999, mModelNum < MODEL_MAX);

    mpModels[mModelNum++] = model;
    return mKey;
}

/* 80084844-800848E8       .text add__18dDlst_shadowReal_cFP8J3DModel */
bool dDlst_shadowReal_c::add(J3DModel* model) {
    if (mModelNum == 0 || model == NULL)
        return false;

    JUT_ASSERT(0xfe0, mModelNum < MODEL_MAX);
    mpModels[mModelNum++] = model;
    return true;
}

#include "assets/l_shadowSealTexDL.h"
#include "assets/l_shadowSealTex2DL.h"
#include "assets/l_shadowSealDL.h"

/* 800848E8-80084AC8       .text draw__20dDlst_shadowSimple_cFv */
void dDlst_shadowSimple_c::draw() {
    static GXColor l_color = { 0x00, 0x00, 0x00, 0x40 };
    l_color.a = mAlpha;

    GXSetTevColor(GX_TEVREG0, l_color);

    GXClearVtxDesc();
    GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
    GXLoadPosMtxImm(mVolumeMtx, GX_PNMTX0);
    GXSetCurrentMtx(GX_PNMTX0);

    GXCallDisplayList(l_frontMat, 0x40);
    GXCallDisplayList(l_shadowVolumeDL, 0x40);
    GXCallDisplayList(l_backSubMat, 0x20);
    GXCallDisplayList(l_shadowVolumeDL, 0x40);

    GXLoadPosMtxImm(mMtx, GX_PNMTX1);
    GXSetCurrentMtx(GX_PNMTX1);
    if (mpTexObj != NULL) {
        GXLoadTexObj(mpTexObj, GX_TEXMAP0);

        GXClearVtxDesc();
        GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
        GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
        GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO);
        GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
        GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_TEXA, GX_CA_ZERO, GX_CA_A2, GX_CA_ZERO);
        GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_COMP_RGB8_GT, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);

        if (GXGetTexObjWidth(mpTexObj) == GXGetTexObjHeight(mpTexObj)) {
            GXCallDisplayList(l_shadowSealTexDL, 0x40);
        } else {
            GXCallDisplayList(l_shadowSealTex2DL, 0x40);
        }
    }
  
    GXClearVtxDesc();
    GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
    GXCallDisplayList(l_shadowSealDL, 0x60);
    GXClearVtxDesc();
    GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
    GXSetCurrentMtx(GX_PNMTX0);
    GXCallDisplayList(l_clearMat, 0x40);
    GXCallDisplayList(l_shadowVolumeDL, 0x40);
}

/* 80084AC8-80084D48       .text set__20dDlst_shadowSimple_cFP4cXyzffP4cXyzsfP9_GXTexObj */
void dDlst_shadowSimple_c::set(cXyz* pos, f32 y, f32 scaleXZ, cXyz* floorNrm, s16 rotY, f32 scaleZ, GXTexObj* texObj) {
    f32 offsetY = scaleXZ * 16.0f * (1.0f - floorNrm->y) + 1.0f;
    mDoMtx_stack_c::transS(pos->x, y + offsetY, pos->z);
    mDoMtx_stack_c::YrotM(rotY);
    mDoMtx_stack_c::scaleM(scaleXZ, offsetY + offsetY + 16.0f, scaleXZ * scaleZ);
    mDoMtx_concat(j3dSys.getViewMtx(), mDoMtx_stack_c::get(), mVolumeMtx);

    f32 xs = std::sqrtf(1.0f - floorNrm->x * floorNrm->x);
    f32 yy;
    f32 zz;
    if (xs != 0.0f) {
        yy = floorNrm->y * xs;
        zz = -floorNrm->z * xs;
    } else {
        yy = 0.0f;
        zz = 0.0f;
    }

    mDoMtx_stack_c::get()[0][0] = xs;
    mDoMtx_stack_c::get()[0][1] = floorNrm->x;
    mDoMtx_stack_c::get()[0][2] = 0.0f;
    mDoMtx_stack_c::get()[0][3] = pos->x;

    mDoMtx_stack_c::get()[1][0] = -floorNrm->x * yy;
    mDoMtx_stack_c::get()[1][1] = floorNrm->y;
    mDoMtx_stack_c::get()[1][2] = zz;
    mDoMtx_stack_c::get()[1][3] = y;

    mDoMtx_stack_c::get()[2][0] = floorNrm->x * zz;
    mDoMtx_stack_c::get()[2][1] = floorNrm->z;
    mDoMtx_stack_c::get()[2][2] = yy;
    mDoMtx_stack_c::get()[2][3] = pos->z;

    mDoMtx_stack_c::YrotM(rotY);
    mDoMtx_stack_c::scaleM(scaleXZ, 1.0f, scaleXZ * scaleZ);
    mDoMtx_concat(j3dSys.getViewMtx(), mDoMtx_stack_c::get(), mMtx);
    f32 dist = 1.0f - (pos->y - y) * 0.0007f;
    if (dist < 0.0f)
        dist = 0.0f;
    else if (dist > 1.0f)
        dist = 1.0f;
    mAlpha = dist * 64.0f;
    mpTexObj = texObj;
}

/* 80084D48-80084D94       .text init__21dDlst_shadowControl_cFv */
void dDlst_shadowControl_c::init() {
    dDlst_shadowReal_c * pReal = &mReal[0];
    for (s32 i = 0; i < (s32)ARRAY_SIZE(mReal); i++, pReal++)
        pReal->init();
}

/* 80084D94-80084DEC       .text reset__21dDlst_shadowControl_cFv */
void dDlst_shadowControl_c::reset() {
    dDlst_shadowReal_c * pReal = &mReal[0];
    for (s32 i = 0; i < (s32)ARRAY_SIZE(mReal); i++, pReal++)
        pReal->reset();
    mSimpleNum = 0;
}

/* 80084DEC-80084EF0       .text imageDraw__21dDlst_shadowControl_cFPA4_f */
void dDlst_shadowControl_c::imageDraw(Mtx mtx) {
    #include "assets/l_matDL__imageDraw__21dDlst_shadowControl_cFPA4_f.h"

    GXSetViewport(0.0f, 0.0f, 256.0f, 256.0f, 0.0f, 1.0f);
    GXSetScissor(0, 0, 0x100, 0x100);
    GXCallDisplayList(l_matDL, 0x80);
    GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
    GXSetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR);
    GXSetClipMode(GX_CLIP_DISABLE);
    GXSetTexCopySrc(0, 0, 256, 256);
    GXSetTexCopyDst(128, 128, GX_TF_I4, GX_TRUE);
    j3dSys.setDrawModeOpaTexEdge();
    dDlst_shadowReal_c * pReal = &mReal[0];
    for (s32 i = 0; i < (s32)ARRAY_SIZE(mReal); i++, pReal++)
        pReal->imageDraw(mtx);
    GXSetClipMode(GX_CLIP_ENABLE);
}

/* 80084EF0-800850D4       .text draw__21dDlst_shadowControl_cFPA4_f */
void dDlst_shadowControl_c::draw(Mtx drawMtx) {
    j3dSys.reinitGX();
#if VERSION > VERSION_JPN
    GXSetNumIndStages(0);
#endif
    dKy_GxFog_set();
    GXSetChanCtrl(GX_ALPHA0, GX_FALSE, GX_SRC_REG, GX_SRC_REG, 0, GX_DF_NONE, GX_AF_NONE);
    GXSetChanMatColor(GX_ALPHA0, (GXColor){ 0x00, 0x00, 0x00, 0x20 });
    GXSetArray(GX_VA_POS, l_shadowVolPos, sizeof(*l_shadowVolPos));
    GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_POS, GX_TEXMTX0);
    GXSetNumTevStages(1);
    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
    GXLoadPosMtxImm(drawMtx, GX_PNMTX0);
    static GXColor clearColor = { 0x00, 0x00, 0x00, 0x40 };
    clearColor.a = mDoGph_gInf_c::getBackColor().a;
    GXSetTevColor(GX_TEVREG1, clearColor);
    GXSetTevColor(GX_TEVREG2, g_whiteColor);

    dDlst_shadowReal_c* real = &mReal[0];
    for (s32 i = 0; i < 8; real++, i++)
        real->draw();

    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S8, 0);
    GXSetArray(GX_VA_POS, l_simpleShadowPos, sizeof(*l_simpleShadowPos));
    GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
    GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
    GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_OR, GX_ALWAYS, 0);

    dDlst_shadowSimple_c* simple = &mSimple[0];
    for (s32 i = 0; i < mSimpleNum; simple++, i++)
        simple->draw();

    GXSetColorUpdate(GX_TRUE);
    GXSetAlphaUpdate(0);
}

/* 800850D4-80085170       .text setReal__21dDlst_shadowControl_cFUlScP8J3DModelP4cXyzffP12dKy_tevstr_c */
int dDlst_shadowControl_c::setReal(u32 key, s8 shouldFade, J3DModel* model, cXyz* pos, f32 casterSize, f32 heightAboveGround, dKy_tevstr_c* tevstr) {
    if (key != 0) {
        dDlst_shadowReal_c * real = &mReal[0];
        for (s32 i = 0; i < (s32)ARRAY_SIZE(mReal); i++, real++) {
            if (real->isUse() && real->checkKey(key)) {
                return real->set(key, shouldFade, model, pos, casterSize, heightAboveGround, tevstr);
            }
        }
    }

    dDlst_shadowReal_c * real = &mReal[0];
    for (s32 i = 0; i < (s32)ARRAY_SIZE(mReal); i++, real++) {
        if (real->isNoUse()) {
            while (++mNextID == 0) {}
            return real->set(mNextID, shouldFade, model, pos, casterSize, heightAboveGround, tevstr);
        }
    }

    return 0;
}

/* 80085170-8008520C       .text setReal2__21dDlst_shadowControl_cFUlScP8J3DModelP4cXyzffP12dKy_tevstr_c */
int dDlst_shadowControl_c::setReal2(u32 key, s8 shouldFade, J3DModel* model, cXyz* pos, f32 casterSize, f32 heightAboveGround, dKy_tevstr_c* tevstr) {
    if (key != 0) {
        dDlst_shadowReal_c * real = &mReal[0];
        for (s32 i = 0; i < (s32)ARRAY_SIZE(mReal); i++, real++) {
            if (real->isUse() && real->checkKey(key)) {
                return real->set2(key, shouldFade, model, pos, casterSize, heightAboveGround, tevstr);
            }
        }
    }

    dDlst_shadowReal_c * real = &mReal[0];
    for (s32 i = 0; i < (s32)ARRAY_SIZE(mReal); i++, real++) {
        if (real->isNoUse()) {
            while (++mNextID == 0) {}
            return real->set2(mNextID, shouldFade, model, pos, casterSize, heightAboveGround, tevstr);
        }
    }

    return 0;
}

/* 8008520C-80085274       .text addReal__21dDlst_shadowControl_cFUlP8J3DModel */
bool dDlst_shadowControl_c::addReal(u32 key, J3DModel* model) {
    if (key == 0)
        return false;

    dDlst_shadowReal_c * real = &mReal[0];
    for (s32 i = 0; i < (s32)ARRAY_SIZE(mReal); i++, real++) {
        if (real->isUse() && real->checkKey(key)) {
            return real->add(model);
        }
    }

    return false;
}

/* 80085274-800852D8       .text setSimple__21dDlst_shadowControl_cFP4cXyzffP4cXyzsfP9_GXTexObj */
int dDlst_shadowControl_c::setSimple(cXyz* pos, f32 groundY, f32 scaleXZ, cXyz* floor_nrm, s16 rotY, f32 scaleZ, GXTexObj* tex) {
    if (floor_nrm == NULL || mSimpleNum >= ARRAY_SIZE(mSimple))
        return false;

    mSimple[mSimpleNum].set(pos, groundY, scaleXZ, floor_nrm, rotY, scaleZ, tex);
    mSimpleNum++;
    return true;
}

/* 800852D8-80085348       .text setSimpleTex__21dDlst_shadowControl_cFPv */
void dDlst_shadowControl_c::setSimpleTex(void* pImg) {
    GXInitTexObj(&mSimpleTexObj, pImg, 128, 128, GX_TF_I4, GX_CLAMP, GX_CLAMP, GX_FALSE);
    GXInitTexObjLOD(&mSimpleTexObj, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE, GX_ANISO_1);
}

#include "assets/l_mirrorProjMat.h"

/* 80085348-800855B4       .text draw__18dDlst_mirrorPacketFv */
void dDlst_mirrorPacket::draw() {
    j3dSys.reinitGX();
#if VERSION > VERSION_JPN
    GXSetNumIndStages(0);
#endif
    dKy_GxFog_set();

    static GXColor l_color = { 0xFF, 0xFF, 0xFF, 0x40 };
    l_color.a = (mAlpha >> 2) & ~3;
    GXSetTevColor(GX_TEVREG0, l_color);

    l_color.a = mDoGph_gInf_c::getBackColor().a;
    GXSetTevColor(GX_TEVREG1, l_color);

    GXSetTevColor(GX_TEVREG2, g_whiteColor);

    GXCallDisplayList(l_shadowVolMat, 0x40);
    GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_REG, GX_SRC_REG, 0, GX_DF_NONE, GX_AF_NONE);

    GXClearVtxDesc();

    GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
    GXLoadPosMtxImm(j3dSys.getViewMtx(), GX_PNMTX0);
    GXSetArray(GX_VA_POS, l_shadowVolPos, sizeof(cXyz));
    GXLoadPosMtxImm(mPosMtx, GX_PNMTX1);
    GXSetCurrentMtx(GX_PNMTX1);
    GXCallDisplayList(l_shadowVolDL, 0x40);
    GXCallDisplayList(l_frontZMat, 0x20);
    GXCallDisplayList(l_shadowVolDL, 0x40);
    GXCallDisplayList(l_frontNoZSubMat, 0x20);
    GXCallDisplayList(l_shadowVolDL, 0x40);
    GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_POS, GX_TEXMTX0);
    GXCallDisplayList(l_mirrorProjMat, 0x40);
    GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
    GXLoadTexObj(&mTexObj, GX_TEXMAP0);
    GXSetTexCoordScaleManually(GX_TEXCOORD0, GX_TRUE, GXGetTexObjWidth(&mTexObj), GXGetTexObjHeight(&mTexObj));
    GXLoadTexMtxImm(mTexMtx, GX_TEXMTX0, GX_MTX3x4);
    GXClearVtxDesc();
    GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
    GXSetCurrentMtx(0);
    mShadowPoly.draw();
    GXSetTexCoordScaleManually(GX_TEXCOORD0, GX_FALSE, 0, 0);
    GXCallDisplayList(l_clearMat, 0x40);
    GXClearVtxDesc();
    GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
    GXSetCurrentMtx(GX_PNMTX1);
    GXCallDisplayList(l_shadowVolDL, 0x40);
    GXSetColorUpdate(GX_TRUE);
    GXSetAlphaUpdate(GX_FALSE);
#if VERSION > VERSION_JPN
    J3DShape::resetVcdVatCache();
#endif
}

/* 800855B4-80085624       .text init__18dDlst_mirrorPacketFP7ResTIMG */
void dDlst_mirrorPacket::init(ResTIMG* pImg) {
    if (pImg == NULL)
        pImg = (ResTIMG*) dComIfG_getObjectRes("Always", dRes_INDEX_ALWAYS_BTI_SHMREF_e);

    mDoLib_setResTimgObj(pImg, &mTexObj, 0, NULL);
}

/* 80085624-80085808       .text mirrorPolygonCheck__FP4cXyzP4cXyzfP18dDlst_shadowPoly_c */
void mirrorPolygonCheck(cXyz* min_p, cXyz* max_p, f32 rad, dDlst_shadowPoly_c* poly) {
    ShdwDrawPoly_c shdwDraw;

    cXyz min, max;
    if (min_p->x < max_p->x) {
        min.x = min_p->x;
        max.x = max_p->x;
    } else {
        min.x = max_p->x;
        max.x = min_p->x;
    }
    min.x -= rad;
    max.x += rad;

    if (min_p->y < max_p->y) {
        min.y = min_p->y;
        max.y = max_p->y;
    } else {
        min.y = max_p->y;
        max.y = min_p->y;
    }
    min.y -= rad;
    max.y += rad;

    if (min_p->z < max_p->z) {
        min.z = min_p->z;
        max.z = max_p->z;
    } else {
        min.z = max_p->z;
        max.z = min_p->z;
    }
    min.z -= rad;
    max.z += rad;

    shdwDraw.Set(min, max);
    shdwDraw.SetCallback(psdRealCallBack);
    shdwDraw.setCenter(min_p);

    cXyz lightVec = *max_p - *min_p;
    shdwDraw.setLightVec(&lightVec);
    shdwDraw.setPoly(poly);

    dComIfG_Bgsp()->ShdwDraw(&shdwDraw);
}

#if VERSION == VERSION_DEMO
void dDlst_mirrorPacket::update(Mtx mtx, u8 alpha)
#else
/* 80085808-800859DC       .text update__18dDlst_mirrorPacketFPA4_fUcf */
void dDlst_mirrorPacket::update(Mtx mtx, u8 alpha, f32 rad)
#endif
{
    mShadowPoly.mCount = 0;
    static cXyz l_p1Offset(0.0f, 0.0f, 0.0f);
    static cXyz l_p2Offset(0.0f, 0.0f, 10000.0f);

    cXyz offs, offs2;
    mDoMtx_multVec(mtx, &l_p1Offset, &offs);
    mDoMtx_multVec(mtx, &l_p2Offset, &offs2);
#if VERSION == VERSION_DEMO
    mirrorPolygonCheck(&offs, &offs2, 60.0f, &mShadowPoly);
#else
    mirrorPolygonCheck(&offs, &offs2, rad, &mShadowPoly);
#endif

    Mtx viewMtx;
    mDoMtx_lookAt(viewMtx, &offs, &offs2, 0);
    C_MTXLightOrtho(mTexMtx, 24.0f, -24.0f, -24.0f, 24.0f, 0.5f, -0.5f, 0.5f, 0.5f);
    mDoMtx_concat(mTexMtx, viewMtx, mTexMtx);
    C_MTXOrtho(mPosMtx, 24.0f, -24.0f, -24.0f, 24.0f, 1.0f, 10000.0f);
    mDoMtx_inverse(viewMtx, mDoMtx_stack_c::get());
    mDoMtx_inverse(mPosMtx, viewMtx);
    viewMtx[2][3] = 0.0f;
    mDoMtx_stack_c::concat(viewMtx);
    mDoMtx_stack_c::scaleM(1.0f, 1.0f, -0.003f);
    mDoMtx_concat(j3dSys.getViewMtx(), mDoMtx_stack_c::get(), mPosMtx);
    mAlpha = alpha;
}

/* 800859DC-80085AF4       .text draw__20dDlst_alphaVolPacketFv */
void dDlst_alphaVolPacket::draw() {
    GXSetChanCtrl(GX_ALPHA0, GX_FALSE, GX_SRC_REG, GX_SRC_REG, 0, GX_DF_NONE, GX_AF_NONE);
    GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_OR, GX_ALWAYS, 0);
    GXSetTevColor(GX_TEVREG0, g_whiteColor);
    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
    GXClearVtxDesc();
    GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
    GXSetArray(GX_VA_POS, l_simpleShadowPos, sizeof(*l_simpleShadowPos));
    GXLoadPosMtxImm(mtx, GX_PNMTX0);
    GXSetCurrentMtx(GX_PNMTX0);
    GXCallDisplayList(l_frontMat, 0x40);
    GXCallDisplayList(l_shadowVolumeDL, 0x40);
    GXCallDisplayList(l_backSubMat, 0x20);
    GXCallDisplayList(l_shadowVolumeDL, 0x40);
    GXSetColorUpdate(GX_TRUE);
    GXSetAlphaUpdate(GX_FALSE);
#if VERSION > VERSION_JPN
    J3DShape::resetVcdVatCache();
#endif
}

/* 80085AF4-80085BBC       .text draw__23dDlst_alphaInvVolPacketFv */
void dDlst_alphaInvVolPacket::draw() {
    #include "assets/l_backMat__draw__23dDlst_alphaInvVolPacketFv.h"

    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
    GXClearVtxDesc();
    GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
    GXSetArray(GX_VA_POS, l_simpleShadowPos, sizeof(*l_simpleShadowPos));
    GXLoadPosMtxImm(mtx, GX_PNMTX0);
    GXSetCurrentMtx(GX_PNMTX0);
    GXSetTevColor(GX_TEVREG0, g_whiteColor);
    GXCallDisplayList(l_backMat, 0x60);
    GXCallDisplayList(l_shadowVolumeDL, 0x40);
    GXSetColorUpdate(GX_TRUE);
    GXSetAlphaUpdate(GX_FALSE);
#if VERSION > VERSION_JPN
    J3DShape::resetVcdVatCache();
#endif
}

/* 80085BBC-80085BFC       .text newData__13dDlst_peekZ_cFssPUl */
int dDlst_peekZ_c::newData(s16 x, s16 y, u32* pDst) {
    if (mCount >= 0x40)
        return 0;

    dDlst_peekZ_entry *pEntry = &mEntries[mCount];
    pEntry->x = x;
    pEntry->y = y;
    pEntry->dst = pDst;
    mCount++;
    return 1;
}

/* 80085BFC-80085C6C       .text peekData__13dDlst_peekZ_cFv */
void dDlst_peekZ_c::peekData() {
    dDlst_peekZ_entry * pEntry = &mEntries[0];
    for (s32 i = 0; i < mCount; pEntry++, i++)
        GXPeekZ(pEntry->x, pEntry->y, pEntry->dst);
    mCount = 0;
}

/* 80085C6C-80085D74       .text __ct__12dDlst_list_cFv */
dDlst_list_c::dDlst_list_c() {
    mpCopy2DEnd = &mpCopy2DArr[ARRAY_SIZE(mpCopy2DArr)];
    mp2DOpaTopEnd = &mp2DOpaTopArr[ARRAY_SIZE(mp2DOpaTopArr)];
    mp2DOpaEnd = &mp2DOpaArr[ARRAY_SIZE(mp2DOpaArr)];
    mp2DXluEnd = &mp2DXluArr[ARRAY_SIZE(mp2DXluArr)];
    mpOpaListSky = NULL;
    mpXluListSky = NULL;
    mpOpaListP0 = NULL;
    mpOpaListP1 = NULL;
    mpXluListP1 = NULL;
    mpOpaListBG = NULL;
    mpXluListBG = NULL;
    mpOpaList = NULL;
    mpXluList = NULL;
    mpOpaListFilter = NULL;
    mpOpaListMaskOff = NULL;
    mpXluListMaskOff = NULL;
    mpOpaListInvisible = NULL;
    mpXluListInvisible = NULL;
    mpOpaList2D = NULL;
    mpAlphaModel = NULL;
    mpSpotModel = NULL;
}

/* 80085F6C-800861F4       .text init__12dDlst_list_cFv */
bool dDlst_list_c::init() {
    mpOpaListSky = J3DDrawBuffer__create(0x20);
    mpXluListSky = J3DDrawBuffer__create(0x20);
    mpOpaListP0 = J3DDrawBuffer__create(1);
    mpOpaListP1 = J3DDrawBuffer__create(0x20);
    mpXluListP1 = J3DDrawBuffer__create(0x20);
    mpOpaListBG = J3DDrawBuffer__create(0x80);
    mpXluListBG = J3DDrawBuffer__create(0x80);
    mpOpaList = J3DDrawBuffer__create(0x100);
    mpXluList = J3DDrawBuffer__create(0x100);
    mpOpaListFilter = J3DDrawBuffer__create(0x20);
    mpOpaListMaskOff = J3DDrawBuffer__create(0x20);
    mpXluListMaskOff = J3DDrawBuffer__create(0x100);
    mpOpaListInvisible = J3DDrawBuffer__create(0x20);
    mpXluListInvisible = J3DDrawBuffer__create(0x20);
    mpOpaList2D = J3DDrawBuffer__create(1);

    if (mpOpaListSky == NULL || mpXluListSky == NULL || mpOpaListP0 == NULL || mpOpaListP1 == NULL || mpXluListP1 == NULL || mpOpaListBG == NULL || mpXluListBG == NULL || mpOpaList == NULL || mpXluList == NULL || mpOpaListFilter == NULL || mpOpaListMaskOff == NULL || mpXluListMaskOff == NULL || mpOpaListInvisible == NULL || mpXluListInvisible == NULL || mpOpaList2D == NULL)
        return false;

    mpOpaListSky->setNonSort();
    mpXluListSky->setNonSort();
    mpOpaListP0->setNonSort();
    mpOpaListP1->setNonSort();
    mpXluListP1->setNonSort();
    mpXluListBG->setNonSort();
    mpXluList->setZSort();
    mpOpaListFilter->setZSort();
    mpXluListMaskOff->setZSort();
    mpXluListInvisible->setZSort();
    mpOpaList2D->setNonSort();
    setOpaList();
    setXluList();
    mpCopy2D = &mpCopy2DArr[0];
    mp2DOpaTop = &mp2DOpaTopArr[0];
    mp2DOpa = &mp2DOpaArr[0];
    mp2DXlu = &mp2DXluArr[0];
    mShadowControl.init();
    mpAlphaModel = dDlst_alphaModel_c::create(0x40);
    mpSpotModel = dDlst_alphaModel_c::create(0x08);
    mpLightModel = dDlst_alphaModel_c::create(0x10);

    if (mpAlphaModel == NULL || mpSpotModel == NULL || mpLightModel == NULL)
        return false;

    return true;
}

/* 800861F4-80086368       .text __dt__12dDlst_list_cFv */
dDlst_list_c::~dDlst_list_c() {
    delete mpOpaListSky;
    delete mpXluListSky;
    delete mpOpaListP0;
    delete mpOpaListP1;
    delete mpXluListP1;
    delete mpOpaListBG;
    delete mpXluListBG;
    delete mpOpaList;
    delete mpXluList;
    delete mpOpaListFilter;
    delete mpOpaListMaskOff;
    delete mpXluListMaskOff;
    delete mpOpaListInvisible;
    delete mpXluListInvisible;
    delete mpOpaList2D;
    if (mpAlphaModel != NULL)
        delete mpAlphaModel;
    if (mpSpotModel != NULL)
        delete mpSpotModel;
}

/* 80086368-80086490       .text reset__12dDlst_list_cFv */
void dDlst_list_c::reset() {
    mpOpaListSky->frameInit();
    mpXluListSky->frameInit();
    mpOpaListP0->frameInit();
    mpOpaListP1->frameInit();
    mpXluListP1->frameInit();
    mpOpaListBG->frameInit();
    mpXluListBG->frameInit();
    mpOpaList->frameInit();
    mpXluList->frameInit();
    mpOpaListFilter->frameInit();
    mpOpaListMaskOff->frameInit();
    mpXluListMaskOff->frameInit();
    mpOpaListInvisible->frameInit();
    mpXluListInvisible->frameInit();
    mpOpaList2D->frameInit();
    setOpaList();
    setXluList();
    mpCopy2D = &mpCopy2DArr[0];
    mp2DOpaTop = &mp2DOpaTopArr[0];
    mp2DOpa = &mp2DOpaArr[0];
    mp2DXlu = &mp2DXluArr[0];
    dComIfGd_resetAlphaModel();
    dComIfGd_resetSpotModel();
    dComIfGd_resetLightModel();
    mShadowControl.reset();
    for (u32 i = 0; i < ARRAY_SIZE(m3DLineMatSortPacket); i++)
        m3DLineMatSortPacket[i].reset();
}

/* 80086490-80086540       .text entryZSortXluDrawList__12dDlst_list_cFP13J3DDrawBufferP9J3DPacketR4cXyz */
void dDlst_list_c::entryZSortXluDrawList(J3DDrawBuffer* pBuffer, J3DPacket* pPacket, cXyz& pos) {
    f32 z = -J3DCalcZValue(j3dSys.getViewMtx(), pos);
    u16 idx;
    if (40.058594f < z) {
        if (9960.941f > z) {
            idx = z / 39.058594f;
        } else {
            idx = 0xFF;
        }
    } else {
        idx = 0;
    }

    idx = 0xFF - idx;
    pBuffer->entryImm(pPacket, idx);
}

/* 80086540-80086570       .text set__12dDlst_list_cFRPP12dDlst_base_cRPP12dDlst_base_cP12dDlst_base_c */
bool dDlst_list_c::set(dDlst_base_c**& pList, dDlst_base_c**& pEnd, dDlst_base_c* pItem) {
    if (pList >= pEnd)
        return false;

    *pList = pItem;
    pList++;
    return true;
}

/* 80086570-800865C8       .text draw__12dDlst_list_cFPP12dDlst_base_cPP12dDlst_base_c */
void dDlst_list_c::draw(dDlst_base_c** pList, dDlst_base_c** pEnd) {
    for (; pList < pEnd; pList++)
        (*pList)->draw();
}

ResTIMG* dDlst_list_c::mToonImage;
ResTIMG* dDlst_list_c::mToonExImage;

GXColor dDlst_list_c::mWipeColor = { 0, 0, 0, 0 };
bool dDlst_list_c::mWipe;
f32 dDlst_list_c::mWipeRate = 0.0f;
f32 dDlst_list_c::mWipeSpeed = 0.0f;
dDlst_2DT2_c dDlst_list_c::mWipeDlst;

/* 800865C8-800866C8       .text wipeIn__12dDlst_list_cFfR8_GXColor */
void dDlst_list_c::wipeIn(f32 speed, GXColor& color) {
    mWipe = true;
    mWipeSpeed = speed;
    mWipeColor = color;
    if (speed >= 0.0f) {
        mWipeRate = 0.0f;
    } else {
        mWipeRate = 1.0f;
    }
    ResTIMG* texture = (ResTIMG*)JKRGetResource('TIMG', "wipe_00.bti", dComIfGp_getMenuArchive());
    JUT_ASSERT(VERSION_SELECT(5679, 5679, 5687, 5687), texture != NULL);
    mWipeDlst.init(texture, -9.0f, -21.0f, 659.0f, 524.0f, 0, 1, 1, 2.0f, 2.436f);
}

/* 800866C8-800866F0       .text wipeIn__12dDlst_list_cFf */
void dDlst_list_c::wipeIn(f32 time) {
    wipeOut(time, g_blackColor);
}

/* 800866F0-80086790       .text calcWipe__12dDlst_list_cFv */
void dDlst_list_c::calcWipe() {
    if (mWipe) {
        mWipeRate += mWipeSpeed;
        if (mWipeRate < 0.0f) {
            mWipeRate = 0.0f;
        } else {
            if (mWipeRate > 1.0f) {
                mWipeRate = 1.0f;
                mWipe = false;
            }
        }

        mWipeDlst.mScrollS = mWipeRate * 2.0f;
        mWipeDlst.mScrollT = mWipeDlst.mScrollS * 1.218f;
        dComIfGd_set2DXlu(&mWipeDlst);
    }
}

/* 80086790-8008696C       .text dDlst_texSpecmapST__FPC4cXyzPC12dKy_tevstr_cP12J3DModelDataf */
void dDlst_texSpecmapST(const cXyz* pos, const dKy_tevstr_c* tevStr, J3DModelData* modelData, f32 scale) {
    static Mtx mtx_adj = {
        0.5f, 0.0f, 0.0f, 0.5f,
        0.0f, -0.5f, 0.0f, 0.5f,
        0.0f, 0.0f, 1.0f, 0.0f,
    };

    f32 inv = 1.0f / scale;
    camera_class * camera = dCam_getCamera();
    cXyz lookDir = *pos - camera->view.mLookat.mEye;
    cXyz refl;
    cXyz lightDir;

    dKyr_get_vectle_calc((cXyz*)&tevStr->mLightPosWorld, (cXyz*)pos, &lightDir);

    C_VECHalfAngle(&lookDir, &lightDir, &refl);
    Mtx reflMtx, effMtx;
    C_MTXLookAt(reflMtx, &cXyz::Zero, &cXyz::BaseY, &refl);
    MTXScale(effMtx, inv, inv, 1.0f);
    MTXConcat(effMtx, mtx_adj, effMtx);
    MTXConcat(effMtx, reflMtx, effMtx);
    effMtx[0][3] = 0.0f;
    effMtx[1][3] = 0.0f;
    effMtx[2][3] = 0.0f;

    s32 materialNum = modelData->getMaterialNum();
    for (s32 i = 0; i < materialNum; i++) {
        J3DMaterial* mat = modelData->getMaterialNodePointer(i);
        for (s32 j = 0; j < 8; j++) {
            J3DTexMtx* texMtx = mat->getTexMtx(j);
            if (texMtx != NULL && texMtx->getTexMtxInfo().mInfo == 10) {
                texMtx->getTexMtxInfo().setEffectMtx(effMtx);
            }
        }
    }
}
