2.3 Modifying onetri (Read from a disk)

In the preceding example using polyline, there was no input or output to disk once the game was started. This section shows an example of simple output from disk using the sample program onetri after the game is started. The original version of onetri reads the static segment from the Game Pak ROM after the game is started, so the program is modified to read this from disk. The meaning of $(WORK) is the same as in the previous section.

1. Copy polyline to $(WORK).

[NW]

% cp -r /usr/src/PR/demos/onetri $(WORK)

[PC]

Use a tool such as Explorer to copy ultra\usr\src\PR\demos\onetri to $(WORK)

2. Switch to that directory.

[NW]

% cd $(WORK)/onetri

[PC]

Open an MS-DOS window, and enter

C>cd $(WORK)\onetri

3. Open an editor and modify Makefile as shown below.

[NW]
.......... 
LDFLAGS = ... -L$(ROOT)/usr/lib 
		lultra_d ... 
.......... 
$(MAKEROM) -r rom spec 
.......... 
[PC]
.......... 
LDFLAGS = ... -L$(LIB) 
		-lgultra_d ... 
.......... 
$(MAKEROM) -r rom spec 
.......... 
(modified) (modified)
.......... 
LDFLAGS = ... -L$(ROOT)/usr/lib 
		-lleo_d -lultra_d.. 
.......... 
/usr/sbin/makedisk -t 0 -r rom spec 
.......... 
.......... 
LDFLAGS = ... -L$(LIB) 
		-lleo_d -lgultra_d ... 
.......... 
$(MAKEROM) -DD64 -t 0 -r rom spec 
.......... 

As noted in the previous section, -t 0 specifies a disk type of 0. For details, please see section "11.5 Disk Types (ROM and RAM areas) ."

LDFLAGS are flags passed to the linker. -lleo.d means to link libleo_d.a. Details are presented in "Chapter 7, Library Functions."

4. Modify spec as shown below.

......... 
beginseg 
	name "static" 
	flags OBJECT 
	number STATIC_SEGMENT 
	include "static.o" 
endseg 
.........
......... 
beginseg 
	name "static" 
	lba 20 
	flags OBJECT 
	number STATIC_SEGMENT 
	include "static.o" 
endseg 
.........

lba 20 means to save the segment (in this case, the static segment) to the location beginning at LBA 20. The smallest access unit of the 64DD is called a "block," and these blocks are numbered consecutively from 0 to 4291. This number is called the Logical Block Address (LBA). The program uses this number to access the disk. For a detailed description of the LBA, please see "Chapter 11, 64DD Hardware Specifications."

5. Modify onetri.c.

The section to modify is that where the static segment is loaded behind the code segment.

#include <ultra64.h>
#include <PR/ramrom.h>  /* needed for argument passing into the app */
#include <assert.h>

#include "onetri.h"
.........

static void
mainproc(void *arg)
{
OSTask		*tlistp;
Dynamic		*dynamicp;
char		*staticSegment;
.........
/*
 * Stick the static segment right after the code/data segment
 */
staticSegment = _codeSegmentEnd;
osPiStartDma(&dmaIOMessageBuf, OS_MESG_PRI_NORMAL, OS_READ,
              (u32)_staticSegmentRomStart, staticSegment,
              (u32)_staticSegmentRomEnd - 
                 (u32)_staticSegmentRomStart,
               &dmaMessageQ);
    
/*
 * Wait for DMA to finish
 */
    (void)osRecvMesg(&dmaMessageQ, NULL, OS_MESG_BLOCK);
    
........
}

Make additions and changes to this section as shown on the following page.

#include <ultra64.h>
#include <PR/ramrom.h>  /* needed for argument passing into the app */
#include <assert.h>

#include <PR/leo.h>				 	      <--added	

#include "onetri.h"

#if __GNUC__ /* { */
extern short int _staticSegmentDiskStart,_staticSegmentDiskEnd;
#else/* }{ */                                                  <--added	
extern char       _staticSegmentDiskStart[],_staticSegmentDiskEnd[];
#endif /* } */
.........

#define NUM_LEO_MESGS   8			         	<--added
static  OSMesg  LeoMessages[NUM_LEO_MESGS];

.........

static void
mainproc(void *arg)
{
OSTask		*tlistp;
Dynamic		*dynamicp;
char		*staticSegment;
LEOCmd		cmdBlock;				        <--added    
.........

/*
 * Create leo manager
 */
LeoCreateLeoManager((OSPri)OS_PRIORITY_LEOMGR - 1,
                                                                <---added	
                       (OSPri)OS_PRIORITY_LEOMGR,
                        LeoMessages, NUM_LEO_MESGS);

/*
 * Stick the static segment right after the code/data segment
 */
staticSegment = _codeSegmentEnd;
LeoReadWrite(&cmdBlock, OS_READ,
             (u32)_staticSegmentDiskStart, staticSegment,
             (u32)_staticSegmentDiskEnd -	                 <--changed
               (u32)_staticSegmentDiskStart,
              &dmaMessageQ);
    
/*
 * Wait for DMA to finish
 */
(void)osRecvMesg(&dmaMessageQ, NULL, OS_MESG_BLOCK);
    
........
}

LeoReadWrite( )is a disk-access function. It corresponds exactly to osPiStartDma( ), which is used when accessing the Game Pak ROM. LeoCreateLeoManager( ) is a function for starting the manager leo manager, which enables LeoReadWrite( )to be used. For more information on these functions, please see "Chapter 7, Library Functions."

6. After making these changes, compile the program.

[NW]

% make

[PC]

C>make

7. Start Partner

[NW]

% ptn64

[PC]

Double-click on the Partner N64 PC icon.

The following are commands entered in the Partner command box.

8. Write the program to disk.

Write the program to disk, load the debugging information, and start the IPL. The IPL loads the game program.

[NW]

> l onetri

[PC]

> l onetri.out (.out can be omitted)

9. Run the game "onetri."

[ NW and PC ]

>g

Note: In the example above, static.c is read as a single segment after the game is started. If it is read successfully, this is displayed on the screen. However, this configuration is inadequate because it provides no means of displaying an error message if the static seqment is not read successfully. This type of configuration was provided as an example of a simple read from disk. With actual games, however, please be sure to include error display functions and display list in the boot segment (See Section 12.2, After the IPL starts the game, disk access is prohibited until the first screen (e.g. title screen)]. Moreover, the IPL loads only the boot segment and cannot be configured to load multiple segments.