summaryrefslogtreecommitdiff
path: root/src/boot_O2
diff options
context:
space:
mode:
Diffstat (limited to 'src/boot_O2')
-rw-r--r--src/boot_O2/loadfragment2.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/src/boot_O2/loadfragment2.c b/src/boot_O2/loadfragment2.c
new file mode 100644
index 000000000..1c706b476
--- /dev/null
+++ b/src/boot_O2/loadfragment2.c
@@ -0,0 +1,109 @@
+#include <ultra64.h>
+#include <global.h>
+
+UNK_TYPE4 D_80096C30 = 2;
+
+#ifdef NON_MATCHING
+// This needs lots of work. Mostly regalloc and getting the address of D_80096C30 placed in s5 at the beginning of the function
+void Load2_Relocate(u32 allocatedVRamAddr, OverlayBlockSizes* overlayInfo, u32 vRamStart) {
+ s32 sectionLocations [4];
+ u32* regReferences[32];
+ u32 regValues[32];
+ u32 i;
+ u32 relocatedAddress;
+ s32 signedOffset;
+ u32* lastInst;
+ u32* inst;
+ u32 relocation;
+ u32 relocationIndex;
+
+ sectionLocations[0] = 0;
+ sectionLocations[1] = allocatedVRamAddr;
+ sectionLocations[2] = overlayInfo->textSize + allocatedVRamAddr;
+ sectionLocations[3] = sectionLocations[2] + overlayInfo->dataSize;
+ for (i = 0, relocationIndex = 0; i < overlayInfo->amountOfRelocations; relocationIndex++) {
+ relocation = overlayInfo->relocations[relocationIndex];
+ i++;
+ inst = (u32 *)(sectionLocations[relocation >> 0x1e] + (relocation & 0xffffff));
+
+ switch (relocation & 0x3f000000) {
+ case 0x2000000:
+ if ((*inst & 0xf000000) == 0) {
+ *inst = (*inst - vRamStart) + allocatedVRamAddr;
+ } else {
+ if (D_80096C30 > 2);
+ }
+ break;
+ case 0x4000000:
+ *inst = (*inst & 0xfc000000) |
+ (((((*inst & 0x3ffffff) << 2 | 0x80000000) - vRamStart) + allocatedVRamAddr & 0xfffffff) >> 2);
+ break;
+ case 0x5000000:
+ regReferences[*inst >> 0x10 & 0x1f] = inst;
+ regValues[*inst >> 0x10 & 0x1f] = *inst;
+ break;
+ case 0x6000000:
+ lastInst = regReferences[*inst >> 0x15 & 0x1f];
+ signedOffset = (s16)*inst;
+ if ((signedOffset + *lastInst * 0x10000 & 0xf000000) == 0) {
+ relocatedAddress = ((signedOffset + regValues[*inst >> 0x15 & 0x1f] * 0x10000) - vRamStart) + allocatedVRamAddr;
+ *lastInst = (((relocatedAddress >> 0x10) & 0xFFFF) + ((relocatedAddress & 0x8000)? 1 : 0)) |
+ (*lastInst & 0xffff0000);
+ *inst = *inst & 0xffff0000 | relocatedAddress & 0xffff;
+ }
+ break;
+ }
+ }
+}
+#else
+GLOBAL_ASM("./asm/non_matchings/loadfragment2/Load2_Relocate.asm")
+#endif
+
+#ifdef NON_MATCHING
+// Very minor stack stuff with a saved value
+s32 Load2_LoadOverlay(u32 vRomStart, u32 vRomEnd, u32 vRamStart, u32 vRamEnd, u32 allocatedVRamAddr) {
+ int nbytes;
+ u32 pad;
+ u32 size;
+ void* end;
+ OverlayBlockSizes* overlayInfo;
+
+ size = vRomEnd - vRomStart;
+
+ if(1);
+
+ Dmamgr_SendRequestAndWait(allocatedVRamAddr, vRomStart, size);
+
+ end = (void*)(allocatedVRamAddr + size);
+ overlayInfo = (OverlayBlockSizes*)((int)end - *(int*)((int)end + -4));
+
+ if(1);
+
+ Load2_Relocate(allocatedVRamAddr, overlayInfo, vRamStart);
+
+ if (overlayInfo->bssSize != 0) {
+ bzero(end, overlayInfo->bssSize);
+ }
+
+ nbytes = vRamEnd - vRamStart;
+
+ osWritebackDCache((void*)allocatedVRamAddr, nbytes);
+ osInvalICache((void*)allocatedVRamAddr, nbytes);
+ return nbytes;
+}
+#else
+GLOBAL_ASM("./asm/non_matchings/loadfragment2/Load2_LoadOverlay.asm")
+#endif
+
+void* Load2_AllocateAndLoad(u32 vRomStart, u32 vRomEnd, u32 vRamStart, u32 vRamEnd) {
+ void* allocatedVRamAddr;
+ u32 size;
+
+ size = vRamEnd - vRamStart;
+ allocatedVRamAddr = StartHeap_AllocR(size);
+ if (allocatedVRamAddr != NULL) {
+ Load2_LoadOverlay(vRomStart, vRomEnd, vRamStart, vRamEnd, (u32)allocatedVRamAddr);
+ }
+
+ return allocatedVRamAddr;
+}