Implemented guest-to-host function pointers (#7)

* Implemented guest-to-host function pointers (WIP)

Co-Authored-By: Skyth (Asilkan) <19259897+blueskythlikesclouds@users.noreply.github.com>

* function: support more types for function pointers

* api: ported BlueBlur headers and misc. research

* Move over function-pointers changes from options-menu branch.

---------

Co-authored-by: Skyth (Asilkan) <19259897+blueskythlikesclouds@users.noreply.github.com>
This commit is contained in:
Hyper 2024-11-25 10:50:10 +00:00 committed by GitHub
parent a908780de8
commit 8f525b571b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
93 changed files with 2957 additions and 62 deletions

View file

@ -0,0 +1,6 @@
#pragma once
namespace Chao::CSD
{
class CBase {};
}

View file

@ -0,0 +1,8 @@
#pragma once
#include <SWA.inl>
namespace Chao::CSD
{
class CMotionPattern : CBase {};
}

View file

@ -0,0 +1,33 @@
#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<Node>, SubjectBase<CNodeObserver, CNode>, CBase
{
public:
SWA_INSERT_PADDING(0x34);
xpointer<CMotionPattern> m_pMotionPattern;
SWA_INSERT_PADDING(0x18);
~CNode();
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"

View file

@ -0,0 +1,51 @@
#include "SWA.inl"
namespace Chao::CSD
{
inline CNode::~CNode()
{
SWA_VIRTUAL_FUNCTION(void, 0, this);
}
inline void CNode::SetText(const char* in_pText)
{
GuestToHostFunction<int>(0x830BF640, this, in_pText);
}
inline void CNode::SetText(const wchar_t* in_pText)
{
GuestToHostFunction<int>(0x830BF640, this, in_pText);
}
inline Hedgehog::Math::CVector2* CNode::GetPosition() const
{
guest_stack_var<Hedgehog::Math::CVector2> pos;
GuestToHostFunction<void>(0x830BF008, pos.get(), this);
return pos.get();
}
inline void CNode::SetPosition(float in_X, float in_Y)
{
GuestToHostFunction<int>(0x830BF078, this, in_X, in_Y);
}
inline void CNode::SetHideFlag(uint32_t in_HideFlag)
{
GuestToHostFunction<int>(0x830BF080, this, in_HideFlag);
}
inline void CNode::SetRotation(float in_Rotation)
{
GuestToHostFunction<int>(0x830BF088, this, in_Rotation);
}
inline void CNode::SetScale(float in_X, float in_Y)
{
GuestToHostFunction<int>(0x830BF090, this, in_X, in_Y);
}
inline void CNode::SetPatternIndex(uint32_t in_PatternIndex)
{
GuestToHostFunction<int>(0x830BF300, this, in_PatternIndex);
}
}

View file

@ -0,0 +1,10 @@
#pragma once
#include "CSD/Manager/csdmObserverBase.h"
namespace Chao::CSD
{
class CNode;
class CNodeObserver : public CObserverBase<CNode> {};
}

View file

@ -0,0 +1,23 @@
#pragma once
#include "SWA.inl"
namespace Chao::CSD
{
template<typename TObservee>
class CObserverBase
{
public:
struct Vftable
{
be<uint32_t> m_fpDtor;
};
xpointer<Vftable> m_pVftable;
SWA_INSERT_PADDING(0x08);
~CObserverBase();
};
}
#include "CSD/Manager/csdmObserverBase.inl"

View file

@ -0,0 +1,8 @@
namespace Chao::CSD
{
template<typename TObservee>
inline CObserverBase<TObservee>::~CObserverBase()
{
GuestToHostFunction<void>(m_pVftable->m_fpDtor, this);
}
}

View file

@ -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<Project>, CBase
{
public:
SWA_INSERT_PADDING(0x1C);
RCPtr<CTexList> m_rcTexList;
SWA_INSERT_PADDING(0x1C);
RCPtr<CScene> CreateScene(const char* in_pName) const;
RCPtr<CScene> CreateScene(const char* in_pName, const char* in_pMotionName) const;
void DestroyScene(CScene* in_pScene);
void DestroyScene(RCPtr<CScene>& inout_rcScene);
static void DestroyScene(CProject* in_pProject, RCPtr<CScene>& inout_rcScene);
};
}
#include "CSD/Manager/csdmProject.inl"

View file

@ -0,0 +1,40 @@
#include "kernel/function.h"
namespace Chao::CSD
{
inline RCPtr<CScene> CProject::CreateScene(const char* in_pName) const
{
RCPtr<CScene> rcScene;
GuestToHostFunction<void>(0x830BEE00, this, rcScene, in_pName, nullptr);
return rcScene;
}
inline RCPtr<CScene> CProject::CreateScene(const char* in_pName, const char* in_pMotionName) const
{
RCPtr<CScene> rcScene;
GuestToHostFunction<void>(0x830BECE0, this, rcScene, in_pName, in_pMotionName, nullptr);
return rcScene;
}
inline void CProject::DestroyScene(CScene* in_pScene)
{
GuestToHostFunction<void>(0x830BE298, this, in_pScene);
}
inline void CProject::DestroyScene(RCPtr<CScene>& inout_rcScene)
{
if (!inout_rcScene)
return;
DestroyScene(inout_rcScene.Get());
inout_rcScene = nullptr;
}
inline void CProject::DestroyScene(CProject* in_pProject, RCPtr<CScene>& inout_rcScene)
{
if (in_pProject)
in_pProject->DestroyScene(inout_rcScene);
else
inout_rcScene = nullptr;
}
}

View file

@ -0,0 +1,28 @@
#pragma once
#include "CSD/Manager/csdmRCPtrAbs.h"
namespace Chao::CSD
{
class RCPtrAbs::RCObject
{
public:
struct Vftable
{
be<uint32_t> m_fpDtor;
be<uint32_t> m_fpDeallocate;
};
xpointer<Vftable> m_pVftable;
xpointer<void> m_pMemory;
be<uint32_t> m_RefCount;
xpointer<void> m_pDealloctor;
be<uint32_t> m_eDealloctor;
~RCObject();
void Deallocate(void* in_pMemory);
void Release();
};
}
#include "CSD/Manager/csdmRCObject.inl"

View file

@ -0,0 +1,35 @@
namespace Chao::CSD
{
inline RCPtrAbs::RCObject::~RCObject()
{
GuestToHostFunction<void>(m_pVftable->m_fpDtor, this);
}
inline RCPtrAbs::~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;
}
inline void RCPtrAbs::RCObject::Deallocate(void* in_pMemory)
{
GuestToHostFunction<void>(m_pVftable->m_fpDeallocate, this, in_pMemory);
}
inline void RCPtrAbs::RCObject::Release()
{
GuestToHostFunction<void>(0x830BA068, this);
}
}

View file

@ -0,0 +1,9 @@
#pragma once
#include "CSD/Manager/csdmRCPtr.h"
namespace Chao::CSD
{
template<typename T>
class RCPtr<T>::RCObjectImp : public RCObject {};
}

View file

@ -0,0 +1,14 @@
namespace Chao::CSD
{
template<typename T>
void RCPtr<T>::RCObjectImp::Deallocate(void* in_pMemory)
{
// delete static_cast<T*>(in_pMemory);
}
template<typename T>
RCPtrAbs::RCObject* RCPtr<T>::CreateRCObject()
{
return new RCObjectImp();
}
}

View file

@ -0,0 +1,32 @@
#pragma once
#include "CSD/Manager/csdmRCPtrAbs.h"
namespace Chao::CSD
{
template<typename T>
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)) {}
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;
};
}
#include "CSD/Manager/csdmRCPtr.inl"

View file

