Kuribo64 Wiki
Home | ForumsLogin


Back to listing

Dynamic Memory Allocation

1. Types of Heaps
2. Base Heap Class
3. Heap Subclasses
4. AllocFromHeapEx
5. AllocFromHeapEx Wrappers

The Wii SDK contains several methods of dynamic memory allocation. These functions are found in its MEM library. Most of these methods can be found in SMG2's code.

1. Types of Heaps

The Wii SDK provides three different types of heaps in its MEM library.

Heap Description
Expanded Heap
Frame Heap
Unit Heap

2. Base Heap Class

SMG2 has code for all three types of heaps. They are found in C++ classes. The base Heap class constructor can be found at 80500F60.

80500F60 Heap_ctor: # CODE XREF: .text1:8001F0ECp
80500F60 # ExpHeap_ctor+20p ...
80500F60 .set arg_0, 0
80500F60 .set arg_4, 4
80500F60 stwu r1, -0x20(r1)
80500F64 mflr r0
80500F68 stw r0, 0x20+arg_4(r1)
80500F6C addi r11, r1, 0x20+arg_0
80500F70 bl sub_8062E160
80500F74 mr r26, r3
80500F78 mr r27, r4
80500F7C mr r28, r5
80500F80 mr r29, r6
80500F84 mr r30, r7
80500F88 bl sub_80504B50
80500F8C lis r3, Heap_vtable@h
80500F90 addi r31, r26, 0x40
80500F94 addi r3, r3, Heap_vtable@l
80500F98 stw r3, 0(r26)
80500F9C mr r3, r31
80500FA0 bl sub_8050D9A0
80500FA4 mr r4, r26
80500FA8 addi r3, r31, 0xC
80500FAC bl sub_8050D860
80500FB0 addi r3, r26, 0x5C
80500FB4 bl sub_8050D9A0
80500FB8 addi r3, r26, 0x18
80500FBC bl sub_805BAD10
80500FC0 cmpwi r29, 0
80500FC4 add r0, r27, r28
80500FC8 stw r28, 0x38(r26)
80500FCC stw r27, 0x30(r26)
80500FD0 stw r0, 0x34(r26)
80500FD4 bne loc_80500FE4
80500FD8 stw r26, -0x1210(r13)
80500FDC stw r26, -0x120C(r13) # Make this the current heap
80500FE0 b loc_8050101C
80500FE4 # ---------------------------------------------------------------------------
80500FE4 loc_80500FE4: # CODE XREF: Heap_ctor+74j
80500FE4 addic. r4, r26, 0x40
80500FE8 beq loc_80500FF0
80500FEC addi r4, r4, 0xC
80500FF0 loc_80500FF0: # CODE XREF: Heap_ctor+88j
80500FF0 addi r3, r29, 0x40
80500FF4 bl sub_8050D9F0
80500FF8 lwz r3, -0x1208(r13)
80500FFC lwz r0, -0x1210(r13)
80501000 cmplw r0, r3
80501004 bne loc_8050100C
80501008 stw r26, -0x1210(r13)
8050100C loc_8050100C: # CODE XREF: Heap_ctor+A4j
8050100C lwz r0, -0x120C(r13)
80501010 cmplw r0, r3
80501014 bne loc_8050101C
80501018 stw r26, -0x120C(r13) # Make this the current heap
8050101C loc_8050101C: # CODE XREF: Heap_ctor+80j
8050101C # Heap_ctor+B4j
8050101C clrlwi r0, r30, 24
80501020 stb r30, 0x68(r26)
80501024 cmplwi r0, 1
80501028 bne loc_80501044
8050102C lwz r0, -0x1204(r13)
80501030 cmpwi r0, 0
80501034 bne loc_80501044
80501038 lis r3, unk_80501810@h
8050103C addi r3, r3, unk_80501810@l
80501040 stw r3, -0x1204(r13)
80501044 loc_80501044: # CODE XREF: Heap_ctor+C8j
80501044 # Heap_ctor+D4j
80501044 lbz r3, -0x6D68(r13)
80501048 li r0, 0
8050104C stb r3, 0x3C(r26)
80501050 addi r11, r1, 0x20+arg_0
80501054 mr r3, r26
80501058 lbz r4, -0x1200(r13)
8050105C stb r4, 0x3D(r26)
80501060 stb r0, 0x69(r26)
80501064 bl sub_8062E1AC
80501068 lwz r0, 0x20+arg_4(r1)
8050106C mtlr r0
80501070 addi r1, r1, 0x20
80501074 blr
80501074 # End of function Heap_ctor

