summaryrefslogtreecommitdiff
path: root/include/d/d_heap_alloc.h
blob: 1703c6b093db2b5efd02e8da2ab67f85dbb0a9bd (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
#ifndef D_HEAP_ALLOC
#define D_HEAP_ALLOC

#include "egg/core/eggHeap.h"

class dHeapAllocatorBase {
public:
    /* vtable at 0x00 */
    dHeapAllocatorBase()
        : mCallbacksInitialized(0), mPreviousAllocCallback(nullptr), mPreviousAllocCallbackArg(nullptr),
          mPreviousFreeCallback(nullptr), mPreviousFreeCallbackArg(nullptr) {}
    inline void doInitCallbacks() {
        if (!mCallbacksInitialized) {
            mCallbacksInitialized = 1;
            EGG::Heap::AllocCallbackBundle prev = EGG::Heap::setAllocCallback(&allocCallback, this);
            mPreviousAllocCallback = prev.AllocCallback;
            mPreviousAllocCallbackArg = prev.AllocCallbackArg;

            EGG::Heap::FreeCallbackBundle prev2 = EGG::Heap::setFreeCallback(&freeCallback, this);
            mPreviousFreeCallback = prev2.FreeCallback;
            mPreviousFreeCallbackArg = prev2.FreeCallbackArg;
        }
    }
    static void allocCallback(EGG::HeapAllocArg *arg) {
        dHeapAllocatorBase *allocator = (dHeapAllocatorBase *)(arg->userArg);
        allocator->onAlloc(arg);
        if (allocator->mPreviousAllocCallback) {
            EGG::HeapAllocArg chainArg = *arg;
            chainArg.userArg = allocator->mPreviousAllocCallbackArg;
            (allocator->mPreviousAllocCallback)(&chainArg);
        }
    };
    static void freeCallback(EGG::HeapFreeArg *arg) {
        dHeapAllocatorBase *allocator = (dHeapAllocatorBase *)(arg->userArg);
        EGG::HeapFreeArg chainArg;
        allocator->onFree(arg);
        if (allocator->mPreviousFreeCallback) {
            chainArg = *arg;
            chainArg.userArg = allocator->mPreviousFreeCallbackArg;
            (allocator->mPreviousFreeCallback)(&chainArg);
        }
    }

    virtual ~dHeapAllocatorBase() {}
    virtual void onAlloc(EGG::HeapAllocArg *arg){};
    virtual void onFree(EGG::HeapFreeArg *arg){};

    /* 0x04 */ bool mCallbacksInitialized;
    /* 0x08 */ EGG::HeapAllocCallback mPreviousAllocCallback;
    /* 0x0C */ void *mPreviousAllocCallbackArg;
    /* 0x10 */ EGG::HeapFreeCallback mPreviousFreeCallback;
    /* 0x14 */ void *mPreviousFreeCallbackArg;
};

void *operator new(size_t size);
void *operator new[](size_t size);
void operator delete(void *ptr);
void operator delete[](void *ptr);

class dHeapAllocator : public dHeapAllocatorBase {
public:
    dHeapAllocator() {}
    virtual ~dHeapAllocator() {}
    virtual void onAlloc(EGG::HeapAllocArg *arg);

    static void initCallbacks();

    static dHeapAllocator sAllocator;
};

#endif