1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
/**
* @file z_overlay.c
*
* Functions for handling transition overlays in memory
*/
#include "z64transition.h"
#include "libu64/loadfragment.h"
#include "z64lib.h"
#include "zelda_arena.h"
void* TransitionOverlay_VramToRam(TransitionOverlay* overlayEntry, void* vramAddr) {
void* loadedRamAddr = Lib_PhysicalToVirtual(overlayEntry->loadInfo.addr);
if ((loadedRamAddr != NULL) && (vramAddr >= overlayEntry->vramStart) && (vramAddr < overlayEntry->vramEnd)) {
return (void*)(((uintptr_t)loadedRamAddr - (uintptr_t)overlayEntry->vramStart) + (uintptr_t)vramAddr);
}
return vramAddr;
}
void TransitionOverlay_VramToRamArray(TransitionOverlay* overlayEntry, void** vramAddrs, s32 count) {
s32 i;
for (i = 0; i < count; i++) {
vramAddrs[i] = TransitionOverlay_VramToRam(overlayEntry, vramAddrs[i]);
}
}
TransitionOverlayStatus TransitionOverlay_Load(TransitionOverlay* overlayEntry) {
s32 count;
void* loadedRamAddr;
if (overlayEntry->file.vromStart == 0) {
return TRANSITION_OVERLAY_STATUS_INTERNAL;
}
if (Lib_PhysicalToVirtual(overlayEntry->loadInfo.addr) == NULL) {
loadedRamAddr = ZeldaArena_Malloc((uintptr_t)overlayEntry->vramEnd - (uintptr_t)overlayEntry->vramStart);
if (loadedRamAddr == NULL) {
return TRANSITION_OVERLAY_STATUS_FAILED;
}
Overlay_Load(overlayEntry->file.vromStart, overlayEntry->file.vromEnd, overlayEntry->vramStart,
overlayEntry->vramEnd, loadedRamAddr);
overlayEntry->loadInfo.addr = Lib_VirtualToPhysical(loadedRamAddr);
overlayEntry->loadInfo.count = 1;
return TRANSITION_OVERLAY_STATUS_LOAD_FREE;
}
count = overlayEntry->loadInfo.count;
if (count != 0) {
count++;
overlayEntry->loadInfo.count = count;
if (count == 0) {
return TRANSITION_OVERLAY_STATUS_LOADED_NO_INSTANCES;
} else {
return TRANSITION_OVERLAY_STATUS_ADD_REMOVAL;
}
}
return TRANSITION_OVERLAY_STATUS_LOADED_NO_INSTANCES;
}
TransitionOverlayStatus TransitionOverlay_Free(TransitionOverlay* overlayEntry) {
s32 count;
void* loadedRamAddr;
if (overlayEntry->file.vromStart == 0) {
return TRANSITION_OVERLAY_STATUS_INTERNAL;
}
loadedRamAddr = Lib_PhysicalToVirtual(overlayEntry->loadInfo.addr);
if (loadedRamAddr != NULL) {
count = overlayEntry->loadInfo.count;
if (count != 0) {
count--;
overlayEntry->loadInfo.count = count;
if (count == 0) {
ZeldaArena_Free(loadedRamAddr);
overlayEntry->loadInfo.addr = Lib_VirtualToPhysical(NULL);
return TRANSITION_OVERLAY_STATUS_LOAD_FREE;
}
return TRANSITION_OVERLAY_STATUS_ADD_REMOVAL;
}
return TRANSITION_OVERLAY_STATUS_LOADED_NO_INSTANCES;
}
return TRANSITION_OVERLAY_STATUS_FAILED;
}
void TransitionOverlay_ClearLoadInfo(TransitionOverlay* overlayEntry) {
overlayEntry->loadInfo.word = 0; // Equivalent to overlayEntry->loadInfo.count = 0, overlayEntry->loadInfo.addr = 0;
}
void TransitionOverlay_SetSegment(TransitionOverlay* overlayEntry, void* vramStart, void* vramEnd, uintptr_t vromStart,
uintptr_t vromEnd) {
overlayEntry->vramStart = vramStart;
overlayEntry->vramEnd = vramEnd;
overlayEntry->file.vromStart = vromStart;
overlayEntry->file.vromEnd = vromEnd;
}
|