n64software.html 8.14 KB
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <title>/tmp/n46software.html</title>
  <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
</head>
<body>
<h2>N64 Software Notes</h2>
May 2002<br>
<br>
The N64 source code is in the bb tree under the directory sw/n64os20l. &nbsp;This
subdirectory is essentially the contents of the PR (project reality) tree.
&nbsp;The source code is a merge of parts of two separate trees. &nbsp;The
n64os20l tree from Nintendo (release 2.0L of the N64 OS), used for continuing
engineering to the n64 software development kit after the hardware was
completed and some of the hardware components (rcp chip verilog source, test
programs)&nbsp; from the SGI PR
tree that Nintendo had dropped from their software tree.<br>
<br>
The idea behind this N64 tree (n64os20l) &nbsp;is to have a working copy
of the verification and development environment for the N64 console. &nbsp;In
the short term, there shouldn't be any BBplayer specific changes to this
part of the tree -- we will maintain a new subtree for BBplayer
development and copy the desirable portions from the n64os20l tree.<br>
<h3>Build Environment</h3>
The original development environment for the N64 was mips-based SGI workstations.
&nbsp;Since a mips processor running in big-endian mode was used in the N64
console, the development environment was relatively straightforward. &nbsp;For
example, the same compiler could be used for generating executable code to
run on the SGI machines and the N64 console.<br>
<br>
Much of the development environment has been ported to run on a linux-x86
cross development system. &nbsp;There are several significant differences
in this environment: &nbsp;the host system is little-endian x86, and the
host operating system is gnu/linux. &nbsp;Most of the SGI build style was
maintained by porting the makefiles to use GNU make, rather than SGI's smake.
&nbsp; Extra tools and files to support x86-linux development are in the
tree under sw/devroot/linux. &nbsp;To create a useable development environment
you need an updated copy of the source tree including sw/devroot and sw/n64os20l
and you need to set the environment variable $ROOT to point at a subdirectory
where headers, libraries, binaries, etc can be installed as part of the development
process. &nbsp;Note that $ROOT has little to do with the location of your
source tree (in SGI-speak, your source tree is pointed to by $WORKAREA, and
$ROOT points at the place where the result of building your source tree should
go).<br>
<br>
Before you can build the n64os20l source tree you need to install the devroot
tools. &nbsp;To do this you need to install some parts such as the mips-linux
cross compiler as root (it gets installed in /usr/mips-linux) and install
the rest as yourself:<br>
<br>
%&nbsp;cd sw/devroot/linux<br>
% su<br>
# make install_root<br>
^D<br>
% make install<br>
<br>
Note that the devroot is still evolving, so it is a good idea to frequently
update the devroot source and reinstall<br>
<br>
Once the devroot is built and installed, you can build the n64 tree from
the toplevel makefile:<br>
<br>
% cd sw/n64os20l<br>
% make headers<br>
% make exports<br>
% make<br>
<br>
make headers builds any generated header files and installs them in $ROOT/usr/include
(mostly in $ROOT/usr/include/PR). &nbsp;make exports builds tools that are
need by other parts of the build and installs them in $ROOT/usr/sbin and
$ROOT/usr/lib. &nbsp;make exports typically builds the entire 'product' part
of the source code, this includes all of the components of the n64 sdk (libraries,
rsp code, etc). &nbsp; The remaining make builds a few additional parts of
the tree.<br>
<h3>Porting/Cross Development Issues</h3>
Issues and strategies for dealing with porting the build environment are
documented here in the hopes of handling things in a consistent way. &nbsp;In
particular, the goal is to keep the tree in a state where the source code
can still be built on an SGI system if necessary. &nbsp;This mostly amounts
to ifdef'ing C source code changes using<br>
<br>
#ifdef __sgi__<br>
&lt; original code&gt;<br>
#else<br>
&lt; new x86 code&gt;<br>
#endif<br>
<br>
and creating separate makefiles.<br>
<br>
1) Makefile portability<br>
<br>
Some of the makefile syntax is not quite the same between SGI smake and GNU
make. &nbsp;In particular, the syntax for conditionals (#ifdef vs. ifdef,
if vs. ifeq) , and some of the special variables, syntax for built-in functions
etc. &nbsp;Rather than try to make changes to the existing Makefiles, we
take advantage of the fact that GNu make looks for a makefile with the name
GNUmakefile first before looking for Makefile. &nbsp;If porting changes
are required, we make a copy of the existing Makefile as GNUmakefile and
make the changes to GNUmakefile.<br>
<br>
There are several makefile porting issues beyond syntax changes. &nbsp;Again,
many of the existing Makefiles assume that the same compiler and options
can be used to compile code targeted to run on the host system as targetted
to run on the N64 console. &nbsp;The SGI build tools include some makefile
variables to try to help with the problem, but they were not used in very
many places. &nbsp;Typically to compile a program intended for the host system,
the variable $(HOST_CC) is used to invoke the compiler, rather than $(CC).
&nbsp;Unfortunately, this mechanism is a little simplistic since it doesn't
also provide definitions for $(HOST_CFLAGS), etc. &nbsp;I have found it simpler
to change GNUmakefiles that involve only code targetted for the host system,
to add a few lines such as
<br>
<br>
CC=$(HOST_CC)<br>
GCINCS=-D_LANGUAGE_C -I$(ROOT)/host_include<br>
GLDOPTS=<br>
<br>
to use the correct compilation environment with the smallest number of changes.
<br>
<br>
Note that this demonstrates another problematic issue with the makefiles.
&nbsp;Some header files are used in code for both the host system and the
N64. &nbsp;Using -I($ROOT)/usr/include for host code often inadvertently
pulls in unwanted/conflicting headers. &nbsp;To minimize the problem, we
create $(ROOT)/host_include that also has a copy of the PR headers $ROOT/host_include/PR
&nbsp;to be used for host code. &nbsp;Similarly, there is a $(ROOT)/host_lib
that contains libraries specific for the host (this one is a little blurrier
since some Makefiles still put host libraries in $ROOT/usr/lib and it hasn't
been necessary to fix them since it works ok).<br>
<br>
2) C/Assembly code portability<br>
<br>
As mentioned above, to retain compatibility with the SGI system, it is preferred
to use #ifdef __sgi__ to keep both the old and new code. <br>
Many of the portability issues have to do with header files that exist
on the SGI system, but not the linux system. &nbsp;e.g., bstring.h. &nbsp;These
can be handled using #ifdefs. &nbsp;Some other differences include some library
differences such as as mmap(), SGI threads (sproc versus pthreads), etc.
&nbsp;These need to be handled on a case by case basis.<br>
<br>
3) Assembly code portability<br>
<br>
The tool chain we are using allows the C-preprocessor to be used with assembly
files to be compatible with the SGI assembler. &nbsp;However, it is a little
pickier. &nbsp;In particular, it doesn't like unmatched ' characters, even
in comments. &nbsp;I fix these by doubling them up, e.g.,<br>
<br>
&nbsp;&nbsp;&nbsp; ori&nbsp;&nbsp;&nbsp; r2,3&nbsp;&nbsp;&nbsp; # don''t
you hate portability problems<br>
<br>
This issue is also true with the rsp assembler<br>
<br>
There are some directives that have slightly different forms, and can be
handled using #ifdef __sgi__, e.g.<br>
<br>
.repeat &lt;x&gt;,&lt;y&gt; &nbsp;becomes .rept &lt;x&gt;, &lt;y&gt;<br>
<br>
4) Endianness Issues<br>
<br>
The x86 uses little-endian byte order whereas the N64 console and SGI host
system are big-endian. &nbsp;Since the N64 target is big-endian, it makes
sense to maintain all external data representations in big-endian format.
&nbsp;This means that when necessary, programs running on x86-linux need
to convert to little endian (native endianness) when reading files, and convert
to big endian when writing them. &nbsp;To maximize portability, I have simply
been using the BSD networking functions (htons, ntohs, htonl, and ntohl).<br>
<br>
<br>
</body>
</html>