UNDERSTANDING THE BASICS

The Yaroze is all fired up, and is just waiting to engage in
some serious development. You've been browsing through the
User Guide, but you feel like sick. You don't understand a
bloody thing. Then, you've looked at some simple demo programs,
and you feel worse.
In this document, my aim is to develop the most basic skeleton
program from which further developments can be made.

Any suggestions or criticisms on this document welcome.

James Chow aka jc             2 June 1998
james@chowfam.demon.co.uk

6 July 1998 - Some corrections. By Mike Kavallierou. Thanks.
---------------------------------------------------------------


Overview
--------
The PlayStation holds 1Mb video memory which is arranged
as an 1024*512 16bit address space.

  (0,0) -----------------
        |               |
        |               |
        |               |
        |               |
        -----------------(1023,511)

This is also known as the frame buffer. We must assign an
area of the frame buffer as the display buffer, and this will
be used to display that area on the monitor. The actual
size of display is restrained to one of a number of resolutions
as indicated in the User Guide.

Double Buffering
----------------
One problem with drawing to the screen whilst it is being
displayed is the amount of flickering that is evident. This
occurs as the screen is cleared in between frames.
To overcome this we use two buffers to draw our display.
When one buffer is displayed on-screen, the other buffer
is being drawn to off-screen. When the drawing is complete,
we simply swap the buffers, so the one that was previously
drawn to is now on-screen, and we can draw to the other one.

The beam in a television which generates travels along
the top left of the screen horizontally, until it reaches
the far right of the screen. Then the beam is switched
off and is traced to the start of the next horizontal, and
the process is repeated until it reaches the bottom right
hand corner. When the beam reaches here, a vertical retrace
occurs, and returns to the top right. Since the vertical
retrace takes the most time, this is the point at which
the buffers are to be swapped.

Ordering Tables
---------------
As any 3D graphics programmer will tell you, the thorn in
displaying 3D graphics quickly, is to display those objects
further away behind those closer to the viewer.
If we were to use traditional sorting to resolve this
problem, we could use a relatively few number of objects
before the CPU is bogged down with sorting these objects.
However, the PlayStation uses ordering tables. The basic
principle behind these, is to use a number of ordering tables.
When the drawing command is registered for an object, a
value which is related to the z (depth) value of the object
is provided. The drawing command is then entered into the
apprioriate ordering table. When we are ready to process
the drawing commands in the ordering tables, they are
traversed in a back to front order, giving the correct scene.

So why are they needed even if I'm working in 2D, I hear you
asking. Well, one simple reason, is that given the resources
to provide sorting, it would be wasteful to develop a new
set of resources simply for working in 2D.
Another reason is that in working in 2D, it may necessary to
provide the illusion of depth working in a number of planes.
Those planes closer to the viewer move faster, than those
further away.

Of course, there are a few drawbacks. The number of ordering
tables avaiable to us (the programmers), is restricted to a
maximum of 14 bits, ie 2 to the power 14 = 16384, and the
minimum is to use 1 bit, ie 2 ordering tables. More tables
requires more time to sort the drawing commands, and so using
the maximum is only necessary if you have a lot of objects to
draw. On the other hand, using a small number of ordering tables
to draw objects with lots of variation in depth, may cause
objects to be displayed incorrectly, as an object further away
may be drawn before those closer, through overcrowding.

One final thing on ordering tables. The ordering table which
represents the plane closest to the viewer is 0. So objects
further away are inserted into ordering tables of _increasing_
value.

Basic Loop
----------
With the basic introduction to the background of the PlayStation
over, we will now look at the basic loop. This will almost
certainly be present in every game.

1. Initialise the various structures and systems.
2. Update our game.
3. Register the drawing commands the game to the active ordering
   table.
4. Swap the display buffers.
5. Perform the drawing of the ordering table.

Skeleton Source Code
--------------------
#include "libps.h"                                 //NOTE 0

#define OTLEN   (1)
#define SCNW    (320)
#define SCNH    (240)

void main(void) {
  GsOT     ot[2];
  GsOT_TAG ottags[2][1<", but Navigator seems to hide
        the text when I type that.
NOTE 1: If you are unfamiliar with bitwise C operations, you
        may find 1<<14 disorientating. This simply raises 2
        to the power of 14, by the magic of binary numbers.
        Binary   0001        Decimal  1
            1 << 3
        Binary   1000        Decimal  8 = 2^3
NOTE 2: In our "game", we will print from 1 to 500 using
        the debug font, before exiting.
NOTE 3: If we don't call SetVideoMode, the libraries default
        to MODE_NTSC. Best call this to avoid any confusion.
NOTE 4: This MUST be called before any of the Gs... functions
        work.
NOTE 5: We indicate the top left corners of the 2 buffers
        in the Video memory.
NOTE 6: Initialise our ordering tables. We have an array of 2,
        one for each buffer.
NOTE 7: Need to find out which buffer we should work on.
NOTE 8: Clear the current ordering table of previous drawing
        commands for the new ones.
NOTE 9: Must wait till the drawing commands are complete.
        Then wait for the vertical retrace, before swapping
        the buffers.
NOTE 10: GsSortClear inserts a drawing command to clear the
         background.
NOTE 11: Draw the commands onto the now off-screen buffer.