<!DOCTYPE Book PUBLIC "-//Davenport//DTD DocBook V2.4.1//EN">
<book>
<title>GBDK libraries documentation</title>
<bookinfo>
<bookbiblio>
<authorgroup>
<author><firstname>Michael</firstname><surname>Hope</surname></author>
</authorgroup>
<productname>Libraries for GBDK</productname>
<pubdate>July 3rd 1998</pubdate>
<copyright>
<year>1998</year>
<holder>Michael Hope</holder>
</copyright>
<abstract>
<para>
This document describes the functions included in the libraries for Pascal Felber's
GBDK that are Gameboy specific.  Currently included are sections on the malloc lib
and the multiple font support routines.
Unfortunately I'm still learning how to use SGML.  Any help would be appreciated :)
</para>
</abstract>
</bookbiblio>
</bookinfo>
<toc></toc>
<chapter id="malloc-lib">
<title>sys/malloc.h - malloc, free and related functions</title>
<sect1><title>Functions</title>
<sect2 id="malloc"><title>malloc</title>
<para>
<synopsis>void *malloc( <link linkend="size-t">size_t</link> numbytes )</synopsis>
Allocate numbytes of memory from the free memory pool and return 
a pointer to the base of the newly allocated region.
</para>
<sect3><title>Description</title>
<para>
Note that the memory is not cleared upon allocation.
</para></sect3>
<sect3><title>Parameters</title>
<para>
numbytes:  The number of bytes to allocate
</para></sect3>
<sect3><title>Returns</title>
<para>
On success, returns a pointer to the newly allocated region.
On failure returns <link linkend="null">NULL</link>.
</para></sect3>
</sect2>

<sect2 id="calloc"><title>calloc</title>
<para>
<synopsis>void *calloc( <link linkend="size-t">size_t</link> nmem, <link linkend="size-t">size_t</link> size )</synopsis>
Attempt to allocate space for nmem objects of size size and return a pointer to the allocated region.
</para>
<sect3><title>Description</title>
<para>
calloc is very similar to malloc but it also clears (fills with zero) the memory region
before returning.
</para></sect3>
<sect3><title>Parameters</title>
<para>
size: size of one object
</para>
<para>
nmem:  Number of objects to allocate space for
</para></sect3>
<sect3><title>Returns</title>
<para>
On success, returns a pointer to the newly allocated and cleared region.
On failure, returns <link linkend="null">NULL</link>.
</para></sect3>
</sect2>

