diff --git a/.gitignore b/.gitignore index e17f9ebe..47d4afcc 100644 --- a/.gitignore +++ b/.gitignore @@ -397,6 +397,3 @@ FodyWeavers.xsd # JetBrains Rider *.sln.iml - -# Don't ignore resources -!UnleashedRecomp/res/[Ww][Ii][Nn]32/ diff --git a/UnleashedRecomp/api/CSD/Manager/csdmBase.h b/UnleashedRecomp/api/CSD/Manager/csdmBase.h new file mode 100644 index 00000000..39eff13d --- /dev/null +++ b/UnleashedRecomp/api/CSD/Manager/csdmBase.h @@ -0,0 +1,8 @@ +#pragma once + +namespace Chao::CSD +{ + class CBase + { + }; +} diff --git a/UnleashedRecomp/api/CSD/Manager/csdmNode.h b/UnleashedRecomp/api/CSD/Manager/csdmNode.h new file mode 100644 index 00000000..3bba6c33 --- /dev/null +++ b/UnleashedRecomp/api/CSD/Manager/csdmNode.h @@ -0,0 +1,31 @@ +#pragma once + +#include "SWA.inl" +#include "CSD/Manager/csdmBase.h" +#include "CSD/Manager/csdmResourceBase.h" +#include "CSD/Manager/csdmNodeObserver.h" +#include "CSD/Manager/csdmSubjectBase.h" + +namespace Chao::CSD +{ + struct Node; + + class CNode : public CResourceBase, SubjectBase, CBase + { + public: + SWA_INSERT_PADDING(0x4C); + + ~CNode() override = default; + + void SetText(const char* in_pText); + void SetText(const wchar_t* in_pText); + Hedgehog::Math::CVector2 GetPosition() const; + void SetPosition(float in_X, float in_Y); + void SetHideFlag(uint32_t in_HideFlag); + void SetRotation(float in_Rotation); + void SetScale(float in_X, float in_Y); + void SetPatternIndex(uint32_t in_PatternIndex); + }; +} + +#include "CSD/Manager/csdmNode.inl" diff --git a/UnleashedRecomp/api/CSD/Manager/csdmNode.inl b/UnleashedRecomp/api/CSD/Manager/csdmNode.inl new file mode 100644 index 00000000..4cca9069 --- /dev/null +++ b/UnleashedRecomp/api/CSD/Manager/csdmNode.inl @@ -0,0 +1,46 @@ +#include "SWA.inl" + +namespace Chao::CSD +{ + inline void CNode::SetText(const char* in_pText) + { + GuestToHostFunction(0x830BF640, this, in_pText); + } + + inline void CNode::SetText(const wchar_t* in_pText) + { + GuestToHostFunction(0x830BF640, this, in_pText); + } + + inline Hedgehog::Math::CVector2 CNode::GetPosition() const + { + Hedgehog::Math::CVector2 position; + GuestToHostFunction(0x830BF008, this, &position); + return position; + } + + inline void CNode::SetPosition(float in_X, float in_Y) + { + GuestToHostFunction(0x830BF078, this, in_X, in_Y); + } + + inline void CNode::SetHideFlag(uint32_t in_HideFlag) + { + GuestToHostFunction(0x830BF080, this, in_HideFlag); + } + + inline void CNode::SetRotation(float in_Rotation) + { + GuestToHostFunction(0x830BF088, this, in_Rotation); + } + + inline void CNode::SetScale(float in_X, float in_Y) + { + GuestToHostFunction(0x830BF090, this, in_X, in_Y); + } + + inline void CNode::SetPatternIndex(uint32_t in_PatternIndex) + { + GuestToHostFunction(0x830BF300, this, in_PatternIndex); + } +} diff --git a/UnleashedRecomp/api/CSD/Manager/csdmNodeObserver.h b/UnleashedRecomp/api/CSD/Manager/csdmNodeObserver.h new file mode 100644 index 00000000..19fcf3cb --- /dev/null +++ b/UnleashedRecomp/api/CSD/Manager/csdmNodeObserver.h @@ -0,0 +1,12 @@ +#pragma once + +#include "CSD/Manager/csdmObserverBase.h" + +namespace Chao::CSD +{ + class CNode; + + class CNodeObserver : public CObserverBase + { + }; +} diff --git a/UnleashedRecomp/api/CSD/Manager/csdmObserverBase.h b/UnleashedRecomp/api/CSD/Manager/csdmObserverBase.h new file mode 100644 index 00000000..1cec107e --- /dev/null +++ b/UnleashedRecomp/api/CSD/Manager/csdmObserverBase.h @@ -0,0 +1,15 @@ +#pragma once + +#include "SWA.inl" + +namespace Chao::CSD +{ + template + class CObserverBase + { + public: + SWA_INSERT_PADDING(0x0C); + + virtual ~CObserverBase() = default; + }; +} diff --git a/UnleashedRecomp/api/CSD/Manager/csdmProject.h b/UnleashedRecomp/api/CSD/Manager/csdmProject.h new file mode 100644 index 00000000..ed01cd3b --- /dev/null +++ b/UnleashedRecomp/api/CSD/Manager/csdmProject.h @@ -0,0 +1,31 @@ +#pragma once + +#include "SWA.inl" +#include "CSD/Manager/csdmBase.h" +#include "CSD/Manager/csdmResourceBase.h" + +namespace Chao::CSD +{ + struct Project; + class CProject; + class CScene; + class CTexList; + + class CProject : public CResourceBase, CBase + { + public: + SWA_INSERT_PADDING(0x1C); + RCPtr m_rcTexList; + SWA_INSERT_PADDING(0x1C); + + RCPtr CreateScene(const char* in_pName) const; + RCPtr CreateScene(const char* in_pName, const char* in_pMotionName) const; + + void DestroyScene(CScene* in_pScene); + void DestroyScene(RCPtr& inout_rcScene); + + static void DestroyScene(CProject* in_pProject, RCPtr& inout_rcScene); + }; +} + +#include "CSD/Manager/csdmProject.inl" diff --git a/UnleashedRecomp/api/CSD/Manager/csdmProject.inl b/UnleashedRecomp/api/CSD/Manager/csdmProject.inl new file mode 100644 index 00000000..c579789e --- /dev/null +++ b/UnleashedRecomp/api/CSD/Manager/csdmProject.inl @@ -0,0 +1,40 @@ +#include "kernel/function.h" + +namespace Chao::CSD +{ + inline RCPtr CProject::CreateScene(const char* in_pName) const + { + RCPtr rcScene; + GuestToHostFunction(0x830BEE00, this, rcScene, in_pName, nullptr); + return rcScene; + } + + inline RCPtr CProject::CreateScene(const char* in_pName, const char* in_pMotionName) const + { + RCPtr rcScene; + GuestToHostFunction(0x830BECE0, this, rcScene, in_pName, in_pMotionName, nullptr); + return rcScene; + } + + inline void CProject::DestroyScene(CScene* in_pScene) + { + GuestToHostFunction(0x830BE298, this, in_pScene); + } + + inline void CProject::DestroyScene(RCPtr& inout_rcScene) + { + if (!inout_rcScene) + return; + + DestroyScene(inout_rcScene.Get()); + inout_rcScene = nullptr; + } + + inline void CProject::DestroyScene(CProject* in_pProject, RCPtr& inout_rcScene) + { + if (in_pProject) + in_pProject->DestroyScene(inout_rcScene); + else + inout_rcScene = nullptr; + } +} diff --git a/UnleashedRecomp/api/CSD/Manager/csdmRCObject.h b/UnleashedRecomp/api/CSD/Manager/csdmRCObject.h new file mode 100644 index 00000000..81844c64 --- /dev/null +++ b/UnleashedRecomp/api/CSD/Manager/csdmRCObject.h @@ -0,0 +1,20 @@ +#pragma once + +#include "CSD/Manager/csdmRCPtrAbs.h" + +namespace Chao::CSD +{ + class RCPtrAbs::RCObject + { + public: + xpointer m_pMemory; + be m_RefCount; + xpointer m_pDealloctor; + be m_eDealloctor; + + virtual ~RCObject(); + virtual void Deallocate(void* in_pMemory) = 0; + + void Release(); + }; +} diff --git a/UnleashedRecomp/api/CSD/Manager/csdmRCObject.inl b/UnleashedRecomp/api/CSD/Manager/csdmRCObject.inl new file mode 100644 index 00000000..f9c7741f --- /dev/null +++ b/UnleashedRecomp/api/CSD/Manager/csdmRCObject.inl @@ -0,0 +1,24 @@ +namespace Chao::CSD +{ + inline void RCPtrAbs::RCObject::Release() + { + GuestToHostFunction(0x830BA068, this); + } + + inline RCPtrAbs::~RCPtrAbs() + { + RCObject* pObj = m_pObject; + m_pObject = nullptr; + + if (pObj) + pObj->Release(); + } + + inline void* RCPtrAbs::GetAbs() const + { + if (!m_pObject) + return nullptr; + + return m_pObject->m_pMemory; + } +} diff --git a/UnleashedRecomp/api/CSD/Manager/csdmRCObjectImp.h b/UnleashedRecomp/api/CSD/Manager/csdmRCObjectImp.h new file mode 100644 index 00000000..c21987d8 --- /dev/null +++ b/UnleashedRecomp/api/CSD/Manager/csdmRCObjectImp.h @@ -0,0 +1,12 @@ +#pragma once + +#include "CSD/Manager/csdmRCPtr.h" + +namespace Chao::CSD +{ + template + class RCPtr::RCObjectImp : public RCObject + { + void Deallocate(void* in_pMemory) override; + }; +} diff --git a/UnleashedRecomp/api/CSD/Manager/csdmRCObjectImp.inl b/UnleashedRecomp/api/CSD/Manager/csdmRCObjectImp.inl new file mode 100644 index 00000000..74465e61 --- /dev/null +++ b/UnleashedRecomp/api/CSD/Manager/csdmRCObjectImp.inl @@ -0,0 +1,14 @@ +namespace Chao::CSD +{ + template + void RCPtr::RCObjectImp::Deallocate(void* in_pMemory) + { + // delete static_cast(in_pMemory); + } + + template + RCPtrAbs::RCObject* RCPtr::CreateRCObject() + { + return new RCObjectImp(); + } +} diff --git a/UnleashedRecomp/api/CSD/Manager/csdmRCPtr.h b/UnleashedRecomp/api/CSD/Manager/csdmRCPtr.h new file mode 100644 index 00000000..a4a3caf5 --- /dev/null +++ b/UnleashedRecomp/api/CSD/Manager/csdmRCPtr.h @@ -0,0 +1,32 @@ +#pragma once + +#include "CSD/Manager/csdmRCPtrAbs.h" + +namespace Chao::CSD +{ + template + class RCPtr : RCPtrAbs + { + public: + class RCObjectImp; + + RCPtr() : RCPtrAbs() {} + RCPtr(T* in_pMemory) : RCPtrAbs(in_pMemory) {} + RCPtr(const RCPtr& in_rOther) : RCPtrAbs(in_rOther) {} + RCPtr(RCPtr&& in_rOther) : RCPtrAbs(std::move(in_rOther)) {} + + RCObject* CreateRCObject() override; + + void Attach(T* in_pObject); + + T* Get() const; + void Set(const RCPtr& in_rOther); + + T* operator*() const; + T* operator->() const; + + RCPtr& operator=(const RCPtr& in_rOther); + + operator bool() const; + }; +} diff --git a/UnleashedRecomp/api/CSD/Manager/csdmRCPtr.inl b/UnleashedRecomp/api/CSD/Manager/csdmRCPtr.inl new file mode 100644 index 00000000..01bcd6e1 --- /dev/null +++ b/UnleashedRecomp/api/CSD/Manager/csdmRCPtr.inl @@ -0,0 +1,45 @@ +namespace Chao::CSD +{ + template + void RCPtr::Attach(T* in_pObject) + { + RCPtrAbs::AttachAbs(in_pObject); + } + + template + T* RCPtr::Get() const + { + return static_cast(RCPtrAbs::GetAbs()); + } + + template + void RCPtr::Set(const RCPtr& in_rOther) + { + RCPtrAbs::SetAbs(in_rOther); + } + + template + T* RCPtr::operator*() const + { + return Get(); + } + + template + T* RCPtr::operator->() const + { + return Get(); + } + + template + RCPtr& RCPtr::operator=(const RCPtr& in_rOther) + { + Set(in_rOther); + return *this; + } + + template + RCPtr::operator bool() const + { + return m_pObject != nullptr; + } +} diff --git a/UnleashedRecomp/api/CSD/Manager/csdmRCPtrAbs.h b/UnleashedRecomp/api/CSD/Manager/csdmRCPtrAbs.h new file mode 100644 index 00000000..429df724 --- /dev/null +++ b/UnleashedRecomp/api/CSD/Manager/csdmRCPtrAbs.h @@ -0,0 +1,33 @@ +#pragma once + +#include "SWA.inl" + +namespace Chao::CSD +{ + class RCPtrAbs + { + public: + class RCObject; + + xpointer m_pObject; + + RCPtrAbs(); + RCPtrAbs(void* in_pMemory); + RCPtrAbs(const RCPtrAbs& in_rOther); + RCPtrAbs(RCPtrAbs&& in_rPtr); + + virtual ~RCPtrAbs(); + virtual RCObject* CreateRCObject() = 0; + + void AttachAbs(void* in_pMemory); + void* GetAbs() const; + void SetAbs(const RCPtrAbs& in_rPtr); + + void* operator*() const; + void* operator->() const; + + RCPtrAbs& operator=(const RCPtrAbs& in_rPtr); + + operator bool() const; + }; +} diff --git a/UnleashedRecomp/api/CSD/Manager/csdmRCPtrAbs.inl b/UnleashedRecomp/api/CSD/Manager/csdmRCPtrAbs.inl new file mode 100644 index 00000000..c6d68674 --- /dev/null +++ b/UnleashedRecomp/api/CSD/Manager/csdmRCPtrAbs.inl @@ -0,0 +1,53 @@ +namespace Chao::CSD +{ + inline RCPtrAbs::RCPtrAbs() + { + AttachAbs(nullptr); + } + + inline RCPtrAbs::RCPtrAbs(void* in_pMemory) + { + AttachAbs(in_pMemory); + } + + inline RCPtrAbs::RCPtrAbs(const RCPtrAbs& in_rOther) + { + SetAbs(in_rOther); + } + + inline RCPtrAbs::RCPtrAbs(RCPtrAbs&& in_rPtr) : m_pObject(in_rPtr.m_pObject) + { + in_rPtr.m_pObject = nullptr; + } + + inline void RCPtrAbs::AttachAbs(void* in_pMemory) + { + GuestToHostFunction(0x830BA298, this, in_pMemory); + } + + inline void RCPtrAbs::SetAbs(const RCPtrAbs& in_rPtr) + { + GuestToHostFunction(0x830BA328, this, in_rPtr); + } + + inline void* RCPtrAbs::operator*() const + { + return GetAbs(); + } + + inline void* RCPtrAbs::operator->() const + { + return GetAbs(); + } + + inline RCPtrAbs& RCPtrAbs::operator=(const RCPtrAbs& in_rPtr) + { + SetAbs(in_rPtr); + return *this; + } + + inline RCPtrAbs::operator bool() const + { + return m_pObject != nullptr; + } +} diff --git a/UnleashedRecomp/api/CSD/Manager/csdmResourceBase.h b/UnleashedRecomp/api/CSD/Manager/csdmResourceBase.h new file mode 100644 index 00000000..089c3048 --- /dev/null +++ b/UnleashedRecomp/api/CSD/Manager/csdmResourceBase.h @@ -0,0 +1,18 @@ +#pragma once + +#include "CSD/Manager/csdmRCPtr.h" + +namespace Chao::CSD +{ + template + class CResourceBase + { + public: + RCPtr m_rcResourceHolder; + xpointer m_pResource; + + virtual ~CResourceBase() = default; + + virtual void CopyResource(const CResourceBase& in_rOther); + }; +} diff --git a/UnleashedRecomp/api/CSD/Manager/csdmResourceBase.inl b/UnleashedRecomp/api/CSD/Manager/csdmResourceBase.inl new file mode 100644 index 00000000..923b8073 --- /dev/null +++ b/UnleashedRecomp/api/CSD/Manager/csdmResourceBase.inl @@ -0,0 +1,9 @@ +namespace Chao::CSD +{ + template + void CResourceBase::CopyResource(const CResourceBase& in_rOther) + { + m_rcResourceHolder = in_rOther.m_rcResourceHolder; + m_pResource = in_rOther.m_pResource; + } +} diff --git a/UnleashedRecomp/api/CSD/Manager/csdmScene.h b/UnleashedRecomp/api/CSD/Manager/csdmScene.h new file mode 100644 index 00000000..d8e683a1 --- /dev/null +++ b/UnleashedRecomp/api/CSD/Manager/csdmScene.h @@ -0,0 +1,64 @@ +#pragma once + +#include "SWA.inl" +#include "CSD/Manager/csdmBase.h" +#include "CSD/Manager/csdmResourceBase.h" +#include "CSD/Manager/csdmSceneObserver.h" +#include "CSD/Manager/csdmSubjectBase.h" + +namespace Chao::CSD +{ + struct Scene; + class CScene; + class CNode; + + enum EMotionRepeatType : uint32_t + { + eMotionRepeatType_PlayOnce = 0, + eMotionRepeatType_Loop = 1, + eMotionRepeatType_PingPong = 2, + eMotionRepeatType_PlayThenDestroy = 3 + }; + + class CScene : public CResourceBase, SubjectBase, CBase + { + public: + SWA_INSERT_PADDING(0x5C); + be m_PrevMotionFrame; + be m_MotionFrame; + be m_MotionSpeed; + be m_MotionStartFrame; + be m_MotionEndFrame; + SWA_INSERT_PADDING(0x0C); + be m_MotionDisableFlag; + SWA_INSERT_PADDING(0x10); + be m_MotionRepeatType; + SWA_INSERT_PADDING(0x2C); + + ~CScene() override = default; + + // Update should be called with a delta time of zero + // after making changes to a motion. + + // Example: + // SetMotion("Intro_Anim"); + // SetMotionFrame(0.0); + // m_MotionSpeed = 2.0f; + // Update(0.0f); + + // Changes are not going to be recognized if + // update is not called. + + virtual void Update(float in_DeltaTime = 0.0f); + virtual void Render(void*); + + RCPtr GetNode(const char* in_pName) const; + + bool SetMotion(const char* in_pName); + void SetMotionFrame(float in_MotionFrame); + void SetPosition(float in_X, float in_Y); + void SetHideFlag(uint32_t in_HideFlag); + void SetRotation(float in_Angle); + void SetScale(float in_X, float in_Y); + }; +} diff --git a/UnleashedRecomp/api/CSD/Manager/csdmScene.inl b/UnleashedRecomp/api/CSD/Manager/csdmScene.inl new file mode 100644 index 00000000..c045987d --- /dev/null +++ b/UnleashedRecomp/api/CSD/Manager/csdmScene.inl @@ -0,0 +1,40 @@ +namespace Chao::CSD +{ + inline RCPtr CScene::GetNode(const char* in_pName) const + { + RCPtr rcNode; + GuestToHostFunction(0x830BCCA8, this, rcNode, in_pName); + return rcNode; + } + + inline bool CScene::SetMotion(const char* in_pName) + { + return GuestToHostFunction(0x830BA760, this, in_pName); + } + + inline void CScene::SetMotionFrame(float in_MotionFrame) + { + m_PrevMotionFrame = in_MotionFrame; + m_MotionFrame = in_MotionFrame; + } + + inline void CScene::SetPosition(float in_X, float in_Y) + { + GuestToHostFunction(0x830BB550, this, in_X, in_Y); + } + + inline void CScene::SetHideFlag(uint32_t in_HideFlag) + { + GuestToHostFunction(0x830BB378, this, in_HideFlag); + } + + inline void CScene::SetRotation(float in_Angle) + { + GuestToHostFunction(0x830BB5F8, this, in_Angle); + } + + inline void CScene::SetScale(float in_X, float in_Y) + { + GuestToHostFunction(0x830BB650, this, in_X, in_Y); + } +} diff --git a/UnleashedRecomp/api/CSD/Manager/csdmSceneObserver.h b/UnleashedRecomp/api/CSD/Manager/csdmSceneObserver.h new file mode 100644 index 00000000..a238062f --- /dev/null +++ b/UnleashedRecomp/api/CSD/Manager/csdmSceneObserver.h @@ -0,0 +1,12 @@ +#pragma once + +#include "CSD/Manager/csdmObserverBase.h" + +namespace Chao::CSD +{ + class CScene; + + class CSceneObserver : public CObserverBase + { + }; +} diff --git a/UnleashedRecomp/api/CSD/Manager/csdmSubjectBase.h b/UnleashedRecomp/api/CSD/Manager/csdmSubjectBase.h new file mode 100644 index 00000000..2570e24c --- /dev/null +++ b/UnleashedRecomp/api/CSD/Manager/csdmSubjectBase.h @@ -0,0 +1,16 @@ +#pragma once + +#include "SWA.inl" + +namespace Chao::CSD +{ + template + class SubjectBase + { + public: + SWA_INSERT_PADDING(0x0C); + + virtual ~SubjectBase() = default; + virtual TObservee* GetObservee() const { return nullptr; } + }; +} diff --git a/UnleashedRecomp/api/CSD/Platform/csdTexList.h b/UnleashedRecomp/api/CSD/Platform/csdTexList.h new file mode 100644 index 00000000..3f5f162c --- /dev/null +++ b/UnleashedRecomp/api/CSD/Platform/csdTexList.h @@ -0,0 +1,15 @@ +#pragma once + +#include "CSD/Manager/csdmBase.h" +#include "CSD/Manager/csdmRCPtr.h" + +namespace Chao::CSD +{ + class CTexList : public CBase + { + public: + RCPtr m_rcData; + + virtual ~CTexList() = default; + }; +} diff --git a/UnleashedRecomp/api/Hedgehog/Base/System/hhAllocator.h b/UnleashedRecomp/api/Hedgehog/Base/System/hhAllocator.h new file mode 100644 index 00000000..baa56d99 --- /dev/null +++ b/UnleashedRecomp/api/Hedgehog/Base/System/hhAllocator.h @@ -0,0 +1,36 @@ +#pragma once + +#include "SWA.inl" + +inline static void* __HH_ALLOC(const uint32_t in_Size) +{ + return GuestToHostFunction(0x82DFA0B0, in_Size, nullptr, 0, 0); +} + +inline static void __HH_FREE(const void* in_pData) +{ + GuestToHostFunction(0x82DF9E50, in_pData); +} + +namespace Hedgehog::Base +{ + template + class TAllocator + { + public: + using value_type = T; + + TAllocator() noexcept {} + template TAllocator(TAllocator const&) noexcept {} + + value_type* allocate(std::size_t n) + { + return reinterpret_cast(__HH_ALLOC(n * sizeof(value_type))); + } + + void deallocate(value_type* p, std::size_t) noexcept + { + __HH_FREE(p); + } + }; +} diff --git a/UnleashedRecomp/api/Hedgehog/Base/Thread/hhHolder.h b/UnleashedRecomp/api/Hedgehog/Base/Thread/hhHolder.h new file mode 100644 index 00000000..1e23c78c --- /dev/null +++ b/UnleashedRecomp/api/Hedgehog/Base/Thread/hhHolder.h @@ -0,0 +1,20 @@ +#pragma once + +#include "Hedgehog/Base/Thread/hhHolderBase.h" + +#define HH_BASE_HOLDER(x) \ + Hedgehog::Base::THolder(x) + +namespace Hedgehog::Base +{ + template + class THolder : public CHolderBase + { + public: + THolder(T* in_pObject) : CHolderBase(in_pObject, ForceSync) {} + + T* get() const; + T* operator->() const; + T* operator*() const; + }; +} diff --git a/UnleashedRecomp/api/Hedgehog/Base/Thread/hhHolderBase.h b/UnleashedRecomp/api/Hedgehog/Base/Thread/hhHolderBase.h new file mode 100644 index 00000000..2d5d80a1 --- /dev/null +++ b/UnleashedRecomp/api/Hedgehog/Base/Thread/hhHolderBase.h @@ -0,0 +1,28 @@ +#pragma once + +#include "SWA.inl" + +namespace Hedgehog::Base +{ + class CSynchronizedObject; + + class CHolderBase + { + protected: + xpointer m_pSynchronizedObject; + bool m_Locked; + + public: + CHolderBase() : m_pSynchronizedObject(nullptr), m_Locked(false) {} + CHolderBase(CSynchronizedObject* in_pSynchronizedObject, bool in_ForceSync = false); + CHolderBase(CHolderBase&& io_rOther); + CHolderBase(const CHolderBase& in_rOther); + ~CHolderBase(); + + CSynchronizedObject* get() const; + CSynchronizedObject* operator->() const; + CSynchronizedObject* operator*() const; + + explicit operator bool() const; + }; +} diff --git a/UnleashedRecomp/api/Hedgehog/Base/Thread/hhSynchronizedObject.h b/UnleashedRecomp/api/Hedgehog/Base/Thread/hhSynchronizedObject.h new file mode 100644 index 00000000..d84df970 --- /dev/null +++ b/UnleashedRecomp/api/Hedgehog/Base/Thread/hhSynchronizedObject.h @@ -0,0 +1,12 @@ +#pragma once + +#include "SWA.inl" + +namespace Hedgehog::Base +{ + class CSynchronizedObject + { + public: + SWA_INSERT_PADDING(0x04); + }; +} diff --git a/UnleashedRecomp/api/Hedgehog/Base/Thread/hhSynchronizedPtr.h b/UnleashedRecomp/api/Hedgehog/Base/Thread/hhSynchronizedPtr.h new file mode 100644 index 00000000..53889dd1 --- /dev/null +++ b/UnleashedRecomp/api/Hedgehog/Base/Thread/hhSynchronizedPtr.h @@ -0,0 +1,27 @@ +#pragma once + +#include "SWA.inl" +#include "Hedgehog/Base/Thread/hhHolder.h" + +namespace Hedgehog::Base +{ + template + class TSynchronizedPtr + { + xpointer m_pObject; + + public: + TSynchronizedPtr(T* in_pObject); + TSynchronizedPtr(); + TSynchronizedPtr(const TSynchronizedPtr& in_rOther); + TSynchronizedPtr(TSynchronizedPtr&& io_rOther); + + TSynchronizedPtr& operator=(T* const in_pObject); + + THolder get() const; + THolder operator->() const; + THolder operator*() const; + + explicit operator bool() const; + }; +} diff --git a/UnleashedRecomp/api/Hedgehog/Base/Type/detail/hhStringHolder.h b/UnleashedRecomp/api/Hedgehog/Base/Type/detail/hhStringHolder.h new file mode 100644 index 00000000..087de601 --- /dev/null +++ b/UnleashedRecomp/api/Hedgehog/Base/Type/detail/hhStringHolder.h @@ -0,0 +1,44 @@ +#pragma once + +#include "SWA.inl" + +namespace Hedgehog::Base +{ + struct SStringHolder + { + union + { + struct + { + be Length; + be RefCount; + }; + + be RefCountAndLength; + }; + + char aStr[1u]; + + static SStringHolder* GetHolder(const char* in_pStr); + + static size_t GetMemorySize(const size_t in_Length); + static size_t GetMemorySizeAligned(const size_t in_Length); + + static SStringHolder* Make(const char* in_pStr, const size_t in_Length); + + static SStringHolder* Concat( + const char* in_pStrA, const size_t in_LengthA, + const char* in_pStrB, const size_t in_LengthB); + + void AddRef(); + void Release(); + + bool IsUnique() const; + + bool TryInplaceAssign(const char* in_pStr, const size_t in_Length); + bool TryInplaceAppend(const char* in_pStr, const size_t in_Length); + bool TryInplacePrepend(const char* in_pStr, const size_t in_Length); + }; +} + +#include "Hedgehog/Base/Type/detail/hhStringHolder.inl" diff --git a/UnleashedRecomp/api/Hedgehog/Base/Type/detail/hhStringHolder.inl b/UnleashedRecomp/api/Hedgehog/Base/Type/detail/hhStringHolder.inl new file mode 100644 index 00000000..235b9426 --- /dev/null +++ b/UnleashedRecomp/api/Hedgehog/Base/Type/detail/hhStringHolder.inl @@ -0,0 +1,134 @@ +namespace Hedgehog::Base +{ + inline SStringHolder* SStringHolder::GetHolder(const char* in_pStr) + { + return (SStringHolder*)((size_t)in_pStr - sizeof(RefCountAndLength)); + } + + inline size_t SStringHolder::GetMemorySize(const size_t in_Length) + { + return sizeof(RefCountAndLength) + in_Length; + } + + inline size_t SStringHolder::GetMemorySizeAligned(const size_t in_Length) + { + return (GetMemorySize(in_Length) + 0x10) & ~0x0F; + } + + inline SStringHolder* SStringHolder::Make(const char* in_pStr, const size_t in_Length) + { + const size_t memSize = GetMemorySize(in_Length); + const size_t memSizeAligned = GetMemorySizeAligned(in_Length); + + SStringHolder* pHolder = (SStringHolder*)__HH_ALLOC(memSizeAligned); + pHolder->RefCount = 1; + pHolder->Length = (uint16_t)in_Length; + + if (in_pStr) + memcpy(pHolder->aStr, in_pStr, in_Length); + + memset(&pHolder->aStr[in_Length], 0, memSizeAligned - memSize); + + return pHolder; + } + + inline SStringHolder* SStringHolder::Concat(const char* in_pStrA, const size_t in_LengthA, const char* in_pStrB, const size_t in_LengthB) + { + SStringHolder* pHolder = Make(nullptr, in_LengthA + in_LengthB); + + memcpy(pHolder->aStr, in_pStrA, in_LengthA); + memcpy(&pHolder->aStr[in_LengthA], in_pStrB, in_LengthB); + + return pHolder; + } + + inline void SStringHolder::AddRef() + { + uint32_t originalValue, incrementedValue; + do + { + originalValue = RefCountAndLength.value; + incrementedValue = std::byteswap(std::byteswap(originalValue) + 1); + } while (InterlockedCompareExchange(reinterpret_cast(&RefCountAndLength), incrementedValue, originalValue) != originalValue); + } + + inline void SStringHolder::Release() + { + uint32_t originalValue, decrementedValue; + do + { + originalValue = RefCountAndLength.value; + decrementedValue = std::byteswap(std::byteswap(originalValue) - 1); + } while (InterlockedCompareExchange(reinterpret_cast(&RefCountAndLength), decrementedValue, originalValue) != originalValue); + + if (RefCountAndLength == 0) + __HH_FREE(this); + } + + inline bool SStringHolder::IsUnique() const + { + return RefCount == 1; + } + + inline bool SStringHolder::TryInplaceAssign(const char* in_pStr, const size_t in_Length) + { + if (!IsUnique()) + return false; + + const size_t memSizeAligned = GetMemorySizeAligned(in_Length); + + if (memSizeAligned > GetMemorySizeAligned(Length)) + return false; + + if (in_pStr) + memcpy(aStr, in_pStr, in_Length); + + memset(&aStr[in_Length], 0, memSizeAligned - GetMemorySize(in_Length)); + + Length = (uint16_t)in_Length; + + return true; + } + + inline bool SStringHolder::TryInplaceAppend(const char* in_pStr, const size_t in_Length) + { + if (!IsUnique()) + return false; + + const size_t memSizeAligned = GetMemorySizeAligned(Length + in_Length); + + if (memSizeAligned > GetMemorySizeAligned(Length)) + return false; + + if (in_pStr) + memcpy(&aStr[Length], in_pStr, in_Length); + + memset(&aStr[Length + in_Length], 0, memSizeAligned - GetMemorySize(Length + in_Length)); + + Length = (uint16_t)(Length + in_Length); + + return true; + } + + inline bool SStringHolder::TryInplacePrepend(const char* in_pStr, const size_t in_Length) + { + if (!IsUnique()) + return false; + + const size_t memSizeAligned = GetMemorySizeAligned(in_Length + Length); + + if (memSizeAligned > GetMemorySizeAligned(Length)) + return false; + + memmove(&aStr[in_Length], aStr, Length); + + if (in_pStr) + memcpy(aStr, in_pStr, in_Length); + + memset(&aStr[in_Length + Length], 0, memSizeAligned - GetMemorySize(in_Length + Length)); + + Length = (uint16_t)(in_Length + Length); + + return true; + } +} diff --git a/UnleashedRecomp/api/Hedgehog/Base/Type/hhSharedString.h b/UnleashedRecomp/api/Hedgehog/Base/Type/hhSharedString.h new file mode 100644 index 00000000..54a22e5b --- /dev/null +++ b/UnleashedRecomp/api/Hedgehog/Base/Type/hhSharedString.h @@ -0,0 +1,88 @@ +#pragma once + +#include + +namespace Hedgehog::Base +{ + class CSharedString + { + private: + xpointer m_pStr; + + SStringHolder* GetHolder() const; + + CSharedString(SStringHolder* in_pHolder); + + public: + static constexpr size_t npos = ~0u; + + CSharedString(); + CSharedString(const char* in_pStr); + CSharedString(const CSharedString& in_rOther); + CSharedString(CSharedString&& io_rOther); + ~CSharedString(); + + const char* get() const; + const char* c_str() const; + const char* data() const; + + size_t size() const; + size_t length() const; + bool empty() const; + + const char* begin() const; + const char* end() const; + + CSharedString substr(size_t pos = 0, size_t len = npos) const; + + size_t find(char c, size_t pos = 0) const; + size_t find(const char* s, size_t pos = 0) const; + size_t rfind(char c, size_t pos = npos) const; + + size_t find_first_of(const char* s, size_t pos = 0) const; + size_t find_last_of(const char* s, size_t pos = npos) const; + size_t find_first_not_of(const char* s, size_t pos = 0) const; + size_t find_last_not_of(const char* s, size_t pos = npos) const; + + size_t find(const CSharedString& str, size_t pos = 0) const; + size_t rfind(const CSharedString& str, size_t pos = npos) const; + + size_t find_first_of(const CSharedString& str, size_t pos = 0) const; + size_t find_last_of(const CSharedString& str, size_t pos = npos) const; + size_t find_first_not_of(const CSharedString& str, size_t pos = 0) const; + size_t find_last_not_of(const CSharedString& str, size_t pos = npos) const; + + void assign(const CSharedString& in_rOther); + void assign(const char* in_pStr); + void assign(CSharedString&& io_rOther); + + void append(const CSharedString& in_rOther); + void append(const char* in_pStr); + + void prepend(const CSharedString& in_rOther); + void prepend(const char* in_pStr); + + int compare(const CSharedString& in_rOther) const; + + CSharedString& operator=(const CSharedString& in_rOther); + CSharedString& operator=(const char* in_pStr); + CSharedString& operator=(CSharedString&& io_rOther); + CSharedString& operator+=(const CSharedString& in_rOther); + CSharedString& operator+=(const char* in_pStr); + + friend CSharedString operator+(const CSharedString& in_rLeft, const CSharedString& in_rRight); + friend CSharedString operator+(const CSharedString& in_rLeft, const char* in_pRight); + friend CSharedString operator+(const char* in_pLeft, const CSharedString& in_pRight); + + bool operator>(const CSharedString& in_rOther) const; + bool operator>=(const CSharedString& in_rOther) const; + bool operator<(const CSharedString& in_rOther) const; + bool operator<=(const CSharedString& in_rOther) const; + bool operator==(const CSharedString& in_rOther) const; + bool operator!=(const CSharedString& in_rOther) const; + bool operator==(const char* in_pOther) const; + bool operator!=(const char* in_pOther) const; + }; +} + +#include diff --git a/UnleashedRecomp/api/Hedgehog/Base/Type/hhSharedString.inl b/UnleashedRecomp/api/Hedgehog/Base/Type/hhSharedString.inl new file mode 100644 index 00000000..023bebef --- /dev/null +++ b/UnleashedRecomp/api/Hedgehog/Base/Type/hhSharedString.inl @@ -0,0 +1,444 @@ +namespace Hedgehog::Base +{ + inline SStringHolder* CSharedString::GetHolder() const + { + return SStringHolder::GetHolder(m_pStr); + } + + inline CSharedString::CSharedString(SStringHolder* in_pHolder) : m_pStr(in_pHolder->aStr) + { + } + + inline CSharedString::CSharedString() : m_pStr(nullptr) + { + } + + inline CSharedString::CSharedString(const char* in_pStr) : m_pStr(nullptr) + { + size_t length; + + if (in_pStr && (length = strlen(in_pStr)) != 0) + m_pStr.ptr = g_memory.MapVirtual(SStringHolder::Make(in_pStr, length)->aStr); + } + + inline CSharedString::CSharedString(const CSharedString& in_rOther) : m_pStr(in_rOther.m_pStr) + { + GetHolder()->AddRef(); + } + + inline CSharedString::CSharedString(CSharedString&& io_rOther) : m_pStr(io_rOther.m_pStr) + { + io_rOther.m_pStr = nullptr; + } + + inline CSharedString::~CSharedString() + { + GetHolder()->Release(); + } + + inline const char* CSharedString::get() const + { + return m_pStr; + } + + inline const char* CSharedString::c_str() const + { + return get(); + } + + inline const char* CSharedString::data() const + { + return get(); + } + + inline size_t CSharedString::size() const + { + return GetHolder()->Length; + } + + inline size_t CSharedString::length() const + { + return size(); + } + + inline bool CSharedString::empty() const + { + return size() == 0; + } + + inline const char* CSharedString::begin() const + { + return get(); + } + + inline const char* CSharedString::end() const + { + return &m_pStr[GetHolder()->Length]; + } + + inline CSharedString CSharedString::substr(size_t pos, size_t len) const + { + if (len == 0) + return CSharedString(); + + if (len > (GetHolder()->Length - pos)) + len = GetHolder()->Length - pos; + + if (pos == 0 && len == GetHolder()->Length) + return *this; + + return SStringHolder::Make(&m_pStr[pos], len); + } + + inline size_t CSharedString::find(char c, size_t pos) const + { + for (size_t i = pos; i < GetHolder()->Length; i++) + { + if (m_pStr[i] == c) + return i; + } + + return npos; + } + + inline size_t CSharedString::find(const char* s, size_t pos) const + { + size_t len = strlen(s); + for (size_t i = pos; i < GetHolder()->Length - len + 1; i++) + { + if (strncmp(m_pStr + i, s, len) == 0) + return i; + } + + return npos; + } + + inline size_t CSharedString::rfind(char c, size_t pos) const + { + if (pos >= GetHolder()->Length) + pos = GetHolder()->Length - 1; + + for (size_t i = pos; i != static_cast(-1); i--) + { + if (m_pStr[i] == c) + return i; + } + + return npos; + } + + inline size_t CSharedString::find_first_of(const char* s, size_t pos) const + { + size_t len = strlen(s); + for (size_t i = pos; i < GetHolder()->Length; i++) + { + for (size_t j = 0; j < len; j++) + { + if (m_pStr[i] == s[j]) + return i; + } + } + + return npos; + } + + inline size_t CSharedString::find_last_of(const char* s, size_t pos) const + { + if (pos >= GetHolder()->Length) + pos = GetHolder()->Length - 1; + + size_t len = strlen(s); + for (size_t i = pos; i != static_cast(-1); i--) + { + for (size_t j = 0; j < len; j++) + { + if (m_pStr[i] == s[j]) + return i; + } + } + + return npos; + } + + inline size_t CSharedString::find_first_not_of(const char* s, size_t pos) const + { + size_t len = strlen(s); + for (size_t i = pos; i < GetHolder()->Length; i++) + { + bool found = false; + for (size_t j = 0; j < len; j++) + { + if (m_pStr[i] == s[j]) + { + found = true; + break; + } + } + + if (!found) + return i; + } + + return npos; + } + + inline size_t CSharedString::find_last_not_of(const char* s, size_t pos) const + { + if (pos >= GetHolder()->Length) + pos = GetHolder()->Length - 1; + + size_t len = strlen(s); + for (size_t i = pos; i != static_cast(-1); i--) + { + bool found = false; + for (size_t j = 0; j < len; j++) + { + if (m_pStr[i] == s[j]) + { + found = true; + break; + } + } + + if (!found) + return i; + } + + return npos; + } + + inline size_t CSharedString::find(const CSharedString& str, size_t pos) const + { + return find(str.c_str(), pos); + } + + inline size_t CSharedString::rfind(const CSharedString& str, size_t pos) const + { + return rfind(str.c_str(), pos); + } + + inline size_t CSharedString::find_first_of(const CSharedString& str, size_t pos) const + { + return find_first_of(str.c_str(), pos); + } + + inline size_t CSharedString::find_last_of(const CSharedString& str, size_t pos) const + { + return find_last_of(str.c_str(), pos); + } + + inline size_t CSharedString::find_first_not_of(const CSharedString& str, size_t pos) const + { + return find_first_not_of(str.c_str(), pos); + } + + inline size_t CSharedString::find_last_not_of(const CSharedString& str, size_t pos) const + { + return find_last_not_of(str.c_str(), pos); + } + + inline void CSharedString::assign(const CSharedString& in_rOther) + { + GetHolder()->Release(); + m_pStr = in_rOther.m_pStr; + GetHolder()->AddRef(); + } + + inline void CSharedString::assign(const char* in_pStr) + { + size_t length; + + if (in_pStr && (length = strlen(in_pStr)) != 0) + { + if (!GetHolder()->TryInplaceAssign(in_pStr, length)) + { + GetHolder()->Release(); + m_pStr = SStringHolder::Make(in_pStr, length)->aStr; + } + } + else + { + GetHolder()->Release(); + m_pStr = nullptr; + } + } + + inline void CSharedString::assign(CSharedString&& io_rOther) + { + m_pStr = io_rOther.m_pStr; + io_rOther.m_pStr = nullptr; + } + + inline void CSharedString::append(const CSharedString& in_rOther) + { + if (!GetHolder()->TryInplaceAppend(in_rOther.GetHolder()->aStr, in_rOther.GetHolder()->Length)) + { + SStringHolder* pHolder = SStringHolder::Concat( + GetHolder()->aStr, GetHolder()->Length, + in_rOther.GetHolder()->aStr, in_rOther.GetHolder()->Length); + + GetHolder()->Release(); + m_pStr = pHolder->aStr; + } + } + + inline void CSharedString::append(const char* in_pStr) + { + size_t length; + + if (in_pStr && (length = strlen(in_pStr)) != 0) + { + if (!GetHolder()->TryInplaceAppend(in_pStr, length)) + { + SStringHolder* pHolder = SStringHolder::Concat( + GetHolder()->aStr, GetHolder()->Length, in_pStr, length); + + GetHolder()->Release(); + m_pStr = pHolder->aStr; + } + } + } + + inline void CSharedString::prepend(const CSharedString& in_rOther) + { + if (!GetHolder()->TryInplacePrepend(in_rOther.GetHolder()->aStr, in_rOther.GetHolder()->Length)) + { + SStringHolder* pHolder = SStringHolder::Concat( + in_rOther.GetHolder()->aStr, in_rOther.GetHolder()->Length, + GetHolder()->aStr, GetHolder()->Length); + + GetHolder()->Release(); + m_pStr = pHolder->aStr; + } + } + + inline void CSharedString::prepend(const char* in_pStr) + { + size_t length; + + if (in_pStr && (length = strlen(in_pStr)) != 0) + { + if (!GetHolder()->TryInplacePrepend(in_pStr, length)) + { + SStringHolder* pHolder = SStringHolder::Concat( + in_pStr, length, GetHolder()->aStr, GetHolder()->Length); + + GetHolder()->Release(); + m_pStr = pHolder->aStr; + } + } + } + + inline int CSharedString::compare(const CSharedString& in_rOther) const + { + // TODO: DO NOT PASS BY REFERENCE. + GuestToHostFunction(0x82DFB028, this, &in_rOther); + } + + inline CSharedString& CSharedString::operator=(const CSharedString& in_rOther) + { + assign(in_rOther); + return *this; + } + + inline CSharedString& CSharedString::operator=(const char* in_pStr) + { + assign(in_pStr); + return *this; + } + + inline CSharedString& CSharedString::operator=(CSharedString&& io_rOther) + { + assign(std::move(io_rOther)); + return *this; + } + + inline CSharedString& CSharedString::operator+=(const CSharedString& in_rOther) + { + append(in_rOther); + return *this; + } + + inline CSharedString& CSharedString::operator+=(const char* in_pStr) + { + append(in_pStr); + return *this; + } + + inline CSharedString operator+(const CSharedString& in_rLeft, const CSharedString& in_rRight) + { + return SStringHolder::Concat( + in_rLeft.GetHolder()->aStr, in_rLeft.GetHolder()->Length, + in_rRight.GetHolder()->aStr, in_rRight.GetHolder()->Length); + } + + inline CSharedString operator+(const CSharedString& in_rLeft, const char* in_pRight) + { + size_t length; + + if (in_pRight && (length = strlen(in_pRight)) != 0) + { + return SStringHolder::Concat( + in_rLeft.GetHolder()->aStr, in_rLeft.GetHolder()->Length, in_pRight, length); + } + else + { + return in_rLeft; + } + } + + inline CSharedString operator+(const char* in_pLeft, const CSharedString& in_pRight) + { + size_t length; + + if (in_pLeft && (length = strlen(in_pLeft)) != 0) + { + return SStringHolder::Concat( + in_pLeft, length, in_pRight.GetHolder()->aStr, in_pRight.GetHolder()->Length); + } + else + { + return in_pRight; + } + } + + inline bool CSharedString::operator>(const CSharedString& in_rOther) const + { + return compare(in_rOther) > 0; + } + + inline bool CSharedString::operator>=(const CSharedString& in_rOther) const + { + return compare(in_rOther) >= 0; + } + + inline bool CSharedString::operator<(const CSharedString& in_rOther) const + { + return compare(in_rOther) < 0; + } + + inline bool CSharedString::operator<=(const CSharedString& in_rOther) const + { + return compare(in_rOther) <= 0; + } + + inline bool CSharedString::operator==(const CSharedString& in_rOther) const + { + return compare(in_rOther) == 0; + } + + inline bool CSharedString::operator!=(const CSharedString& in_rOther) const + { + return !(*this == in_rOther); + } + + inline bool CSharedString::operator==(const char* in_pOther) const + { + return strcmp(c_str(), in_pOther) == 0; + } + + inline bool CSharedString::operator!=(const char* in_pOther) const + { + return !(*this == in_pOther); + } +} diff --git a/UnleashedRecomp/api/Hedgehog/Base/hhObject.h b/UnleashedRecomp/api/Hedgehog/Base/hhObject.h new file mode 100644 index 00000000..80723ee2 --- /dev/null +++ b/UnleashedRecomp/api/Hedgehog/Base/hhObject.h @@ -0,0 +1,23 @@ +#pragma once + +#include "SWA.inl" + +namespace Hedgehog::Base +{ + class CObject + { + public: + CObject(); + CObject(const swa_null_ctor&); + + void* operator new(const size_t in_Size); + void* operator new(const size_t in_Size, const size_t in_Align); + + void operator delete(void* in_pMem); + + void* operator new(const size_t in_Size, void* in_pObj); + void* operator new(const size_t in_Size, const size_t in_Align, void* in_pObj); + + void operator delete(void* in_pMem, void* in_pObj); + }; +} diff --git a/UnleashedRecomp/api/Hedgehog/Database/System/hhDatabaseData.h b/UnleashedRecomp/api/Hedgehog/Database/System/hhDatabaseData.h new file mode 100644 index 00000000..7bfdb4f9 --- /dev/null +++ b/UnleashedRecomp/api/Hedgehog/Database/System/hhDatabaseData.h @@ -0,0 +1,32 @@ +#pragma once + +#include "Hedgehog/Base/hhObject.h" + +namespace Hedgehog::Database +{ + enum EDatabaseDataFlags : uint8_t + { + eDatabaseDataFlags_IsMadeOne = 0x1, + eDatabaseDataFlags_IsMadeAll = 0x2, + eDatabaseDataFlags_CreatedFromArchive = 0x4, + eDatabaseDataFlags_IsMadeMakingOne = 0x8 + }; + + class CDatabaseData : public Base::CObject + { + public: + uint8_t m_Flags; // see EDatabaseDataFlags + SWA_INSERT_PADDING(0x04); // TODO: Base::CSharedString m_TypeAndName; + + virtual ~CDatabaseData() = default; + virtual bool CheckMadeAll(); + + bool IsMadeOne() const; + void SetMadeOne(); + + bool IsMadeAllInternal(); + bool IsMadeAll(); + }; +} + +#include "Hedgehog/Database/System/hhDatabaseData.inl" diff --git a/UnleashedRecomp/api/Hedgehog/Database/System/hhDatabaseData.inl b/UnleashedRecomp/api/Hedgehog/Database/System/hhDatabaseData.inl new file mode 100644 index 00000000..b544a718 --- /dev/null +++ b/UnleashedRecomp/api/Hedgehog/Database/System/hhDatabaseData.inl @@ -0,0 +1,31 @@ +namespace Hedgehog::Database +{ + inline bool CDatabaseData::CheckMadeAll() + { + return true; + } + + inline bool CDatabaseData::IsMadeOne() const + { + return (m_Flags & eDatabaseDataFlags_IsMadeOne) != 0; + } + + inline void CDatabaseData::SetMadeOne() + { + m_Flags |= eDatabaseDataFlags_IsMadeOne; + } + + inline bool CDatabaseData::IsMadeAllInternal() + { + if ((m_Flags & eDatabaseDataFlags_IsMadeOne) == 0 || !CheckMadeAll()) + return false; + + m_Flags |= eDatabaseDataFlags_IsMadeAll; + return true; + } + + inline bool CDatabaseData::IsMadeAll() + { + return (m_Flags & eDatabaseDataFlags_IsMadeAll) != 0 || IsMadeAllInternal(); + } +} diff --git a/UnleashedRecomp/api/Hedgehog/Math/Vector2.h b/UnleashedRecomp/api/Hedgehog/Math/Vector2.h new file mode 100644 index 00000000..bc167197 --- /dev/null +++ b/UnleashedRecomp/api/Hedgehog/Math/Vector2.h @@ -0,0 +1,13 @@ +#pragma once + +#include "SWA.inl" + +namespace Hedgehog::Math +{ + class CVector2 + { + public: + be X; + be Y; + }; +} diff --git a/UnleashedRecomp/api/Hedgehog/MirageCore/Renderable/hhRenderable.h b/UnleashedRecomp/api/Hedgehog/MirageCore/Renderable/hhRenderable.h new file mode 100644 index 00000000..ccca4133 --- /dev/null +++ b/UnleashedRecomp/api/Hedgehog/MirageCore/Renderable/hhRenderable.h @@ -0,0 +1,14 @@ +#pragma once + +#include "SWA.inl" +#include "Hedgehog/Base/hhObject.h" + +namespace Hedgehog::Mirage +{ + class CRenderable : public Base::CObject + { + public: + bool m_Enabled; + be m_SortDepth; + }; +} diff --git a/UnleashedRecomp/api/Hedgehog/Universe/Engine/hhMessageActor.h b/UnleashedRecomp/api/Hedgehog/Universe/Engine/hhMessageActor.h new file mode 100644 index 00000000..978e31de --- /dev/null +++ b/UnleashedRecomp/api/Hedgehog/Universe/Engine/hhMessageActor.h @@ -0,0 +1,14 @@ +#pragma once + +#include "SWA.inl" +#include "Hedgehog/Universe/Engine/hhMessageProcess.h" +#include "Hedgehog/Universe/Thread/hhParallelJob.h" + +namespace Hedgehog::Universe +{ + class CMessageActor : public IMessageProcess, public IParallelJob + { + public: + SWA_INSERT_PADDING(0x7C); + }; +} diff --git a/UnleashedRecomp/api/Hedgehog/Universe/Engine/hhMessageProcess.h b/UnleashedRecomp/api/Hedgehog/Universe/Engine/hhMessageProcess.h new file mode 100644 index 00000000..b5b42d49 --- /dev/null +++ b/UnleashedRecomp/api/Hedgehog/Universe/Engine/hhMessageProcess.h @@ -0,0 +1,14 @@ +#pragma once + +#include "SWA.inl" +#include "Hedgehog/Base/hhObject.h" + +namespace Hedgehog::Universe +{ + class IMessageProcess : public Base::CObject + { + public: + IMessageProcess() {} + IMessageProcess(const swa_null_ctor& nil) : CObject(nil) {} + }; +} diff --git a/UnleashedRecomp/api/Hedgehog/Universe/Engine/hhUpdateInfo.h b/UnleashedRecomp/api/Hedgehog/Universe/Engine/hhUpdateInfo.h new file mode 100644 index 00000000..4369392e --- /dev/null +++ b/UnleashedRecomp/api/Hedgehog/Universe/Engine/hhUpdateInfo.h @@ -0,0 +1,13 @@ +#pragma once + +#include "SWA.inl" + +namespace Hedgehog::Universe +{ + struct SUpdateInfo + { + be DeltaTime; + be Frame; + Base::CSharedString Category; + }; +} diff --git a/UnleashedRecomp/api/Hedgehog/Universe/Engine/hhUpdateUnit.h b/UnleashedRecomp/api/Hedgehog/Universe/Engine/hhUpdateUnit.h new file mode 100644 index 00000000..ac04cda0 --- /dev/null +++ b/UnleashedRecomp/api/Hedgehog/Universe/Engine/hhUpdateUnit.h @@ -0,0 +1,22 @@ +#pragma once + +#include "SWA.inl" +#include "Hedgehog/Universe/Thread/hhParallelJob.h" + +namespace Hedgehog::Universe +{ + class CUpdateUnit : public Base::CObject, public IParallelJob + { + public: + SWA_INSERT_PADDING(0x24); + + CUpdateUnit(const swa_null_ctor& nil) : CObject(nil), IParallelJob(nil) {} + CUpdateUnit(); + virtual ~CUpdateUnit(); + + virtual void ExecuteParallelJob(const SUpdateInfo& in_rUpdateInfo) override; + + virtual void UpdateParallel(const SUpdateInfo& in_rUpdateInfo) {} + virtual void UpdateSerial(const SUpdateInfo& in_rUpdateInfo) {} + }; +} diff --git a/UnleashedRecomp/api/Hedgehog/Universe/Thread/hhParallelJob.h b/UnleashedRecomp/api/Hedgehog/Universe/Thread/hhParallelJob.h new file mode 100644 index 00000000..adf23117 --- /dev/null +++ b/UnleashedRecomp/api/Hedgehog/Universe/Thread/hhParallelJob.h @@ -0,0 +1,18 @@ +#pragma once + +#include "SWA.inl" +#include "Hedgehog/Universe/Engine/hhUpdateInfo.h" + +namespace Hedgehog::Universe +{ + class IParallelJob + { + public: + IParallelJob() {} + IParallelJob(const swa_null_ctor&) {} + + virtual ~IParallelJob() = default; + + virtual void ExecuteParallelJob(const SUpdateInfo& in_rUpdateInfo) = 0; + }; +} diff --git a/UnleashedRecomp/api/SWA.h b/UnleashedRecomp/api/SWA.h index 7a93b527..555c49c8 100644 --- a/UnleashedRecomp/api/SWA.h +++ b/UnleashedRecomp/api/SWA.h @@ -1,6 +1,41 @@ #pragma once +#include "Hedgehog/Base/hhObject.h" +#include "Hedgehog/Base/System/hhAllocator.h" +#include "Hedgehog/Base/Thread/hhHolder.h" +#include "Hedgehog/Base/Thread/hhHolderBase.h" +#include "Hedgehog/Base/Thread/hhSynchronizedObject.h" +#include "Hedgehog/Base/Thread/hhSynchronizedPtr.h" +#include "Hedgehog/Base/Type/hhSharedString.h" +#include "Hedgehog/Database/System/hhDatabaseData.h" +#include "Hedgehog/Math/Vector2.h" +#include "Hedgehog/MirageCore/Renderable/hhRenderable.h" +#include "Hedgehog/Universe/Engine/hhMessageActor.h" +#include "Hedgehog/Universe/Engine/hhMessageProcess.h" +#include "Hedgehog/Universe/Engine/hhUpdateInfo.h" +#include "Hedgehog/Universe/Engine/hhUpdateUnit.h" +#include "Hedgehog/Universe/Thread/hhParallelJob.h" + +#include "CSD/Manager/csdmBase.h" +#include "CSD/Manager/csdmNode.h" +#include "CSD/Manager/csdmNodeObserver.h" +#include "CSD/Manager/csdmObserverBase.h" +#include "CSD/Manager/csdmProject.h" +#include "CSD/Manager/csdmRCObject.h" +#include "CSD/Manager/csdmRCObjectImp.h" +#include "CSD/Manager/csdmRCPtr.h" +#include "CSD/Manager/csdmRCPtrAbs.h" +#include "CSD/Manager/csdmResourceBase.h" +#include "CSD/Manager/csdmScene.h" +#include "CSD/Manager/csdmSceneObserver.h" +#include "CSD/Manager/csdmSubjectBase.h" +#include "CSD/Platform/csdTexList.h" + #include "SWA/Camera/Camera.h" +#include "SWA/CSD/CsdDatabaseWrapper.h" +#include "SWA/CSD/CsdProject.h" +#include "SWA/CSD/CsdTexListMirage.h" +#include "SWA/CSD/GameObjectCSD.h" #include "SWA/Player/Character/EvilSonic/Hud/EvilHudGuide.h" #include "SWA/Player/Character/EvilSonic/EvilSonic.h" #include "SWA/Player/Character/EvilSonic/EvilSonicContext.h" diff --git a/UnleashedRecomp/api/SWA.inl b/UnleashedRecomp/api/SWA.inl index 005c0c83..b83b15eb 100644 --- a/UnleashedRecomp/api/SWA.inl +++ b/UnleashedRecomp/api/SWA.inl @@ -1,9 +1,12 @@ #pragma once #include +#include #define SWA__CONCAT2(x, y) x##y #define SWA_CONCAT2(x, y) _CONCAT(x, y) #define SWA_INSERT_PADDING(length) \ uint8_t SWA_CONCAT2(pad, __LINE__)[length] + +struct swa_null_ctor {}; diff --git a/UnleashedRecomp/api/SWA/CSD/CsdDatabaseWrapper.h b/UnleashedRecomp/api/SWA/CSD/CsdDatabaseWrapper.h new file mode 100644 index 00000000..94abf973 --- /dev/null +++ b/UnleashedRecomp/api/SWA/CSD/CsdDatabaseWrapper.h @@ -0,0 +1,25 @@ +#pragma once + +#include "boost/smart_ptr/shared_ptr.h" + +namespace Hedgehog::Database +{ + class CDatabase; +} + +namespace SWA +{ + class CCsdProject; + + class CCsdDatabaseWrapper + { + public: + Hedgehog::Database::CDatabase* m_pDatabase; + + CCsdDatabaseWrapper(Hedgehog::Database::CDatabase* in_pDatabase) : m_pDatabase(in_pDatabase) {} + + boost::shared_ptr GetCsdProject(const Hedgehog::Base::CSharedString& in_rName); + }; +} + +#include "SWA/CSD/CsdDatabaseWrapper.inl" diff --git a/UnleashedRecomp/api/SWA/CSD/CsdDatabaseWrapper.inl b/UnleashedRecomp/api/SWA/CSD/CsdDatabaseWrapper.inl new file mode 100644 index 00000000..414c6465 --- /dev/null +++ b/UnleashedRecomp/api/SWA/CSD/CsdDatabaseWrapper.inl @@ -0,0 +1,9 @@ +namespace SWA +{ + inline boost::shared_ptr CCsdDatabaseWrapper::GetCsdProject(const Hedgehog::Base::CSharedString& in_rName) + { + boost::shared_ptr spCsdProject; + GuestToHostFunction(0x825E2B40, &in_rName, this, &spCsdProject, 0); + return spCsdProject; + } +} diff --git a/UnleashedRecomp/api/SWA/CSD/CsdProject.h b/UnleashedRecomp/api/SWA/CSD/CsdProject.h new file mode 100644 index 00000000..0211933a --- /dev/null +++ b/UnleashedRecomp/api/SWA/CSD/CsdProject.h @@ -0,0 +1,18 @@ +#pragma once + +#include "CSD/Manager/csdmRCPtr.h" +#include "Hedgehog/Database/System/hhDatabaseData.h" + +namespace Chao::CSD +{ + class CProject; +} + +namespace SWA +{ + class CCsdProject : public Hedgehog::Database::CDatabaseData + { + public: + Chao::CSD::RCPtr m_rcProject; + }; +} diff --git a/UnleashedRecomp/api/SWA/CSD/CsdTexListMirage.h b/UnleashedRecomp/api/SWA/CSD/CsdTexListMirage.h new file mode 100644 index 00000000..ee0be919 --- /dev/null +++ b/UnleashedRecomp/api/SWA/CSD/CsdTexListMirage.h @@ -0,0 +1,18 @@ +#pragma once + +#include "CSD/Platform/csdTexList.h" + +namespace Hedgehog::Mirage +{ + class CTexsetData; +} + +namespace SWA +{ + class CCsdTexListMirage : public Chao::CSD::CTexList + { + public: + boost::shared_ptr m_spTexsetData; + SWA_INSERT_PADDING(0x04); + }; +} diff --git a/UnleashedRecomp/api/SWA/CSD/GameObjectCSD.h b/UnleashedRecomp/api/SWA/CSD/GameObjectCSD.h new file mode 100644 index 00000000..834fbb57 --- /dev/null +++ b/UnleashedRecomp/api/SWA/CSD/GameObjectCSD.h @@ -0,0 +1,20 @@ +#pragma once + +#include "SWA.inl" +#include "CSD/Manager/csdmRCPtr.h" +#include "SWA/System/GameObject.h" + +namespace Chao::CSD +{ + class CProject; +} + +namespace SWA +{ + class CGameObjectCSD : public CGameObject + { + public: + Chao::CSD::RCPtr m_rcProject; + SWA_INSERT_PADDING(0x38); + }; +} diff --git a/UnleashedRecomp/api/SWA/Sequence/Utility/SequencePlayMovieWrapper.h b/UnleashedRecomp/api/SWA/Sequence/Utility/SequencePlayMovieWrapper.h new file mode 100644 index 00000000..c225c01a --- /dev/null +++ b/UnleashedRecomp/api/SWA/Sequence/Utility/SequencePlayMovieWrapper.h @@ -0,0 +1,22 @@ +#pragma once + +#include "SWA.inl" +#include "Hedgehog/MirageCore/Renderable/hhRenderable.h" + +namespace SWA::Sequence::Utility +{ + class CPlayMovieWrapper + { + class CRender : public Hedgehog::Mirage::CRenderable + { + SWA_INSERT_PADDING(0x08); + be m_ScreenWidth; + be m_ScreenHeight; + be m_MovieWidth; + be m_MovieHeight; + }; + + SWA_INSERT_PADDING(0x18); + CRender* m_pRender; + }; +} diff --git a/UnleashedRecomp/api/SWA/Sound/Sound.h b/UnleashedRecomp/api/SWA/Sound/Sound.h new file mode 100644 index 00000000..f31c82fd --- /dev/null +++ b/UnleashedRecomp/api/SWA/Sound/Sound.h @@ -0,0 +1,20 @@ +#pragma once + +namespace SWA +{ + class CSound // : public CGameObject + { + public: + struct SSoundInfo + { + public: + SWA_INSERT_PADDING(0x04); + xpointer m_pAdminSimplePlayer; + SWA_INSERT_PADDING(0x04); + xpointer m_pAdminBgm; + }; + + SWA_INSERT_PADDING(0xC4); + xpointer m_pSoundInfo; + }; +} diff --git a/UnleashedRecomp/api/SWA/Sound/SoundBGMActEvil.h b/UnleashedRecomp/api/SWA/Sound/SoundBGMActEvil.h new file mode 100644 index 00000000..c23a3f03 --- /dev/null +++ b/UnleashedRecomp/api/SWA/Sound/SoundBGMActEvil.h @@ -0,0 +1,8 @@ +#pragma once + +namespace SWA +{ + class CSoundBGMActEvil + { + }; +} diff --git a/UnleashedRecomp/api/SWA/System/GameDocument.h b/UnleashedRecomp/api/SWA/System/GameDocument.h index e13f6071..f4695315 100644 --- a/UnleashedRecomp/api/SWA/System/GameDocument.h +++ b/UnleashedRecomp/api/SWA/System/GameDocument.h @@ -1,21 +1,32 @@ #pragma once +#include "SWA/Sound/Sound.h" + +namespace Hedgehog::Database +{ + class CDatabase; +} + namespace SWA { - class CGameDocument // : public Hedgehog::Base::CSynchronizedObject + class CGameDocument : public Hedgehog::Base::CSynchronizedObject { public: class CMember { public: - SWA_INSERT_PADDING(0x20C); + SWA_INSERT_PADDING(0x1C); + boost::shared_ptr m_spDatabase; + SWA_INSERT_PADDING(0x90); + xpointer m_pSound; + SWA_INSERT_PADDING(0x158); be m_Score; }; // TODO: Hedgehog::Base::TSynchronizedPtr static CGameDocument* GetInstance(); - SWA_INSERT_PADDING(0x08); + SWA_INSERT_PADDING(0x04); xpointer m_pMember; }; } diff --git a/UnleashedRecomp/api/SWA/System/GameObject.h b/UnleashedRecomp/api/SWA/System/GameObject.h new file mode 100644 index 00000000..962c8d15 --- /dev/null +++ b/UnleashedRecomp/api/SWA/System/GameObject.h @@ -0,0 +1,26 @@ +#pragma once + +#include "SWA.inl" +#include "Hedgehog/Base/Thread/hhSynchronizedPtr.h" +#include "Hedgehog/Universe/Engine/hhMessageActor.h" +#include "Hedgehog/Universe/Engine/hhUpdateUnit.h" + +namespace SWA +{ + class CGameDocument; + class CWorld; + + class CGameObject : public Hedgehog::Universe::CUpdateUnit, public Hedgehog::Universe::CMessageActor + { + public: + class CMember + { + public: + Hedgehog::Base::TSynchronizedPtr m_pGameDocument; + Hedgehog::Base::TSynchronizedPtr m_pWorld; + SWA_INSERT_PADDING(0x78); + }; + + xpointer m_pMember; + }; +} diff --git a/UnleashedRecomp/api/SWA/System/World.h b/UnleashedRecomp/api/SWA/System/World.h new file mode 100644 index 00000000..aafbcd2f --- /dev/null +++ b/UnleashedRecomp/api/SWA/System/World.h @@ -0,0 +1,20 @@ +#pragma once + +#include "SWA.inl" +#include "Hedgehog/Base/Thread/hhSynchronizedObject.h" +#include "Hedgehog/Universe/Engine/hhMessageActor.h" + +namespace SWA +{ + class CWorld : public Hedgehog::Base::CSynchronizedObject, public Hedgehog::Universe::CMessageActor + { + public: + class CMember + { + public: + SWA_INSERT_PADDING(0x80); + }; + + xpointer m_pMember; + }; +} diff --git a/UnleashedRecomp/api/boost/smart_ptr/make_shared_object.h b/UnleashedRecomp/api/boost/smart_ptr/make_shared_object.h new file mode 100644 index 00000000..9bba6b4b --- /dev/null +++ b/UnleashedRecomp/api/boost/smart_ptr/make_shared_object.h @@ -0,0 +1,12 @@ +#pragma once + +#include "boost/smart_ptr/shared_ptr.h" + +namespace boost +{ + template + shared_ptr make_shared(TArgs&&... args) + { + return shared_ptr(new T(std::forward(args)...)); + } +} diff --git a/UnleashedRecomp/api/boost/smart_ptr/shared_ptr.h b/UnleashedRecomp/api/boost/smart_ptr/shared_ptr.h new file mode 100644 index 00000000..afe54f20 --- /dev/null +++ b/UnleashedRecomp/api/boost/smart_ptr/shared_ptr.h @@ -0,0 +1,81 @@ +#pragma once + +#include +#include + +namespace boost +{ + template + class shared_ptr + { + private: + xpointer m_pObject; + xpointer m_pRefCount; + + void release() + { + if (m_pRefCount && --(*m_pRefCount) == 0) + { + delete m_pObject; + delete m_pRefCount; + } + } + + public: + shared_ptr() : m_pObject(nullptr), m_pRefCount(nullptr) {} + + explicit shared_ptr(T* p) : m_pObject(p), m_pRefCount(new size_t(1)) {} + + shared_ptr(const shared_ptr& other) : m_pObject(other.m_pObject), m_pRefCount(other.m_pRefCount) + { + if (m_pRefCount) + ++(*m_pRefCount); + } + + shared_ptr(shared_ptr&& other) noexcept : m_pObject(std::exchange(other.m_pObject, nullptr)), + m_pRefCount(std::exchange(other.m_pRefCount, nullptr)) {} + + ~shared_ptr() + { + release(); + } + + shared_ptr& operator=(const shared_ptr& other) + { + if (this != &other) + { + release(); + + m_pObject = other.m_pObject; + m_pRefCount = other.m_pRefCount; + + if (m_pRefCount) + ++(*m_pRefCount); + } + + return *this; + } + + shared_ptr& operator=(shared_ptr&& other) noexcept + { + if (this != &other) + { + release(); + + m_pObject = std::exchange(other.m_pObject, nullptr); + m_pRefCount = std::exchange(other.m_pRefCount, nullptr); + } + + return *this; + } + + T* get() const { return m_pObject; } + + T& operator*() const { assert(m_pObject); return *m_pObject; } + T* operator->() const { assert(m_pObject); return m_pObject; } + + explicit operator bool() const { return m_pObject != nullptr; } + + size_t use_count() const { return m_pRefCount ? *m_pRefCount : 0; } + }; +} diff --git a/UnleashedRecomp/cfg/config.cpp b/UnleashedRecomp/cfg/config.cpp index 4db3dea2..b9f4fbcd 100644 --- a/UnleashedRecomp/cfg/config.cpp +++ b/UnleashedRecomp/cfg/config.cpp @@ -14,7 +14,7 @@ void Config::Load() { auto toml = toml::parse_file(configPath.string()); - for (auto def : Definitions) + for (auto def : Config::Definitions) { def->ReadValue(toml); #if _DEBUG @@ -38,7 +38,7 @@ void Config::Save() std::string result; std::string section; - for (auto def : Definitions) + for (auto def : Config::Definitions) { auto isFirstSection = section.empty(); auto isDefWithSection = section != def->GetSection(); diff --git a/UnleashedRecomp/cfg/config_detail.h b/UnleashedRecomp/cfg/config_detail.h index e256bc45..dbb0c4f9 100644 --- a/UnleashedRecomp/cfg/config_detail.h +++ b/UnleashedRecomp/cfg/config_detail.h @@ -19,12 +19,6 @@ #define CONFIG_DEFINE_CALLBACK(section, type, name, defaultValue, readCallback) \ inline static ConfigDef name{section, #name, defaultValue, [](ConfigDef* def) readCallback}; -#define CONFIG_DEFINE_LOCALE(name) \ - inline static std::unordered_map g_##name##_locale = - -#define CONFIG_DEFINE_ENUM_LOCALE(type) \ - inline static std::unordered_map> g_##type##_locale = - #define CONFIG_DEFINE_ENUM_TEMPLATE(type) \ inline static std::unordered_map g_##type##_template = diff --git a/UnleashedRecomp/gpu/video.cpp b/UnleashedRecomp/gpu/video.cpp index 715b409c..cc2c408f 100644 --- a/UnleashedRecomp/gpu/video.cpp +++ b/UnleashedRecomp/gpu/video.cpp @@ -926,23 +926,23 @@ static void ProcSetRenderState(const RenderCommand& cmd) static const std::pair g_setRenderStateFunctions[] = { - { D3DRS_ZENABLE, GuestFunction> }, - { D3DRS_ZWRITEENABLE, GuestFunction> }, - { D3DRS_ALPHATESTENABLE, GuestFunction> }, - { D3DRS_SRCBLEND, GuestFunction> }, - { D3DRS_DESTBLEND, GuestFunction> }, - { D3DRS_CULLMODE, GuestFunction> }, - { D3DRS_ZFUNC, GuestFunction> }, - { D3DRS_ALPHAREF, GuestFunction> }, - { D3DRS_ALPHABLENDENABLE, GuestFunction> }, - { D3DRS_BLENDOP, GuestFunction> }, - { D3DRS_SCISSORTESTENABLE, GuestFunction> }, - { D3DRS_SLOPESCALEDEPTHBIAS, GuestFunction> }, - { D3DRS_DEPTHBIAS, GuestFunction> }, - { D3DRS_SRCBLENDALPHA, GuestFunction> }, - { D3DRS_DESTBLENDALPHA, GuestFunction> }, - { D3DRS_BLENDOPALPHA, GuestFunction> }, - { D3DRS_COLORWRITEENABLE, GuestFunction> } + { D3DRS_ZENABLE, HostToGuestFunction> }, + { D3DRS_ZWRITEENABLE, HostToGuestFunction> }, + { D3DRS_ALPHATESTENABLE, HostToGuestFunction> }, + { D3DRS_SRCBLEND, HostToGuestFunction> }, + { D3DRS_DESTBLEND, HostToGuestFunction> }, + { D3DRS_CULLMODE, HostToGuestFunction> }, + { D3DRS_ZFUNC, HostToGuestFunction> }, + { D3DRS_ALPHAREF, HostToGuestFunction> }, + { D3DRS_ALPHABLENDENABLE, HostToGuestFunction> }, + { D3DRS_BLENDOP, HostToGuestFunction> }, + { D3DRS_SCISSORTESTENABLE, HostToGuestFunction> }, + { D3DRS_SLOPESCALEDEPTHBIAS, HostToGuestFunction> }, + { D3DRS_DEPTHBIAS, HostToGuestFunction> }, + { D3DRS_SRCBLENDALPHA, HostToGuestFunction> }, + { D3DRS_DESTBLENDALPHA, HostToGuestFunction> }, + { D3DRS_BLENDOPALPHA, HostToGuestFunction> }, + { D3DRS_COLORWRITEENABLE, HostToGuestFunction> } }; static std::unique_ptr g_resolveMsaaDepthPipelines[3]; @@ -1367,7 +1367,7 @@ static uint32_t CreateDevice(uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, memset(device, 0, sizeof(*device)); uint32_t functionOffset = 0x443344; // D3D - g_codeCache.Insert(functionOffset, reinterpret_cast(GuestFunction)); + g_codeCache.Insert(functionOffset, reinterpret_cast(HostToGuestFunction)); for (size_t i = 0; i < _countof(device->setRenderStateFunctions); i++) device->setRenderStateFunctions[i] = functionOffset; diff --git a/UnleashedRecomp/kernel/function.h b/UnleashedRecomp/kernel/function.h index 14eb09cc..ee41a742 100644 --- a/UnleashedRecomp/kernel/function.h +++ b/UnleashedRecomp/kernel/function.h @@ -1,7 +1,9 @@ #pragma once + #include #include #include "xbox.h" +#include "memory.h" template constexpr std::tuple function_args(R(*)(T...)) noexcept @@ -78,10 +80,54 @@ struct ArgTranslator [[unlikely]] default: break; } - // how did you end up here + // TODO: get value from stack. return 0; } + FORCEINLINE constexpr static void SetIntegerArgumentValue(PPCContext& ctx, uint8_t* base, size_t arg, uint64_t value) noexcept + { + if (arg <= 7) + { + switch (arg) + { + case 0: ctx.r3.u64 = value; return; + case 1: ctx.r4.u64 = value; return; + case 2: ctx.r5.u64 = value; return; + case 3: ctx.r6.u64 = value; return; + case 4: ctx.r7.u64 = value; return; + case 5: ctx.r8.u64 = value; return; + case 6: ctx.r9.u64 = value; return; + case 7: ctx.r10.u64 = value; return; + [[unlikely]] default: break; + } + } + + assert(arg < 7 && "Pushing to stack memory is not yet supported."); + } + + FORCEINLINE static void SetPrecisionArgumentValue(PPCContext& ctx, uint8_t* base, size_t arg, double value) noexcept + { + switch (arg) + { + case 0: ctx.f1.f64 = value; return; + case 1: ctx.f2.f64 = value; return; + case 2: ctx.f3.f64 = value; return; + case 3: ctx.f4.f64 = value; return; + case 4: ctx.f5.f64 = value; return; + case 5: ctx.f6.f64 = value; return; + case 6: ctx.f7.f64 = value; return; + case 7: ctx.f8.f64 = value; return; + case 8: ctx.f9.f64 = value; return; + case 9: ctx.f10.f64 = value; return; + case 10: ctx.f11.f64 = value; return; + case 11: ctx.f12.f64 = value; return; + case 12: ctx.f13.f64 = value; return; + [[unlikely]] default: break; + } + + assert(arg < 12 && "Pushing to stack memory is not yet supported."); + } + template FORCEINLINE constexpr static std::enable_if_t, T> GetValue(PPCContext& ctx, uint8_t* base, size_t idx) noexcept { @@ -106,6 +152,39 @@ struct ArgTranslator return reinterpret_cast(base + static_cast(v)); } + + template + FORCEINLINE constexpr static std::enable_if_t, void> SetValue(PPCContext& ctx, uint8_t* base, size_t idx, T value) noexcept + { + if constexpr (is_precise_v) + { + SetPrecisionArgumentValue(ctx, base, idx, value); + } + else if constexpr (std::is_null_pointer_v) + { + SetIntegerArgumentValue(ctx, base, idx, 0); + } + else if constexpr (std::is_pointer_v) + { + SetIntegerArgumentValue(ctx, base, idx, g_memory.MapVirtual(value)); + } + else + { + SetIntegerArgumentValue(ctx, base, idx, value); + } + } + + template + FORCEINLINE constexpr static std::enable_if_t, void> SetValue(PPCContext& ctx, uint8_t* base, size_t idx, T value) noexcept + { + const auto v = g_memory.MapVirtual((void*)value); + if (!v) + { + return; + } + + SetValue(ctx, base, idx, v); + } }; struct Argument @@ -155,27 +234,42 @@ struct arg_ordinal_t }; template -FORCEINLINE void _translate_args(PPCContext& ctx, uint8_t* base, std::tuple&) noexcept -requires (I >= sizeof...(TArgs)) +FORCEINLINE void _translate_args_to_host(PPCContext& ctx, uint8_t* base, std::tuple&) noexcept + requires (I >= sizeof...(TArgs)) { } template -FORCEINLINE std::enable_if_t<(I < sizeof...(TArgs)), void> _translate_args(PPCContext& ctx, uint8_t* base, std::tuple& tpl) noexcept +FORCEINLINE std::enable_if_t<(I < sizeof...(TArgs)), void> _translate_args_to_host(PPCContext& ctx, uint8_t* base, std::tuple& tpl) noexcept { using T = std::tuple_element_t>; std::get(tpl) = ArgTranslator::GetValue(ctx, base, arg_ordinal_t::value); - _translate_args(ctx, base, tpl); + _translate_args_to_host(ctx, base, tpl); +} + +template +FORCEINLINE void _translate_args_to_guest(PPCContext& ctx, uint8_t* base, std::tuple&) noexcept + requires (I >= sizeof...(TArgs)) +{ +} + +template +FORCEINLINE std::enable_if_t<(I < sizeof...(TArgs)), void> _translate_args_to_guest(PPCContext& ctx, uint8_t* base, std::tuple& tpl) noexcept +{ + using T = std::tuple_element_t>; + ArgTranslator::SetValue(ctx, base, I, std::get(tpl)); + + _translate_args_to_guest(ctx, base, tpl); } template -FORCEINLINE PPC_FUNC(GuestFunction) +FORCEINLINE PPC_FUNC(HostToGuestFunction) { using ret_t = decltype(std::apply(Func, function_args(Func))); auto args = function_args(Func); - _translate_args(ctx, base, args); + _translate_args_to_host(ctx, base, args); if constexpr (std::is_same_v) { @@ -207,8 +301,49 @@ FORCEINLINE PPC_FUNC(GuestFunction) } } +template +FORCEINLINE T GuestToHostFunction(uint32_t addr, TArgs... argv) +{ + auto args = std::make_tuple(argv...); + auto& currentCtx = *GetPPCContext(); + auto newCtx = PPCContext{}; + + newCtx.fn = currentCtx.fn; + newCtx.r1 = currentCtx.r1; + newCtx.r13 = currentCtx.r13; + newCtx.fpscr = currentCtx.fpscr; + + _translate_args_to_guest>(newCtx, (uint8_t*)g_memory.base, args); + + SetPPCContext(newCtx); + (*(PPCFunc**)(newCtx.fn + uint64_t(addr) * 2))(newCtx, (uint8_t*)g_memory.base); + currentCtx.fpscr = newCtx.fpscr; + SetPPCContext(currentCtx); + + if constexpr (std::is_void_v) + { + return; + } + else if constexpr (std::is_pointer_v) + { + return reinterpret_cast((uint64_t)g_memory.Translate(newCtx.r3.u32)); + } + else if constexpr (is_precise_v) + { + return static_cast(newCtx.f1.f64); + } + else if constexpr (std::is_integral_v) + { + return static_cast(newCtx.r3.u64); + } + else + { + static_assert(false, "Unsupported return type."); + } +} + #define GUEST_FUNCTION_HOOK(subroutine, function) \ - PPC_FUNC(subroutine) { GuestFunction(ctx, base); } + PPC_FUNC(subroutine) { HostToGuestFunction(ctx, base); } #define GUEST_FUNCTION_STUB(subroutine) \ PPC_FUNC(subroutine) { } diff --git a/UnleashedRecomp/patches/fps_patches.cpp b/UnleashedRecomp/patches/fps_patches.cpp index f2928fdd..d55c5e90 100644 --- a/UnleashedRecomp/patches/fps_patches.cpp +++ b/UnleashedRecomp/patches/fps_patches.cpp @@ -3,6 +3,9 @@ #include #include +float m_lastLoadingFrameDelta = 0.0f; +std::chrono::steady_clock::time_point m_lastLoadingFrameTime; + void HighFrameRateDeltaTimeFixMidAsmHook(PPCRegister& f1) { // Having 60 FPS threshold ensures we still retain @@ -58,3 +61,15 @@ void Camera2DSlopeLerpFixMidAsmHook(PPCRegister& t, PPCRegister& deltaTime) { t.f64 = ComputeLerpFactor(t.f64, deltaTime.f64 / 60.0); } + +void LoadingScreenSpeedFixMidAsmHook(PPCRegister& r4) +{ + auto now = std::chrono::high_resolution_clock::now(); + + m_lastLoadingFrameDelta = std::min(std::chrono::duration(now - m_lastLoadingFrameTime).count(), 1.0f / 15.0f); + m_lastLoadingFrameTime = now; + + auto pDeltaTime = (be*)g_memory.Translate(r4.u32); + + *pDeltaTime = m_lastLoadingFrameDelta; +} diff --git a/UnleashedRecomp/res/.gitignore b/UnleashedRecomp/res/.gitignore index db4787e6..e3285599 100644 --- a/UnleashedRecomp/res/.gitignore +++ b/UnleashedRecomp/res/.gitignore @@ -1 +1,2 @@ +![Ww][Ii][Nn]32/ *.h \ No newline at end of file diff --git a/UnleashedRecomp/stdafx.h b/UnleashedRecomp/stdafx.h index b0075c44..96152f7b 100644 --- a/UnleashedRecomp/stdafx.h +++ b/UnleashedRecomp/stdafx.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include diff --git a/UnleashedRecompLib/config/SWA.toml b/UnleashedRecompLib/config/SWA.toml index 2d44cb33..8d2fe1a3 100644 --- a/UnleashedRecompLib/config/SWA.toml +++ b/UnleashedRecompLib/config/SWA.toml @@ -417,3 +417,8 @@ jump_address_on_true = 0x827D20EC name = "ParticleTestDrawIndexedPrimitiveMidAsmHook" address = 0x827D25AC registers = ["r7"] + +[[midasm_hook]] +name = "LoadingScreenSpeedFixMidAsmHook" +address = 0x824DAB60 +registers = ["r4"]