summaryrefslogtreecommitdiff
path: root/src/m/m_heap.cpp
diff options
context:
space:
mode:
authorrobojumper <robojumper@gmail.com>2024-04-27 15:43:31 +0200
committerrobojumper <robojumper@gmail.com>2024-04-27 16:46:05 +0200
commit63a858728931d42551f7d3a13a31f8fa7a5d5429 (patch)
tree37a1b1ca2b6df209121c620c3aa283c2050e60f6 /src/m/m_heap.cpp
parent1ee2fdd8845d7ec2502b33ef2f45b4ab17e9d88e (diff)
Some m_heap work
Diffstat (limited to 'src/m/m_heap.cpp')
-rw-r--r--src/m/m_heap.cpp180
1 files changed, 166 insertions, 14 deletions
diff --git a/src/m/m_heap.cpp b/src/m/m_heap.cpp
index 5595136b..e2e31385 100644
--- a/src/m/m_heap.cpp
+++ b/src/m/m_heap.cpp
@@ -1,6 +1,7 @@
#include <egg/core/eggAssertHeap.h>
#include <egg/core/eggExpHeap.h>
#include <egg/core/eggFrmHeap.h>
+#include <m/m_heap.h>
namespace mHeap {
@@ -12,6 +13,8 @@ static const char *s_GameHeapNames[4] = {
0,
};
+#define MIN_ALIGN 0x20
+
EGG::ExpHeap *g_gameHeaps[4];
EGG::ExpHeap *s_SavedCurrentHeap;
EGG::ExpHeap *g_archiveHeap;
@@ -19,23 +22,162 @@ EGG::ExpHeap *g_commandHeap;
EGG::ExpHeap *g_dylinkHeap;
EGG::AssertHeap *g_assertHeap;
-u32 getHeapAttribute(u32) {}
+u16 copyAttribute(u32 arg) {
+ u16 result = 0;
+
+ if ((arg & 1) != 0) {
+ result = 1;
+ }
+ if ((arg & 2) != 0) {
+ result |= 2;
+ }
+ if ((arg & 4) != 0) {
+ result |= 4;
+ }
+ return result;
+}
EGG::Heap *setCurrentHeap(EGG::Heap *heap) {
return heap->becomeCurrentHeap();
}
-EGG::ExpHeap *createExpHeap(size_t, EGG::Heap *parent, const char *name, unsigned long, unsigned long) {}
-void adjustExpHeap(EGG::ExpHeap *) {}
-size_t expHeapCost(unsigned long, unsigned long) {}
+EGG::ExpHeap *createExpHeap(size_t size, EGG::Heap *parent, const char *name, unsigned long align, unsigned long attrs) {
+ if (parent == nullptr) {
+ parent = EGG::Heap::sCurrentHeap;
+ }
+
+ if (align < MIN_ALIGN) {
+ align = MIN_ALIGN;
+ }
+
+ if (size != 0xFFFFFFFF) {
+ size = expHeapCost(size, align);
+ } else {
+ size = parent->getAllocatableSize(align);
+ }
+
+ void *mem = parent->alloc(size, align);
+ EGG::ExpHeap *heap = nullptr;
+ if (mem != nullptr) {
+ heap = EGG::ExpHeap::create(mem, size, copyAttribute(attrs));
+ if (heap == nullptr) {
+ parent->free(mem);
+ } else if (name != nullptr) {
+ heap->mName = name;
+ }
+ }
+ return heap;
+}
+
+size_t adjustExpHeap(EGG::ExpHeap *heap) {
+ int ret = 0;
+ if (heap != nullptr) {
+ size_t ad = heap->adjust();
+ size_t cost = mHeap::frmHeapCost(0, 4);
+ if (ad >= cost) {
+ ret = ad - cost;
+ }
+ }
+ return ret;
+}
+size_t expHeapCost(size_t size, size_t align) {
+ // TODO this generates an andc where it should be a nor + and
+ size_t r5 = align - 1;
+ return size + (~r5 & (r5 + 0x84));
+}
+
+EGG::FrmHeap *createFrmHeap(size_t size, EGG::Heap *parent, const char *name, unsigned long align, unsigned long attrs) {
+ if (parent == nullptr) {
+ parent = EGG::Heap::sCurrentHeap;
+ }
-EGG::FrmHeap *createFrmHeap(unsigned long, EGG::Heap *, const char *, unsigned long, unsigned long) {}
-void destroyFrmHeap(EGG::FrmHeap *) {}
-size_t adjustFrmHeap(EGG::FrmHeap *) {}
-size_t frmHeapCost(unsigned long, unsigned long) {}
+ if (align < MIN_ALIGN) {
+ align = MIN_ALIGN;
+ }
-EGG::ExpHeap *createHeap(unsigned long, EGG::Heap *, const char *) {}
-void saveCurrentHeap() {}
-void restoreCurrentHeap() {}
+ if (size != 0xFFFFFFFF) {
+ size = expHeapCost(size, align);
+ } else {
+ size = parent->getAllocatableSize(align);
+ }
+
+ void *mem = parent->alloc(size, align);
+ EGG::FrmHeap *heap = nullptr;
+ if (mem != nullptr) {
+ heap = EGG::FrmHeap::create(mem, size, copyAttribute(attrs));
+ if (heap == nullptr) {
+ parent->free(mem);
+ } else if (name != nullptr) {
+ heap->mName = name;
+ }
+ }
+ return heap;
+}
+void destroyFrmHeap(EGG::FrmHeap *heap) {
+ if (heap != nullptr) {
+ heap->destroy();
+ }
+}
+
+size_t adjustFrmHeap(EGG::FrmHeap *heap) {
+ int ret = 0;
+ if (heap != nullptr) {
+ size_t ad = heap->adjust();
+ size_t cost = mHeap::frmHeapCost(0, 4);
+ if (ad >= cost) {
+ ret = ad - cost;
+ }
+ }
+ return ret;
+}
+
+size_t frmHeapCost(size_t size, size_t align) {
+ size_t r5 = align - 1;
+ return size + (~r5 & (r5 + 0x7d));
+}
+
+EGG::Heap **setTempHeap(EGG::Heap **prevHeap, EGG::Heap *tempNewHeap) {
+ *prevHeap = tempNewHeap->becomeCurrentHeap();
+ return prevHeap;
+}
+EGG::Heap **restoreTempHeap(EGG::Heap **prevHeap, s32 size) {
+ if (prevHeap != nullptr) {
+ (*prevHeap)->becomeCurrentHeap();
+ if (size > 0) {
+ delete prevHeap;
+ }
+ }
+ return prevHeap;
+}
+
+EGG::ExpHeap *createHeap(size_t size, EGG::Heap *block, const char *name) {
+ EGG::ExpHeap *heap = EGG::ExpHeap::create(size, block, 4);
+ if (heap != nullptr) {
+ heap->setGroupID(0);
+ if (name != nullptr) {
+ heap->mName = name;
+ }
+ } else {
+ block->dump();
+ }
+
+ return heap;
+}
+void saveCurrentHeap() {
+ s_SavedCurrentHeap = (EGG::ExpHeap*) EGG::Heap::sCurrentHeap;
+}
+void restoreCurrentHeap() {
+ s_SavedCurrentHeap->becomeCurrentHeap();
+ EGG::Heap::sCurrentHeap = nullptr;
+}
+
+EGG::FrmHeap *makeFrmHeapAndUpdate(size_t size, EGG::Heap *parentHeap, const char *name, s32 align, u32 unk) {
+ EGG::FrmHeap *heap = createFrmHeap(size, parentHeap, name, align, unk);
+ if (heap != nullptr) {
+ EGG::Heap *heap2 = setCurrentHeap(heap);
+ s_SavedCurrentHeap = (EGG::ExpHeap*)heap2;
+ }
+ return heap;
+}
int getDefaultGameHeapId() {
return g_DefaultGameHeapId;
@@ -60,16 +202,26 @@ EGG::ExpHeap *createGameHeap1(size_t size, EGG::Heap *parent) {
return createGameHeap(getDefaultGameHeapId(), size, parent);
}
EGG::ExpHeap *createArchiveHeap(size_t size, EGG::Heap *parent) {
- g_archiveHeap = createHeap(size, parent, "");
+ g_archiveHeap = createHeap(size, parent, "汎用ファイル読み込み用ヒープ(mHeap::archiveHeap)");
+ return g_archiveHeap;
}
EGG::ExpHeap *createCommandHeap(size_t size, EGG::Heap *parent) {
g_commandHeap = createHeap(size, parent, "DVD読み込みコマンド用ヒープ(mHeap::commandHeap)");
+ return g_commandHeap;
}
EGG::ExpHeap *createDylinkHeap(size_t size, EGG::Heap *parent) {
g_dylinkHeap = createHeap(size, parent, "ダイナミックリンク用ヒープ(mHeap::dylinkHeap)");
+ return g_dylinkHeap;
}
-EGG::ExpHeap *createAssertHeap(EGG::Heap *parent) {
+EGG::AssertHeap *createAssertHeap(EGG::Heap *parent) {
+ const char *name = "アサートヒープ(mHeap::assertHeap)";
g_assertHeap = EGG::AssertHeap::create(EGG::AssertHeap::getSize(), parent);
- g_assertHeap->mName = "アサートヒープ(mHeap::assertHeap)";
+ g_assertHeap->mName = name;
+ return g_assertHeap;
}
+
+EGG::Heap *makeHeapOnCurrentGameHeap(size_t size, char *name, s32 align, u32 flags) {
+ return makeFrmHeapAndUpdate(size, g_gameHeaps[0], name, align, flags);
+}
+
} // namespace mHeap