mirror of
https://github.com/zeldaret/ss
synced 2026-05-28 00:15:59 -04:00
138 lines
2.9 KiB
C++
138 lines
2.9 KiB
C++
#include "nw4r/snd/snd_FrameHeap.h"
|
|
#include <new>
|
|
|
|
namespace nw4r {
|
|
namespace snd {
|
|
namespace detail {
|
|
|
|
FrameHeap::FrameHeap() : mHandle(NULL) {}
|
|
|
|
FrameHeap::~FrameHeap() {
|
|
if (IsValid()) {
|
|
Destroy();
|
|
}
|
|
}
|
|
|
|
bool FrameHeap::Create(void* pBase, u32 size) {
|
|
if (IsValid()) {
|
|
Destroy();
|
|
}
|
|
|
|
void* pEnd = static_cast<u8*>(pBase) + size;
|
|
pBase = ut::RoundUp(pBase, 4);
|
|
if (pBase > pEnd) {
|
|
return false;
|
|
}
|
|
|
|
mHandle = MEMCreateFrmHeap(pBase, ut::GetOffsetFromPtr(pBase, pEnd));
|
|
if (mHandle == NULL) {
|
|
return false;
|
|
}
|
|
|
|
if (!NewSection()) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void FrameHeap::Destroy() {
|
|
if (!IsValid()) {
|
|
return;
|
|
}
|
|
|
|
ClearSection();
|
|
MEMFreeToFrmHeap(mHandle, MEM_FRM_HEAP_FREE_ALL);
|
|
|
|
MEMDestroyFrmHeap(mHandle);
|
|
mHandle = NULL;
|
|
}
|
|
|
|
void FrameHeap::Clear() {
|
|
ClearSection();
|
|
MEMFreeToFrmHeap(mHandle, MEM_FRM_HEAP_FREE_ALL);
|
|
|
|
NewSection();
|
|
}
|
|
|
|
void* FrameHeap::Alloc(u32 size, FreeCallback pCallback, void* pCallbackArg) {
|
|
void* pBuffer = MEMAllocFromFrmHeapEx(
|
|
mHandle, BLOCK_BUFFER_SIZE + ut::RoundUp(size, HEAP_ALIGN), HEAP_ALIGN);
|
|
|
|
if (pBuffer == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
void *pBuffer2 = ut::AddOffsetToPtr(pBuffer, BLOCK_BUFFER_SIZE);
|
|
Block* pBlock = new (pBuffer) Block(pBuffer2, size, pCallback, pCallbackArg);
|
|
mSectionList.GetBack().AppendBlock(pBlock);
|
|
|
|
return pBuffer2;
|
|
}
|
|
|
|
int FrameHeap::SaveState() {
|
|
if (!MEMRecordStateForFrmHeap(mHandle, mSectionList.GetSize())) {
|
|
return -1;
|
|
}
|
|
|
|
if (!NewSection()) {
|
|
MEMFreeByStateToFrmHeap(mHandle, 0);
|
|
return -1;
|
|
}
|
|
|
|
return GetCurrentLevel();
|
|
}
|
|
|
|
void FrameHeap::LoadState(int id) {
|
|
if (id == 0) {
|
|
Clear();
|
|
return;
|
|
}
|
|
|
|
while (id < static_cast<int>(mSectionList.GetSize())) {
|
|
Section& rSection = mSectionList.GetBack();
|
|
rSection.~Section();
|
|
mSectionList.Erase(&rSection);
|
|
}
|
|
|
|
MEMFreeByStateToFrmHeap(mHandle, id);
|
|
MEMRecordStateForFrmHeap(mHandle, mSectionList.GetSize());
|
|
|
|
NewSection();
|
|
}
|
|
|
|
int FrameHeap::GetCurrentLevel() const {
|
|
return mSectionList.GetSize() - 1;
|
|
}
|
|
|
|
u32 FrameHeap::GetFreeSize() const {
|
|
u32 freeSize = MEMGetAllocatableSizeForFrmHeapEx(mHandle, HEAP_ALIGN);
|
|
if (freeSize < sizeof(Block)) {
|
|
return 0;
|
|
}
|
|
|
|
return ut::RoundDown(freeSize - sizeof(Block), HEAP_ALIGN);
|
|
}
|
|
|
|
bool FrameHeap::NewSection() {
|
|
void* pSection = MEMAllocFromFrmHeap(mHandle, sizeof(Section));
|
|
if (pSection == NULL) {
|
|
return false;
|
|
}
|
|
|
|
mSectionList.PushBack(new (pSection) Section());
|
|
return true;
|
|
}
|
|
|
|
void FrameHeap::ClearSection() {
|
|
while (!mSectionList.IsEmpty()) {
|
|
Section& rSection = mSectionList.GetBack();
|
|
rSection.~Section();
|
|
mSectionList.Erase(&rSection);
|
|
}
|
|
}
|
|
|
|
} // namespace detail
|
|
} // namespace snd
|
|
} // namespace nw4r
|