7-4 Tutorial


By using an actual sample this section describes the program compilation/link, creation of the ROM image file, and the debugging method. Before you use the sample, we will describe the procedure for creating the ROM image file. Proceed to the next step after you have an understanding of this.


7-4-1 Procedure for creating the ROM image file


The ROM image file is created by designating the object file and the picture/sound data to the ROM image creation tool after the relocationable object file is created one time using the compiler/linker. (Relocationable object file: Object files where the function and argument addresses have not been determined). The ROM image creation tool outputs the ROM image file and the debugger symbol file. When a name for the ROM image file is not specified it is output using the name, "rom". Specify the symbol file name within "beginwave" and "endwave" of the spec file specified to the ROM image creation tool.



7-4-2 The compilation/link/creation of the ROM image using an actual sample.


Now let us do the compilation/link/creating the ROM image of the actual sample. Here, we will use the sample called, "simple". "simple" has been installed in the directory, "/usr/src/PR/demos/simple". Copy it into the appropriate directory from the console. For example, you can make the directory, "simple". copied into the current directory by executing

% cp -r /usr/src/PR/demos/simple .


1. Makefile
The compilation/link/ROM image creation on "simple" are provided by using the program, "make".
"make" provides the process based on the contents defined in the text file, "Makefile" (see the online manual, "make", for details).