@ -0,0 +1,45 @@
namespace Chao::CSD
{
template<typename T>
void RCPtr<T>::Attach(T* in_pObject)
{
RCPtrAbs::AttachAbs(in_pObject);
}
template<typename T>
T* RCPtr<T>::Get() const
{
return static_cast<T*>(RCPtrAbs::GetAbs());
}
template<typename T>
void RCPtr<T>::Set(const RCPtr& in_rOther)
{
RCPtrAbs::SetAbs(in_rOther);
}
template<typename T>
T* RCPtr<T>::operator*() const
{
return Get();
}
template<typename T>
T* RCPtr<T>::operator->() const
{
return Get();
}
template<typename T>
RCPtr<T>& RCPtr<T>::operator=(const RCPtr& in_rOther)
{
Set(in_rOther);
return *this;
}
template<typename T>
RCPtr<T>::operator bool() const
{
return m_pObject != nullptr;
}
}

View file

@ -0,0 +1,42 @@
#pragma once
#include "SWA.inl"
namespace Chao::CSD
{
class RCPtrAbs
{
public:
class RCObject;
struct Vftable
{
be<uint32_t> m_fpDtor;
be<uint32_t> m_fpCreateRCObject;
};
xpointer<Vftable> m_pVftable;
xpointer<RCObject> m_pObject;
RCPtrAbs();
RCPtrAbs(void* in_pMemory);
RCPtrAbs(const RCPtrAbs& in_rOther);
RCPtrAbs(RCPtrAbs&& in_rPtr);
~RCPtrAbs();
RCObject* CreateRCObject();
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;
};
}
#include "CSD/Manager/csdmRCPtrAbs.inl"

View file

@ -0,0 +1,58 @@
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 RCPtrAbs::RCObject* RCPtrAbs::CreateRCObject()
{
return GuestToHostFunction<RCPtrAbs::RCObject*>(m_pVftable->m_fpCreateRCObject, this);
}
inline void RCPtrAbs::AttachAbs(void* in_pMemory)
{
GuestToHostFunction<void>(0x830BA298, this, in_pMemory);
}
inline void RCPtrAbs::SetAbs(const RCPtrAbs& in_rPtr)
{
GuestToHostFunction<void>(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;
}
}

View file

@ -0,0 +1,26 @@
#pragma once
#include "CSD/Manager/csdmRCPtr.h"
namespace Chao::CSD
{
template<typename T>
class CResourceBase
{
public:
struct Vftable
{
be<uint32_t> m_fpDtor;
be<uint32_t> m_fpCopyResource;
};
xpointer<Vftable> m_pVftable;
RCPtr<uint8_t> m_rcResourceHolder;
xpointer<T> m_pResource;
~CResourceBase();
void CopyResource(const CResourceBase& in_rOther);
};
}
#include "CSD/Manager/csdmResourceBase.h"

View file

@ -0,0 +1,15 @@
namespace Chao::CSD
{
template<typename T>
inline CResourceBase<T>::~CResourceBase()
{
GuestToHostFunction<void>(m_pVftable->m_fpDtor, this);
}
template<typename T>
inline void CResourceBase<T>::CopyResource(const CResourceBase& in_rOther)
{
m_rcResourceHolder = in_rOther.m_rcResourceHolder;
m_pResource = in_rOther.m_pResource;
}
}

View file

@ -0,0 +1,53 @@
#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<Scene>, SubjectBase<CSceneObserver, CScene>, CBase
{
public:
SWA_INSERT_PADDING(0x60);
be<float> m_PrevMotionFrame;
be<float> m_MotionFrame;
be<float> m_MotionSpeed;
be<float> m_MotionStartFrame;
be<float> m_MotionEndFrame;
SWA_INSERT_PADDING(0x0C);
be<uint32_t> m_MotionDisableFlag;
SWA_INSERT_PADDING(0x10);
be<EMotionRepeatType> m_MotionRepeatType;
SWA_INSERT_PADDING(0x2C);
~CScene();
void Update(float in_DeltaTime = 0.0f);
void Render(void* in_pUnk);
void GetNode(RCPtr<CNode>& out_rResult, const char* in_pName);
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);
};
}
#include "CSD/Manager/csdmScene.inl"

View file

@ -0,0 +1,53 @@
namespace Chao::CSD
{
inline CScene::~CScene()
{
SWA_VIRTUAL_FUNCTION(void, 0, this);
}
inline void CScene::Update(float in_DeltaTime)
{
SWA_VIRTUAL_FUNCTION(void, 2, this, in_DeltaTime);
}
inline void CScene::Render(void* in_pUnk)
{
SWA_VIRTUAL_FUNCTION(void, 3, this, in_pUnk);
}
inline void CScene::GetNode(RCPtr<CNode>& out_rResult, const char* in_pName)
{
GuestToHostFunction<void>(sub_830BCCA8, &out_rResult, this, in_pName);
}
inline bool CScene::SetMotion(const char* in_pName)
{
return GuestToHostFunction<bool>(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<void>(0x830BB550, this, in_X, in_Y);
}
inline void CScene::SetHideFlag(uint32_t in_HideFlag)
{
GuestToHostFunction<void>(0x830BB378, this, in_HideFlag);
}
inline void CScene::SetRotation(float in_Angle)
{
GuestToHostFunction<void>(0x830BB5F8, this, in_Angle);
}
inline void CScene::SetScale(float in_X, float in_Y)
{
GuestToHostFunction<void>(0x830BB650, this, in_X, in_Y);
}
}

View file

@ -0,0 +1,10 @@
#pragma once
#include "CSD/Manager/csdmObserverBase.h"
namespace Chao::CSD
{
class CScene;
class CSceneObserver : public CObserverBase<CScene> {};
}

View file

@ -0,0 +1,25 @@
#pragma once
#include "SWA.inl"
namespace Chao::CSD
{
template<typename TObserver, typename TObservee>
class SubjectBase
{
public:
struct Vftable
{
be<uint32_t> m_fpDtor;
be<uint32_t> m_fpGetObservee;
};
xpointer<Vftable> m_pVftable;
SWA_INSERT_PADDING(0x0C);
~SubjectBase();
TObservee* GetObservee() const;
};
}
#include "CSD/Manager/csdmSubjectBase.inl"

View file

@ -0,0 +1,14 @@
namespace Chao::CSD
{
template<typename TObserver, typename TObservee>
inline SubjectBase<TObserver, TObservee>::~SubjectBase()
{
GuestToHostFunction<void>(m_pVftable->m_fpDtor, this);
}
template<typename TObserver, typename TObservee>
inline TObservee* SubjectBase<TObserver, TObservee>::GetObservee() const
{
return nullptr;
}
}

View file

@ -0,0 +1,23 @@
#pragma once
#include "CSD/Manager/csdmBase.h"
#include "CSD/Manager/csdmRCPtr.h"
namespace Chao::CSD
{
class CTexList : public CBase
{
public:
struct Vftable
{
be<uint32_t> m_fpDtor;
};
xpointer<Vftable> m_pVftable;
RCPtr<uint8_t> m_rcData;
~CTexList();
};
}
#include "CSD/Platform/csdTexList.inl"

View file

@ -0,0 +1,7 @@
namespace Chao::CSD
{
inline CTexList::~CTexList()
{
GuestToHostFunction<void>(m_pVftable->m_fpDtor, this);
}
}

View file

@ -0,0 +1,36 @@
#pragma once
#include "SWA.inl"
inline static void* __HH_ALLOC(const uint32_t in_Size)
{
return GuestToHostFunction<void*>(0x82DFA0B0, in_Size, nullptr, 0, 0);
}
inline static void __HH_FREE(const void* in_pData)
{
GuestToHostFunction<void>(0x82DF9E50, in_pData);
}
namespace Hedgehog::Base
{
template<class T>
class TAllocator
{
public:
using value_type = T;
TAllocator() noexcept {}
template<class U> TAllocator(TAllocator<U> const&) noexcept {}
value_type* allocate(std::size_t n)
{
return reinterpret_cast<value_type*>(__HH_ALLOC(n * sizeof(value_type)));
}
void deallocate(value_type* p, std::size_t) noexcept
{
__HH_FREE(p);
}
};
}

View file

@ -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<typename T, bool ForceSync = true>
class THolder : public CHolderBase
{
public:
THolder(T* in_pObject) : CHolderBase(in_pObject, ForceSync) {}
T* get() const;
T* operator->() const;
T* operator*() const;
};
}

