/*---------------------------------------------------------------------------* Project: rsodemo File: static.c Copyright 2006 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. @version $Id: static.c,v 1.2 2008/06/13 04:43:37 mitu Exp $ $NoKeywords: $ *---------------------------------------------------------------------------*/ #include #include #ifdef _DEBUG #define MODULE_A "/aD.rso" #define MODULE_B "/bD.rso" #define STATIC_RSO "/staticD.sel" #else #define MODULE_A "/a.rso" #define MODULE_B "/b.rso" #define STATIC_RSO "/static.sel" #endif void _unresolved(); /*---------------------------------------------------------------------------* Load *---------------------------------------------------------------------------*/ // Load and link the specified module static RSOObjectHeader* RsoLoadFixed(char* moduleName,RSOFixedLevel i_fixed_level) { DVDFileInfo fileInfo; s32 length; BOOL result; RSOObjectHeader* module; u8* bss; u32 fixed_size; u32 new_arenaLo; u32 old_arenaLo; result = DVDOpen(moduleName, &fileInfo); if (!result) return NULL; length = (s32) OSRoundUp32B(DVDGetLength(&fileInfo)); module = OSAllocFromArenaLo((u32) length, 32); result = DVDRead(&fileInfo, module, length, 0); if (!result) return NULL; DVDClose(&fileInfo); // fixed_size = RSOGetFixedSize(module,i_fixed_level); // 0 indicates failure ASSERT(fixed_size); // bss = (u8 *)((u32)module + fixed_size); // 32-byte alignment bss = (u8*) OSRoundUp32B(bss); new_arenaLo = ((u32)bss + (u32)module->bssSize); new_arenaLo = OSRoundUp32B(new_arenaLo); old_arenaLo = (u32)OSGetMEM1ArenaLo(); // if (module->bssSize > 0) { if(old_arenaLo < new_arenaLo) { // Increase the allocated region // When increasing, increase before executing RSOLocateObjectFixed OSSetMEM1ArenaLo((void*)new_arenaLo); } } else { bss = NULL; } // RSOLinkListFixed(module,bss,i_fixed_level); // When decreasing the memory area, do so after executing RSOLocateObjectFixed if(bss == NULL || old_arenaLo > new_arenaLo) { OSSetMEM1ArenaLo((void*)new_arenaLo); } return module; } // Load and link the static module static RSOObjectHeader* StaticRsoLoad(char* moduleName) { DVDFileInfo fileInfo; s32 length; BOOL result; RSOObjectHeader* module; result = DVDOpen(moduleName, &fileInfo); if (!result) return NULL; length = (s32) OSRoundUp32B(DVDGetLength(&fileInfo)); module = OSAllocFromArenaLo((u32) length, 32); result = DVDRead(&fileInfo, module, length, 0); if (!result) return NULL; DVDClose(&fileInfo); RSOListInit(module); return module; } // void _unresolved() { OSReport("_unresolved func.\n"); } // Functions and variables we want to access void (*MainA)(); void (*IsAThere)(); int (*g_intA); // static RSOExportFuncTable exp_tbl[] = { {"MainA", (u32 *)&MainA}, {"IsAThere",(u32 *)&IsAThere}, {"g_intA", (u32 *)&g_intA}, }; // static void RSOResolvedModuleA(const RSOObjectHeader* module) { int i; for(i = 0; i < sizeof(exp_tbl)/sizeof(RSOExportFuncTable); i++) { *(exp_tbl[i].symbol_ptr) = (u32)RSOFindExportSymbolAddr(module, exp_tbl[i].symbol_name); } } // // static void RSOUnresolvedModuleA(void) { int i; for(i = 0; i < sizeof(exp_tbl)/sizeof(RSOExportFuncTable); i++) { *(exp_tbl[i].symbol_ptr) = (u32)_unresolved; } } //Main int main(void) { RSOObjectHeader* staticRso; RSOObjectHeader* moduleA; RSOObjectHeader* moduleB; // Generate weak symbol 'InlineFunc' DVDInit(); //Read // Load static rso file OSReport("Loading static rso...\n"); staticRso = StaticRsoLoad(STATIC_RSO); if (!staticRso) return 1; // Load and link module A OSReport("Linking module A...\n"); moduleA = RsoLoadFixed(MODULE_A,RSO_FL_INTERNAL); if (!moduleA) { return 1; } // Load and link module B OSReport("Linking module B...\n"); moduleB = RsoLoadFixed(MODULE_B,RSO_FL_INTERNAL); if (!moduleB) { return 1; } //Check whether everything has been resolved if (RSOIsImportSymbolResolvedAll(moduleA)) { OSReport("moduleA's ImportSymbol is resolved all.\n"); } if (RSOIsImportSymbolResolvedAll(moduleB)) { OSReport("moduleB's ImportSymbol is resolved all.\n"); } // Since A and B are mutually linked, resolve both and then call prolog. OSReport("\nA prolog()\n"); ((u32 (*)(void)) moduleA->prolog)(); OSReport("\nB prolog()\n"); ((u32 (*)(void)) moduleB->prolog)(); // RSOResolvedModuleA(moduleA); // OSReport("MainA = %x\n",MainA); OSReport("g_intA = %x\n",g_intA); MainA(); OSReport("g_intA = %d\n", *g_intA); *g_intA += 5; OSReport("g_intA + 5 = %d\n", *g_intA); MainA(); // OSReport("\nA epilog()\n"); ((u32 (*)(void)) moduleA->epilog)(); RSOUnresolvedModuleA(); // OSReport("\nB epilog()\n"); ((u32 (*)(void)) moduleB->epilog)(); // Since A and B mutually refer to each other, unlink after the epilog for both RSOUnLinkList(moduleA); RSOUnLinkList(moduleB); // OSReport("\nRSOLink finish all!\n"); return 0; }