Now, we will describe the contents defined in "Makefile". Open the text file, "Makefile", in the directory, "simple", with your editor (the actual "Makefile" does not describe the following #comments).

[Makefile]

#!smake
include $(ROOT)/usr/include/make/PRdefs # Files reserved in the system [defining
# the compiler name and
# dependency, etc.

# to make the tags file do "make simpletags"
# to make just the simple_d directory do "make SUBDIRS=simple_d"

SUBDIRS=simple_d simple simple_rom # Specify the subdirectory
# In "simple", you create the following three types of ROM image files
# and symbol files
# 1. For debugging simple_d
# 2. For ordinary use simple
# 3. For master submitting simple_rom

COMMONPREF = simple # unused

APP = simple # Specifying the symbol file name
TARGETS = rom # Specifies the ROM image file name

HFILES = \ # Specifies the header file name for "simple"
:
CODEFILES = \ # Specifies the .c (the program code) file name
:
CODEOBJECTS = $(CODEFILES:.c=.o)
# Specifies (the program code) file name
# (The name is changed from .c to .o, which is
# the file name specified in CODEFIELES
# Example) test.c -> test.o

CODESEGMENT = codesegment.o # Specifies the relocationable
# object file name created as a
# result of linking the program code
# Data files that have their own segments:

DATAFILES = \ # Specifies the .o(data) file name
:
DATAOBJECTS = $(DATAFILES:.c=.o)
# Specifies the .o (data code) file name
# (Same as CODDOBJECTS above)

OBJECTS = $(CODESEGMENT)$(DATAOBJECTS)
# Specifies all relocationable object file names
# Specifies to the ROM image creation tool


LCINCS = -I.. -I$(ROOT)/usr/include/PR
# Specifies the passing of the include file specified to the compiler (for local use)
LCOPTS = $(DFLAG) -fullwarn -non_shared -G 0 -Xcpluscomm
# Designates the option to specify to the compiler (for local use)
LCDEFS =
# Specifies the symbol definition to specify to the compiler (for local use)
# Unused in "simple"

LDIRT = load.map # Specifies the map file name

LDFLAGS = $(MKDEPOPT) -nostdlib -L$(ROOT)/usr/lib
-L$(ROOT)/usr/lib/PR -l$(ULTRALIB)
# Designates the option to specify to the linker
# MKDEPOPT is the reserved name and the file defined to dependent
# relation of each object file.
# "-nostdlib" is a specification which is not use the standard library
# "-L$(ROOT)/usr/lib -L$(ROOT)/usr/lib/PR -l$(ULTRALIB)" is the
# option to link the N64 OS library.

.PATH: .. # The path specification of "simple"
# "simple" is to execute "make" in each subdirectory.
# The file reserved in the system..
sinclude locdefs

#include $(COMMONRULES) # Note that "#" is a comment.

default:z # Specifies to provide the following
# process with default in this "Makefile".
for i in $(SUBDIRS) ; do \ # Specifies to go to each subdirectory
echo ==== $$i === ; \ # and execute "make".
cd $$i ; \
$(MAKE) -f ../Makefile loc_$$i ; \
cd .. ; \
done

$(COMMONTARGS) : # Specifies to provide the process when it specifies
# the reserved command in the system to "make"
# Example) make clean
for i in $(SUBDIRS) ; do \ # default: the same
echo ==== clobber $$i === ; \
cd $$i ; \
$(MAKE) -f ../Makefile loc_$@ ; \
cd .. ; \
done

include $(COMMONRULES) # Accept the reserved file in the
# system

install: default # Specifies to install "simple"
# The files below are installed.
# Before executing this, execute the default
# if it is not executed.
$(INSTALL) -m 444 -F /usr/src/PR/demos/simple \
$(HFILES) $(CODEFILES) \
$(DATAFILES) Makefile spec \
simple/log.fmt simple_d/locdefs \
simple/locdefs simple_rom/locdefs

$(CODESEGMENT): $(CODEOBJECTS)
# Specifies the dependent relation between "codesegment.o" and the .o file.
# If the .o file is updated, provide the following process.
$(LD) -m -o $(CODESEGMENT) -r $(CODEOBJECTS) \
$(LDFLAGS) > load.map
# Specifies to create the relocationable object file by using the linker.
# "-m" specifies to output the map file.
# "-o" $(CODESEGMENT) is an option to specify the output file name.
# "-r" is the option to create the relocationable object file.
# "$(CODEOBJECTS)" specifies the linking object file name.
# "$(LDFLAGS)" specifies to pass other options to the linker.

rom: ../spec $(OBJECTS)
# Specifies the ROM image file, all ".o" files and the dependent relation of the spec file
# Provide the following process when the .o file and the spec file are updated
$(MAKEROM) $(MAKEROMDEFS) ../spec
# Specifies to create the ROM image file by using the ROM image creation tool.
# "$(MAKEROSDEFS)" is the standard option specified to the image creation tool.
# "spec" is the text file to specify the ROM image to the ROM image creation tool.
# We will describe this later.


The contents mentioned above are just one example. The compiler/linker/ROM image creation tool has many other convenient functions. Utilize them based on what the program can be used for.


2. Specifying the ROM Image
Next, we will describe the contents defined in the script file to specify the ROM image. Open the text file, "spec", in the directory, "simple", with your editor (in the actual "spec", the /*Comments*/ below are not described). Read the "makerom" online manual along with this explanation.

[spec]

/* The ROM image manages in units of segments.*/
/* Define the segments having the program code attributes.*/
beginseg /* Initiate to define the segments*/
name "code" /* Specify the segment names */
flags BOOT OBJECT /* Designate the boot attribute and the object attribute */
entry boot /* Specify the boot function */
stack bootStack + STACKSIZEBYTES
/* Specify the stack used by the boot function */
include "codesegment.o"
/* Specify the object file mapping within the segment */
include "$(ROOT)/usr/lib/PR/rspboot.o"
/* Specify the boot microcode*/
include "$(ROOT)/usr/lib/PR/gspFast3D.o"
/* Specify the graphic microcode */
include "$(ROOT)/usr/lib/PR/gspFast3D.dram.o"
/* Specify the graphic microcode */
include "$(ROOT)/usr/lib/PR/aspMain.o"
/* Specify the sound microcode */
endseg /* End segment definitions */
/* The following is a description only about the parts which do not overlap with the "code" segments. */
beginseg
name "gfxdlists"
flags OBJECT /* Designate the object attribute */
after code /* Specify mapping right after the "code" segment. */
include "gfxdlists.o"
endseg
beginseg
name "zbuffer"
flags OBJECT /* Designate the object attribute */
address 0x801da800 /* Specify mapping on the 0x801da800 address*/
include "gfxzbuffer.o"
endseg

beginseg
name "cfb"
flags OBJECT /* Designate the object attribute */
address 0x80200000 /* Specify mapping on the 0x80200000 address*/
include "gfxcfb.o"
endseg
beginseg
name "static"
flags OBJECT /* Designate the object attribute */
number STATIC_SEGMENT /* Specify the static segment number */
include "gfxinit.o"
include "gfxstatic.o"
endseg
beginseg
name "dynamic"
flags OBJECT /* Designate the data attribute */
number DYNAMIC_SEGMENT /* Specify the dynamic segment number */
include "gfxdynamic.o"
endseg
beginseg
name "bank"
flags RAW /* Designate the data attribute */
include "$(ROOT)/usr/lib/PR/soundbanks/GenMidiBank.ctl"
/* Specify the sound bank data */
endseg
beginseg
name "table"
flags RAW /* Designate the data attribute */
include "$(ROOT)/usr/lib/PR/soundbanks/GenMidiBank.tbl"
/* Specify the sound table data. */
endseg
beginseg
name "seq"
flags RAW /* Designate the data attribute */
include "$(ROOT)/usr/lib/PR/sequences/BassDrive.seq"
/* Specify the sound sequence data */
endseg

beginwave /* Initiate to define waves */
name "simple" /* Specify the symbol file name (ignore ".out") */
include "code" /* The following are the specification of mapping segments. */
include "gfxdlists"
include "static"
include "dynamic"
include "cfb"
include "zbuffer"
include "table"
include "bank"
include "seq"
endwave /* End the wave definition */


The preceding is the required procedure to do the compilation/link/ROM image creation for the sample with "make".


3. Executing "make"
Now, we will actually execute, "make". Execute "make" from the directory, "simple".

% make

After completion of "make" in three subdirectories, the ROM image file, "rom" and the symbol file, "simple" are created. Verify this with the "Is" command, etc.



7-4-3 Executing the Sample

Execute the sample by using the ROM image and symbol files which were created in "5-4-2: The Compilation/Link/ROM Image Creation of the Sample" (you use "simple" again here). Do the execution of the sample by using the debugger (The rest is called "PARTNER"). Continue with the following procedure:


1. Move the Directory
Move to the subdirectory "simple_d" of "simple".

% cd simple_d


2. Activate PARTNER
In the moved directory, enter the shell script "ptn64" for the "PARTNER" activation.

% ptn64

Note: Before the "PARTNER" activation, specify the directory of, "simple", to the environment argument, "PTSRC".


3. Load the File
Enter the "I command" in the command window.

>l simple


4. The Execution
Enter the "g command" or the F5 key in the command window.


5. End the Program
Press the ESC key.



7-4-4 Debug the Sample


Here we will describe some debugging examples (the operation methods of PARTNER) using the sample. We use "simple" here again.


1. Setting/Freeing the Breakpoint
We will describe the setting method of the breakpoint. Set the breakpoint in "simple" - "gfx.c" - "createGfxTask()".

After loading the sample, press the F1 key. After you press the key, the window, "Select reference file name", is displayed. Select "fgx.c" with the cursor key, and press the "Enter" key,



After the end of the module selection, the contents of "gfx.c" are displayed in the command window of PARTNER. Scroll sources until you reach, "createGfxTask()", by using the PageDown key or the scroll key. Line numbers are displayed at the left side of the code window. Scroll until you reach between the 110th and 130th lines.

On the 127th line of "gfx.c", there is a place which is bringing up the assert() function. Bring the mouse cursor to the line number and click on it with the left button of the mouse. Then a line is displayed under the line bringing up the assert() function from the code window. Now the breakpoint is set.



Next, execute the program.



After execution, the line which set the breakpoint is highlighted and the program breaks. When you free the breakpoint, click on the line number with the left mouse button in the same way as with the setting. After clicking, the underline of the line which set the breakpoint disappears. Now you have freed the breakpoint.


2. The Step Execution/ The Trace Execution
Next we will describe the step execution/the trace execution of the program. First execute the contents explained in "1. Setting/ Freeing the Breakpoint". After the break, provide the step execution.

The trace execution is done by entering the "t command" or F8 key in the command window. The difference between this and the step execution is that if a function is brought up, the trace execution goes into the function, but the step execution just provides the function call and does not go inside of the function.


Enter the "p command" or the F10 key in the command window. After doing this, the highlighted line in the code window moves along in the process of the program. This shows that the step execution is being done.


3. The Dump/Editing
Next we will describe the dump/editing functions. First we will execute the contents explained in "1. Setting/ Freeing the Breakpoint." After the break, do the dump.

The dump is done using the "d command" from the command window. In "createGfxTask()" the argument called "glistp" provides the data setting. Dump this content.

>d glistp

After inputting, the 16-byte dump data is displayed in the command window. If you want to do the dump continuously, simply enter the "d command" only. The dump data is displayed in units of 16-bytes.



We have only described the dump in units of byte here. However, the "d command" can dump in various sizes. Try out some of these.

Next we will do editing. The dump is done by using the "e command" from the command window. The editing also uses the argument called "glistp". Do the following input in the command window.

>e glistp

After inputting, it will enter the input wait status. Enter "ff" and enter "." next. ("." specefies the end of editing).



After clicking, when you dump "glistp" again, you will find that the first byte becomes "Oxff".

Though we have only described the editing in units of bytes here, you can edit in various sizes with the "e command". Try out some of these.


4. Refering to the Argument of C
Next we will describe the source code debug function which refers to the arguments of C. First execute the contents explained in "1. Setting/Freeing the Breakpoint." After the break, we will carry out the argument reference.

First, let us try to reference using the inspect window. In "createGfxTask()", the local argument "dynamicp" is passed to the function "doLogo()". Set the mouse cursor to "dynamicp" on the code window, and double-click the left mouse button.



After double-clicking, the inspect window is displayed and you can look up the contents of "dynamicp". The inspect window is displayed in horizontal lines. If it's hard to see, double-click the @ address in the inspect window with the left mouse button. You can display them vertically. You can also do the inspect by using the "ins command" from the command window.

>ins dynamicp



Next, let us provide the reference using the watch window. The operation of the watch window is basically the same as the inspect window. This time, try to look up the argument "glistp". Set the mouse cursor on "dynamicp" in the code window, and enter CTRL+W or CTRL+F7. After clicking, the watch window is displayed, and you can look up the contents of "glistp".



You can also carry out the watch by using the "w command" from the command window.

Finally, if you want to look up the local argument, you can do so by operating the local window of the option window. You do not have to do the inspect and the watch.




5. The Debug Print
In PARTNER, you can look up the debug print during programming. To display the debug print, "osSyncPrintf( )" which is compatible with the N64 OS functions, is used. The output result of "osSyncPrintf( )" is displayed in the command window. "simple" is the program which displays the debug print when the A, B and C button of the controller are entered. After loading "simple", execute it without setting the breakpoint. When you enter the button of the controller while executing the program, the debug print is displayed in the command window.





All of the above are simple examples of debugging. PARTNER has various other functions. Find the most suitable debugging method from among them.