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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
|
#include "global.h"
#include "nitro.h"
#include "FS_file.h"
#include "FS_rom.h"
#include "poke_overlay.h"
static struct LoadedOverlay gLoadedOverlays[3][8];
THUMB_FUNC void FreeOverlayAllocation(struct LoadedOverlay * loaded)
{
GF_ASSERT(loaded->active == TRUE);
GF_ASSERT(FS_UnloadOverlay(MI_PROCESSOR_ARM9, loaded->id) == TRUE);
loaded->active = FALSE;
}
THUMB_FUNC void UnloadOverlayByID(FSOverlayID id)
{
struct LoadedOverlay * loaded = GetLoadedOverlaysInRegion(GetOverlayLoadDestination(id));
int i;
for (i = 0; i < 8; i++)
{
if (loaded[i].active == TRUE && loaded[i].id == id)
{
FreeOverlayAllocation(&loaded[i]);
break;
}
}
}
THUMB_FUNC s32 GetOverlayLoadDestination(FSOverlayID id)
{
FSOverlayInfo info;
u8 *end;
u8 *start;
GF_ASSERT(FS_LoadOverlayInfo(&info, MI_PROCESSOR_ARM9, id) == TRUE);
start = (u8 *)HW_ITCM_IMAGE;
end = (u8 *)HW_ITCM_END;
if (info.header.ram_address <= end && info.header.ram_address >= start)
return OVERLAY_LOAD_ITCM;
start = (u8 *)HW_DTCM;
end = start + HW_DTCM_SIZE;
if (info.header.ram_address <= end && info.header.ram_address >= start)
return OVERLAY_LOAD_DTCM;
return OVERLAY_LOAD_WRAM;
}
THUMB_FUNC BOOL HandleLoadOverlay(FSOverlayID id, s32 a1)
{
u32 sp0 = FS_DMA_NOT_USE;
struct LoadedOverlay *r3;
int r7;
int r6;
BOOL result;
if (!CanOverlayBeLoaded(id))
return FALSE;
r7 = GetOverlayLoadDestination(id);
r3 = GetLoadedOverlaysInRegion(r7);
for (r6 = 0; r6 < 8; r6++)
{
if (!r3[r6].active)
{
struct LoadedOverlay * ovly;
ovly = &r3[r6];
ovly->active = TRUE;
ovly->id = id;
break;
}
}
if (r6 >= 8)
{
GF_ASSERT(0);
return FALSE;
}
if (r7 == OVERLAY_LOAD_ITCM || r7 == OVERLAY_LOAD_DTCM)
{
sp0 = FS_SetDefaultDMA(FS_DMA_NOT_USE);
}
switch (a1)
{
case 0:
result = LoadOverlayNormal(MI_PROCESSOR_ARM9, id);
break;
case 1:
result = LoadOverlayNoInit(MI_PROCESSOR_ARM9, id);
break;
case 2:
result = LoadOverlayNoInitAsync(MI_PROCESSOR_ARM9, id);
break;
default:
GF_ASSERT(0);
return FALSE;
}
if (r7 == OVERLAY_LOAD_ITCM || r7 == OVERLAY_LOAD_DTCM)
{
FS_SetDefaultDMA(sp0);
}
if (result == 0)
{
GF_ASSERT(0);
return FALSE;
}
return TRUE;
}
THUMB_FUNC BOOL CanOverlayBeLoaded(FSOverlayID id)
{
void *start, *end, *start2, *end2;
struct LoadedOverlay *r5;
int i;
if (!GetOverlayRamBounds(id, &start, &end))
return FALSE;
r5 = GetLoadedOverlaysInRegion(GetOverlayLoadDestination(id));
for (i = 0; i < 8; i++)
{
if (r5[i].active == TRUE && GetOverlayRamBounds(r5[i].id, &start2, &end2) == TRUE)
{
if ((start >= start2 && start < end2) || (end > start2 && end <= end2) || (start <= start2 && end >= end2))
{
GF_ASSERT(0);
return FALSE;
}
}
}
return TRUE;
}
THUMB_FUNC struct LoadedOverlay* GetLoadedOverlaysInRegion(s32 a0)
{
switch (a0)
{
case OVERLAY_LOAD_WRAM:
default:
return gLoadedOverlays[0];
case OVERLAY_LOAD_ITCM:
return gLoadedOverlays[1];
case OVERLAY_LOAD_DTCM:
return gLoadedOverlays[2];
}
}
THUMB_FUNC BOOL GetOverlayRamBounds(FSOverlayID id, void ** start, void ** end)
{
FSOverlayInfo info;
if (!FS_LoadOverlayInfo(&info, MI_PROCESSOR_ARM9, id)) {
GF_ASSERT(0);
return FALSE;
}
*start = (void *)info.header.ram_address;
*end = (char *)*start + (info.header.ram_size + info.header.bss_size);
return TRUE;
}
THUMB_FUNC BOOL LoadOverlayNormal(MIProcessor target, FSOverlayID id)
{
return FS_LoadOverlay(target, id);
}
THUMB_FUNC BOOL LoadOverlayNoInit(MIProcessor target, FSOverlayID id)
{
FSOverlayInfo info;
if (!FS_LoadOverlayInfo(&info, target, id))
return FALSE;
if (!FS_LoadOverlayImage(&info))
return FALSE;
FS_StartOverlay(&info);
return TRUE;
}
THUMB_FUNC BOOL LoadOverlayNoInitAsync(MIProcessor target, FSOverlayID id)
{
FSOverlayInfo info;
FSFile file;
if (!FS_LoadOverlayInfo(&info, target, id))
return FALSE;
FS_InitFile(&file);
FS_LoadOverlayImageAsync(&info, &file);
FS_WaitAsync(&file);
FS_CloseFile(&file);
FS_StartOverlay(&info);
return TRUE;
}
|