<html><head><title>GnarlPlot</title></head><body>
<h1>GnarlPlot</h1>
<br>
GnarlPlot is a set of custom sprite plotting and editing macros and routines, designed to work with just about any sprite and screen format required possible. This is because writing a good sprite plotter isn't a very nice task, and will often produce quite gnarly code which is hard to debug.<p><br><br>

<a name="screen_model"><h2>The GnarlPlot screen model</h2></a>
As flexible as GnarlPlot is designed to be, it must have some basic rules otherwise it would run too slowly. One of these sets of rules is how the screen (or other buffer you want to plot to) must be laid out. In C notation, the screen can be defined by the following set of variables:<p>
<pre>typedef struct {
	int width;	/* This is the number of pixels on each row of the screen */
	int height;	/* This is the number of pixels on each column of the screen */
	int ps;		/* This the pixel size; 1 &lt;&lt; ps = number of bytes per pixel */
	int gap;	/* This is the 'end-of-line' gap, measured in bytes (see below) */
	void *bank0;	/* Pointer to the first pixel (i.e. (0,0)) of the screen bank/buffer which is to be drawn to */
	void *bank1;	/* Pointer to the first pixel of the screen bank/buffer which is to be read from */
} gp_screen;
</pre>
The screen can be pictorally represented as:<p>
<img src="img1.gif" alt="Diagram of screen model"><p>
Currently, GnarlPlot is limited to screens with pixel sizes which are a power of 2 in length. This means that the address of any pixel on screen can be calculated by the formula:<p>
<pre>pixel_address = screen_base + ((width &lt;&lt; ps) + gap)*y + (x &lt;&lt; ps)
</pre>
Where <tt>screen_base</tt> is the base address of a screen bank, <tt>ps</tt> is the size of each pixel (such that 1 << ps is the size in bytes), <tt>x</tt> and <tt>y</tt> are the coordinates of the pixel, and <tt>width</tt> and <tt>gap</tt> are parameters of the screen.<p><br><br>

<h3>Common screen settings</h3>
The most common setting for a GnarlPlot screen definition is to reference some subset of the computers own screen. For example, to initialise <tt>gp_screen scr</tt> to an area <tt>w</tt> by <tt>h</tt> pixels offset <tt>xofs</tt> by <tt>yofs</tt> into the currently active VDU and display banks, use:<p>
<pre>scr.width = w;
scr.height = h;
scr.ps = vdu_var(9)-3;
scr.gap = (vdu_var(11)+1 - w) &lt;&lt; (vdu_var(9)-3);
scr.bank0 = vdu_var(94) + (yofs*vdu_var(6)) + (xofs &lt;&lt; (vdu_var(9)-3));
scr.bank1 = vdu_var(95) + (yofs*vdu_var(6)) + (xofs &lt;&lt; (vdu_var(9)-3));
</pre>
Where <tt>int vdu_var(int v)</tt> is a function to return the value of the VDU Variable/Mode Variable '<tt>v</tt>'<p><br><br>

<a name="sprite_model"><h2>The GnarlPlot sprite model</h2></a>
The GnarlPlot sprite model is designed to be as flexible as possible, in order to support the wide range of sprite formats possible. There are two structures used to describe sprites and their formats. In C notation, a sprite can be seen as:<p>
<pre>typedef struct {
	gp_sprfmt *f;	/* Sprite format descriptor (shared between multiple sprites) */
	void *d;	/* Sprite data block (local to this sprite object) */
} gp_spr;
</pre>
The format of <tt>d</tt> is defined fully by the format each sprite is stored in. The format itself (<tt>f</tt>) is defined as a struct of function pointers - each function is an operation that can be performed on a sprite. The types of operations available through <tt>f</tt> are:<p>
<ul><li>Sprite object creation and deletion<br>
There are three ways of creating a sprite - creating a blank sprite, creating a sprite from a section of a screen buffer, or copying data from another sprite.</li>
<li>Sprite attribute reading and writing<br>
These include functions to read the size, mask type, etc. of a sprite, as well as to change the attributes to new values (e.g. to resize a sprite).</li>
<li>Pixel reading and writing<br>
These are the most basic operations used to edit sprites. Pixels (and mask values) can be read and written in any colour format <a href="#colour_formats">(see below)</a></li>
<li>Sprite plotting<br>
There are various plotting operations supported by GnarlPlot<br>
<b>Finish me!</b></li>
<li>Sprite-to-screen conversion<br>
Sprite to screen conversion is where a <tt>gp_screen</tt> data structure is created, representing the contents of a sprite. This means that any operation which works on a screen can be used on the sprite. However, only <a href="#gloss_simple">simple</a> sprite formats support sprite-to-screen conversion, as more complex formats may store extra data between pixels (e.g. mask values), may store the pixels using different methods (e.g. <a href="#gloss_preshift">preshifting</a>), or may compress the data. It's important to note that any plotting operations performed on the produced screen will have an immediate affect on the sprite.</li></ul>