First, this code stores the Heap vtable pointer at the beginning of the class. Then it sets the heap that was just created to the current heap. It does this by writing the heap's pointer to -0x120C(r13). Here is the base Heap vtable.

80704000 Heap_vtable: .long 0 # DATA XREF: Heap_ctor+2Co
80704000 # Heap_ctor+34o ...
80704004 .long 0
80704008 .long sub_80501100
8070400C .long sub_805013D0
80704010 .long 0
80704014 .long 0
80704018 .long sub_8001F350
8070401C .long 0
80704020 .long 0
80704024 .long 0
80704028 .long 0
8070402C .long 0
80704030 .long 0
80704034 .long 0
80704038 .long 0
8070403C .long 0
80704040 .long 0
80704044 .long 0
80704048 .long 0
8070404C .long sub_8001F340
80704050 .long sub_8001F330
80704054 .long nullsub_66
80704058 .long sub_805018D0
8070405C .long nullsub_65

The base Heap vtable is missing most of its functions. This is because the subclasses of the Heap class actually implement the functionality.

3. Heap Subclasses

As mentioned above, the base Heap class doesn't implement most of the functionality, because the subclasses that inherit from it do. The subclasses are the three types of heaps mentioned above, which are Expanded, Frame, and Unit.

Here is the Expanded Heap constructor.

80501C90 ExpHeap_ctor: # CODE XREF: sub_805019F0+54p
80501C90 # sub_80501A70+90p ...
80501C90 .set arg_0, 0
80501C90 .set arg_4, 4
80501C90 stwu r1, -0x20(r1)
80501C94 mflr r0
80501C98 stw r0, 0x20+arg_4(r1)
80501C9C addi r11, r1, 0x20+arg_0
80501CA0 bl sub_8062E168
80501CA4 mr r28, r3
80501CA8 mr r29, r4
80501CAC mr r30, r5
80501CB0 bl Heap_ctor
80501CB4 lis r3, ExpHeap_vtable@h
80501CB8 li r31, 0
80501CBC addi r3, r3, ExpHeap_vtable@l
80501CC0 li r0, 0xFF
80501CC4 stw r3, 0(r28)
80501CC8 mr r3, r29
80501CCC addi r6, r30, -0x10
80501CD0 li r4, 0
80501CD4 stb r31, 0x6A(r28)
80501CD8 li r5, 0
80501CDC li r7, 0
80501CE0 li r8, 0
80501CE4 stb r0, 0x6B(r28)
80501CE8 stw r29, 0x78(r28)
80501CEC stw r29, 0x7C(r28)
80501CF0 bl sub_80503480
80501CF4 stw r31, 0x80(r28)
80501CF8 addi r11, r1, 0x20+arg_0
80501CFC mr r3, r28
80501D00 stw r31, 0x84(r28)
80501D04 bl sub_8062E1B4
80501D08 lwz r0, 0x20+arg_4(r1)
80501D0C mtlr r0
80501D10 addi r1, r1, 0x20
80501D14 blr
80501D14 # End of function ExpHeap_ctor

The Expanded Heap's class constructor is much shorter than the base Heap's class constructor, because the base Heap class constructor actually does most of the work. The Expanded Heap's class constructor calls the base Heap class constructor, and then replaces its vtable with its own.

807043F8 ExpHeap_vtable: .long 0 # DATA XREF: ExpHeap_ctor+24o
807043F8 # ExpHeap_ctor+2Co ...
807043FC .long 0
80704400 .long sub_80501D20
80704404 .long sub_805013D0
80704408 .long sub_80503660
8070440C .long sub_80502EC0
80704410 .long sub_80503280
80704414 .long sub_805030B0
80704418 .long sub_80501C00
8070441C .long ExpHeap__AllocFromHeapEx
80704420 .long sub_80502440
80704424 .long sub_805024D0
80704428 .long sub_80502550
8070442C .long nullsub_64
80704430 .long sub_80502650
80704434 .long sub_80502810
80704438 .long sub_805028A0
8070443C .long sub_80502910
80704440 .long sub_80502990
80704444 .long sub_80502600
80704448 .long sub_80503650
8070444C .long sub_80503570
80704450 .long sub_80503620
80704454 .long nullsub_65

