[Plugin] Added plugin that logs some memory infos

This commit is contained in:
Maschell 2018-02-24 13:49:59 +01:00
parent 55dd57d62f
commit db8643d3f5
9 changed files with 836 additions and 0 deletions

View File

@ -0,0 +1,291 @@
DO_LOGGING := 1
#---------------------------------------------------------------------------------
# Clear the implicit built in rules
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
endif
ifeq ($(strip $(DEVKITPRO)),)
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>devkitPRO")
endif
export PATH := $(DEVKITPPC)/bin:$(PORTLIBS)/bin:$(PATH)
export PORTLIBS := $(DEVKITPRO)/portlibs/ppc
export WUPSDIR := $(DEVKITPRO)/wups
export GCC_VER := $(shell $(DEVKITPPC)/bin/powerpc-eabi-gcc -dumpversion)
PREFIX := powerpc-eabi-
export AS := $(PREFIX)as
export CC := $(PREFIX)gcc
export CXX := $(PREFIX)g++
export LD := $(PREFIX)ld
export AR := $(PREFIX)ar
export OBJCOPY := $(PREFIX)objcopy
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR)).mod
BUILD := build
SOURCES := src
DATA :=
INCLUDES := src
MAP ?= $(TARGET:.mod=.map)
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
# -Os: optimise size
# -Wall: generate lots of warnings
# -DGEKKO_U: define the symbol GEKKO (used in some headers)
# -D__wiiu__: define the symbol __wii__ (used in some headers)
# -mrvl: enable wii/gamecube compilation
# -mcpu=750: enable processor specific compilation
# -meabi: enable eabi specific compilation
# -mhard-float: enable hardware floating point instructions
# -fshort-wchar: use 16 bit whcar_t type in keeping with Wii executables
# -fno-common: stop common variables which the loader can't understand
# -msdata-none: do not use r2 or r13 as small data areas
# -memb: enable embedded application specific compilation
# -ffunction-sections: split up functions so linker can garbage collect
# -fdata-sections: split up data so linker can garbage collect
COMMON_CFLAGS += -Os -Wall -DGEKKO_U -D__wiiu__ -mrvl -mcpu=750 -meabi -mhard-float -fshort-wchar -fno-common -msdata=none -memb -ffunction-sections -fdata-sections
# -x c: compile as c code
# -std=c11: use the c11 standard
CFLAGS += $(COMMON_CFLAGS) -x c -std=c11
# -x c: compile as c++ code
# -std=gnu++11: use the c++11 standard
CXXFLAGS += $(COMMON_CFLAGS) -x c++ -std=gnu++11
ifeq ($(DO_LOGGING), 1)
CFLAGS += -D__LOGGING__
CXXFLAGS += -D__LOGGING__
endif
ASFLAGS := -mregnames
# --relocatable: make sure ld doesn't remove relocations wups will need
# -s: strip local symbols to speed linking
# -u: keep certain sections
# -wrap: wrap function
# --gc-sections: remove unneeded symbols
# -T: use the linker script specified (to force certain wups sections together)
# -Map: generate a map file
LDFLAG_COMMON += -u wups_load -u wups_meta -u wups_hooks -T $(WUPSDIR)/wups.ld \
-Wl,-wrap,open,-wrap,close,-wrap,write,-wrap,read,-wrap,lseek,-wrap,stat,-wrap,fstat,-wrap,opendir,-wrap,closedir,-wrap,readdir \
-Wl,-Map,$(notdir $@).map,-wrap,malloc,-wrap,free,-wrap,memalign,-wrap,calloc,-wrap,realloc,-wrap,malloc_usable_size,-wrap,_malloc_r,-wrap,_free_r,-wrap,_realloc_r,-wrap,_calloc_r,-wrap,_memalign_r,-wrap,_malloc_usable_size_r,--gc-sections
LDFLAGS_MOD += $(LDFLAG_COMMON),--relocatable
LDFLAGS_ELF += --relocatable -s -T $(WUPSDIR)/wups_elf.ld
#---------------------------------------------------------------------------------
Q := @
MAKEFLAGS += --no-print-directory
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -lwups -lutils -ldynamiclibs
#
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(DEVKITPPC)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export PROJECTDIR := $(CURDIR)
export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
#---------------------------------------------------------------------------------
# automatically build a list of object files for our project
#---------------------------------------------------------------------------------
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
TTFFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.ttf)))
PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
export LD_MOD := $(CC)
else
export LD_MOD := $(CXX)
endif
export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
$(sFILES:.s=.o) $(SFILES:.S=.o) \
$(PNGFILES:.png=.png.o) $(addsuffix .o,$(BINFILES))
#---------------------------------------------------------------------------------
# build a list of include paths
#---------------------------------------------------------------------------------
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD) -I$(PORTLIBS)/include \
-I$(PORTLIBS)/include/libutils -I$(WUPSDIR)/include
#---------------------------------------------------------------------------------
# build a list of library paths
#---------------------------------------------------------------------------------
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
-L$(PORTLIBS)/lib \
-L$(WUPSDIR)/lib
export OUTPUT := $(CURDIR)/$(TARGET)
.PHONY: $(BUILD) clean install
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).bin $(BUILD_DBG).elf $(OUTPUT)
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
THIS_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
###############################################################################
# Rule to make everything.
PHONY += all
all : $(OUTPUT)
###############################################################################
# Special build rules
# Rule to make the module file.
$(OUTPUT) : output.elf
@echo "checking for missing symbols ..."
@$(LD_MOD) ../$(BUILD)/output.elf $(LDFLAG_COMMON) $(LIBS) $(LIBPATHS) -o check_linking.elf
@echo "linking ..." $@
@$(LD_MOD) ../$(BUILD)/output.elf $(LDFLAGS_MOD) $(LIBS) $(LIBPATHS) -o $@
# Rule to make the module file.
output.elf : $(OFILES)
@echo "linking ... output.elf"
@$(LD) $(OFILES) $(LDFLAGS_ELF) $(LIBS) $(LIBPATHS) -o $@
###############################################################################
# Standard build rules
#---------------------------------------------------------------------------------
%.a:
#---------------------------------------------------------------------------------
@echo $(notdir $@)
@rm -f $@
@$(AR) -rc $@ $^
#---------------------------------------------------------------------------------
%.o: %.cpp
@echo $(notdir $<)
@$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) $(INCLUDE) -c $< -o $@ $(ERROR_FILTER)
#---------------------------------------------------------------------------------
%.o: %.c
@echo $(notdir $<)
@$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CFLAGS) $(INCLUDE) -c $< -o $@ $(ERROR_FILTER)
#---------------------------------------------------------------------------------
%.o: %.S
@echo $(notdir $<)
@$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@ $(ERROR_FILTER)
#---------------------------------------------------------------------------------
%.png.o : %.png
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
#---------------------------------------------------------------------------------
%.jpg.o : %.jpg
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
#---------------------------------------------------------------------------------
%.ttf.o : %.ttf
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
#---------------------------------------------------------------------------------
%.bin.o : %.bin
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
#---------------------------------------------------------------------------------
%.wav.o : %.wav
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
#---------------------------------------------------------------------------------
%.mp3.o : %.mp3
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
#---------------------------------------------------------------------------------
%.ogg.o : %.ogg
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
###############################################################################
# Assembly listing rules
# Rule to make assembly listing.
PHONY += list
list : $(LIST)
# Rule to make the listing file.
%.list : $(TARGET)
$(LOG)
-$Qmkdir -p $(dir $@)
$Q$(OBJDUMP) -d $< > $@
###############################################################################
# Clean rule
# Rule to clean files.
PHONY += clean
clean :
$Qrm -rf $(wildcard $(BUILD) $(BIN))
###############################################################################
# Phony targets
.PHONY : $(PHONY)
-include $(DEPENDS)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------

