1 /*---------------------------------------------------------------------------*
2 Project: rsodemo
3 File: static.c
4
5 Copyright 2006 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 @version $Id: static.c,v 1.9 2006/09/11 06:35:16 srd_komatu Exp $
14
15 $NoKeywords: $
16 *---------------------------------------------------------------------------*/
17
18 #include <revolution.h>
19
20 #include <revolution/rso.h>
21 #include <revolution/RSOLink.h>
22
23
24 #ifdef _DEBUG
25 #define MODULE_A "/aD.rso"
26 #define MODULE_B "/bD.rso"
27 #define STATIC_RSO "/staticD.sel"
28 #else
29 #define MODULE_A "/a.rso"
30 #define MODULE_B "/b.rso"
31 #define STATIC_RSO "/static.sel"
32 #endif
33
34 void _unresolved();
35
36 /*---------------------------------------------------------------------------*
37 Load
38 *---------------------------------------------------------------------------*/
39 // Load and link the specified module
RsoLoadFixed(char * moduleName,int i_fixed_level)40 static RSOObjectHeader* RsoLoadFixed(char* moduleName,int i_fixed_level)
41 {
42 DVDFileInfo fileInfo;
43 s32 length;
44 BOOL result;
45 RSOObjectHeader* module;
46 u8* bss;
47 u32 fixed_size;
48 u32 new_arenaLo;
49 u32 old_arenaLo;
50 result = DVDOpen(moduleName, &fileInfo);
51 if (!result)
52 return NULL;
53 length = (s32) OSRoundUp32B(DVDGetLength(&fileInfo));
54 module = OSAllocFromArenaLo((u32) length, 32);
55 result = DVDRead(&fileInfo, module, length, 0);
56 if (!result)
57 return NULL;
58 DVDClose(&fileInfo);
59 //
60 fixed_size = RSOGetFixedSize(module,i_fixed_level);
61
62 // 0 indicates failure
63 ASSERT(fixed_size);
64 //
65 bss = (u8 *)((u32)module + fixed_size);
66 // 32-byte alignment
67 bss = (u8*) OSRoundUp32B(bss);
68
69 new_arenaLo = ((u32)bss + (u32)module->bssSize);
70 new_arenaLo = OSRoundUp32B(new_arenaLo);
71 old_arenaLo = (u32)OSGetMEM1ArenaLo();
72 //
73 if (module->bssSize > 0) {
74 if(old_arenaLo < new_arenaLo) {
75 // Increase the allocation memory
76 // When increasing, increase before executing RSOLocateObjectFixed
77 OSSetMEM1ArenaLo((void*)new_arenaLo);
78 }
79 } else {
80 bss = NULL;
81 }
82 //
83 RSOLinkListFixed(module,bss,i_fixed_level);
84 // When decreasing the memory area, do so after executing RSOLocateObjectFixed
85 if(bss == NULL || old_arenaLo > new_arenaLo) {
86 OSSetMEM1ArenaLo((void*)new_arenaLo);
87 }
88 return module;
89 }
90
91 // Load and link the static module
StaticRsoLoad(char * moduleName)92 static RSOObjectHeader* StaticRsoLoad(char* moduleName)
93 {
94 DVDFileInfo fileInfo;
95 s32 length;
96 BOOL result;
97 RSOObjectHeader* module;
98
99 result = DVDOpen(moduleName, &fileInfo);
100 if (!result)
101 return NULL;
102 length = (s32) OSRoundUp32B(DVDGetLength(&fileInfo));
103 module = OSAllocFromArenaLo((u32) length, 32);
104 result = DVDRead(&fileInfo, module, length, 0);
105 if (!result)
106 return NULL;
107 DVDClose(&fileInfo);
108
109 RSOListInit(module);
110
111 return module;
112 }
113
114 //
_unresolved()115 void _unresolved()
116 {
117 OSReport("_unresolved func.\n");
118 }
119
120
121 // Functions and variables to be accessed
122 void (*MainA)();
123 void (*IsAThere)();
124 int (*g_intA);
125
126 //
127 static RSOExportFuncTable exp_tbl[] =
128 {
129 {"MainA", (u32 *)&MainA},
130 {"IsAThere",(u32 *)&IsAThere},
131 {"g_intA", (u32 *)&g_intA},
132 };
133
134 //
RSOResolvedModuleA(const RSOObjectHeader * module)135 static void RSOResolvedModuleA(const RSOObjectHeader* module)
136 {
137 int i;
138 for(i = 0; i < sizeof(exp_tbl)/sizeof(RSOExportFuncTable); i++) {
139 *(exp_tbl[i].symbol_ptr) =
140 (u32)RSOFindExportSymbolAddr(module, exp_tbl[i].symbol_name);
141
142 }
143 }
144
145 //
146 //
RSOUnresolvedModuleA(void)147 static void RSOUnresolvedModuleA(void)
148 {
149 int i;
150 for(i = 0; i < sizeof(exp_tbl)/sizeof(RSOExportFuncTable); i++) {
151 *(exp_tbl[i].symbol_ptr) = (u32)_unresolved;
152 }
153 }
154
155
156 //main
main(void)157 int main(void)
158 {
159 RSOObjectHeader* staticRso;
160 RSOObjectHeader* moduleA;
161 RSOObjectHeader* moduleB;
162
163 // Generate weak symbol 'InlineFunc'
164 DVDInit();
165
166 // Read data
167 // Load static rso file
168 OSReport("Loading static rso...\n");
169 staticRso = StaticRsoLoad(STATIC_RSO);
170 if (!staticRso)
171 return 1;
172
173 // Load and link module A
174 OSReport("Linking module A...\n");
175 moduleA = RsoLoadFixed(MODULE_A,RSO_FL_INTERNAL);
176 if (!moduleA) {
177 return 1;
178 }
179
180 // Load and link module B
181 OSReport("Linking module B...\n");
182 moduleB = RsoLoadFixed(MODULE_B,RSO_FL_INTERNAL);
183 if (!moduleB) {
184 return 1;
185 }
186
187 // Check whether all symbols are resolved
188 if (RSOIsImportSymbolResolvedAll(moduleA))
189 {
190 OSReport("moduleA's ImportSymbol is resolved all.\n");
191 }
192 if (RSOIsImportSymbolResolvedAll(moduleB))
193 {
194 OSReport("moduleB's ImportSymbol is resolved all.\n");
195 }
196
197 // Since A and B are mutually linked, resolve both and then call prolog.
198 OSReport("\nA prolog()\n");
199 ((u32 (*)(void)) moduleA->prolog)();
200 OSReport("\nB prolog()\n");
201 ((u32 (*)(void)) moduleB->prolog)();
202
203 //
204 RSOResolvedModuleA(moduleA);
205 //
206 OSReport("MainA = %x\n",MainA);
207 OSReport("g_intA = %x\n",g_intA);
208
209 MainA();
210 OSReport("g_intA = %d\n", *g_intA);
211 *g_intA += 5;
212 OSReport("g_intA + 5 = %d\n", *g_intA);
213 MainA();
214
215 //
216 OSReport("\nA epilog()\n");
217 ((u32 (*)(void)) moduleA->epilog)();
218 RSOUnresolvedModuleA();
219 //
220 OSReport("\nB epilog()\n");
221 ((u32 (*)(void)) moduleB->epilog)();
222
223 // Since A and B mutually refer to each other, unlink after the epilog for both
224 RSOUnLinkList(moduleA);
225 RSOUnLinkList(moduleB);
226
227 //
228 OSReport("\nRSOLink finish all!\n");
229
230 return 0;
231 }
232