diff --git a/include/JSystem/JGadget/define.h b/include/JSystem/JGadget/define.h index 0f6d4f3..2417792 100644 --- a/include/JSystem/JGadget/define.h +++ b/include/JSystem/JGadget/define.h @@ -31,6 +31,10 @@ extern "C" #ifdef JGADGET_DEBUG +#define JGADGET_WARN(msg) \ + (JGadget_outMessage(JGadget_outMessage::warning, __FILE__, __LINE__) \ + << (msg)) + #define JGADGET_ASSERTWARN(cond) \ ((cond) || ((JGadget_outMessage(JGadget_outMessage::warning, __FILE__, __LINE__) << (#cond)), false)) @@ -46,6 +50,8 @@ extern "C" #else +#define JGADGET_WARN(msg) ((void)0) + #define JGADGET_ASSERTWARN(cond) \ ((cond) || (false)) @@ -65,4 +71,4 @@ extern "C" } #endif -#endif \ No newline at end of file +#endif diff --git a/include/JSystem/JGadget/std-list.h b/include/JSystem/JGadget/std-list.h index 3fb3fb0..3e3848d 100644 --- a/include/JSystem/JGadget/std-list.h +++ b/include/JSystem/JGadget/std-list.h @@ -13,8 +13,8 @@ namespace JGadget { template > struct TList { struct TNode_ { - TNode_ *pPrev_; TNode_ *pNext_; + TNode_ *pPrev_; }; class iterator { @@ -23,21 +23,31 @@ struct TList { iterator(TNode_* node) { this->p_ = node; } iterator& operator++() { - this->p_ = this->p_->getNext(); + this->p_ = this->p_->pNext_; return *this; } iterator& operator--() { - this->p_ = this->p_->getPrev(); + this->p_ = this->p_->pPrev_; return *this; } - TNode_& operator*() const { + T& operator*() const { JGADGET_ASSERT(p_!=0); - return *this->p_; + return *(T*)(this->p_ + 1); } - TNode_* operator->() const { return this->p_; } + T* operator->() const { + return (T*)(this->p_ + 1); + } + + friend bool operator==(const iterator& a, const iterator& b) { + return a.p_ == b.p_; + } + + friend bool operator!=(const iterator& a, const iterator& b) { + return a.p_ != b.p_; + } TNode_* p_; }; @@ -48,42 +58,128 @@ struct TList { const_iterator(iterator it) { this->p_ = it.p_; } const const_iterator& operator++() { - this->p_ = this->p_->getNext(); + this->p_ = this->p_->pNext_; return *this; } const const_iterator& operator--() { - this->p_ = this->p_->getPrev(); + this->p_ = this->p_->pPrev_; return *this; } - const TNode_* operator->() const { return this->p_; } + const T& operator*() const { + JGADGET_ASSERT(p_!=0); + return *(const T*)(this->p_ + 1); + } + + const T* operator->() const { + return (const T*)(this->p_ + 1); + } + + friend bool operator==(const const_iterator& a, const const_iterator& b) { + return a.p_ == b.p_; + } + + friend bool operator!=(const const_iterator& a, const const_iterator& b) { + return a.p_ != b.p_; + } const TNode_* p_; }; - TList(const TAllocator &allocator=0) { + ~TList() { clear(); } + + TList(const TAllocator& alloc = TAllocator()) + { + oAllocator_ = alloc; oSize_ = 0; - Initialize_(); - } + Initialize_(); + } void Initialize_() { - oEnd_.pNext_ = &this->oNode_; - oEnd_.pPrev_ = &this->oNode_; + oEnd_.pNext_ = &this->oEnd_; + oEnd_.pPrev_ = &this->oEnd_; + } + + TNode_* CreateNode_(TNode_* pNext, TNode_* pPrev, const T& value) + { + JGADGET_ASSERT(pNext!=0); + JGADGET_ASSERT(pPrev!=0); + + void* raw = oAllocator_.AllocateRaw(sizeof(TNode_) + sizeof(T)); + + if (raw == nullptr) { + JGADGET_WARN("can't allocate memory"); + return nullptr; + } + + TNode_* const ret = (TNode_*)raw; + + ret->pNext_ = pNext; + ret->pPrev_ = pPrev; + oAllocator_.construct((T*)(ret + 1), value); + return ret; } void DestroyNode_(TNode_ *p) { - // probably doesn't match JGADGET_ASSERT(p!=0); JGADGET_ASSERT(p!=&oEnd_); JGADGET_ASSERT(p->pNext_->pPrev_!=p); JGADGET_ASSERT(p->pPrev_->pNext_!=p); - oAllocator_.destroy(p + 1); + + oAllocator_.destroy((T*)(p + 1)); oAllocator_.DeallocateRaw(p); } - iterator end() {return &this->oNode_; } - const_iterator end() const { return &this->oNode_; } + iterator insert(iterator where, const T& what) + { + TNode_* const pNext = where.p_; + JGADGET_ASSERT(pNext!=0); + + TNode_* const pPrev = pNext->pPrev_; + + TNode_* const newNode = CreateNode_(pNext, pPrev, what); + + if (newNode == nullptr) { + return end(); + } + + pNext->pPrev_ = newNode; + pPrev->pNext_ = newNode; + ++oSize_; + return iterator(newNode); + } + + iterator erase(iterator what) + { + TNode_* p = what.p_; + TNode_* next = p->pNext_; + p->pPrev_->pNext_ = next; + next->pPrev_ = p->pPrev_; + DestroyNode_(p); + oSize_--; + return iterator(next); + } + + iterator erase(iterator start, iterator end) + { + while (start != end) { + start = erase(start); + } + return start; + } + + void push_back(const T& what) { + insert(end(), what); + } + + iterator begin() { return iterator(oEnd_.pNext_); } + const_iterator begin() const { return const_iterator(oEnd_.pNext_); } + + iterator end() { return iterator(&this->oEnd_); } + const_iterator end() const { return const_iterator(&this->oEnd_); } + + iterator clear() { return erase(begin(), end()); } private: TAllocator oAllocator_; // 0 @@ -93,6 +189,4 @@ struct TList { } - - #endif diff --git a/include/JSystem/JGadget/std-memory.h b/include/JSystem/JGadget/std-memory.h index 7493e7b..01b6a3e 100644 --- a/include/JSystem/JGadget/std-memory.h +++ b/include/JSystem/JGadget/std-memory.h @@ -18,12 +18,23 @@ struct TAllocator { DeallocateRaw(mem); } - void DeallocateRaw(T* mem) { + void DeallocateRaw(void* mem) { delete mem; } + void construct(T* p, const T& value) + { + // clang-format off + JGADGET_ASSERT(p!=0); + // clang-format on + (void)::new (p) T(value); + } + void destroy(T* p) { - JUT_ASSERT(p!=0); + // clang-format off + JGADGET_ASSERT(p!=0); + // clang-format on + p->~T(); } u8 mAllocator; // 00 diff --git a/include/Kaneshige/ViewCtrlModel.h b/include/Kaneshige/ViewCtrlModel.h index 3c19527..2588603 100644 --- a/include/Kaneshige/ViewCtrlModel.h +++ b/include/Kaneshige/ViewCtrlModel.h @@ -28,6 +28,7 @@ class ViewCtrlModel : public ExModel void setDetailFlg() { mFlags |= 0x10; } void setVisibleAll() { mFlags |= 0xf; } void setVisible(u32 cnsNo) { mFlags |= (1 << cnsNo); } + u8 getFlags() const { return mFlags; } private: u8 mFlags; // 0x8c diff --git a/include/Osako/shadowMgr.h b/include/Osako/shadowMgr.h index 91305ac..803bd60 100644 --- a/include/Osako/shadowMgr.h +++ b/include/Osako/shadowMgr.h @@ -3,10 +3,12 @@ #include "JSystem/JUtility/TColor.h" #include "JSystem/JGadget/std-list.h" +#include "JSystem/JKernel/JKRDisposer.h" #include "Osako/shadowModel.h" #include "types.h" -class ShadowManager { +class ShadowManager : public JKRDisposer +{ public: ShadowManager(); @@ -49,16 +51,31 @@ class ShadowManager { return 0xff; } + JUTColor getShadowColor() { + return mShadowColor; + } + + u8 getDepth(int index) { + return mDepth[index]; + } + + u8 getDepthMode() { + return mDepthMode; + } + static ShadowManager* mspShadowManager; -//private: - u8 _00[0x58]; +private: + List _18; + List _28; + List _38; + List _48; + JUTColor mShadowColor; u8 mDepth[2]; u8 mDepthMode; u8 _5f; bool mIsMirror; - u8 _61[3]; // i thought operator new always gets aligned by 4? }; // Size: 0x64 #endif // SHADOWMGR_H diff --git a/include/Osako/shadowModel.h b/include/Osako/shadowModel.h index 9c55c0e..df5855f 100644 --- a/include/Osako/shadowModel.h +++ b/include/Osako/shadowModel.h @@ -24,6 +24,11 @@ class ShadowModel : public ViewCtrlModel _95 = 0; } + ShadowKind getShadowKind() const { return mKind; } + u8 getAlpha() const { return _94; } + u8 getFlag95() const { return _95; } + void setFlag95(bool flag) { _95 = flag; } + virtual bool createModel(JKRSolidHeap *, u32, u32); // 0x801f7154, override private: ShadowKind mKind; diff --git a/src/Osako/shadowMgr.cpp b/src/Osako/shadowMgr.cpp index e69de29..f19462f 100644 --- a/src/Osako/shadowMgr.cpp +++ b/src/Osako/shadowMgr.cpp @@ -0,0 +1,173 @@ +#include "Osako/shadowMgr.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "JSystem/J3D/J3DColorBlock.h" +#include "Dolphin/os.h" +#include "Dolphin/gx.h" + +ShadowManager* ShadowManager::mspShadowManager = nullptr; + +ShadowManager::ShadowManager() : mShadowColor(0x00, 00, 0x14, 0x50) +{ + mDepthMode = 0; + _5f = 0; + mIsMirror = false; + mDepth[0] = 0x40; + mDepth[1] = 0x18; +} + +ShadowManager::List &ShadowManager::getShadowModelList(ShadowModel::ShadowKind shadowKind) +{ + switch (shadowKind) { + case ShadowModel::cShadowKind_Kart: + return _18; + case ShadowModel::cShadowKind_Geo: + return _28; + case ShadowModel::cShadowKind_2: + return _38; + case ShadowModel::cShadowKind_SkyShip: + return _48; + default: + #line 57 + JUT_ASSERT_F(false, "%s", "Regist error!"); + return _18; + } +} + +void ShadowManager::regist(ShadowModel* pModel) +{ + #line 68 + JUT_ASSERT_F(pModel != nullptr, "%s", "pModel != 0"); + + ShadowModel::ShadowKind kind = pModel->getShadowKind(); + List& modelList = getShadowModelList(kind); + + modelList.push_back(pModel); +} + +void ShadowManager::draw(u32 viewNo, List& modelList) { + if (_5f == 0) { + return; + } + + // Setup initial GX state + GXSetZMode(GX_TRUE, GX_GEQUAL, GX_FALSE); + GXSetNumTexGens(0); + GXSetNumTevStages(1); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); + GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR); + GXSetNumChans(1); + GXSetChanCtrl(GX_ALPHA0, GX_FALSE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); + GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0); + GXSetZCompLoc(GX_TRUE); + GXSetColorUpdate(GX_FALSE); + GXSetAlphaUpdate(GX_TRUE); + GXSetDstAlpha(GX_DISABLE, 0); + + List::iterator it = modelList.begin(); + List::const_iterator itEnd = modelList.end(); + + for (; it != itEnd; ++it) { + (*it)->setCurrentViewNo(viewNo); + + if (((*it)->getFlags() & 0xF) != 0 && (*it)->getFlag95() != 0) { + J3DModelData* pModelData = (*it)->getModelData(); + J3DModel* pJ3DModel = (*it)->getModel(); + u32 numShapes = pModelData->getShapeNum(); + + // Calculate alpha value + u8 alphaValue = (mDepth[mDepthMode] * (*it)->getAlpha()) / 0xFF; + + if (mDepthMode == 1) { + J3DMaterial* pMat = pModelData->getMaterialNodePointer(0); + u8 matAlpha = pMat->getColorBlock()->getMatColor(0)->a; + alphaValue = (alphaValue * matAlpha) / 0xFF & 0xFC; + } + + // Set material color + JUTColor chanColor = JUTColor(0, 0, 0, alphaValue); + GXSetChanMatColor(GX_COLOR0A0, chanColor); + + // First pass + GXSetBlendMode(GX_BM_SUBTRACT, GX_BL_ONE, GX_BL_ONE, GX_LO_NOOP); + + if ((mDepthMode == 1 && !mIsMirror) || (mDepthMode == 0 && mIsMirror)) { + GXSetCullMode(GX_CULL_BACK); + } else { + GXSetCullMode(GX_CULL_FRONT); + } + + for (u16 i = 0; i < numShapes; i++) { + pJ3DModel->getShapePacket(i)->draw(); + } + + // Second pass + GXSetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_NOOP); + + if ((mDepthMode == 1 && !mIsMirror) || (mDepthMode == 0 && mIsMirror)) { + GXSetCullMode(GX_CULL_FRONT); + } else { + GXSetCullMode(GX_CULL_BACK); + } + + for (u16 i = 0; i < numShapes; i++) { + pJ3DModel->getShapePacket(i)->draw(); + } + } + } + + // Restore GX state + GXSetColorUpdate(GX_TRUE); + setDstAlpha(); + GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); +} + +void ShadowManager::calc() +{ + for (u8 i = 0; i < 4; i++) { + List& modelList = getShadowModelList((ShadowModel::ShadowKind)i); + + List::iterator it = modelList.begin(); + List::const_iterator itEnd = modelList.end(); + + for (; it != itEnd; ++it) { + if (((*it)->getFlags() & 0xF) != 0) { + (*it)->calc(); + (*it)->setFlag95(true); + } else { + (*it)->setFlag95(false); + } + } + } + + if (_5f == 0) { + _5f += 1; + } +} + +void ShadowManager::viewCalc(u32 viewNo) +{ + for (u8 i = 0; i < 4; i++) { + List& modelList = getShadowModelList((ShadowModel::ShadowKind)i); + + List::const_iterator itEnd = modelList.end(); + List::iterator it = modelList.begin(); + + for (; it != itEnd; ++it) { + if (((*it)->getFlags() & 0xF) != 0) { + (*it)->viewCalc(viewNo); + } + } + } +} + +void ShadowManager::setDstAlpha() +{ + // Enable alpha updates + GXSetAlphaUpdate(GX_TRUE); + + // u8 alphaValue = (mDepthMode == 1) ? 0xff - (mDepth[1] & 0xfc) : 0xff; + u8 alphaValue = getDstAlpha(); + + // Set destination alpha + GXSetDstAlpha(GX_ENABLE, alphaValue); +} diff --git a/src/Osako/shadowScr.cpp b/src/Osako/shadowScr.cpp index 93a6dd2..b60dcf9 100644 --- a/src/Osako/shadowScr.cpp +++ b/src/Osako/shadowScr.cpp @@ -19,7 +19,7 @@ void ShadowScreen::draw() { ShadowManager *shadowMgr = ShadowManager::ptr(); - u8 mode = shadowMgr->mDepthMode; + u8 mode = shadowMgr->getDepthMode(); switch (mode) { case 1: @@ -33,7 +33,7 @@ void ShadowScreen::draw() GXSetCurrentMtx(0); GXSetProjection(mProjMtx, GX_ORTHOGRAPHIC); GXSetNumChans(1); - GXSetChanMatColor(GX_COLOR0A0, shadowMgr->mShadowColor); + GXSetChanMatColor(GX_COLOR0A0, shadowMgr->getShadowColor()); GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_REG, GX_SRC_REG, 0, GX_DF_NONE, GX_AF_NONE); GXSetZMode(GX_FALSE, GX_NEVER, GX_FALSE); @@ -58,14 +58,14 @@ void ShadowScreen::draw() GXEnd(); break; case 1: - GXColorS10 color = {0, 0, 0, (shadowMgr->mDepth[1] & 0xfc) - 0xff}; + GXColorS10 color = {0, 0, 0, (shadowMgr->getDepth(1) & 0xfc) - 0xff}; GXSetNumTevStages(1); GXSetNumTexGens(1); GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 60, GX_FALSE, 125); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); GXSetTevColorS10(GX_TEVREG0, color); - GXSetTevColor(GX_TEVREG1, shadowMgr->mShadowColor); + GXSetTevColor(GX_TEVREG1, shadowMgr->getShadowColor()); GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_C1); 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_ZERO, GX_CA_A0); @@ -90,4 +90,4 @@ void ShadowScreen::draw() GXEnd(); break; } -} \ No newline at end of file +}