View file

@ -0,0 +1,28 @@
#pragma once
#include "SWA.inl"
namespace Hedgehog::Base
{
class CSynchronizedObject;
class CHolderBase
{
protected:
xpointer<CSynchronizedObject> 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;
};
}

View file

@ -0,0 +1,12 @@
#pragma once
#include "SWA.inl"
namespace Hedgehog::Base
{
class CSynchronizedObject
{
public:
SWA_INSERT_PADDING(0x04);
};
}

View file

@ -0,0 +1,27 @@
#pragma once
#include "SWA.inl"
#include "Hedgehog/Base/Thread/hhHolder.h"
namespace Hedgehog::Base
{
template<typename T, bool ForceSync = false>
class TSynchronizedPtr
{
xpointer<T> m_pObject;
public:
TSynchronizedPtr(T* in_pObject);
TSynchronizedPtr();
TSynchronizedPtr(const TSynchronizedPtr& in_rOther);
TSynchronizedPtr(TSynchronizedPtr&& io_rOther);
TSynchronizedPtr<T, ForceSync>& operator=(T* const in_pObject);
THolder<T, ForceSync> get() const;
THolder<T, ForceSync> operator->() const;
THolder<T, ForceSync> operator*() const;
explicit operator bool() const;
};
}

View file

@ -0,0 +1,44 @@
#pragma once
#include "SWA.inl"
namespace Hedgehog::Base
{
struct SStringHolder
{
union
{
struct
{
be<uint16_t> Length;
be<uint16_t> RefCount;
};
be<uint32_t> 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"

View file

@ -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);
auto 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<LONG*>(&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<LONG*>(&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;
}
}

View file

@ -0,0 +1,88 @@
#pragma once
#include <Hedgehog/Base/Type/detail/hhStringHolder.h>
namespace Hedgehog::Base
{
class CSharedString
{
private:
xpointer<const char> 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 <Hedgehog/Base/Type/hhSharedString.inl>

View file

@ -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<size_t>(-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<size_t>(-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<size_t>(-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.
return GuestToHostFunction<int>(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);
}
}

View file

@ -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);
};
}

View file

@ -0,0 +1,39 @@
#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:
struct Vftable
{
be<uint32_t> m_fpDtor;
be<uint32_t> m_fpCheckMadeAll;
};
xpointer<Vftable> m_pVftable;
uint8_t m_Flags;
Base::CSharedString m_TypeAndName;
~CDatabaseData();
bool CheckMadeAll();
bool IsMadeOne() const;
void SetMadeOne();
bool IsMadeAllInternal();
bool IsMadeAll();
};
}
#include "Hedgehog/Database/System/hhDatabaseData.inl"

View file

@ -0,0 +1,36 @@
namespace Hedgehog::Database
{
inline CDatabaseData::~CDatabaseData()
{
GuestToHostFunction<void>(m_pVftable->m_fpDtor, this);
}
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();
}
}

View file

@ -0,0 +1,13 @@
#pragma once
#include "SWA.inl"
namespace Hedgehog::Math
{
class CVector2
{
public:
be<float> X;
be<float> Y;
};
}

View file

@ -0,0 +1,14 @@
#pragma once
#include "SWA.inl"
#include "Hedgehog/Base/hhObject.h"
namespace Hedgehog::Mirage
{
class CRenderable : public Base::CObject
{
public:
xpointer<void> m_pVftable;
bool m_Enabled;
};
}

View file

@ -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(0x88);
};
}

View file

@ -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) {}
};
}

View file

@ -0,0 +1,13 @@
#pragma once
#include "SWA.inl"
namespace Hedgehog::Universe
{
struct SUpdateInfo
{
be<float> DeltaTime;
be<uint32_t> Frame;
Base::CSharedString Category;
};
}

View file

@ -0,0 +1,25 @@
#pragma once
#include "SWA.inl"
#include "Hedgehog/Universe/Thread/hhParallelJob.h"
namespace Hedgehog::Universe
{
class CUpdateUnit : public Base::CObject, public IParallelJob
{
public:
xpointer<void> m_pVftable;
SWA_INSERT_PADDING(0x20);
CUpdateUnit(const swa_null_ctor& nil) : CObject(nil), IParallelJob(nil) {}
CUpdateUnit();
// TODO: implement virtual functions.
// virtual ~CUpdateUnit();
//
// virtual void ExecuteParallelJob(const SUpdateInfo& in_rUpdateInfo) override;
//
// virtual void UpdateParallel(const SUpdateInfo& in_rUpdateInfo) {}
// virtual void UpdateSerial(const SUpdateInfo& in_rUpdateInfo) {}
};
}

View file

@ -0,0 +1,21 @@
#pragma once
#include "SWA.inl"
#include "Hedgehog/Universe/Engine/hhUpdateInfo.h"
namespace Hedgehog::Universe
{
class IParallelJob
{
public:
xpointer<void> m_pVftable;
IParallelJob() {}
IParallelJob(const swa_null_ctor&) {}
// TODO: implement virtual functions.
// virtual ~IParallelJob() = default;
//
// virtual void ExecuteParallelJob(const SUpdateInfo& in_rUpdateInfo) = 0;
};
}

View file

@ -1,10 +1,68 @@
#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/csdmMotionPattern.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/HUD/GeneralWindow/GeneralWindow.h"
#include "SWA/HUD/Loading/Loading.h"
#include "SWA/HUD/Pause/HudPause.h"
#include "SWA/HUD/Sonic/HudSonicStage.h"
#include "SWA/Movie/MovieDisplayer.h"
#include "SWA/Movie/MovieManager.h"
#include "SWA/Player/Character/EvilSonic/Hud/EvilHudGuide.h"
#include "SWA/Player/Character/EvilSonic/EvilSonic.h"
#include "SWA/Player/Character/EvilSonic/EvilSonicContext.h"
#include "SWA/Sequence/Unit/SequenceUnitBase.h"
#include "SWA/Sequence/Unit/SequenceUnitPlayMovie.h"
#include "SWA/Sequence/Utility/SequencePlayMovieWrapper.h"
#include "SWA/Sound/Sound.h"
#include "SWA/Sound/SoundBGMActSonic.h"
#include "SWA/Sound/SoundBGMBase.h"
#include "SWA/System/GameMode/Title/TitleMenu.h"
#include "SWA/System/GameMode/Title/TitleStateBase.h"
#include "SWA/System/GameMode/GameMode.h"
#include "SWA/System/GameMode/GameModeStage.h"
#include "SWA/System/GameMode/GameModeStageMovie.h"
#include "SWA/System/Application.h"
#include "SWA/System/ApplicationD3D9.h"
#include "SWA/System/ApplicationXenon.h"
#include "SWA/System/ApplicationDocument.h"
#include "SWA/System/Game.h"
#include "SWA/System/GameDocument.h"
#include "SWA/System/GameObject.h"
#include "SWA/System/InputState.h"
#include "SWA/System/PadState.h"

View file

