A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
ExpHeap.cc
1#include "ExpHeap.hh"
2
3#include <limits>
4
5using namespace Abstract::Memory;
6
7namespace EGG {
8
9ExpHeap::ExpHeap(MEMiHeapHead *handle) : Heap(handle) {}
10
12ExpHeap::~ExpHeap() {
13 dispose();
14 dynamicCastHandleToExp()->destroy();
15}
16
18ExpHeap *ExpHeap::create(void *startAddress, size_t size, u16 opt) {
19 ExpHeap *heap = nullptr;
20 void *buffer = startAddress;
21
22 void *endAddress = RoundDown(AddOffset(startAddress, size), 4);
23 startAddress = RoundUp(startAddress, 4);
24
25 size_t addrRange = GetAddrNum(endAddress) - GetAddrNum(startAddress);
26 if (startAddress > endAddress || addrRange < sizeof(ExpHeap) + 4) {
27 return nullptr;
28 }
29
30 void *handleStart = AddOffset(startAddress, sizeof(ExpHeap));
31 MEMiExpHeapHead *handle =
32 MEMiExpHeapHead::create(handleStart, addrRange - sizeof(ExpHeap), opt);
33 if (handle) {
34 heap = new (startAddress) ExpHeap(handle);
35 heap->registerHeapBuffer(buffer);
36 }
37
38 return heap;
39}
40
42ExpHeap *ExpHeap::create(size_t size, Heap *pHeap, u16 opt) {
43 ExpHeap *heap = nullptr;
44
45 if (!pHeap) {
46 pHeap = Heap::getCurrentHeap();
47 }
48
49 if (size == std::numeric_limits<size_t>::max()) {
50 size = pHeap->getAllocatableSize();
51 }
52
53 void *block = pHeap->alloc(size, 4);
54 if (block) {
55 heap = create(block, size, opt);
56 if (heap) {
57 heap->setParentHeap(pHeap);
58 } else {
59 pHeap->free(block);
60 }
61 }
62
63 return heap;
64}
65
67void ExpHeap::destroy() {
68 Heap *pParent = getParentHeap();
69 this->~ExpHeap();
70 if (pParent) {
71 pParent->free(this);
72 }
73}
74
76void *ExpHeap::alloc(size_t size, s32 align) {
77 if (tstDisableAllocation()) {
78 PANIC("HEAP ALLOC FAIL (%p, %s): Heap is locked", this, m_name);
79 }
80
81 return dynamicCastHandleToExp()->alloc(size, align);
82}
83
85void ExpHeap::free(void *block) {
86 dynamicCastHandleToExp()->free(block);
87}
88
90u32 ExpHeap::getAllocatableSize(s32 align) const {
91 return dynamicCastHandleToExp()->getAllocatableSize(align);
92}
93
95void ExpHeap::addGroupSize(void *block, MEMiHeapHead * /* heap */, uintptr_t param) {
96 MEMiExpBlockHead *blockHead =
97 static_cast<MEMiExpBlockHead *>(SubOffset(block, sizeof(MEMiExpBlockHead)));
98 u16 groupID = blockHead->m_attribute.fields.groupId;
99
100 GroupSizeRecord *record = reinterpret_cast<GroupSizeRecord *>(param);
101 record->addSize(groupID, blockHead->m_size);
102}
103
105void ExpHeap::calcGroupSize(GroupSizeRecord *record) {
106 record->reset();
107 dynamicCastHandleToExp()->visitAllocated(addGroupSize, GetAddrNum(record));
108}
109
111void ExpHeap::setGroupID(u16 groupID) {
112 return dynamicCastHandleToExp()->setGroupID(groupID);
113}
114
115u16 ExpHeap::getGroupID() const {
116 return dynamicCastHandleToExp()->getGroupID();
117}
118
119MEMiExpHeapHead *ExpHeap::dynamicCastHandleToExp() {
120 return reinterpret_cast<MEMiExpHeapHead *>(m_handle);
121}
122
123const MEMiExpHeapHead *ExpHeap::dynamicCastHandleToExp() const {
124 return reinterpret_cast<MEMiExpHeapHead *>(m_handle);
125}
126
128ExpHeap::GroupSizeRecord::GroupSizeRecord() {
129 reset();
130}
131
133void ExpHeap::GroupSizeRecord::reset() {
134 for (auto &entry : m_entries) {
135 entry = 0;
136 }
137}
138
139size_t ExpHeap::GroupSizeRecord::getGroupSize(u16 groupID) const {
140 return m_entries[groupID];
141}
142
144void ExpHeap::GroupSizeRecord::addSize(u16 groupID, size_t size) {
145 m_entries[groupID] += size;
146}
147
148} // namespace EGG
Low-level implementation of a memory heap for managing dynamic memory allocation. Allocation may occu...
Definition ExpHeap.hh:72
A low-level representation of a memory heap for managing dynamic memory allocation....
Definition HeapCommon.hh:13
EGG core library.
Definition Archive.cc:6
Head of the memory block. Contains information about the block and a link in the corresponding used/f...
Definition ExpHeap.hh:38