Home | Forums — Login |
Dynamic Memory Allocation
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 HeapsThe Wii SDK provides three different types of heaps in its MEM library.
2. Base Heap ClassSMG2 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 80500F60 .set arg_0, 0 80500F60 .set arg_4, 4 80500F60 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 80500FE4 loc_80500FE4: # CODE XREF: Heap_ctor+74j 80500FE4 addic. r4, r26, 0x40 80500FE8 beq loc_80500FF0 80500FEC addi r4, r4, 0xC 80500FF0 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 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 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 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 SubclassesAs 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 80501C90 .set arg_0, 0 80501C90 .set arg_4, 4 80501C90 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.
4. AllocFromHeapExHere, 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 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 80501348 loc_80501348: # CODE XREF: AllocFromHeapEx+28j 80501348 li r3, 0 8050134C blr 80501350 # --------------------------------------------------------------------------- 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 WrappersFinally, there are several wrapper functions for the AllocFromHeapEx function above.
|
Page rendered in 0.010 seconds. (2048KB of memory used) MySQL - queries: 17, rows: 66/66, time: 0.007 seconds. |