1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
#include "egg/core/eggFrmHeap.h"
namespace EGG {
FrmHeap::FrmHeap(MEMiHeapHead *pHead) : Heap(pHead) {}
FrmHeap::~FrmHeap() {
dispose();
MEMDestroyFrmHeap(mHeapHandle);
}
FrmHeap *FrmHeap::create(void *pBlock, u32 size, u16 attr) {
FrmHeap *heap = nullptr;
void *startAddr = pBlock;
void *heapEnd = ROUND_DOWN_PTR((u8 *)pBlock + size, 0x04);
pBlock = ROUND_UP_PTR(pBlock, 0x04);
if (pBlock > heapEnd || ((u8 *)heapEnd - (u8 *)pBlock) < 0x38u) {
return nullptr;
}
MEMiHeapHead *head =
MEMCreateFrmHeapEx((u8 *)pBlock + sizeof(FrmHeap), ((u8 *)heapEnd - (u8 *)pBlock) - sizeof(FrmHeap), attr);
if (head != nullptr) {
heap = new (pBlock) FrmHeap(head);
heap->mParentBlock = startAddr;
if (sCreateCallback != nullptr) {
(sCreateCallback)(heap);
}
}
return heap;
}
void FrmHeap::destroy() {
if (sDestroyCallback) {
sDestroyCallback(this);
}
Heap *parent = findParentHeap();
this->~FrmHeap();
if (parent) {
parent->free(this);
}
}
void *FrmHeap::alloc(u32 size, s32 align) {
void *pBlock = MEMAllocFromFrmHeapEx(mHeapHandle, size, align);
if (sAllocCallback) {
HeapAllocArg arg;
arg.userArg = sAllocCallbackArg;
arg.ptr = pBlock;
arg.size = size;
arg.align = align;
arg.heap = this;
sAllocCallback(&arg);
}
return pBlock;
}
void FrmHeap::free(void *pBlock) {
if (sFreeCallback != nullptr) {
HeapFreeArg arg;
arg.userArg = sFreeCallbackArg;
arg.ptr = pBlock;
arg.heap = this;
(sFreeCallback)(&arg);
}
}
void FrmHeap::free(s32 flags) {
MEMFreeToFrmHeap(mHeapHandle, flags);
}
u32 FrmHeap::resizeForMBlock(void *pBlock, u32 size) {
return MEMResizeForMBlockFrmHeap(mHeapHandle, pBlock, size);
}
u32 FrmHeap::getTotalFreeSize() {
return getAllocatableSize(4);
}
u32 FrmHeap::getAllocatableSize(s32 align) {
return MEMGetAllocatableSizeForFrmHeapEx(mHeapHandle, align);
}
u32 FrmHeap::adjust() {
u32 adjustedSize = MEMAdjustFrmHeap(mHeapHandle);
u32 totalSize = adjustedSize + sizeof(FrmHeap);
if (totalSize > sizeof(FrmHeap)) {
Heap *parent = findParentHeap();
if (parent != nullptr) {
parent->resizeForMBlock(mParentBlock, totalSize);
return totalSize;
}
}
return 0;
}
void FrmHeap::recordState(u32 id) {
MEMRecordStateForFrmHeap(mHeapHandle, id);
}
void FrmHeap::freeByState(u32 id) {
MEMFreeByStateToFrmHeap(mHeapHandle, id);
}
Heap::eHeapKind FrmHeap::getHeapKind() const {
return HEAP_KIND_FRAME;
}
} // namespace EGG
|