@ -1,9 +1,16 @@
#pragma once
#include <cpu/guest_code.h>
#include <cpu/guest_stack_var.h>
#include <kernel/function.h>
#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]
#define SWA_VIRTUAL_FUNCTION(returnType, virtualIndex, ...) \
GuestToHostFunction<returnType>(*(be<uint32_t>*)(g_memory.Translate(*(be<uint32_t>*)(this) + (4 * virtualIndex))), __VA_ARGS__)
struct swa_null_ctor {};

View file

@ -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<CCsdProject> GetCsdProject(const Hedgehog::Base::CSharedString& in_rName);
};
}
#include "SWA/CSD/CsdDatabaseWrapper.inl"

View file

@ -0,0 +1,9 @@
namespace SWA
{
inline boost::shared_ptr<CCsdProject> CCsdDatabaseWrapper::GetCsdProject(const Hedgehog::Base::CSharedString& in_rName)
{
boost::shared_ptr<CCsdProject> spCsdProject;
GuestToHostFunction<void>(0x825E2B40, &in_rName, this, &spCsdProject, 0);
return spCsdProject;
}
}

View file

@ -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<Chao::CSD::CProject> m_rcProject;
};
}

View file

@ -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<Hedgehog::Mirage::CTexsetData> m_spTexsetData;
SWA_INSERT_PADDING(0x04);
};
}

View file

@ -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:
xpointer<void> m_pVftable;
Chao::CSD::RCPtr<Chao::CSD::CProject> m_rcProject;
};
}

View file

@ -1,13 +1,15 @@
#pragma once
#include "SWA.inl"
#include <SWA.inl>
#include <SWA/System/GameObject.h>
namespace SWA
{
class CCamera // : public CGameObject, public Hedgehog::Universe::TStateMachine<CCamera>
class CCamera : public CGameObject // , public Hedgehog::Universe::TStateMachine<CCamera>
{
public:
SWA_INSERT_PADDING(0x184);
xpointer<void> m_pVftable;
SWA_INSERT_PADDING(0xC4);
be<float> m_VertAspectRatio;
SWA_INSERT_PADDING(0x48);
be<float> m_HorzAspectRatio;
@ -15,5 +17,8 @@ namespace SWA
be<float> m_FieldOfView;
be<float> m_VertFieldOfView;
be<float> m_HorzFieldOfView;
SWA_INSERT_PADDING(0x18);
bool m_InvertY;
bool m_InvertX;
};
}

View file

@ -0,0 +1,18 @@
#pragma once
#include <SWA.inl>
namespace SWA
{
class CGeneralWindow
{
public:
SWA_INSERT_PADDING(0xD0);
Chao::CSD::RCPtr<Chao::CSD::CProject> m_rcGeneral;
Chao::CSD::RCPtr<Chao::CSD::CScene> m_rcBg;
Chao::CSD::RCPtr<Chao::CSD::CScene> m_rcWindow;
Chao::CSD::RCPtr<Chao::CSD::CScene> m_rcWindow_2;
Chao::CSD::RCPtr<Chao::CSD::CScene> m_rcWindowSelect;
Chao::CSD::RCPtr<Chao::CSD::CScene> m_rcFooter;
};
}

View file

@ -0,0 +1,30 @@
#pragma once
#include <SWA.inl>
namespace SWA
{
enum ELoadingDisplayType
{
eLoadingDisplayType_MilesElectric,
eLoadingDisplayType_None,
eLoadingDisplayType_WerehogMovie,
eLoadingDisplayType_MilesElectricContext,
eLoadingDisplayType_Arrows,
eLoadingDisplayType_NowLoading,
eLoadingDisplayType_EventGallery,
eLoadingDisplayType_ChangeTimeOfDay,
eLoadingDisplayType_Blank
};
class CLoading
{
public:
SWA_INSERT_PADDING(0x128);
bool m_IsVisible;
SWA_INSERT_PADDING(0x0C);
be<ELoadingDisplayType> m_LoadingDisplayType;
SWA_INSERT_PADDING(0x65);
bool m_IsNightToDay;
};
}

View file

@ -0,0 +1,67 @@
#pragma once
#include <SWA.inl>
using namespace Chao::CSD;
namespace SWA
{
enum EActionType : uint32_t
{
eActionType_Undefined,
eActionType_Status,
eActionType_Return,
eActionType_Inventory,
eActionType_Skills,
eActionType_Lab,
eActionType_Wait,
eActionType_Restart = 8,
eActionType_Continue
};
enum EMenuType : uint32_t
{
eMenuType_WorldMap,
eMenuType_Village,
eMenuType_Stage,
eMenuType_Hub,
eMenuType_Misc
};
enum EStatusType : uint32_t
{
eStatusType_Idle,
eStatusType_Accept,
eStatusType_Decline
};
enum ETransitionType : uint32_t
{
eTransitionType_Undefined,
eTransitionType_Quit = 2,
eTransitionType_Dialog = 5,
eTransitionType_Hide,
eTransitionType_Abort,
eTransitionType_SubMenu
};
class CHudPause : public CGameObject
{
public:
xpointer<void> m_pVftable;
SWA_INSERT_PADDING(0x2C);
RCPtr<CProject> m_rcPause;
RCPtr<CScene> m_rcBg;
RCPtr<CScene> m_rcBg1;
RCPtr<CScene> m_rcBg1_2;
RCPtr<CScene> m_rcBg1Select;
RCPtr<CScene> m_rcBg1Select_2;
RCPtr<CScene> m_rcStatusTitle;
RCPtr<CScene> m_rcFooterA;
SWA_INSERT_PADDING(0x5C);
be<EActionType> m_Action;
be<EMenuType> m_Menu;
be<EStatusType> m_Status;
be<ETransitionType> m_Transition;
};
}

View file

@ -0,0 +1,22 @@
#pragma once
#include <SWA.inl>
namespace SWA
{
class CHudSonicStage
{
public:
SWA_INSERT_PADDING(0xE0);
Chao::CSD::RCPtr<Chao::CSD::CProject> m_rcPlayScreen;
Chao::CSD::RCPtr<Chao::CSD::CScene> m_rcSpeedGauge;
Chao::CSD::RCPtr<Chao::CSD::CScene> m_rcRingEnergyGauge;
Chao::CSD::RCPtr<Chao::CSD::CScene> m_rcGaugeFrame;
SWA_INSERT_PADDING(0x28);
Chao::CSD::RCPtr<Chao::CSD::CNode> m_rcScoreCount;
Chao::CSD::RCPtr<Chao::CSD::CNode> m_rcTimeCount;
Chao::CSD::RCPtr<Chao::CSD::CNode> m_rcTimeCount2;
Chao::CSD::RCPtr<Chao::CSD::CNode> m_rcTimeCount3;
Chao::CSD::RCPtr<Chao::CSD::CNode> m_rcPlayerCount;
};
}

View file

@ -0,0 +1,14 @@
#pragma once
#include <SWA.inl>
namespace SWA
{
class CMovieDisplayer : public Hedgehog::Universe::CUpdateUnit, public Hedgehog::Mirage::CRenderable
{
public:
SWA_INSERT_PADDING(0x04);
be<uint32_t> m_MovieWidth;
be<uint32_t> m_MovieHeight;
};
}

View file

@ -0,0 +1,17 @@
#pragma once
#include <SWA.inl>
namespace SWA
{
class CMovieManager // : Hedgehog::Base::TSingleton<SWA::CMovieManager, 0>
{
public:
static CMovieManager* GetInstance();
xpointer<void> m_pVftable;
SWA_INSERT_PADDING(0x330);
};
}
#include "SWA/Movie/MovieManager.inl"

View file

@ -0,0 +1,7 @@
namespace SWA
{
inline CMovieManager* CMovieManager::GetInstance()
{
return *(xpointer<CMovieManager>*)MmGetHostAddress(0x8336758C);
}
}

View file

