Using Overlays

The total application code size and data will probably be greater than what is actively being used at any point in time. To conserve DRAM, applications may choose to only have active code and data resident. To facilitate this, the application can be partitioned into a number of segments, where some segments share the same memory region during different phases of execution. Here is an excerpt from a specification file that contains a kernel code segment that can call routines in either of two overlay segments, texture and plain:

    beginseg
            name “kernel”
            flags BOOT OBJECT
            entry boot
            stack bootStack + STACKSIZE
            include “kernel.o”
            include “$(ROOT)/usr/lib/PR/rspboot.o”
            include “$(ROOT)/usr/lib/PR/gspFast3D.o”
    endseg

    beginseg
            name “plain”
            flags OBJECT
            after “kernel”
            include “plain.o”
    endseg

    beginseg
            name “texture”
            flags OBJECT
            after “kernel”
            include “texture.o”
    endseg

    beginwave
    	name “overlay”
    	include “kernel”
    	include “plain”
    	include “texture”
    endwave

Note the use of the after keyword to place both of the overlay segments at the same address. Also note that makerom must be called with the -o option to disable the checking of overlapping segments in the above specification file.

Prior to loading a segment into memory, the application must invalidate the corresponding instruction and data cache lines. The makerom (1P) makes appropriate symbols available to the application that can be used to construct the arguments to the osInvalICache(3P) and osInvalDCache(3P) routines. Then the actual DMA from ROM to DRAM may be performed, as well as the clearing of the uninitialized data (bss) section of the segment.

Again, makerom(1P) generated symbols may be used for the bzero() call. After the segment is loaded, any procedure in the segment may be called or any data in the segment referenced. Following is sample code that illustrates the entire process:

    extern char _plainSegmentRomStart[], _plainSegmentRomEnd[];
    extern char _plainSegmentStart[];
    extern char _plainSegmentTextStart[], _plainSegmentTextEnd[];
    extern char _plainSegmentDataStart[], _plainSegmentDataEnd[];
    extern char _plainSegmentBssStart[], _plainSegmentBssEnd[];

    	osInvalICache(_plainSegmentTextStart,
    	    _plainSegmentTextEnd-_plainSegmentTextStart);
    	osInvalDCache(_plainSegmentDataStart,
    	    _plainSegmentDataEnd-_plainSegmentDataStart);
    	osPiStartDma(&dmaIOMessageBuf, OS_MESG_PRI_NORMAL,OS_READ,
    	    (u32)_plainSegmentRomStart, _plainSegmentStart,
    	    (u32)_plainSegmentRomEnd - (u32)_plainSegmentRomStart,
    	    &dmaMessageQ);

    	bzero(_plainSegmentBssStart,
    	      _plainSegmentBssEnd-_plainSegmentBssStart);
    (void)osRecvMesg(&dmaMessageQ, NULL, OS_MESG_BLOCK);

Copyright © 1999 Nintendo of America Inc. All Rights Reserved Nintendo and N64 are registered trademarks of Nintendo Last Updated January, 1999