There are also other functions available, which are either format-specific extensions (e.g. loading and saving <tt>gp_spr_paint</tt> format sprites as RISC OS Sprite files), or functions which haven't made it into the spec yet (e.g. loading and saving any sprite in its format-specific format).<p><br><br>

<a name="colour_formats"><h2>Colour formats</h2></a>
GnarlPlot uses three main colour formats:<p>
<ul><li>8bpp format (Pixel size 0)<br>
In this format, a pixel is a single byte of the format '<tt>BGGRBRTT</tt>' (binary), where B are the Blue bits, G the Green, R the Red, and T the tint. This format corresponds to the default palette in all 256 colour modes under RISC OS. The leftmost bits are more significant in the colour groups, and the tint bits are the least significant overall; a 4 bit component can be constructed by the bit pattern '<tt>CCTT</tt>' where C is the chosen colour (R, G or B).<p>
Note that this format is different to the default given to 256 colour Sprites, which is <tt>TTBBGGRR</tt>.</li>
<li>16bpp format (Pixel size 1)<br>
In this format, a pixel is composed of two bytes. 5 bits are given to each component, arranged in the order '<tt>0BBBBBGGGGGRRRRR</tt>' (binary). The least significant byte (the one containing the red component) is stored in the lowest location in memory, as is common in little endian machines. You would probably argue that this format should be called 15bpp since there is one bit left unused, but I prefer to call it 16bpp since the three formats the form a multiple of 8 (8, 16, and 24). This format is the one used by the 32K colour modes available under RISC OS.<p>
Unless otherwise stated, GnarlPlot code will ignore (or pass through where necessary) the unused bit. RISC OS ignores this bit also.</li>
<li>24bpp format (Pixel size 2)<br>
In this format, a pixel is composed of four bytes. They are arranged as '<tt>00BBGGRR</tt>' (hex), where B is the Blue, G the Green, and R the Red component. Like 16bpp this is stored in little-endian format. Although the data will fit in 3 bytes, all the 24bpp RISC OS modes store it in 4 and simply ignore the topmost byte. Unless otherwise stated, GnarlPlot will ignore the topmost byte (or pass the data through).</li></ul><p><br><br>

<a name="mask_formats"><h2>Mask formats</h2></a>
At its simplist, a mask is a method of specifying how a pixel in a sprite should be combined with a pixel currently on screen. There are many different combinations possible, but in order for the GnarlPlot plotting functions to reach any acceptable speed, the number of formats available must be limited. Below are the formats supported by GnarlPlot:<p>
<ul><li>No mask<br>
This is the simplest format of them all, since no masking is involved; all pixels in the sprite will be drawn to screen.</li>
<li>On/off mask<br>
At its simplest, this format uses 1 extra bit per pixel to flag whether the pixel is visible or not. If the bit is set the pixel is drawn; if it is clear, then the pixel is skipped. For 16bpp and 24bpp formats this requires no extra storage space, but 8bpp formats will need to store the data elsewhere (usually by doubling the pixel size to two bytes and using the extra byte as the mask).</li>
<li>Greyscale alpha<br>
This system uses an extra byte to provide an intensity value for the pixel data currently on screen. The resulting pixel is calculated using the following formula:<br>
<tt>scr = (scr*alpha)/255 + spr</tt><br>
Where <tt>scr</tt> and <tt>spr</tt> are individual components of the <tt>scr</tt>een and <tt>spr</tt>ite pixel, and <tt>alpha</tt> is the alpha value. Thus, if the alpha byte is 0 then the pixel is transparent, and so all of the pixel 'below' will be visible, combined with the pixel of the sprite. If the alpha byte is 255 then the pixel is solid and only the sprite pixel will be visible. This allows for numerous effects, and is best suited to 24bpp formats since no extra memory is required. With 8bpp pixels an extra byte is required, while with 16bpp two extra bytes will be required (since GnarlPlot is only designed to use pixel sizes which are a power of two). This makes the 16bpp version redundant, since it takes the same amount of space as 24bpp.</li>
<li>RGB alpha<br>
This is essentially identical to greyscale alpha, except that there are three seperate alpha channels - each for a different colour component of the pixel. This system uses an extra pixel (i.e. in the same format as the colour data) to store the alpha information. Thus the pixel size will double; 8bpp will require two bytes, 16bpp 4 bytes, and 24bpp 8 bytes.</li></ul><p><br><br>