@ -5,7 +5,7 @@
namespace SWA::Player
{
class CEvilSonic
class CEvilSonic // : public CPlayer
{
public:
SWA_INSERT_PADDING(0xC4);

View file

@ -18,12 +18,13 @@ namespace SWA::Player
eGuideType_Y
};
class CEvilHudGuide
class CEvilHudGuide : public CGameObject
{
public:
SWA_INSERT_PADDING(0x14D);
xpointer<void> m_pVftable;
SWA_INSERT_PADDING(0x8D);
bool m_IsShown;
bool m_IsVisible;
EGuideType m_GuideType;
be<EGuideType> m_GuideType;
};
}

View file

@ -0,0 +1,13 @@
#pragma once
#include <SWA.inl>
namespace SWA::Sequence::Unit
{
class CUnitBase : public Hedgehog::Base::CObject
{
public:
xpointer<void> m_pVftable;
SWA_INSERT_PADDING(0x14);
};
}

View file

@ -0,0 +1,8 @@
#pragma once
#include <SWA.inl>
namespace SWA::Sequence::Unit
{
class CPlayMovieUnit : public CUnitBase {};
}

View file

@ -0,0 +1,39 @@
#pragma once
#include "SWA.inl"
#include "Hedgehog/MirageCore/Renderable/hhRenderable.h"
namespace SWA::Sequence::Utility
{
class CPlayMovieWrapper
{
public:
class CRender : public Hedgehog::Mirage::CRenderable
{
public:
be<uint32_t> m_ScreenWidth;
be<uint32_t> m_ScreenHeight;
be<float> m_MovieWidth;
be<float> m_MovieHeight;
SWA_INSERT_PADDING(0x74);
be<float> m_TopLeftX;
be<float> m_TopLeftY;
SWA_INSERT_PADDING(0x0C);
be<float> m_TopRightX;
be<float> m_TopRightY;
SWA_INSERT_PADDING(0x0C);
be<float> m_BottomRightX;
be<float> m_BottomRightY;
SWA_INSERT_PADDING(0x0C);
be<float> m_BottomLeftX;
be<float> m_BottomLeftY;
SWA_INSERT_PADDING(0xD4);
bool m_MaintainAspectRatio;
SWA_INSERT_PADDING(0x18);
be<float> m_TimeElapsed;
};
SWA_INSERT_PADDING(0x18);
xpointer<CRender> m_pRender;
};
}

View file

@ -0,0 +1,56 @@
#pragma once
#include <SWA.inl>
#include <SWA/Sound/SoundBGMBase.h>
namespace SWA
{
class CSoundAdministrator : public CGameObject
{
public:
class CSimplePlayer {};
class CBgm
{
public:
xpointer<CSoundAdministrator> m_pThis;
boost::shared_ptr<CSoundBGMBase> m_spSoundBGM;
be<float> m_Volume1;
be<float> m_Volume2;
be<float> m_Volume3;
be<float> m_Volume4;
SWA_INSERT_PADDING(0x10);
};
class CCommunicator
{
public:
class CCommunicatorDevice : Hedgehog::Base::CSynchronizedObject
{
public:
SWA_INSERT_PADDING(0x08);
Hedgehog::Base::CSharedString m_HostName;
SWA_INSERT_PADDING(0x04);
Hedgehog::Base::CSharedString m_Category;
Hedgehog::Base::CSharedString m_Command;
SWA_INSERT_PADDING(0x04);
};
xpointer<CSoundAdministrator> m_pThis;
boost::shared_ptr<CCommunicatorDevice> m_spCommunicatorDevice;
};
class CMember
{
public:
boost::shared_ptr<CSimplePlayer> m_spSimplePlayer;
boost::shared_ptr<CBgm> m_spBgm;
boost::shared_ptr<CCommunicator> m_spCommunicator;
SWA_INSERT_PADDING(0x58);
};
xpointer<void> m_pVftable;
SWA_INSERT_PADDING(0x04);
xpointer<CMember> m_pMember;
};
}

View file

@ -0,0 +1,21 @@
#pragma once
#include <SWA.inl>
#include <SWA/Sound/SoundBGMBase.h>
namespace SWA
{
class CSoundBGMActSonic : public CSoundBGMBase
{
public:
class CMember
{
public:
SWA_INSERT_PADDING(0x58);
be<float> m_Volume1;
be<float> m_Volume2;
};
xpointer<CMember> m_pMember;
};
}

View file

@ -0,0 +1,15 @@
#pragma once
#include <SWA.inl>
namespace SWA
{
class CSoundBGMBase : Hedgehog::Universe::CMessageActor
{
public:
SWA_INSERT_PADDING(0x04); // vftable ptr
SWA_INSERT_PADDING(0x04);
xpointer<CGameDocument> m_pGameDocument;
bool m_Unk;
};
}

View file

@ -0,0 +1,21 @@
#pragma once
#include <SWA.inl>
#include <SWA/System/ApplicationDocument.h>
namespace SWA
{
class CApplication : public Hedgehog::Base::CObject
{
public:
class CMember
{
public:
xpointer<CApplicationDocument> m_pApplicationDocument;
};
xpointer<void> m_pVftable;
xpointer<CMember> m_pMember;
SWA_INSERT_PADDING(0x18);
};
}

View file

@ -0,0 +1,8 @@
#pragma once
#include <SWA.inl>
namespace SWA
{
class CApplicationD3D9 : public CApplication {};
}

View file

@ -1,24 +1,54 @@
#pragma once
#include <SWA.inl>
#include <SWA/System/Game.h>
namespace SWA
{
class CApplicationDocument // : public Hedgehog::Base::CSynchronizedObject
enum ELanguage : uint32_t
{
eLanguage_English,
eLanguage_Japanese,
eLanguage_German,
eLanguage_French,
eLanguage_Italian,
eLanguage_Spanish
};
enum EVoiceLanguage : uint32_t
{
eVoiceLanguage_English,
eVoiceLanguage_Japanese
};
enum ERegion : uint32_t
{
eRegion_Japan,
eRegion_RestOfWorld
};
class CApplicationDocument : public Hedgehog::Base::CSynchronizedObject
{
public:
class CMember
{
public:
SWA_INSERT_PADDING(0x138);
void* m_spGameParameter;
SWA_INSERT_PADDING(0x20);
boost::shared_ptr<CGame> m_pGame;
SWA_INSERT_PADDING(0x114);
xpointer<void> m_spGameParameter;
};
// TODO: Hedgehog::Base::TSynchronizedPtr<CApplicationDocument>
static CApplicationDocument* GetInstance();
SWA_INSERT_PADDING(0x04);
xpointer<CMember> m_pMember;
SWA_INSERT_PADDING(0x14);
be<uint32_t> m_Region;
be<ELanguage> m_Language;
be<EVoiceLanguage> m_VoiceLanguage;
SWA_INSERT_PADDING(0x08);
be<ERegion> m_Region;
bool m_InspireVoices;
bool m_InspireSubtitles;
};
}

View file

@ -0,0 +1,12 @@
#pragma once
#include <SWA.inl>
namespace SWA
{
class CApplicationXenon : public CApplicationD3D9
{
public:
SWA_INSERT_PADDING(0x1B4);
};
}

View file

@ -0,0 +1,10 @@
#pragma once
namespace SWA
{
class CGame // : Hedgehog::Universe::TStateMachine<SWA::CGame>
{
public:
SWA_INSERT_PADDING(0xFC);
};
}

View file

@ -1,21 +1,30 @@
#pragma once
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<Hedgehog::Database::CDatabase> m_spDatabase;
SWA_INSERT_PADDING(0x8C);
xpointer<CSoundAdministrator> m_pSoundAdministrator;
SWA_INSERT_PADDING(0x158);
be<uint32_t> m_Score;
};
// TODO: Hedgehog::Base::TSynchronizedPtr<CGameDocument>
static CGameDocument* GetInstance();
SWA_INSERT_PADDING(0x08);
xpointer<void> m_pVftable;
xpointer<CMember> m_pMember;
};
}

