pokestadium/src/util.c

189 lines
6.9 KiB
C

#include <ultra64.h>
#include "memmap.h"
#include "memory.h"
#include "util.h"
/**
* Based on the context of this variable's usage, it appears to be intended to
* be non-0 whenever the expansion RAM is in, however it is never initialized
* properly. It seems to serve as whereever the new start of memory will be
* located whenever plugged in, but its only functional with the debug profiler.
* It will, however, allocate a much bigger pool if set to non-0.
*/
u32 gExpansionRAMStart = FALSE;
extern struct MainPool** gMainPool; // gMainPool
void func_80003860(void);
s32 func_80007A58(void);
/**
* Convert any valid address to its virtual (KSEG0) counterpart.
*/
uintptr_t Util_ConvertAddrToVirtAddr(uintptr_t addr) {
uintptr_t retaddr = NULL; // any invalid cases are treated as NULL return.
// convert physical (in installed memory range) to virtual.
if (addr < osMemSize) {
retaddr = addr | 0x80000000;
// convert segmented to virtual.
} else if (addr < 0x10000000U) {
retaddr = Memmap_GetSegmentVaddr(addr);
// convert a fragment pre-relocated address to a post-relocated virtual address.
} else if ((addr >= 0x81000000U) &&
(addr < 0x90000000U)) { // is the address in fragment space? convert it to its post-relocated address.
retaddr = Memmap_GetFragmentVaddr(addr);
// pass-through addresses that are already virtual (in installed memory range)
} else if ((addr >= 0x80000000U) && (addr < (uintptr_t)(osMemSize + 0x80000000U))) {
retaddr = addr;
}
return retaddr;
}
/**
* Copy memory from one address to the other.
*/
void Util_Memcpy(u32* dest, u32* src, int size) {
while (size-- > 0) {
*(dest++) = *(src++);
}
}
/**
* Initialize the global memory pools and set the main pool after the
* global pool.
*/
void Util_InitMainPools(void) {
/**
* wat? mem sizes are only ever 0x400000 or 0x800000. This check makes no sense
* in normal contexts. However, since osGetMemSize checks each MB at a time, if
* the 7MB check fails for whatever reason it can theoretically set osMemSize to
* 0x600000. This is not known to occur in practical contexts, but there may be
* some other unknown reason for this.
*/
if ((gExpansionRAMStart > 0) && (osMemSize > 0x600000U)) {
main_pool_init(&gPool, POOL_END_6MB);
} else {
main_pool_init(&gPool, POOL_END_4MB);
gExpansionRAMStart = 0;
}
func_80003860();
gMainPool = mem_pool_try_init(0x10000, 0);
}
/**
* Allocate memory from the main pool.
*/
void* Util_Malloc(s32 size) {
return mem_pool_alloc(gMainPool, size);
}
/**
* Free a pointer being used in the main pool.
*/
void Util_Free(void* ptr) {
mem_pool_free(gMainPool, ptr);
}
/**
* Draws a profiler rectangle with given coordinates. Solely used by the next function
* which facilitates the tacked on memory profiler.
*/
void Util_DrawRect(Gfx** dlist, s32 ulx, s32 lrx, u16 color) {
s32 uly = 15;
s32 lry = 17;
Gfx* gfx = *dlist;
if (func_80007A58() != 0) {
ulx <<= 1;
lrx <<= 1;
uly <<= 1;
lry <<= 1;
}
gDPPipeSync(gfx++);
gDPSetFillColor(gfx++, color << 16 | color);
gDPFillRectangle(gfx++, ulx, uly, lrx, lry);
*dlist = gfx;
}
/**
* Render the memory profiler bar and print the MEM display. For some reason, this
* is not within profiler.c itself but added in this "util" file. This seems to be
* tacked onto the profiler by HAL instead of EAD.
*/
void Util_DrawMemProfiler(Gfx** dlist) {
struct MainPool* pool = main_pool_get_pool(); // get pool pointer
/**
* Get the available memory offset by gExpansionRAMStart variable. This variable is weird; it
* seems to be used in reference to osMemSize checks >= 0x600000 which would only be true
* in Expansion RAM contexts. However, this game does not use the expansion RAM in any
* other context. This variable is negative when gExpansionRAMStart is too big, and not when
* it isnt. It is therefore reasonable to assume that this variable would represent how much
* memory is leftover and if negative would mean this cant fit into 4MB, which would therefore
* mean that the developers need to trim more memory to get it to fit into 4MB.
*/
s32 available = main_pool_get_available() - gExpansionRAMStart;
if (available >= 0) {
// calculate approximation coordinates based on the current pool addresses in order
// to display them on the memory profiler.
s32 baseX = 30;
s32 startX = ((u32)(K0_TO_PHYS(pool->start)) >> 15) + baseX;
s32 headLX = ((u32)(K0_TO_PHYS(pool->listHeadL)) >> 15) + baseX;
s32 headRX = ((u32)(K0_TO_PHYS(pool->listHeadR) - gExpansionRAMStart) >> 15) + baseX;
s32 endX = ((u32)(K0_TO_PHYS(pool->end) - gExpansionRAMStart) >> 15) + baseX;
// draw the rects.
Util_DrawRect(dlist, baseX, startX, GPACK_RGBA5551(248, 120, 40, 1)); // orange
Util_DrawRect(dlist, startX, headLX, GPACK_RGBA5551(248, 248, 40, 1)); // yellow
Util_DrawRect(dlist, headLX, headRX, GPACK_RGBA5551(40, 80, 248, 1)); // blue
Util_DrawRect(dlist, headRX, endX, GPACK_RGBA5551(248, 248, 40, 1)); // yellow
// how many bytes and kilobytes are available?
HAL_Printf(baseX, 20, "MEM: +%XH (+%dK)", available, available / 1024);
} else {
// same as above.
s32 baseX = 30;
s32 startX = ((u32)(K0_TO_PHYS(pool->start)) >> 15) + baseX;
s32 headLX = ((u32)(K0_TO_PHYS(pool->listHeadL)) >> 15) + baseX;
s32 headRX = ((u32)(K0_TO_PHYS(pool->listHeadR) - gExpansionRAMStart) >> 15) + baseX;
s32 endX = ((u32)(K0_TO_PHYS(pool->end) - gExpansionRAMStart) >> 15) + baseX;
// draw the rects. if we are negative in the memory, we are using red for the backwards
// allocations to indicate too much memory is being used.
Util_DrawRect(dlist, baseX, startX, GPACK_RGBA5551(248, 120, 40, 1)); // orange
Util_DrawRect(dlist, startX, headRX, GPACK_RGBA5551(248, 248, 40, 1)); // yellow
Util_DrawRect(dlist, headRX, headLX, GPACK_RGBA5551(248, 40, 40, 1)); // red
Util_DrawRect(dlist, headLX, endX, GPACK_RGBA5551(248, 248, 40, 1)); // yellow
// how many bytes and kilobytes are available?
HAL_Printf(baseX, 20, "MEM: -%XH (-%dK)", -available, -available / 1024);
}
}
/**
* Clear memory address area.
*/
void Util_Memclear(u64* dest, u32 size) {
while (size-- > 0) {
*(dest++) = -1;
}
}
/**
* Unused function for checking some 64-bit range (possibly some display list?) for values
* cooresponding to 0x8040000080400000. This could have been for some memory test however
* the code for such a test is not present in this ROM, so we can only guess this function's
* intended usage.
*/
s32 Util_CheckStubMemArea(u64* ptr) {
s32 ret = 0;
while (*(ptr++) == 0x8040000080400000) {
ret++;
}
return ret * sizeof(*ptr);
}