<sect2 id="realloc"><title>realloc</title>
<para>
<synopsis>
void *realloc( void *current, <link linkend="size-t">size_t</link> size )</synopsis>
Attempt to re-size a currently allocated region.
</para>
<sect3><title>Description</title>
<para>
realloc is used to resize a currently allocated block without loosing the 
data contained within.  If the current block is larger than the requested 
block the the trailing data is lost.  Note that the end of the block is
not cleared if the current block is smaller than the requested one.
If current is NULL, then this is equivalent to <link linkend="malloc">malloc</link>.
If size is zero, then this is equivalent to <link linkend="free">free</link>.
</para></sect3>
<sect3><title>Parameters</title>
<para>
current: Pointer to the currently allocated block.
</para>
<para>
size: Size of the new block
</para></sect3>
<sect3><title>Returns</title>
<para>
On success returns a pointer to the newly allocated block.  Note that the new
block may be at a different location to the old.
On failure or if size is zero, then NULL is returned.
</para></sect3>
</sect2>
<sect2 id="free"><title>free</title>
<para>
<synopsis>int free( void *region )</synopsis>
Free a previously allocated region.
</para>
<sect3><title>Description</title>
<para>
Attempts to free a region previously allocated by <link linkend="malloc">malloc</link>, 
<link linkend="realloc">realloc</link> or <link linkend="calloc">calloc</link>.  Note that only valid regions can
be freed.  Note also that this prototype differs from the standard C free
as it returns an error code.
</para></sect3>
<sect3><title>Parameters</title>
<para>
region:  Pointer to a previously allocated region.
</para></sect3>
<sect3><title>Returns</title>
<para>
On success, returns zero (0).
If the region is already free, returns -1.
If the region was never allocated, returns -2.
</para></sect3>
</sect2></sect1>
<sect1><title>Data types</title>
<sect2 id="null"><title>NULL</title>
<para>
NULL is returned by <link linkend="malloc">malloc</link> and others upon failure.  Currently
defined to be equal to zero.
</para>
</sect2>
<sect2 id="size-t"><title>size_t:  UWORD</title>
<para>
size_t is used to specify the size of an object in bytes.  As the GB has an
8 bit processor with a 16 bit address space, size_t is currently defined as
a UWORD.  Note that due to the banked nature of most GB programs, it might
be changed to UDWORD at a later date.
</para></sect2>
</sect1>
<sect1><title>Implementation</title>
<para>
This malloc library is implemented using a simple signally linked list of hunks
where a hunk is a a header and section of memory that can be either free or used.
There is nothing particularly clever about the allocation algorithms.  I'm
an engineer as opposed to a computer scientist, so if the code gets the job
done then it's close enough.  Note that I do not know how well this system will
hold up against heavy fragmentation caused by allocating many small blocks
and keeping some of them.  However, I also cant think of a program that you'd
want to run on a GB that would do this.
</para>
<sect2><title>Functions</title>
<sect3 id="malloc-init"><title>malloc_init</title>
<para>
<synopsis>int malloc_init( void )</synopsis>
If the malloc system is currently uninitialised, initialise it.
</para>
<sect4><title>Description</title>
<para>
Checks to see if the header malloc_first is valid by checking its
magic number.  If it is not, initialise it by marking it as free, setting it
to occupy all of the free ram in the area C000h to D000h, setting the
<link linkend="mmalloc-hunk">region header</link> pointer to NULL and finally setting the
<link linkend="malloc-magic">magic number</link>.
</para></sect4>
<sect4><title>Parameters</title>
<para>
None
</para></sect4>
<sect4><title>Returns</title>
<para>
On success, returns zero (0).
If the malloc system is already setup, return -1.
</para></sect4>
</sect3>
<sect3 id="malloc-gc"><title>malloc_gc</title>
<para>
<synopsis>void malloc_gc( void )</synopsis>
Perform garbage collection on the malloc hunk list by joining consecutive free
blocks.
</para>
<sect4><title>Description</title>
<para>
malloc_gc is called by <link linkend="malloc">malloc</link> when an attempt to allocate a
region fails.  malloc_gc attempts to improve the situation by scanning through
the malloc hunk list and joining adjacent free blocks into one larger block.
In each scan, if two adjacent free blocks are found then they are combined and
the scan continued from the first block.  At the end of a scan, if any
combinations were made then the list is rescanned.  I'm not really sure why the
rescan is there as in theory all combinations should be made on the first pass.
</para></sect4>
<sect4><title>Parameters</title>
<para>
None
</para></sect4>
<sect4><title>Returns</title>
<para>
Nothing
</para></sect4>
</sect3>
</sect2>
<sect2><title>Data types</title>
<sect3 id="mmalloc-hunk"><title>mmalloc_hunk</title>
<para>
<synopsis>
struct smalloc_hunk {
	UBYTE magic;
	pmmalloc_hunk	next;
	UWORD size;
	int status;
};
</synopsis>
mmalloc_hunk is an internal structure used by the <link linkend="malloc">malloc</link> library
to keep track of allocated and free regions of memory.
</para>
<sect4><title>Members</title>
<para>
magic:  A magic number that identifies this as a valid mmalloc_hunk
next:  Pointer to the next hunk, <link linkend="null">NULL</link> if this is the last.
size:  Size in bytes of the hunk.
status:  Current status of the block that this hunk refers to.  One of
MALLOC_UNUSED (0), MALLOC_FREE (1) and MALLOC_USED (2).  I have no idea why
I defined both a MALLOC_UNUSED and a MALLOC_FREE :)
</para></sect4>
</sect3>
<sect3 id="malloc-magic"><title>MALLOC_MAGIC:  UBYTE</title>
<para>
The magic number associated with a valid malloc hunk header.  Currently set
at a really boring 123.  Suggestions for something better will be greatly
appreciated.
</para>
</sect3>
</sect2>
<sect2><title>Notes</title>
<para>
The <link linkend="mmalloc-hunk">header</link> for a hunk occurs just before the
region.  Any errant programs that write past their region could overwrite
this header and break the linked list.  But you get that.  Most routines
check the magic number while walking the list and abort if a broken
header is found.
</para>
<para>
The amount of memory free after static variables are allocated is determined
by using a new linker area called _HEAP, defined in crt0.s.  _HEAP occurs
after _BSS, so it should occur at the start of free memory.  The only data
initially in _HEAP is a reference to malloc_heap_start which is used
by <link linkend="malloc-init">malloc_init</link>.  Note that it is possibly on a real GB for the
magic number to occur in a bad place.  This should be fixed in crt0.s at
the initialisation time.  malloc also shares the ram with the stack.
Currently the problem of the stack growing down into allocated memory is
lessened by allocating from low memory first and by providing a 512 byte
buffer (set in <link linkend="malloc-init">malloc_init</link>).
</para>
<para>
On cartridges with internal memory an extra 8k from A000h to BFFFh is
available.  Unfortunately <link linkend="free">free</link> assumes that hunks are consecutive
which causes problems.  Two solutions are shifting _BSS to start at A000h
or defining an extra flag in <link linkend="mmalloc-hunk">the header</link> that is set if
the next hunk is consecutive to the current one.  The second option would 
also allow paged ram to be used, although it would have to be managed carefully.
</para>
</sect2>
</sect1>
</chapter>
<chapter id="font-lib">
<title>sys/font.h - Support for multiple fonts</title>
<sect1><title>Functions</title>
<sect2 id="init-font"><title>init_font</title>
<para>
<synopsis>
void init_font(void)
</synopsis>
Initialise the font system by clearing all font handles and releasing all tiles.
</para>
<sect3><title>Description</title>
<para>
Initialises the font system.  This routine should be called at the start of the program before any calls to <link linkend="load-font">load_font</link>.
</para></sect3>
<sect3><title>Parameters</title>
<para>
None.
</para></sect3>
<sect3><title>Returns</title>
<para>
Nothing.
</para></sect3>
</sect2>
<sect2 id="load-font"><title>load_font</title>
<para>
<synopsis>
<link linkend="font-handle">FONT_HANDLE</link> load_font( void *<link linkend="font-structure">font_structure</link> )
</synopsis>
Attempt to load the font font, returning a <link linkend="font-handle">FONT_HANDLE</link> on success or NULL on failure.
</para>
<sect3><title>Description</title>
<para>
load_font should be called once for each font that is required.  Note that currently there is no unload_font support.
</para></sect3>
<sect3><title>Parameters</title>
<para>
font: pointer to the base of a valid font structure
</para></sect3>
<sect3><title>Returns</title>
<para>
On success, returns a <link linkend="font-handle">FONT_HANDLE</link>.  On failure, returns NULL (0)
</para></sect3>
</sect2>
<sect2 id="set-font"><title>set_font</title>
<para>
<synopsis>
void set_font( <link linkend="font-handle">FONT_HANDLE</link> font_handle )
</synopsis>
Set the current font to the previously loaded font font_handle
</para>
<sect3><title>Description</title>
<para>
set_font changes current output font to the one specified by font_handle
</para></sect3>
<sect3><title>Parameters</title>
<para>
font_handle: handle from a previous <link linkend="load-font">load_font</link> call.
</para></sect3>
<sect3><title>Returns</title>
<para>
Nothing.
</para></sect3>
<sect3><title>Bugs</title>
<para>
No check is made to see if font_handle is a valid font handle.
</para></sect3>
</sect2>
<sect2 id="mprint-string"><title>mprint_string</title>
<para>
<synopsis>
void mprint_string( char *string )
</synopsis>
Print string string using the current font.
</para>
<sect3><title>Description</title>
<para>
This is a temporary routine used to test the font library.
</para></sect3>
<sect3><title>Parameters</title>
<para>
string: null terminated string to print.
</para></sect3>
<sect3><title>Returns</title>
<para>
Nothing.
</para></sect3>
</sect2>
</sect1>
<sect1><title>Data types</title>
<sect2 id="font-handle"><title>FONT_HANDLE:  UWORD</title>
<sect3><title>Description</title>
<para>
A FONT_HANDLE is a 16 bit value returned from <link linkend="load-font">load_font</link> and used by <link linkend="set-font">set_font</link>.  Physically it is a pointer to an entry in the font_table.
</para>
</sect3>
</sect2>
<sect2 id="font-structure"><title>font_structure</title>
<sect3><title>Description</title>
<para>
A font_structure is a container for the data related to a font, including the <link linkend="font-structure-encoding">encoding data</link> and <link linkend="font-structure-tile-data">tile</link> (bitmap) image data.
Due to the variable length nature of the encoding table and the tile data no default C structure exists.
</para></sect3>
<sect3><title>Format</title>
<para>
A font structure is made up of four fields - the font type, the number of tiles used, the encoding table and the tile data.
</para>
<sect4 id="font-structure-type"><title>type:  UBYTE</title>
<para>
The Font type is a single bit that describes the encoding table and the format of
the tile data.  The encoding table length is specified by the lower two bits
00:  256 byte encoding table
01:  128 byte encoding table
10 and 11 are reserved.
The third bit (0x04) is used to determine if the tile data is compressed.  Many tiles do not use shades of grey, and so can be represented in 8 bytes instead of 16.  If bit 2 is set, then the tiles are assumed to be 8 bytes long and are expanded to 16 bytes at the load stage.
</para></sect4>
<sect4 id="font-structure-num-tiles"><title>num_tiles:  UBYTE</title>
<para>
num_tiles gives the number of tiles present in the tile data and hence the number of tiles required by the font.
</para></sect4>
<sect4 id="font-structure-encoding"><title>encoding:  array of UBYTE</title>
<para>
The encoding table is an array that maps an ASCII character to the appropriate tile in the tile data.  For example, suppose that the letter 'A' was the tenth tile.  Then the 65th (the ASCII code for 'A') entry in the encoding table would be 10.
Any ASCII characters that don't have a corresponding tile should be mapped to a default tile.  Space is recommended tile.
</para></sect4>
<sect4 id="font-structure-tile-data"><title>tile_data:  array of UBYTE</title>
<para>
The final field is the actual tile data.  Note that tile numbering starts from zero.
</para></sect4>
</sect3>
</sect2>
</sect1>
</chapter>
</book>