View file

@ -0,0 +1,13 @@
#pragma once
#include <SWA.inl>
namespace SWA
{
class CGameMode // : Hedgehog::Universe::TStateMachine<SWA::CGame>::TState
{
public:
SWA_INSERT_PADDING(0x60); // base
SWA_INSERT_PADDING(0x08);
};
}

View file

@ -0,0 +1,13 @@
#pragma once
#include <SWA.inl>
namespace SWA
{
class CGameModeStage : public CGameMode
{
public:
xpointer<void> m_pVftable;
SWA_INSERT_PADDING(0x1B4);
};
}

View file

@ -0,0 +1,20 @@
#pragma once
#include <SWA.inl>
namespace SWA
{
class CGameModeStageMovie : public CGameModeStage
{
public:
class CRender : public Hedgehog::Mirage::CRenderable
{
public:
xpointer<CGameModeStageMovie> m_pThis;
};
xpointer<void> m_pVftable;
SWA_INSERT_PADDING(0x224);
xpointer<CRender> m_pRender;
};
}

View file

@ -0,0 +1,13 @@
#pragma once
#include <SWA.inl>
namespace SWA
{
class CTitleMenu
{
public:
SWA_INSERT_PADDING(0x44);
be<uint32_t> m_CursorIndex;
};
}

View file

@ -0,0 +1,22 @@
#pragma once
#include <SWA.inl>
namespace SWA
{
class CTitleStateBase // : Hedgehog::Universe::TStateMachine<SWA::CTitleManager>::TState
{
public:
class CMember
{
public:
SWA_INSERT_PADDING(0x1E8);
xpointer<CTitleMenu> m_pTitleMenu;
};
SWA_INSERT_PADDING(0x08);
xpointer<CMember> m_pMember;
SWA_INSERT_PADDING(0x5C);
be<uint32_t> m_State;
};
}

View file

@ -0,0 +1,27 @@
#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<CGameDocument> m_pGameDocument;
Hedgehog::Base::TSynchronizedPtr<CWorld> m_pWorld;
SWA_INSERT_PADDING(0x70);
};
xpointer<void> m_pVftable;
xpointer<CMember> m_pMember;
};
}

View file

@ -5,16 +5,14 @@
namespace SWA
{
class CInputState // : public Hedgehog::Base::CSynchronizedObject
class CInputState : public Hedgehog::Base::CSynchronizedObject
{
public:
// TODO: Hedgehog::Base::TSynchronizedPtr<CInputState>
static CInputState* GetInstance();
SPadState m_PadStates[40];
SWA_INSERT_PADDING(0x50);
SPadState m_PadStates[8];
be<uint32_t> m_CurrentPadStateIndex;
SWA_INSERT_PADDING(0x04);
const SPadState& GetPadState() const;
};

View file

@ -3,7 +3,7 @@ namespace SWA
// TODO: Hedgehog::Base::TSynchronizedPtr<CInputState>
inline CInputState* CInputState::GetInstance()
{
return *(xpointer<CInputState>*)MmGetHostAddress(0x833671EC);
return *(xpointer<CInputState>*)MmGetHostAddress(0x83361F5C);
}
inline const SPadState& CInputState::GetPadState() const

View file

@ -43,15 +43,11 @@ namespace SWA
struct SPadState
{
SWA_INSERT_PADDING(0x20);
be<uint32_t> DownState;
be<uint32_t> UpState;
be<uint32_t> TappedState;
be<uint32_t> ReleasedState;
SWA_INSERT_PADDING(0x04);
be<float> LeftStickHorizontal;
be<float> LeftStickVertical;
@ -65,7 +61,7 @@ namespace SWA
be<float> LeftTrigger;
be<float> RightTrigger;
SWA_INSERT_PADDING(0x20);
SWA_INSERT_PADDING(0x08);
bool IsDown(const EKeyState in_Keys) const;
bool IsUp(const EKeyState in_Keys) const;

View file

@ -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<CMember> m_pMember;
};
}

View file

@ -0,0 +1,12 @@
#pragma once
#include "boost/smart_ptr/shared_ptr.h"
namespace boost
{
template<typename T, typename... TArgs>
shared_ptr<T> make_shared(TArgs&&... args)
{
return shared_ptr<T>(new T(std::forward<TArgs>(args)...));
}
}

View file

@ -0,0 +1,164 @@
#pragma once
#include <cstddef>
#include <utility>
namespace boost
{
namespace detail
{
class sp_counted_base
{
protected:
struct vftable_t
{
be<uint32_t> destructor;
be<uint32_t> dispose;
be<uint32_t> destroy;
be<uint32_t> get_deleter;
};
xpointer<vftable_t> vftable_;
be<uint32_t> use_count_;
be<uint32_t> weak_count_;
public:
// TODO
sp_counted_base() = delete;
void add_ref()
{
be<uint32_t> original, incremented;
do
{
original = use_count_;
incremented = original + 1;
} while (InterlockedCompareExchange((unsigned long*)&use_count_, incremented.value, original.value) != original.value);
}
void release()
{
be<uint32_t> original, decremented;
do
{
original = use_count_;
decremented = original - 1;
} while (InterlockedCompareExchange((unsigned long*)&use_count_, decremented.value, original.value) != original.value);
if (decremented == 0)
{
GuestToHostFunction<void>(vftable_->dispose, this);
weak_release();
}
}
void weak_release()
{
be<uint32_t> original, decremented;
do
{
original = weak_count_;
decremented = original - 1;
} while (InterlockedCompareExchange((unsigned long*)&weak_count_, decremented.value, original.value) != original.value);
if (decremented == 0)
{
GuestToHostFunction<void>(vftable_->destroy, this);
}
}
uint32_t use_count() const
{
return use_count_;
}
};
template< class T > struct sp_dereference
{
typedef T& type;
};
template<> struct sp_dereference< void >
{
typedef void type;
};
}
template<typename T>
class shared_ptr
{
private:
xpointer<T> px;
xpointer<boost::detail::sp_counted_base> pn;
void add_ref()
{
if (pn)
pn->add_ref();
}
void release()
{
if (pn)
pn->release();
}
public:
shared_ptr() : px(nullptr), pn(nullptr) {}
// TODO
explicit shared_ptr(T* p) = delete;
shared_ptr(const shared_ptr& other) : px(other.px), pn(other.pn)
{
add_ref();
}
shared_ptr(shared_ptr&& other) noexcept : px(std::exchange(other.px, nullptr)),
pn(std::exchange(other.pn, nullptr)) {}
~shared_ptr()
{
release();
}
shared_ptr& operator=(const shared_ptr& other)
{
if (this != &other)
{
release();
px = other.px;
pn = other.pn;
add_ref();
}
return *this;
}
shared_ptr& operator=(shared_ptr&& other) noexcept
{
if (this != &other)
{
release();
px = std::exchange(other.px, nullptr);
pn = std::exchange(other.pn, nullptr);
}
return *this;
}
T* get() const { return px; }
detail::sp_dereference<T> operator*() const { assert(px); return *px; }
T* operator->() const { assert(px); return px; }
explicit operator bool() const { return px != nullptr; }
size_t use_count() const { return pn ? pn->use_count() : 0; }
};
using anonymous_shared_ptr = shared_ptr<void>;
}

View file

