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.2 2008/06/13 04:43:33 mitu Exp $
14 
15   $NoKeywords: $
16  *---------------------------------------------------------------------------*/
17 
18 #include <revolution.h>
19 
20 #include <revolution/rso.h>
21 
22 
23 #ifdef _DEBUG
24 #define MODULE_A     "/aD.rso"
25 #define MODULE_B     "/bD.rso"
26 #define STATIC_RSO   "/staticD.sel"
27 #else
28 #define MODULE_A     "/a.rso"
29 #define MODULE_B     "/b.rso"
30 #define STATIC_RSO   "/static.sel"
31 #endif
32 
33 //
34 void _unresolved();
35 
36 /*---------------------------------------------------------------------------*
37    Load
38  *---------------------------------------------------------------------------*/
39 // Load and link the specified module
RsoLoad(char * moduleName)40 static RSOObjectHeader* RsoLoad(char* moduleName)
41 {
42     DVDFileInfo     fileInfo;
43     s32             length;
44     BOOL            result;
45     RSOObjectHeader* module;
46     u8*             bss;
47 
48     result = DVDOpen(moduleName, &fileInfo);
49     if (!result)
50         return NULL;
51     length = (s32) OSRoundUp32B(DVDGetLength(&fileInfo));
52     module = OSAllocFromArenaLo((u32) length, 32);
53     result = DVDRead(&fileInfo, module, length, 0);
54     if (!result)
55         return NULL;
56     DVDClose(&fileInfo);
57 
58     if (module->bssSize > 0)
59     {
60         bss = OSAllocFromArenaLo(module->bssSize, 32); // Alloc bss area
61     }
62     RSOLinkList(module, bss);
63 
64     return module;
65 }
66 
67 // Load and link the static module
StaticRsoLoad(char * moduleName)68 static RSOObjectHeader* StaticRsoLoad(char* moduleName)
69 {
70     DVDFileInfo     fileInfo;
71     s32             length;
72     BOOL            result;
73     RSOObjectHeader* module;
74 
75     result = DVDOpen(moduleName, &fileInfo);
76     if (!result)
77         return NULL;
78     length = (s32) OSRoundUp32B(DVDGetLength(&fileInfo));
79     module = OSAllocFromArenaLo((u32) length, 32);
80     result = DVDRead(&fileInfo, module, length, 0);
81     if (!result)
82         return NULL;
83     DVDClose(&fileInfo);
84 
85     RSOListInit(module);
86 
87     return module;
88 }
89 
90 //
_unresolved()91 void _unresolved()
92 {
93     OSReport("_unresolved func.\n");
94 }
95 
96 
97 // Functions and variables we want to access
98 void (*MainA)();
99 void (*IsAThere)();
100 int  (*g_intA);
101 
102 static RSOExportFuncTable exp_tbl[] =
103 {
104     {"MainA",   (u32 *)&MainA},
105     {"IsAThere",(u32 *)&IsAThere},
106     {"g_intA",  (u32 *)&g_intA},
107 };
108 
109 //
RSOResolvedModuleA(const RSOObjectHeader * module)110 static void RSOResolvedModuleA(const RSOObjectHeader* module)
111 {
112     int i;
113     for(i = 0; i < sizeof(exp_tbl)/sizeof(RSOExportFuncTable); i++) {
114         *(exp_tbl[i].symbol_ptr) =
115             (u32)RSOFindExportSymbolAddr(module, exp_tbl[i].symbol_name);
116     }
117 }
118 
119 //
RSOUnresolvedModuleA(void)120 static void RSOUnresolvedModuleA(void)
121 {
122     int i;
123     for(i = 0; i < sizeof(exp_tbl)/sizeof(RSOExportFuncTable); i++) {
124         *(exp_tbl[i].symbol_ptr) = (u32)_unresolved;
125     }
126 }
127 
128 
129 //Main
main(void)130 int main(void)
131 {
132     RSOObjectHeader* staticRso;
133     RSOObjectHeader* moduleA;
134     RSOObjectHeader* moduleB;
135 
136     // Generate weak symbol 'InlineFunc'
137     DVDInit();
138 
139     //Read
140     // Load static rso file
141     OSReport("Loading static rso...\n");
142     staticRso = StaticRsoLoad(STATIC_RSO);
143     if (!staticRso)
144         return 1;
145 
146     // Load and link module A
147     OSReport("Linking module A...\n");
148     moduleA = RsoLoad(MODULE_A);
149     if (!moduleA) {
150         return 1;
151     }
152 
153     // Load and link module B
154     OSReport("Linking module B...\n");
155     moduleB = RsoLoad(MODULE_B);
156     if (!moduleB) {
157         return 1;
158     }
159 
160     //Check whether everything has been resolved
161     if (RSOIsImportSymbolResolvedAll(moduleA))
162     {
163         OSReport("moduleA's ImportSymbol is resolved all.\n");
164     }
165     if (RSOIsImportSymbolResolvedAll(moduleB))
166     {
167         OSReport("moduleB's ImportSymbol is resolved all.\n");
168     }
169 
170     // Since A and B are mutually linked, resolve both and then call prolog.
171     OSReport("\nA prolog()\n");
172     ((u32 (*)(void)) moduleA->prolog)();
173     OSReport("\nB prolog()\n");
174     ((u32 (*)(void)) moduleB->prolog)();
175 
176     //
177     RSOResolvedModuleA(moduleA);
178     //
179     OSReport("MainA = %x\n",MainA);
180     OSReport("g_intA = %x\n",g_intA);
181 
182     MainA();
183     OSReport("g_intA = %d\n", *g_intA);
184     *g_intA += 5;
185     OSReport("g_intA + 5 = %d\n", *g_intA);
186     MainA();
187 
188     //
189     OSReport("\nA epilog()\n");
190     ((u32 (*)(void)) moduleA->epilog)();
191     RSOUnresolvedModuleA();
192     //
193     OSReport("\nB epilog()\n");
194     ((u32 (*)(void)) moduleB->epilog)();
195 
196     // Since A and B mutually refer to each other, unlink after the epilog for both
197     RSOUnLinkList(moduleA);
198     RSOUnLinkList(moduleB);
199 
200     // Check whether MainA is unprocessed
201     OSReport("call MainA()\n");
202     MainA();
203     //
204     OSReport("\nRSOLink finish all!\n");
205 
206     return 0;
207 }
208