summaryrefslogtreecommitdiff
path: root/src/egg/core/eggAssertHeap.cpp
blob: 83afa1949e66db1ea8a4516c045eccb506560265 (plain)
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include "egg/core/eggAssertHeap.h"

namespace EGG {

AssertHeap::AssertHeap(MEMiHeapHead *pHead) : Heap(pHead) {}

AssertHeap::~AssertHeap() {
    dispose();
    MEMDestroyFrmHeap(mHeapHandle);
}

AssertHeap *AssertHeap::create(void *pBlock, u32 size) {
    AssertHeap *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(AssertHeap), ((u8 *)heapEnd - (u8 *)pBlock) - sizeof(AssertHeap), 0);
    if (head != nullptr) {
        heap = new (pBlock) AssertHeap(head);
        heap->mParentBlock = startAddr;
        if (sCreateCallback != nullptr) {
            (sCreateCallback)(heap);
        }
    }

    return heap;
}

AssertHeap *AssertHeap::create(u32 size, Heap *pHeap) {
    AssertHeap *assertHeap = nullptr;

    if (!pHeap) {
        pHeap = sCurrentHeap;
    }
    if (size == -1) {
        size = pHeap->getAllocatableSize(4);
    } else if (size == 0) {
        size = getSize();
    }

    void *pBlock = pHeap->alloc(size, 4);
    if (pBlock) {
        assertHeap = create(pBlock, size);
        if (!assertHeap) {
            pHeap->free(pBlock);
        }
    }

    return assertHeap;
}

void AssertHeap::destroy() {
    if (sDestroyCallback) {
        sDestroyCallback(this);
    }

    Heap *parent = findParentHeap();
    this->~AssertHeap();
    if (parent) {
        parent->free(this);
    }
}

void *AssertHeap::alloc(u32 size, s32 align) {
    if (sAllocCallback) {
        HeapAllocArg arg;
        arg.userArg = sAllocCallbackArg;
        arg.size = size;
        arg.align = align;
        arg.heap = this;
        arg.ptr = nullptr;
        sAllocCallback(&arg);
    }
    return nullptr;
}

void AssertHeap::free(void *pBlock) {
    if (sFreeCallback != nullptr) {
        HeapFreeArg arg;
        arg.userArg = sFreeCallbackArg;
        arg.ptr = pBlock;
        arg.heap = this;
        (sFreeCallback)(&arg);
    }
}

u32 AssertHeap::resizeForMBlock(void *pBlock, u32 size) {
    return 0;
}

u32 AssertHeap::getTotalFreeSize() {
    return 0;
}

u32 AssertHeap::getAllocatableSize(s32 align) {
    return 0;
}

u32 AssertHeap::adjust() {
    u32 adjustedSize = MEMAdjustFrmHeap(mHeapHandle);
    u32 totalSize = adjustedSize + sizeof(AssertHeap);
    if (totalSize > sizeof(AssertHeap)) {
        Heap *parent = findParentHeap();
        if (parent != nullptr) {
            parent->resizeForMBlock(mParentBlock, totalSize);
            return totalSize;
        }
    }
    return 0;
}

size_t AssertHeap::getSize() {
    return 0x7C;
}

Heap::eHeapKind AssertHeap::getHeapKind() const {
    return HEAP_KIND_ASSERT;
}

} // namespace EGG