@ -0,0 +1,123 @@
#pragma once
#include "ppc_context.h"
#include <kernel/memory.h>
// DO NOT use this type as anything other than a local variable.
// This includes returning. It'll cause memory to leak in the guest stack!
template<typename T, bool Init = true>
class guest_stack_var
{
private:
uint32_t m_ptr = NULL;
uint32_t m_oldStackPtr = NULL;
void AllocGuestStackMemory()
{
auto ctx = GetPPCContext();
m_oldStackPtr = ctx->r1.u32;
m_ptr = (ctx->r1.u32 - sizeof(T)) & ~(std::max<uint32_t>(alignof(T), 8) - 1);
ctx->r1.u32 = m_ptr;
}
public:
T* get()
{
return reinterpret_cast<T*>(g_memory.Translate(m_ptr));
}
const T* get() const
{
return reinterpret_cast<const T*>(g_memory.Translate(m_ptr));
}
template<typename... Args>
guest_stack_var(Args&&... args)
{
AllocGuestStackMemory();
if (Init)
new (get()) T(std::forward<Args>(args)...);
}
guest_stack_var(const guest_stack_var<T>& other)
{
AllocGuestStackMemory();
if (Init)
new (get()) T(*other->get());
}
guest_stack_var(guest_stack_var<T>&& other)
{
AllocGuestStackMemory();
if (Init)
new (get()) T(std::move(*other->get()));
}
~guest_stack_var()
{
get()->~T();
auto ctx = GetPPCContext();
// This assert will fail if the type was used as anything other than a local variable.
assert(ctx->r1.u32 == m_ptr);
ctx->r1.u32 = m_oldStackPtr;
}
void operator=(const guest_stack_var<T>& other)
{
if (this != &other)
*get() = *other->get();
}
void operator=(guest_stack_var<T>&& other)
{
if (this != &other)
*get() = std::move(*other->get());
}
void operator=(const T& other)
{
if (get() != &other)
*get() = *other;
}
void operator=(T&& other)
{
if (get() != &other)
*get() = std::move(*other);
}
operator const T* () const
{
return get();
}
operator T* ()
{
return get();
}
const T* operator->() const
{
return get();
}
T* operator->()
{
return get();
}
const T& operator*() const
{
return *get();
}
T& operator*()
{
return *get();
}
};

View file

@ -935,23 +935,23 @@ static void ProcSetRenderState(const RenderCommand& cmd)
static const std::pair<GuestRenderState, void*> g_setRenderStateFunctions[] =
{
{ D3DRS_ZENABLE, GuestFunction<SetRenderState<D3DRS_ZENABLE>> },
{ D3DRS_ZWRITEENABLE, GuestFunction<SetRenderState<D3DRS_ZWRITEENABLE>> },
{ D3DRS_ALPHATESTENABLE, GuestFunction<SetRenderState<D3DRS_ALPHATESTENABLE>> },
{ D3DRS_SRCBLEND, GuestFunction<SetRenderState<D3DRS_SRCBLEND>> },
{ D3DRS_DESTBLEND, GuestFunction<SetRenderState<D3DRS_DESTBLEND>> },
{ D3DRS_CULLMODE, GuestFunction<SetRenderState<D3DRS_CULLMODE>> },
{ D3DRS_ZFUNC, GuestFunction<SetRenderState<D3DRS_ZFUNC>> },
{ D3DRS_ALPHAREF, GuestFunction<SetRenderState<D3DRS_ALPHAREF>> },
{ D3DRS_ALPHABLENDENABLE, GuestFunction<SetRenderState<D3DRS_ALPHABLENDENABLE>> },
{ D3DRS_BLENDOP, GuestFunction<SetRenderState<D3DRS_BLENDOP>> },
{ D3DRS_SCISSORTESTENABLE, GuestFunction<SetRenderState<D3DRS_SCISSORTESTENABLE>> },
{ D3DRS_SLOPESCALEDEPTHBIAS, GuestFunction<SetRenderState<D3DRS_SLOPESCALEDEPTHBIAS>> },
{ D3DRS_DEPTHBIAS, GuestFunction<SetRenderState<D3DRS_DEPTHBIAS>> },
{ D3DRS_SRCBLENDALPHA, GuestFunction<SetRenderState<D3DRS_SRCBLENDALPHA>> },
{ D3DRS_DESTBLENDALPHA, GuestFunction<SetRenderState<D3DRS_DESTBLENDALPHA>> },
{ D3DRS_BLENDOPALPHA, GuestFunction<SetRenderState<D3DRS_BLENDOPALPHA>> },
{ D3DRS_COLORWRITEENABLE, GuestFunction<SetRenderState<D3DRS_COLORWRITEENABLE>> }
{ D3DRS_ZENABLE, HostToGuestFunction<SetRenderState<D3DRS_ZENABLE>> },
{ D3DRS_ZWRITEENABLE, HostToGuestFunction<SetRenderState<D3DRS_ZWRITEENABLE>> },
{ D3DRS_ALPHATESTENABLE, HostToGuestFunction<SetRenderState<D3DRS_ALPHATESTENABLE>> },
{ D3DRS_SRCBLEND, HostToGuestFunction<SetRenderState<D3DRS_SRCBLEND>> },
{ D3DRS_DESTBLEND, HostToGuestFunction<SetRenderState<D3DRS_DESTBLEND>> },
{ D3DRS_CULLMODE, HostToGuestFunction<SetRenderState<D3DRS_CULLMODE>> },
{ D3DRS_ZFUNC, HostToGuestFunction<SetRenderState<D3DRS_ZFUNC>> },
{ D3DRS_ALPHAREF, HostToGuestFunction<SetRenderState<D3DRS_ALPHAREF>> },
{ D3DRS_ALPHABLENDENABLE, HostToGuestFunction<SetRenderState<D3DRS_ALPHABLENDENABLE>> },
{ D3DRS_BLENDOP, HostToGuestFunction<SetRenderState<D3DRS_BLENDOP>> },
{ D3DRS_SCISSORTESTENABLE, HostToGuestFunction<SetRenderState<D3DRS_SCISSORTESTENABLE>> },
{ D3DRS_SLOPESCALEDEPTHBIAS, HostToGuestFunction<SetRenderState<D3DRS_SLOPESCALEDEPTHBIAS>> },
{ D3DRS_DEPTHBIAS, HostToGuestFunction<SetRenderState<D3DRS_DEPTHBIAS>> },
{ D3DRS_SRCBLENDALPHA, HostToGuestFunction<SetRenderState<D3DRS_SRCBLENDALPHA>> },
{ D3DRS_DESTBLENDALPHA, HostToGuestFunction<SetRenderState<D3DRS_DESTBLENDALPHA>> },
{ D3DRS_BLENDOPALPHA, HostToGuestFunction<SetRenderState<D3DRS_BLENDOPALPHA>> },
{ D3DRS_COLORWRITEENABLE, HostToGuestFunction<SetRenderState<D3DRS_COLORWRITEENABLE>> }
};
static std::unique_ptr<RenderPipeline> g_resolveMsaaDepthPipelines[3];
@ -1407,7 +1407,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<void*>(GuestFunction<SetRenderStateUnimplemented>));
g_codeCache.Insert(functionOffset, reinterpret_cast<void*>(HostToGuestFunction<SetRenderStateUnimplemented>));
for (size_t i = 0; i < _countof(device->setRenderStateFunctions); i++)
device->setRenderStateFunctions[i] = functionOffset;
@ -3831,8 +3831,8 @@ void SetShadowResolutionMidAsmHook(PPCRegister& r11)
static void SetResolution(be<uint32_t>* device)
{
uint32_t width = uint32_t(g_swapChain->getWidth() * Config::ResolutionScale);
uint32_t height = uint32_t(g_swapChain->getHeight() * Config::ResolutionScale);
uint32_t width = uint32_t(round(g_swapChain->getWidth() * Config::ResolutionScale));
uint32_t height = uint32_t(round(g_swapChain->getHeight() * Config::ResolutionScale));
device[46] = width == 0 ? 880 : width;
device[47] = height == 0 ? 720 : height;
}