<h2>GnarlPlot code overview</h2>
The GnarlPlot code is split over several files:<p>
<ul><li>gp/screen.c - Screen handling C code</li>
<li>gp/spr.c - Sprite handling C code</li>
<li>gp/col.h - Colour handling/manipulation C header</li>
<li>gp/screen.h - Screen handling C header</li>
<li>gp/spr.h - Sprite handling C header</li>
<li>gp/col.s - Colour handling/manipulation assembler code</li>
<li>gp/gp.s - Common assembler macros and definitions</li>
<li>gp/plot.s - Sprite plotting specific assembler macros and definitions</li>
<li>blah blah blah, more to come</li>
</ul>

<h3>gp/gp.s</h3>
gp/gp.s contains assembler definitions for the following:<p>
<ul><li>Register bindings<br>
Bindings for R0 to R14 and PC, as used by the other GnarlPlot assembler files.</li>
<li>gp_screen_* constants<br>
Some constants describing the GnarlPlot screen strucure. See <a href="#screen_model">The GnarlPlot screen model</a> for more information.</li>
<li>MACRO GP_GEN_CALCPOS<br>
A macro to calculate the address offset into a sprite, given the sprite dimensions, pixel size, and the coordinate wanted</li>
<li>MACRO GP_ROUND<br>
A macro to round off a (fixed point) value to lie within a certain range: 0 &lt;= val &lt; lim. Uses an addition/subtraction system, so is not suitable for numbers a long way away from 'lim'.</li>
<li>MACRO GP_8_TO_24<br>
MACRO GP_8_TO_16<br>
MACRO GP_16_TO_24<br>
MACRO GP_16_TO_8<br>
MACRO GP_24_TO_16<br>
MACRO GP_24_TO_8<br>
A set of macros to convert individual pixels between the three main colour formats.</li></ul>

<h3>gp/plot.s</h3>
gp/plot.s contains assembler definitions for the following:<p><br><br>

<h4>Pre-plot calculation code</h4>
<ul><li>MACRO GP_SPR_CALCDRAW<br>
A macro to calculate the variables needed to draw a <a href="#gloss_simple">simple sprite</a> (of any <a href="#gloss_ps">pixel size</a>) onto a screen (of any <a href="#gloss_ps">pixel size</a>).</li>
<li>MACRO GP_SPR_CALCDRAW_PRESHIFTED_8BPP<br>
A macro to calculate the variables needed to draw a preshifted 8bpp sprite to an 8bpp screen.</li></ul>

<h4>Plotting code</h4>
<ul><li>MACRO GP_SPRDRAW_SIMPLE_8BPP<br>
A macro to draw a simple 8bpp sprite to an 8bpp screen, pixel by pixel</li>
<li>MACRO GP_SPRDRAW_SIMPLE_16BPP<br>
A macro to draw a simple 16bpp sprite to a 16bpp screen, pixel by pixel</li>
<li>MACRO GP_SPRDRAW_SIMPLE_WORDALIGNED<br>
A macro to draw a simple wordaligned sprite to a wordaligned screen, up to 4 words at once</li>
<li>MACRO GP_SPRDRAW_PRESHIFTED<br>
A macro to draw a preshifted sprite to screen, up to 4 words at once</li>
<li>MACRO GP_SPRDRAW_TRANSFORMEDROW_8BPP<br>
A macro to draw data from a simple transformed 8bpp sprite onto a row of an 8bpp screen</li>
<li>MACRO GP_SPRDRAW_BOUNDEDTRANSFORMEDROW_8BPP<br>
A macro to draw data from a simple transformed 8bpp sprite onto a row of an 8bpp screen, stopping drawing if the coordinates leave the sprite</li></ul>

<h2>Glossary</h2>

<a name="gloss_simple"><b>Simple sprite</b></a><br>
A sprite containing just pixel data (i.e. no mask/alpha information)<p><br><br>

<a name="gloss_preshift"><b>Preshifted sprite</b></a><br>
A set of n sprites (contigous in memory), where each sprite is shifted a different number of pixels horizontally. If n pixels can fit in one word of data, there are n sprites in the preshifted set. Sprite 0 is at offset 0, sprite 1 at offset 1, etc. Each sprite has an extra word of data on the right hand edge of each row to contain the 'overspilled' pixels.<p><br><br>

<a name="gloss_ps"><b>Pixel size</b></a><br>
A value denoting the number of bytes used to store a pixel. Most code accepts this as a number 'n' such that 1 &lt;&lt; n provides the number of bytes per pixel.<p><br><br>

</body></html>