View File

@ -0,0 +1,13 @@
# Memory info for the Wii U Plugin System
Prints information about the current memory usage when pressing L+R+X+Y+A+B via the UDPReader
## Building
For building you need:
- [wups](https://github.com/Maschell/WiiUPluginSystem)
- [dynamic_libs](https://github.com/Maschell/dynamic_libs/tree/lib) for access to the functions.
- [libutils](https://github.com/Maschell/libutils) for common functions.
Install them (in this order) according to their README's. Don't forget the dependencies of the libs itself.

View File

@ -0,0 +1,27 @@
/****************************************************************************
* Copyright (C) 2018 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include "c_retain_vars.h"
memHeapInfo expHeapPointer[MAX_EXP_HEAP_INFOS] __attribute__((section(".data")));
memHeapInfo frmHeapPointer[MAX_FRM_HEAP_INFOS] __attribute__((section(".data")));
memUnitHeapInfo unitHeapPointer[MAX_UNIT_HEAP_INFOS] __attribute__((section(".data")));
baseHeapInfo baseHeaphandles[MAX_BASE_HEAP_INFOS] __attribute__((section(".data")));
blockHeapInfo blockHeapInfos[MAX_BLOCK_HEAP_INFOS] __attribute__((section(".data")));
memHeapInfo userHeapInfos[MAX_USER_HEAP_INFOS] __attribute__((section(".data")));
u8 gButtonComboCooldown __attribute__((section(".data"))) = 0;

View File

@ -0,0 +1,32 @@
/****************************************************************************
* Copyright (C) 2018 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef C_RETAINS_VARS_H_
#define C_RETAINS_VARS_H_
#include "memory_defs.h"
extern memHeapInfo expHeapPointer[MAX_EXP_HEAP_INFOS];
extern memHeapInfo frmHeapPointer[MAX_FRM_HEAP_INFOS];
extern memUnitHeapInfo unitHeapPointer[MAX_UNIT_HEAP_INFOS];
extern baseHeapInfo baseHeaphandles[MAX_BASE_HEAP_INFOS];
extern blockHeapInfo blockHeapInfos[MAX_BLOCK_HEAP_INFOS];
extern memHeapInfo userHeapInfos[MAX_USER_HEAP_INFOS];
extern u8 gButtonComboCooldown;
#endif // C_RETAINS_VARS_H_

View File

@ -0,0 +1,34 @@
#include <wups.h>
#include <string.h>
#include <dynamic_libs/os_functions.h>
#include <dynamic_libs/vpad_functions.h>
#include <utils/logger.h>
#include "main.h"
DECL_FUNCTION(void, __PPCExit, void) {
// We reset them at ende, in case at application even uses the functions
// BEFORE with have our init hook.
memset(expHeapPointer,0,sizeof(expHeapPointer));
memset(unitHeapPointer,0,sizeof(unitHeapPointer));
memset(frmHeapPointer,0,sizeof(frmHeapPointer));
memset(baseHeaphandles,0,sizeof(baseHeaphandles));
memset(userHeapInfos,0,sizeof(userHeapInfos));
real___PPCExit();
}
DECL_FUNCTION(int, VPADRead, int chan, VPADData *buffer, u32 buffer_size, s32 *error) {
int result = real_VPADRead(chan, buffer, buffer_size, error);
int btns = VPAD_BUTTON_R | VPAD_BUTTON_L | VPAD_BUTTON_A | VPAD_BUTTON_B | VPAD_BUTTON_X | VPAD_BUTTON_Y;
if(result > 0 && ((buffer[0].btns_h & (btns)) == btns) && gButtonComboCooldown == 0 && OSIsHomeButtonMenuEnabled()) {
print_memory_info();
gButtonComboCooldown = 0x3C;
}
if(gButtonComboCooldown > 0) {
gButtonComboCooldown--;
}
return result;
}
WUPS_MUST_REPLACE(__PPCExit, WUPS_LOADER_LIBRARY_COREINIT, __PPCExit);
WUPS_MUST_REPLACE(VPADRead, WUPS_LOADER_LIBRARY_VPAD, VPADRead);

View File

@ -0,0 +1,106 @@
#include <wups.h>
#include <string.h>
#include <dynamic_libs/os_functions.h>
#include <dynamic_libs/socket_functions.h>
#include <utils/logger.h>
#include "main.h"
WUPS_PLUGIN_NAME("Memory Info");
WUPS_PLUGIN_DESCRIPTION("Prints information about the current memory usage when pressing L+R+X+Y+A+B.");
WUPS_PLUGIN_VERSION("v1.0");
WUPS_PLUGIN_AUTHOR("Maschell");
WUPS_PLUGIN_LICENSE("GPL");
INITIALIZE(args) {
InitOSFunctionPointers();
InitSocketFunctionPointers();
log_init();
//InitVPadFunctionPointers();
}
void printMemHeapInfo(memHeapInfo * listStart, u32 listLength, const char * listname) {
for(int i = 0; i<listLength; i++) {
if(listStart[i].handle != 0) {
s32 parent = MEMFindParentHeap(listStart[i].handle);
DEBUG_FUNCTION_LINE("%s:", listname);
if(parent == 0) {
log_print(" parent: <NONE> ");
} else {
log_printf(" parent: 0x%08X ", parent);
}
log_printf(" address 0x%08X handle 0x%08X size %07d kb old size %07d kb flags 0x%04X\n",listStart[i].address,listStart[i].handle,listStart[i].size/1024,listStart[i].oldSize/1024,listStart[i].flags);
}
}
}
void print_memory_info() {
DEBUG_FUNCTION_LINE("Print expanded heap infos\n");
printMemHeapInfo(expHeapPointer,MAX_EXP_HEAP_INFOS, "Expanded heap:");
DEBUG_FUNCTION_LINE("Print frmHeap\n");
printMemHeapInfo(frmHeapPointer,MAX_FRM_HEAP_INFOS, "Frame heap:");
DEBUG_FUNCTION_LINE("Print unitHeap\n");
for(int i = 0; i<MAX_UNIT_HEAP_INFOS; i++) {
if(unitHeapPointer[i].handle != 0) {
DEBUG_FUNCTION_LINE("unitHeap: address 0x%08X handle 0x%08X heapSize %07d kb memSize %07d kb align 0x%08X flags 0x%04X\n",unitHeapPointer[i].address,unitHeapPointer[i].handle,unitHeapPointer[i].heapSize/1024,unitHeapPointer[i].memSize/1024,unitHeapPointer[i].align,unitHeapPointer[i].flags);
}
}
DEBUG_FUNCTION_LINE("Print set base heap info\n");
for(int i = 0; i<MAX_BASE_HEAP_INFOS; i++) {
if(baseHeaphandles[i].newHandle != 0) {
DEBUG_FUNCTION_LINE("MEMSetBaseHeapHandle was called: oldHandle 0x%08X newHandle 0x%08X arena %d\n",baseHeaphandles[i].oldHandle,baseHeaphandles[i].newHandle,baseHeaphandles[i].memArena);
}
}
DEBUG_FUNCTION_LINE("Print set block heap info\n");
for(int i = 0; i<MAX_BLOCK_HEAP_INFOS; i++) {
if(blockHeapInfos[i].startAddress != 0) {
DEBUG_FUNCTION_LINE("MEMInitBlockHeap was called: handle 0x%08X tracking 0x%08X\n",blockHeapInfos[i].handle,blockHeapInfos[i].tracking);
}
}
DEBUG_FUNCTION_LINE("Print set user heap info\n");
printMemHeapInfo(userHeapInfos,MAX_USER_HEAP_INFOS, "User heap:");
DEBUG_FUNCTION_LINE("Testing malloc\n");
u32 size = 0x1000;
bool success = false;
do {
void * result = malloc(size);
if(result != NULL) {
//DEBUG_FUNCTION_LINE("Allocated %d kb from default heap\n",size/1024);
free(result);
result = NULL;
success = true;
} else {
//DEBUG_FUNCTION_LINE("Failed to allocate %d kb from default heap\n",size/1024);
success = false;
}
size += 0x1000;
} while(success);
DEBUG_FUNCTION_LINE("I was able to allocate %07d kb from default heap (alignment 4)\n",size/1024);
for(int i = 0; i<2; i++) {
s32 defaultHeap = MEMGetBaseHeapHandle(i);
if(defaultHeap != 0) {
u32 start = 0;
u32 size_bytes = 0;
OSGetMemBound(i+1,&start,&size_bytes);
DEBUG_FUNCTION_LINE("Memory Bound MEM%d: startAddress 0x%08X size 0x%08X\n",i+1,start,size_bytes);
s32 size = MEMGetAllocatableSizeForExpHeapEx(defaultHeap, 4);
s32 totalSize = MEMGetTotalFreeSizeForExpHeap(defaultHeap);
DEBUG_FUNCTION_LINE("BaseHandle address 0x%08X: MEM%d with %07d kb memory free in one block, %07d kb in total.\n",defaultHeap,i+1,size/1024,totalSize/1024);
s32 parent = MEMFindParentHeap(defaultHeap);
if(parent != 0) {
size = MEMGetAllocatableSizeForExpHeapEx(parent, 4);
s32 totalSize = MEMGetTotalFreeSizeForExpHeap(parent);
DEBUG_FUNCTION_LINE("It's parent heap is 0x%08X: With %07d kb memory free in one block, %07d kb in total.\n",parent,size/1024,totalSize/1024);
} else {
DEBUG_FUNCTION_LINE("No parent found =(\n");
}
}
}
}

View File

@ -0,0 +1,25 @@
/****************************************************************************
* Copyright (C) 2018 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef MAIN_H_
#define MAIN_H_
#include "memory_defs.h"
#include "c_retain_vars.h"
void print_memory_info();
#endif // MAIN_H_

View File

@ -0,0 +1,64 @@
/****************************************************************************
* Copyright (C) 2018 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef _MEMORY_DEFS_H_
#define _MEMORY_DEFS_H_
#include <dynamic_libs/os_types.h>
#define MAX_USER_HEAP_INFOS 50
#define MAX_FRM_HEAP_INFOS 50
#define MAX_EXP_HEAP_INFOS 50
#define MAX_UNIT_HEAP_INFOS 50
#define MAX_ALLOCATOR_EXP_INFOS 50
#define MAX_BASE_HEAP_INFOS 50
#define MAX_BLOCK_HEAP_INFOS 50
typedef struct memHeapInfo_ {
s32 handle;
void * address;
u32 size;
u32 oldSize;
u16 flags;
} memHeapInfo;
typedef struct memUnitHeapInfo_ {
s32 handle;
void * address;
u32 heapSize;
u32 memSize;
u32 align;
u16 flags;
} memUnitHeapInfo;
typedef struct baseHeapInfo_ {
s32 oldHandle;
s32 newHandle;
s32 memArena;
} baseHeapInfo;
typedef struct blockHeapInfo_ {
s32 handle;
void * tracking;
void * startAddress;
void * endAddress;
void * initTrackMem;
u32 initTrackMemBytes;
u16 flags;
} blockHeapInfo;
#endif

View File

@ -0,0 +1,244 @@
#include <wups.h>
#include <dynamic_libs/os_types.h>
#include "memory_defs.h"
#include "c_retain_vars.h"
DECL_FUNCTION(s32, MEMCreateFrmHeapEx, void* address, u32 size, u16 flags) {
s32 result = real_MEMCreateFrmHeapEx(address,size,flags);
for(int i = 0; i<MAX_FRM_HEAP_INFOS; i++) {
if(frmHeapPointer[i].handle == 0) {
frmHeapPointer[i].handle = result;
frmHeapPointer[i].address = address;
frmHeapPointer[i].size = size;
frmHeapPointer[i].flags = flags;
break;
}
}
return result;
}
DECL_FUNCTION(s32, MEMCreateUserHeapHandle, void* startAddress, u32 size) {
s32 result = real_MEMCreateUserHeapHandle(startAddress,size);
for(int i = 0; i<MAX_USER_HEAP_INFOS; i++) {
if(userHeapInfos[i].handle == 0) {
userHeapInfos[i].handle = result;
userHeapInfos[i].address = startAddress;
userHeapInfos[i].size = size;
break;
}
}
return result;
}
DECL_FUNCTION(s32, MEMCreateExpHeapEx, void* address, u32 size, u16 flags) {
u32 oldSize = size;
s32 result = 0;
bool allocated = false;
/*
real_MEMCreateExpHeapEx Just accepts ALL sizes... so.. well..
if(size > 0x3B600000 && (u32) address < 0x11000000){
//We are pretty sure this the MEM2 default heap.
//Let's try to increase it's capacity.
//u32 maximumSize = 0x50000000 - (u32) address;
u32 maximumSize = 0x80000000;
//u32 maximumSize = size + 0x500000;
maximumSize -= 0x500000; // remove 5MB, just to leave at least _some_ space.
u32 curSizeTest = maximumSize;
do{
if(curSizeTest < oldSize){
break;
}
result = real_MEMCreateExpHeapEx(address,curSizeTest,flags);
if(result == 0){ // On failure:
maximumSize -= 0x100000; // reduce by 1MB and try again.
}else{
allocated = true;
break;
}
}while(!allocated); // Until the allocation was successful, or we are below default size.
}*/
if(!allocated || result == 0) {
result = real_MEMCreateExpHeapEx(address,size,flags);
}
for(int i = 0; i<MAX_EXP_HEAP_INFOS; i++) {
if(expHeapPointer[i].handle == 0) {
expHeapPointer[i].handle = result;
expHeapPointer[i].address = address;
expHeapPointer[i].size = size;
expHeapPointer[i].oldSize = oldSize;
expHeapPointer[i].flags = flags;
break;
}
}
return result;
}
DECL_FUNCTION(s32, MEMCreateUnitHeapEx, void* address, u32 heapSize, u32 memSize, u32 align, u16 flags) {
s32 result = real_MEMCreateUnitHeapEx(address,heapSize,memSize,align,flags);
for(int i = 0; i<MAX_UNIT_HEAP_INFOS; i++) {
if(unitHeapPointer[i].handle == 0) {
unitHeapPointer[i].handle = result;
unitHeapPointer[i].address = address;
unitHeapPointer[i].heapSize = heapSize;
unitHeapPointer[i].memSize = memSize;
unitHeapPointer[i].align = align;
unitHeapPointer[i].flags = flags;
break;
}
}
return result;
}
DECL_FUNCTION(void *, MEMDestroyExpHeap, s32 heap) {
void * result = real_MEMDestroyExpHeap(heap);
for(int i = 0; i<MAX_EXP_HEAP_INFOS; i++) {
if(expHeapPointer[i].handle == heap) {
expHeapPointer[i].handle = 0;
expHeapPointer[i].address = 0;
expHeapPointer[i].size = 0;
expHeapPointer[i].flags = 0;
break;
}
}
return result;
}
DECL_FUNCTION(void *, MEMDestroyFrmHeap, s32 heap) {
void * result = real_MEMDestroyFrmHeap(heap);
for(int i = 0; i<MAX_FRM_HEAP_INFOS; i++) {
if(frmHeapPointer[i].handle == heap) {
frmHeapPointer[i].handle = 0;
frmHeapPointer[i].address = 0;
frmHeapPointer[i].size = 0;
frmHeapPointer[i].flags = 0;
break;
}
}
return result;
}
DECL_FUNCTION(void *, MEMDestroyUnitHeap, s32 heap) {
void * result = real_MEMDestroyUnitHeap(heap);
for(int i = 0; i<MAX_UNIT_HEAP_INFOS; i++) {
if(unitHeapPointer[i].handle == heap) {
unitHeapPointer[i].handle = 0;
unitHeapPointer[i].address = 0;
unitHeapPointer[i].heapSize = 0;
unitHeapPointer[i].memSize = 0;
unitHeapPointer[i].align = 0;
unitHeapPointer[i].flags = 0;
break;
}
}
return result;
}
DECL_FUNCTION(s32, MEMSetBaseHeapHandle, s32 arena, s32 heap) {
s32 result = real_MEMSetBaseHeapHandle(arena,heap);
for(int i = 0; i<MAX_BASE_HEAP_INFOS; i++) {
if(baseHeaphandles[i].newHandle == 0) {
baseHeaphandles[i].oldHandle = result;
baseHeaphandles[i].newHandle = heap;
baseHeaphandles[i].memArena = arena;
break;
}
}
return result;
}
DECL_FUNCTION(s32, MEMInitBlockHeap,void * tracking, void * startAddress,void * endAddress, void * initTrackMemory, u32 initTrackMemoryBytes, u16 flags) {
s32 result = real_MEMInitBlockHeap(tracking,startAddress,endAddress,initTrackMemory,initTrackMemoryBytes,flags);
for(int i = 0; i<MAX_BLOCK_HEAP_INFOS; i++) {
if(blockHeapInfos[i].startAddress == NULL) {
blockHeapInfos[i].handle = result;
blockHeapInfos[i].tracking = tracking;
blockHeapInfos[i].startAddress = startAddress;
blockHeapInfos[i].endAddress = endAddress;
blockHeapInfos[i].initTrackMem = initTrackMemory;
blockHeapInfos[i].initTrackMemBytes = initTrackMemoryBytes;
blockHeapInfos[i].flags = flags;
break;
}
}
return result;
}
WUPS_MUST_REPLACE(MEMInitBlockHeap, WUPS_LOADER_LIBRARY_COREINIT, MEMInitBlockHeap);
WUPS_MUST_REPLACE(MEMSetBaseHeapHandle, WUPS_LOADER_LIBRARY_COREINIT, MEMSetBaseHeapHandle);
WUPS_MUST_REPLACE(MEMDestroyUnitHeap, WUPS_LOADER_LIBRARY_COREINIT, MEMDestroyUnitHeap);
WUPS_MUST_REPLACE(MEMDestroyFrmHeap, WUPS_LOADER_LIBRARY_COREINIT, MEMDestroyFrmHeap);
WUPS_MUST_REPLACE(MEMDestroyExpHeap, WUPS_LOADER_LIBRARY_COREINIT, MEMDestroyExpHeap);
WUPS_MUST_REPLACE(MEMCreateUnitHeapEx, WUPS_LOADER_LIBRARY_COREINIT, MEMCreateUnitHeapEx);
WUPS_MUST_REPLACE(MEMCreateExpHeapEx, WUPS_LOADER_LIBRARY_COREINIT, MEMCreateExpHeapEx);
WUPS_MUST_REPLACE(MEMCreateUserHeapHandle, WUPS_LOADER_LIBRARY_COREINIT, MEMCreateUserHeapHandle);
WUPS_MUST_REPLACE(MEMCreateFrmHeapEx, WUPS_LOADER_LIBRARY_COREINIT, MEMCreateFrmHeapEx);
/*
Unused stuff that might get useful in the future.
void * allocateFromExpHeap(s32 * usedHandle, u32 size, u32 align){
void * result = NULL;
for(int i = 0;i<MAX_EXP_HEAP_INFOS;i++){
if(expHeapPointer[i].handle != 0){
result = MEMAllocFromExpHeapEx(expHeapPointer[i].handle, size, align);
if(result != NULL){
*usedHandle = expHeapPointer[i].handle;
return result;
}
}
}
return NULL;
}
void * allocateFromFrmHeap(s32 * usedHandle, u32 size, u32 align){
void * result = NULL;
for(int i = 0;i<MAX_FRM_HEAP_INFOS;i++){
if(frmHeapPointer[i].handle != 0){
result = MEMAllocFromFrmHeapEx(frmHeapPointer[i].handle, size, align);
if(result != NULL){
*usedHandle = frmHeapPointer[i].handle;
return result;
}
}
}
return NULL;
}
void freeToExpHeap(s32 usedHandle, void * addr){
MEMFreeToExpHeap(usedHandle, addr);
}
allocatorExpInfo allocatorExpPointer[MAX_ALLOCATOR_EXP_INFOS] __attribute__((section(".data")));
typedef struct allocatorExpInfo_{
void * allocator;
s32 heap;
s32 align;
} allocatorExpInfo;
DECL(void , MEMInitAllocatorForExpHeap, void* allocator, s32 heap, s32 align){
for(int i = 0;i<MAX_ALLOCATOR_EXP_INFOS;i++){
if(allocatorExpPointer[i].allocator == 0){
allocatorExpPointer[i].allocator = (void*)allocator;
allocatorExpPointer[i].heap = heap;
allocatorExpPointer[i].align = align;
break;
}
}
real_MEMInitAllocatorForExpHeap(allocator,heap,align);
return;
}
*/