View file

@ -1,7 +1,9 @@
#pragma once
#include <cpu/ppc_context.h>
#include <array>
#include "xbox.h"
#include "memory.h"
template <typename R, typename... T>
constexpr std::tuple<T...> 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<typename T>
FORCEINLINE constexpr static std::enable_if_t<!std::is_pointer_v<T>, T> GetValue(PPCContext& ctx, uint8_t* base, size_t idx) noexcept
{
@ -106,6 +152,39 @@ struct ArgTranslator
return reinterpret_cast<T>(base + static_cast<uint32_t>(v));
}
template<typename T>
FORCEINLINE constexpr static std::enable_if_t<!std::is_pointer_v<T>, void> SetValue(PPCContext& ctx, uint8_t* base, size_t idx, T value) noexcept
{
if constexpr (is_precise_v<T>)
{
SetPrecisionArgumentValue(ctx, base, idx, value);
}
else if constexpr (std::is_null_pointer_v<T>)
{
SetIntegerArgumentValue(ctx, base, idx, 0);
}
else if constexpr (std::is_pointer_v<T>)
{
SetIntegerArgumentValue(ctx, base, idx, g_memory.MapVirtual(value));
}
else
{
SetIntegerArgumentValue(ctx, base, idx, value);
}
}
template<typename T>
FORCEINLINE constexpr static std::enable_if_t<std::is_pointer_v<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
@ -114,10 +193,10 @@ struct Argument
int ordinal{};
};
template<auto Func>
constexpr std::array<Argument, arg_count_t<Func>::value> GatherFunctionArguments()
template<typename T1>
constexpr std::array<Argument, std::tuple_size_v<T1>> GatherFunctionArguments(const T1& tpl)
{
std::array<Argument, arg_count_t<Func>::value> args{};
std::array<Argument, std::tuple_size_v<T1>> args{};
int floatOrdinal{};
size_t i{};
@ -126,9 +205,9 @@ constexpr std::array<Argument, arg_count_t<Func>::value> GatherFunctionArguments
{
std::apply([&](const auto& first, const auto&... rest)
{
auto append = [&]<typename T>(const T & v)
auto append = [&]<typename T2>(const T2& v)
{
if constexpr (is_precise_v<T>)
if constexpr (is_precise_v<T2>)
{
args[i] = { 1, floatOrdinal++ };
}
@ -142,12 +221,18 @@ constexpr std::array<Argument, arg_count_t<Func>::value> GatherFunctionArguments
append(first);
(append(rest), ...);
}, function_args(Func));
}, tpl);
}
return args;
}
template<auto Func>
constexpr std::array<Argument, arg_count_t<Func>::value> GatherFunctionArguments()
{
return GatherFunctionArguments(function_args(Func));
}
template<auto Func, size_t I>
struct arg_ordinal_t
{
@ -155,27 +240,42 @@ struct arg_ordinal_t
};
template<auto Func, int I = 0, typename ...TArgs>
FORCEINLINE void _translate_args(PPCContext& ctx, uint8_t* base, std::tuple<TArgs...>&) noexcept
FORCEINLINE void _translate_args_to_host(PPCContext& ctx, uint8_t* base, std::tuple<TArgs...>&) noexcept
requires (I >= sizeof...(TArgs))
{
}
template <auto Func, int I = 0, typename ...TArgs>
FORCEINLINE std::enable_if_t<(I < sizeof...(TArgs)), void> _translate_args(PPCContext& ctx, uint8_t* base, std::tuple<TArgs...>& tpl) noexcept
FORCEINLINE std::enable_if_t<(I < sizeof...(TArgs)), void> _translate_args_to_host(PPCContext& ctx, uint8_t* base, std::tuple<TArgs...>& tpl) noexcept
{
using T = std::tuple_element_t<I, std::remove_reference_t<decltype(tpl)>>;
std::get<I>(tpl) = ArgTranslator::GetValue<T>(ctx, base, arg_ordinal_t<Func, I>::value);
_translate_args<Func, I + 1>(ctx, base, tpl);
_translate_args_to_host<Func, I + 1>(ctx, base, tpl);
}
template<int I = 0, typename ...TArgs>
FORCEINLINE void _translate_args_to_guest(PPCContext& ctx, uint8_t* base, std::tuple<TArgs...>&) noexcept
requires (I >= sizeof...(TArgs))
{
}
template <int I = 0, typename ...TArgs>
FORCEINLINE std::enable_if_t<(I < sizeof...(TArgs)), void> _translate_args_to_guest(PPCContext& ctx, uint8_t* base, std::tuple<TArgs...>& tpl) noexcept
{
using T = std::tuple_element_t<I, std::remove_reference_t<decltype(tpl)>>;
ArgTranslator::SetValue<T>(ctx, base, GatherFunctionArguments(std::tuple<TArgs...>{})[I].ordinal, std::get<I>(tpl));
_translate_args_to_guest<I + 1>(ctx, base, tpl);
}
template<auto Func>
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<Func>(ctx, base, args);
_translate_args_to_host<Func>(ctx, base, args);
if constexpr (std::is_same_v<ret_t, void>)
{
@ -207,8 +307,54 @@ FORCEINLINE PPC_FUNC(GuestFunction)
}
}
template<typename T, typename TFunction, typename... TArgs>
FORCEINLINE T GuestToHostFunction(const TFunction& func, TArgs&&... argv)
{
auto args = std::make_tuple(std::forward<TArgs>(argv)...);
auto& currentCtx = *GetPPCContext();
PPCContext newCtx; // NOTE: No need for zero initialization, has lots of unnecessary code generation.
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);
if constexpr (std::is_function_v<TFunction>)
func(newCtx, (uint8_t*)g_memory.base);
else
(*(PPCFunc**)(newCtx.fn + uint64_t(func) * 2))(newCtx, (uint8_t*)g_memory.base);
currentCtx.fpscr = newCtx.fpscr;
SetPPCContext(currentCtx);
if constexpr (std::is_void_v<T>)
{
return;
}
else if constexpr (std::is_pointer_v<T>)
{
return reinterpret_cast<T>((uint64_t)g_memory.Translate(newCtx.r3.u32));
}
else if constexpr (is_precise_v<T>)
{
return static_cast<T>(newCtx.f1.f64);
}
else if constexpr (std::is_integral_v<T>)
{
return static_cast<T>(newCtx.r3.u64);
}
else
{
static_assert(false, "Unsupported return type.");
}
}
#define GUEST_FUNCTION_HOOK(subroutine, function) \
PPC_FUNC(subroutine) { GuestFunction<function>(ctx, base); }
PPC_FUNC(subroutine) { HostToGuestFunction<function>(ctx, base); }
#define GUEST_FUNCTION_STUB(subroutine) \
PPC_FUNC(subroutine) { }

View file

@ -1,7 +1,6 @@
#pragma once
#include "mutex.h"
#include <o1heap.h>
struct Heap
{

View file

@ -16,11 +16,17 @@ public:
void* Translate(size_t offset) const noexcept
{
if (offset)
assert(offset < 0x100000000ull);
return base + offset;
}
uint32_t MapVirtual(void* host) const noexcept
{
if (host)
assert(host >= base && host < (base + size));
return static_cast<uint32_t>(static_cast<char*>(host) - base);
}
};

View file

@ -26,6 +26,7 @@
#include <imgui.h>
#include <imgui_internal.h>
#include <imgui_impl_sdl2.h>
#include <o1heap.h>
#include "framework.h"
#include "mutex.h"

@ -1 +1 @@
Subproject commit d8676283fd1e8990b415cc0e4810c6db895b9fba
Subproject commit 7dd4f91ac635b001a56cc7a27af48f0436bbad3f