This vtable contains all of the functions of the Expanded Heap. The most important function is AllocFromHeapEx. Its C++ function prototype is this.

void *AllocFromHeapEx(unsigned int size, int alignment);

This function appears in all of the other Heap classes. Even though they are implemented differently, they provide the same abstracted C++ interface. The reason for this is so when using the vtable to allocate memory on a heap, you don't need to worry which type of heap it is.

Because all three Heap subclasses have a very similar interface, and the only main difference between them is the implementation details of some functions, there is no need to go into detail about the other 2 types of heaps. However, they can be found at these addresses.

Constructor Vtable
Expanded Heap 80501C90 807043F8
Frame Heap 80503780 807045C8
Unit Heap 805040C0 80704680

4. AllocFromHeapEx

Here, we have the most important dynamic memory allocation function. AllocFromHeapEx provides a basic C++ interface for allocating memory from a Heap class. Its C++ function prototype is this.

void *AllocFromHeapEx(unsigned int size, int alignment, Heap *heap);

As explained above, this function is part of every Heap subclass. However, there are two differences. First of all, this function is not part of any class. Except for the fact that it calls functions from a class, it is a plain C function. Second, its interface is slightly different. Even though the first two arguments are the same in both the Heap versions and this function, this function also has a third argument. This third argument is the heap to allocate on. If 0, it will allocate on the current heap.

The code for AllocFromHeapEx is here.

80501310 AllocFromHeapEx: # CODE XREF: arc_file_read+42Cp
80501310 # arc_file_read+468p ...
80501310 cmpwi r5, 0
80501314 mr r6, r3
80501318 mr r0, r4
8050131C beq use_default_heap # If we didn't specify a heap, use the default one
80501320 mr r3, r5 # r3 = Heap
80501324 mr r4, r6 # r4 = Size
80501328 mr r5, r0 # r5 = Alignment
8050132C b call_heap_alloc # Call the heap's allocate function
80501330 # ---------------------------------------------------------------------------
80501330 use default_heap: # CODE XREF: AllocFromHeapEx+Cj
80501330 lwz r3, -0x120C(r13) # r3 = Current heap
80501334 cmpwi r3, 0
80501338 beq loc_80501348
8050133C mr r4, r6 # r4 = Size
80501340 mr r5, r0 # r5 = Alignment
80501344 b call_heap_alloc # Call the current heap's allocate function
80501348 # ---------------------------------------------------------------------------
80501348 loc_80501348: # CODE XREF: AllocFromHeapEx+28j
80501348 li r3, 0
8050134C blr
80501350 # ---------------------------------------------------------------------------
80501350 call_heap_alloc: # CODE XREF: .text1:8001F23Cp
80501350 # .text1:80041320j ...
80501350 lwz r12, 0(r3) # Get the heap's vtable
80501354 lwz r12, 0x24(r12) # Get the address of its allocate function
80501358 mtctr r12
8050135C bctr # Branch to its allocate function
8050135C # End of function AllocFromHeapEx

This code first checks the third argument to see if we've specified a heap. If we haven't, it branches to use_default_heap to get the current heap from -0x120C(r13). Whenever a new Heap object is created, a pointer to the new Heap object is written here. This is also described above, in the base Heap class constructor. If we have specified a heap, it uses the one we've given it.

Once we have a heap to allocate on, it sets up the parameters to call the AllocFromHeapEx function of the Heap class. The this pointer goes in r3, the size goes in r4, and the alignment goes in r5. Finally, the function gets a pointer to the Heap object's vtable and calls its AllocFromHeapEx function.

5. AllocFromHeapEx Wrappers

Finally, there are several wrapper functions for the AllocFromHeapEx function above.

Address Function Prototype Description
80501850 sub_80501850(unsigned int size); Allocate 4 byte aligned memory using the current heap
80501860 sub_80501860(unsigned int size, Heap *heap, int alignment); Allocate memory from a specified heap
80501870 sub_80501870(unsigned int size); Allocate 4 byte aligned memory using the current heap
80501880 sub_80501880(unsigned int size, int alignment); Allocate memory using the current heap
80501890 sub_80501890(unsigned int size, Heap *heap, int alignment); Allocate memory from a specified heap

Page rendered in 0.014 seconds. (2048KB of memory used)
MySQL - queries: 17, rows: 68/68, time: 0.010 seconds.