#LyX 1.1 created this file. For more info see http://www.lyx.org/
\lyxformat 2.15
\textclass book
\language default
\inputencoding default
\fontscheme default
\graphics default
\paperfontsize default
\spacing single 
\papersize Default
\paperpackage a4
\use_geometry 0
\use_amsmath 0
\paperorientation portrait
\secnumdepth 2
\tocdepth 2
\paragraph_separation indent
\defskip medskip
\quotes_language english
\quotes_times 2
\papercolumns 1
\papersides 1
\paperpagestyle default

\layout Title

Cryptic Allusion Libdream 0.95 / Programmer's Manual
\layout Author

(c)2000 Dan Potter
\layout Standard


\begin_inset LatexCommand \tableofcontents{}

\end_inset 


\layout Chapter*

Legal
\layout Standard


\begin_inset Quotes eld
\end_inset 

Sega
\begin_inset Quotes erd
\end_inset 

 and 
\begin_inset Quotes eld
\end_inset 

Dreamcast
\begin_inset Quotes erd
\end_inset 

 are registered trademarks of Sega Enterprises, Ltd.
 This package has no association with Sega or any of its affiliates, besides
 working on their hardware.
 All other trademarks are owned by their respective trademark holders.
\layout Standard

libdream (c)2000 Dan Potter, Jordan DeLong.
 Other portions (c) their individual authors; please contact the authors
 for information on using and/or distriburing their code.
\layout Standard

Permission is hereby granted, free of charge, to any person obtaining a
 copy of this software and associated documentation files (the 
\begin_inset Quotes eld
\end_inset 

Software
\begin_inset Quotes erd
\end_inset 

), to deal in the Software without restriction, including without limitation
 the rights to use, copy, modify, merge, publish, distribute, sublicense,
 and/or sell copies of the Software, and to permit persons to whom the Software
 is furnished to do so, subject to the following conditions:
\layout Standard

The above copyright notice and the following permission notice shall be
 included in all copies of the Software:
\layout Standard

THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
 IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE HELD LIABLE FOR ANY CLAIM, DAMAGES
 OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF
 OTHER DEALINGS IN THE SOFTWARE.
\layout Standard

Except as contained in this notice, the name of the copyright holders shall
 not be used in advertising or otherwise to promote the use or other dealings
 in this Software without prior written authorization from the copyright
 holders.
\layout Chapter

Getting Started
\layout Standard

Welcome to Libdream 0.95! This new and improved version has lots of extra
 goodies that people have been asking for for a good long time.
 For a better explanation of 
\shape italic 
what
\shape default 
 Libdream is, please take a look at the README file in the root of the package
 directory.
\layout Standard

The first thing you'll want to do is compile Libdream.
 Included in the package is a pre-compiled library with the default options,
 and you can use this to compile the examples.
 But compiling the library itself will help make sure that your compiler
 environment is setup properly and it allows you to make changes if you
 need them for your program.
 We've tried to make sure that everything you'll need for most programs
 is available at runtime, but we don't always think of everything.
 Thus: open source!
\layout Standard

If you do not have a proper SH-4 compilation environment, then you'll probably
 need to start by getting that setup.
 That's a bit out of scope for this libdream document, so you'll want to
 take a look at, e.g., HitMen's DC site for more info on getting it.
\layout Standard

To begin, edit the file Makefile.config in the libdream root.
 You'll find a set of default compiler paths that match my system.
 You should change these to match your system appropriately.
\layout Standard

Once Makefile.config is edited, if everything is well, you should be able
 to type 'make' and have everything built (including the examples).
 On BSD, you'll need to use gmake, or potentially 
\begin_inset Quotes eld
\end_inset 

MAKE=gmake gmake
\begin_inset Quotes erd
\end_inset 

 (in bash parlance).
 Cygwin users ought to be able to use 
\begin_inset Quotes eld
\end_inset 

make
\begin_inset Quotes erd
\end_inset 

 and have it compile ok.
\layout Standard

If you'd like to compile just the examples and skip the libdream step, then
 edit Makefile.config like before, but change into 
\begin_inset Quotes eld
\end_inset 

examples
\begin_inset Quotes erd
\end_inset 

 and then do the make/gmake step.
 This will build all of the examples, leaving only a bin and srec in each
 directory.
 These can be loaded using dc-tool/DDH or Marcus Comstedt's serial slave
 (respectively).
 Each example program has notes with it on operation which you should look
 at before running it.
 Most of them have serial output by default, so you'll need to add serial_disabl
e before dc_setup if you want to run them using a CDR.
\layout Standard

To compile your own libdream-based programs you'll need to add the appropriate
 include and lib paths to your CC and LD lines.
 These are the 
\begin_inset Quotes eld
\end_inset 

include
\begin_inset Quotes erd
\end_inset 

 and 
\begin_inset Quotes eld
\end_inset 

lib
\begin_inset Quotes erd
\end_inset 

 subdirectories of the libdream root.
\layout Standard

Well, now that that is (hopefully) out of the way, we'll proceed on to writing
 a libdream program.
\layout Chapter

A Basic Libdream Program
\layout Standard

A libdream program is pretty simple and straightforward -- you should have
 a 
\begin_inset Quotes eld
\end_inset 

main
\begin_inset Quotes erd
\end_inset 

, which is called 
\begin_inset Quotes eld
\end_inset 

main
\begin_inset Quotes erd
\end_inset 

 if you're using a default crt0, or 
\begin_inset Quotes eld
\end_inset 

dc_main
\begin_inset Quotes erd
\end_inset 

 if you use my (Dan's) crt0.
 Inside this main routine you'll do one of two things: initialize only a
 few subsystems of libdream and use those, or do a full initialization with
 dc_setup and go from there.
\layout Standard

The major advantage of initializing only a small portion of the subsystems
 is if you have a very simple program that will only use a few of them.
 For example, you might want to make a program that displays a menu over
 the serial port to the user, and lets them manage VMU files.
 In this case you'd only need maple support and serial support, so you could
 save about 8k of binary code in the finished program.
 This isn't really a significant advantage though, since including all of
 libdream generally costs about 20k and manually initializaing is error
 prone, but caveat emptor; do it however you like.
\layout Standard

For the rest of the documentation, I'm going to assume that you are doing
 the full initialization.
 This full initialization can take two forms as well: a normal and a quiet
 form.
 Normal form is good for debugging because it gives you some information
 on startup saying that it's alive, and about what is attached to your maple
 bus.
 Quiet form is useful if you want to do something that implements a serial
 protocol and so you don't want to disable serial entirely, but you don't
 want garbage at the front either.
\layout Standard

The basic normal call looks something like this:
\layout LyX-Code

dc_setup(DM_640x480, PM_RGB565);
\layout Standard

This call will setup the video with a 640x480 mode, color depth 16 with
 a pixel format of R/G/B 5/6/5.
 Other choices are DM_320x240 and DM_800x608 for the first parameter, and
 PM_RGB555 and PM_RGB888 for the second.
 You should always check dream.h for the most up-to-date information.
\layout Standard

Once dc_setup is called, all hardware should be initialized and ready to
 go with the major exception of the Tile Accelerator.
 The TA is special in that it pretty much requires clobbering a lot of assumptio
ns that the normal video setup makes, and it takes a bit longer.
 The code is also fairly large compared to the other subsystems.
 For these reasons, ta_init is not called by default but you must call it
 before you use any portion of the TA library (texture loading, polygons,
 etc).
\layout Standard

Congratulations! ;-) You've now written your first libdream program.
 For more info on the different subsystems, please see the chapter devoted
 to that system.
 For examples, see the 
\begin_inset Quotes eld
\end_inset 

examples
\begin_inset Quotes erd
\end_inset 

 directory off the libdream root.
\layout Chapter

The Subsystems
\layout Standard

Now that you know what a basic libdream program looks like, you'll probably
 want to start figuring out how to use the various parts of the library.
 The following chapter is more in the way of a reference manual than a tutorial,
 which is kind of what I intended to begin with.
 ^_^;
\layout Section

Data Types
\layout Standard

Before we get started on the individual systems, I figured a small word
 about data types is in order.
 Almost everything in libdream uses the following conventions for data types.
 dream.h defines types int8, int16, int32, and int64 to match signed integers
 of the appropriate number of bits.
 uint8, uint16, uint32, and uint64 are the same, but unsigned.
 Booleans or counts are often stored as 
\begin_inset Quotes eld
\end_inset 

int
\begin_inset Quotes erd
\end_inset 

, but counts are usually 
\begin_inset Quotes eld
\end_inset 

uint32
\begin_inset Quotes erd
\end_inset 

.
 Functions that can return errors generally return them as a negative int,
 and success as a zero int.
 Strings are stored as 
\begin_inset Quotes eld
\end_inset 

char *
\begin_inset Quotes erd
\end_inset 

.
 Indivudual characters are generally 
\begin_inset Quotes eld
\end_inset 

int
\begin_inset Quotes erd
\end_inset 

.
\layout Section

Serial (serial.c)
\layout Standard

The serial system accesses the 
\begin_inset Quotes eld
\end_inset 

SCIF
\begin_inset Quotes erd
\end_inset 

 (serial communications interface w/FIFO) of the SH-4 CPU.
 This port of the CPU is attached to the external 
\begin_inset Quotes eld
\end_inset 

Serial I/O
\begin_inset Quotes erd
\end_inset 

 port of the Dreamcast.
\layout Standard

The various functions of the serial module are pretty straightforward.
 Here is a short explanation of each:
\layout Subsection

void serial_disable()
\layout Standard

Disables serial access through the serial module; all serial output will
 be discarded and serial input will always return 
\begin_inset Quotes eld
\end_inset 

no character available
\begin_inset Quotes erd
\end_inset 

.
 This is generally used before burning the program to a CDR so that it won't
 hang on a non-development machine waiting for serial output to complete.
\layout Subsection

void serial_init(int baud)
\layout Standard

Initialize the SCIF interface with the given baud rate.
 Interrupts will be turned off and flow control through the FIFOs will be
 enabled.
\layout Subsection

void serial_write(int c)
\layout Standard

Write a single character to the SCIF output.
 Note that the character may or may not be transmitted depending on the
 state of the transmit FIFO.
 If you wish instant output, you will need to call serial_flush().
\layout Subsection

void serial_flush()
\layout Standard

Flushes all data remaining in the transmit FIFO.
 Use this to ensure that all queued serial output is actually sent.
\layout Subsection

void serial_write_buffer(uint8 *data, int len)
\layout Standard

Writes an entire buffer of (potentially) binary data to the SCIF output.
 This function automatically executes a serial_flush().
\layout Subsection

void serial_write_str(char *str)
\layout Standard

Writes a null-terminated string of data to the SCIF.
 Uses serial_write_buffer(), so all output is flushed immidiately.
\layout Subsection

int serial_read()
\layout Standard

Reads one character from the SCIF input FIFO if one is waiting, otherwise
 returns -1.
\layout Subsection

int serial_printf(char *fmt, ...)
\layout Standard

Uses vsprintf() from libc to process format args, then sends the data to
 the SCIF using serial_write_str().
 In dream.h, printf() is an alias for this function.
\layout Section

Basic Video (video.c)
\layout Standard

The basic video subsystem of libdream is designed to facilitate frame buffer
 setup and access.
 It does not handle 3D acceleration, that is handled in the 
\begin_inset Quotes eld
\end_inset 

TA
\begin_inset Quotes erd
\end_inset 

 module.
 The basic usage of the video system is to call vid_init with the desired
 parameters, and then use one of the 
\begin_inset Quotes eld
\end_inset 

vram
\begin_inset Quotes erd
\end_inset 

 pointers to access video memory.
\layout Standard

The following variables and functions are available in basic video:
\layout Subsection

uint32 *vram_l
\layout Standard

Pointer to video memory (0xa5000000) as a 32-bit unsigned integer array.
 Use this to access video memory when in RGB888 mode, or when copying large
 regions (not recommended =).
\layout Subsection

uint32 *vram_s
\layout Standard

Similar to vram_l, but accesses as a 16-bit unsigned integer array.
 Use this to access video memory when in RGB555 or RGB565 mode.
\layout Subsection

int vram_config
\layout Standard

Stores the first parameter to vid_init, which is the pixel format.
\layout Subsection

int vram_size
\layout Standard

Stores the total size (in pixels) of one page of video frame buffer.
\layout Subsection

int vid_cable_type
\layout Standard

Stores the cable_type parameter to the video init function below.
\layout Subsection

int vid_check_cable()
\layout Standard

Checks and returns the attached video cable type; the three constants matching
 the return values are CT_VGA, CT_RGB, and CT_COMPOSITE.
\layout Subsection

int vid_init(int cable_type, int disp_mode, int pixel_mode)
\layout Standard

Does full frame buffer initialization with the requested cable type, display
 mode, and pixel mode.
 You should pass the return value from vid_check_cable() as the first parameter.
 dc_setup() does this for you.
 disp_mode constants are DM_320x240, DM_640x480 and DM_800x608.
 pixel_mode constants are PM_RGB555, PM_RGB565, and PM_RGB888.
\layout Subsection

void vid_set_start(uint32 start)
\layout Standard

Set the 
\begin_inset Quotes eld
\end_inset 

start address
\begin_inset Quotes erd
\end_inset 

 register, which governs where in the frame buffer the output picture comes
 from.
 This can be used for 
\begin_inset Quotes eld
\end_inset 

double buffering
\begin_inset Quotes erd
\end_inset 

, but it will most commonly be used during 3D acceleration.
\layout Subsection

void vid_border_color(int r, int g, int b)
\layout Standard

Set the border color.
 The border is the area outside the standard viewing area.
 On NTSC this is mostly above and below the picture.
 I'm not sure what it is on PAL.
 Generally unless you're doing some odd debugging you'll want to set this
 to black (vid_init does this for you).
\layout Subsection

void vid_clear(int r, int g, int b)
\layout Standard

Clears the first page of frame buffer based on the current video mode, with
 the given color.
 This is most useful when using frame buffer access, not 3D access.
\layout Subsection

void vid_empty()
\layout Standard

Clear the entirety of video memory using zeros.
 This is done using longwords so it's fairly quick.
 Once again, mainly used with 3D setup.
\layout Subsection

void vid_waitvbl()
\layout Standard

Wait for a vertical blank period.
 Vertical blank is the period between the time that the scan beam reaches
 the bottom of the screen and the time that it reaches the top and starts
 drawing again.
 This is relevant because this is the best time to draw to the frame buffer
 without causing 
\begin_inset Quotes eld
\end_inset 

tearing
\begin_inset Quotes erd
\end_inset 

 or other artifacts.
 It's also generally when you want to switch start addresses.
\layout Section

BIOS Fonts (biosfont.c)
\layout Standard

BIOS fonts are the ones you see in the boot manager on the Dreamcast.
 These are stored in ROM and so are available to any program.
 You will probably recognize them immidiately since they are used all over
 the place in official productions.
 The BIOS font contains European Latin-1 characters (which we support) and
 Kanji (which we don't support yet but will eventually).
 The Latin-1 characters are bit masks of size 12x24, so each character uses
 36 bytes.
 I suspect that the Kanji characters are 24x24, but I haven't tested this
 yet.
 These functions are frame-buffer agnostic except that they expect a 16-bit
 pixel size.
\layout Standard

The following functions are available:
\layout Subsection

void* bfont_find_char(int ch)
\layout Standard

Returns the address in ROM of the given character, after being mapped to
 the BIOS font.
 
\layout Subsection

void bfont_draw(uint16 *buffer, int bufwidth, int c)
\layout Standard

Draws Latin-1 character 'c' at the given location in 'buffer', and assumes
 that 'buffer' is 'bufwidth' pixels wide.
 For example, to draw an 'a' at 20,20 in a 640x480 framebuffer, you'd use
 bfont_draw(vram_s+20*640+20, 640, 'a').
\layout Subsection

void bfont_draw_str(uint16 *buffer, int bufwidth, char *str)
\layout Standard

Exactly like bfont_draw, but it takes a string and draws each character
 in turn.
\layout Section

PC Fonts (font.c)
\layout Standard

The PC font system handles bitmapped fonts that are 8 pixels wide, and any
 number of pixels tall.
 The module is being deprecated in favor of the BIOS font module, so I won't
 describe it here.
 If you want more information, please reference font.c itself.
\layout Section

Sound Processor Unit (spu.c)
\layout Standard

The sound processor unit (as mentioned in the README) is a Yamaha(tm) AICA
 sound system.
 To use the processor you will need to write a seperate program that runs
 on the ARM7 RISC core and uses the AICA's own registers.
 This isn't covered in this document (or anywhere, to my knowledge).
 For some decent examples, though, take a look at 
\begin_inset Quotes eld
\end_inset 

s3mplay
\begin_inset Quotes erd
\end_inset 

 on the Cryptic Allusion DCDev site (see README).
\layout Standard

The following defines and functions are available to assist in using the
 sound processor:
\layout Subsection

SMP_BASE
\layout Standard

All samples loaded to the AICA should proceed from this location relative
 to sound RAM (which maps to 0xa0810000 in the SH-4).
 This is mainly used in the S3M player but it's a good guideline to follow
 in general since it gives you 64k of space for the sound program (which
 is generally plenty).
\layout Subsection

void snd_ram_write_wait()
\layout Standard

The AICA's RAM is attached to the chip itself rather than the SH-4, and
 so access proceeds through an ASIC.
 You must call this function every 8 long-words of written sound memory
 so that the ASIC's FIFO can catch up.
 If you don't, the data won't be written accurately.
\layout Subsection

void snd_load_arm(void *src, int size)
\layout Standard

Loads an ARM7 program and starts it executing.
 The program will be loaded at offset 0, so it needs to begin with reset/excepti
on vectors.
\layout Subsection

void snd_stop_arm()
\layout Standard

Stops execution in the ARM7, and disables all AICA synthesizer channels.
 This insures that whatever was going on in the SPU is stopped completely.
\layout Subsection

void snd_init()
\layout Standard

Initialize the SPU: disable the ARM7 and clear sound memory.
\layout Subsection

void snd_load(void *src, int dest, int len)
\layout Standard

Load miscellaneous data into the SPU's RAM.
 'src' is where to load from, and 'dest' is relative to the SPU based (so
 you could pass, e.g., SMP_BASE here).
 'len' is in bytes but will be rounded up to long-words.
\layout Section

CD-Rom Access (cdfs.c)
\layout Standard

Libdream provides the capability to use CD and CDR discs in the GD-Rom drive
 using this module.
\layout Standard

Note that this file has been specifically crippled (or rather, we just never
 wrote it in) so that it can't access Sega's GD discs.
 This means that you can't access the data on any commercial game.
 There are really only a few legitimate reasons for doing this so we've
 disabled the feature to avoid coming under fire for assisting with copyright
 infringement.
 If you really want to know how, I'm sure you can figure it out =).
\layout Standard

The following functions are available:
\layout Subsection

uint32 iso_open(const char *path, int oflag)
\layout Standard

Open a file on the CD, using absolute path 
\begin_inset Quotes eld
\end_inset 

path
\begin_inset Quotes erd
\end_inset 

, with open flags 
\begin_inset Quotes eld
\end_inset 

oflag
\begin_inset Quotes erd
\end_inset 

.
 Note that in the current system, 
\begin_inset Quotes eld
\end_inset 

path
\begin_inset Quotes erd
\end_inset 

 must use forward slashes for path seperators (but can mix upper and lower
 case freely with no troubles), and 
\begin_inset Quotes eld
\end_inset 

oflag
\begin_inset Quotes erd
\end_inset 

 must be O_RDONLY or (O_RDONLY | O_DIR).
 A file descriptor will be returned, or a zero on error.
\layout Subsection

void iso_close(uint32 fd)
\layout Standard

Close the file referenced by the given file descriptor.
\layout Subsection

int iso_read(uint32 fd, void *buf, int count)
\layout Standard

Read 
\begin_inset Quotes eld
\end_inset 

nbyte
\begin_inset Quotes erd
\end_inset 

 bytes from the file referenced by 
\begin_inset Quotes eld
\end_inset 

fd
\begin_inset Quotes erd
\end_inset 

, into buffer 
\begin_inset Quotes eld
\end_inset 

buf
\begin_inset Quotes erd
\end_inset 

.
 Note that this function will always read the surrounding 2048 byte sector
 before extracting the parts you want, so you should never read less than
 2048 bytes unless that's all you want.
 Reading more than 2048 does work.
 The number of bytes read will be returned.
\layout Subsection

long iso_lseek(uint32 fd, long offset, int whence)
\layout Standard

Seek in file 
\begin_inset Quotes eld
\end_inset 

fd
\begin_inset Quotes erd
\end_inset 

 by 
\begin_inset Quotes eld
\end_inset 

offset
\begin_inset Quotes erd
\end_inset 

 bytes, relative to 
\begin_inset Quotes eld
\end_inset 

whence
\begin_inset Quotes erd
\end_inset 

.
 
\begin_inset Quotes eld
\end_inset 

whence
\begin_inset Quotes erd
\end_inset 

 is one of the standard STDIO constants: SEEK_SET, SEEK_CUR, SEEK_END.
 
\begin_inset Quotes eld
\end_inset 

offset
\begin_inset Quotes erd
\end_inset 

 may be positive or negative depending on the usage.
 The new file location will be returned.
\layout Subsection

long iso_tell(uint32 fd)
\layout Standard

Returns the current file pointer within 
\begin_inset Quotes eld
\end_inset 

fd
\begin_inset Quotes erd
\end_inset 

.
\layout Subsection

dirent_t *iso_readdir(uint32 dirfd)
\layout Standard

Read the next entry (if any) from the opened directory.
 Returns a pointer to a dirent_t on success (see fs_iso9660.h for more info
 on dirent_t) or NULL if nothing is left.
\layout Subsection

int cdrom_init() int iso_init()
\layout Standard

Initialize the GD-Rom drive for reading CD/CDR media, and initialize the
 file system driver.
\layout Section

Timer Counters (timer.c)
\layout Standard

This module supports the SH-4's internal timer perhipherals.
 Support is provided for TMU0 through TMU2.
 WDT (watchdog) is defined but not supported yet.
 TMU0 through TMU2 may all be used independently and count at different
 rates.
\layout Standard

The following defines and functions are available:
\layout Subsection

TMU0, TMU1, TMU2, WDT
\layout Standard

These are constants used to identify which timer you wish to operate on.
\layout Subsection

int timer_prime(int which, uint32 speed)
\layout Standard

Primes a timer, but does not start it.
 
\begin_inset Quotes eld
\end_inset 

which
\begin_inset Quotes erd
\end_inset 

 is one of the timer constants, and 
\begin_inset Quotes eld
\end_inset 

speed
\begin_inset Quotes erd
\end_inset 

 is a times per second rate which the counter will bottom out.
 So if you set speed to 
\begin_inset Quotes eld
\end_inset 

1
\begin_inset Quotes erd
\end_inset 

, then the timer will hit bottom after one second, and start counting again.
 Returns 0 for success.
\layout Subsection

int timer_start(int which)
\layout Standard

Starts the requested timer counting (after priming it).
\layout Subsection

int timer_stop(int which)
\layout Standard

Stops the requested timer.
\layout Subsection

uint32 timer_count(int which)
\layout Standard

Returns the current timer count.
 The only way you can really make use of this externally is to get the timer
 count after priming but before starting, and scale the real-time results.
\layout Subsection

int timer_clear(int which)
\layout Standard

Clears the timer underflow bit and returns what its value was.
 Underflow is set when the timer counts down.
 So for example, you could start a timer on a 1HZ cycle and poll this function
 until it returns true.
 At that point you'd have waited for a second, and the timer is already
 counting down again.
\layout Subsection

void timer_sleep(int ms)
\layout Standard

Uses TMU0 to sleep for the given number of milliseconds.
\layout Subsection

int timer_init()
\layout Standard

Setup timers (enable and stop all).
\layout Section

Maple Access (maple.c)
\layout Standard

Libdream 0.7 includes Jordan DeLong's rewritten maple access code.
 This is a lot more modular and it is setup for future expansion with queueing
 multiple frames and DMA completion interrupts.
 For now it basically does the same as Marcus' old maple routines but with
 cleaner code.
\layout Standard

In general using the maple bus consists of finding your peripheral (using
 DEVINFO queries), and storing this address; when you want to use the peripheral
, you send it a condition query message and get a frame back describing
 the state of the peripheral.
 Most of the exported functions in maple.c won't be useful to mere mortals
 =) but that's a good thing since there are specific support modules for
 each of the major peripherals we have had access to.
\layout Standard

The following functions are available:
\layout Subsection

void maple_init(int quiet)
\layout Standard

Initialize the maple bus; if 
\begin_inset Quotes eld
\end_inset 

quiet
\begin_inset Quotes erd
\end_inset 

 is non-zero, then the bus scan will not produce any output.
\layout Subsection

void maple_shutdown()
\layout Standard

Shut down all maple bus operations.
\layout Subsection

uint8 maple_create_addr(uint8 port, uint8 unit)
\layout Standard

Create a maple address for the given port and unit.
\layout Subsection

int maple_docmd_block(...)
\layout Standard

Parameters omitted for topic brevity: int8 cmd, uint8 addr, uint8 datalen,
 void *data, maple_frame_t retframe.
 This is the main 
\begin_inset Quotes eld
\end_inset 

work horse
\begin_inset Quotes erd
\end_inset 

 of the maple system.
 
\begin_inset Quotes eld
\end_inset 

cmd
\begin_inset Quotes erd
\end_inset 

 should be one of the maple command constants in maple.h; 
\begin_inset Quotes eld
\end_inset 

addr
\begin_inset Quotes erd
\end_inset 

 should be created with maple_create_addr (or one of the maple_*_addr functions
 below); 
\begin_inset Quotes eld
\end_inset 

datalen
\begin_inset Quotes erd
\end_inset 

 is the length of the extra data (beyond what's in the frame header), 
\begin_inset Quotes eld
\end_inset 

data
\begin_inset Quotes erd
\end_inset 

 is a pointer to extra data (if any) that goes after the frame header; and
 
\begin_inset Quotes eld
\end_inset 

retframe
\begin_inset Quotes erd
\end_inset 

 is a maple_frame_t that you should pass in to be filled in with return
 data.
 Zero is returned on success, and -1 returned on error.
 For some examples of using docmd_block directly, please check one of the
 maple peripheral modules.
\layout Subsection

int maple_rescan_bus(int quiet)
\layout Standard

Rescans the maple bus.
 This will be neccessary if the user swaps out any controllers or memory
 cards.
 It also determines what is where and stores that info for later usage.
 If 
\begin_inset Quotes eld
\end_inset 

quiet
\begin_inset Quotes erd
\end_inset 

 is non-zero, it produces no output.
\layout Subsection

uint8 maple_device_addr(int code)
\layout Standard

Pass a maple function code, and it returns the address of the first one
 that matches it.
 
\layout Subsection

uint8 maple_*_addr()
\layout Standard

These include controller, mouse, kb, lcd, and vmu currently.
 Each one searches the maple bus to find the first matching type of peripheral
 and returns an address.
\layout Section

Maple Peripheral Support Modules
\layout Standard

Support modules are included for standard controllers, keyboards, VMUs,
 and mice.
 Most peripherals fit into these molds.
 Eventually we'll probably add support for more things like the purupuru
 pack (force feedback) but we don't have one yet, so we can't.
 =) Notable among this list is the mouse since it just came out.
 Wow your friends by writing software that uses it before Sega gets a chance!
 =)
\layout Standard

Since these are mostly the same (except for names and structure values)
 I won't go over them in detail.
 Each module generally contains a poll function that checks the state of
 the peripheral and fills in a device-specific structure.
 See the header files for the specific structure information.
 I'll list out the poll functions here for convienence though.
\layout Subsection

int cont_get_cond(uint8 addr, cont_cond_t *cond)
\layout Standard

Check controller status.
 Returns which buttons are pressed and the state of the various analog controls.
\layout Subsection

int kbd_get_cond(uint8 addr, kbd_cond_t *cond)
\layout Standard

Check keyboard status.
 Returns up to six keys being pressed at once.
 There are other support functions for the keyboard that you should look
 up in keyboard.h if you want to use it seriously.
 These do queueing and buffering for you.
 If you want this functionality, you should use kbd_poll(uint8 addr) and
 then kbd_get_key() to get key presses.
\layout Subsection

int vmu_draw_lcd(uint8 addr, void *bitmap)
\layout Standard

Draws the given bitmap to the LCD screen.
 Generally these are on VMUs (which is why it's part of vmu.c) but it's not
 required.
 The bitmap should be a 48x32 bit array.
 The picture will show up right side up on the VMU itself, so when it's
 inserted in a controller you'll need to flip it in each direction.
\layout Subsection

int vmu_block_read(uint8 addr, uint16 blocknum, uint8 *buffer)
\layout Standard

Read the requested block of the VMU's flash ram and put it in 
\begin_inset Quotes eld
\end_inset 

buffer
\begin_inset Quotes erd
\end_inset 

.
\layout Subsection

int vmu_block_write(uint8 addr, uint16 blocknum, uint8 *buffer)
\layout Standard

Take what's in 
\begin_inset Quotes eld
\end_inset 

buffer
\begin_inset Quotes erd
\end_inset 

 and write it to the requested block of the VMU's flash ram.
\layout Subsection

int mouse_get_cond(uint8 addr, mouse_cond_t *cond)
\layout Standard

Gets the condition of the mouse peripheral specified.
 Returns button states and delta x, y, and z (roller).
\layout Section

Tile Accelerator (ta.c)
\layout Standard

The Tile Accelerator (3D acceleration) really deserves its own book, but
 for completeness (and my hands are getting tired =) I'm just going to go
 over the basics of setting it up and the functions you use to do so.
 For more specific information, look around on the web for various documents
 describing the TA, and look in the examples.
 Hopefully this section can be more fleshed out in future versions.
\layout Standard

The TA is exactly what it says: the screen in the PVR 3D chip is broken
 up into 32x32 pixel tiles.
 So in 640x480, you'd really have a 20x15 tile field, not a 640x480 pixel
 field.
 The PVR's 3D magic happens by taking each of these tiles along with a 
\begin_inset Quotes eld
\end_inset 

display list
\begin_inset Quotes erd
\end_inset 

 describing what is to be displayed on the screen, and doing internal z-bufferin
g.
 This means that each polygon is drawn only once, so even though there is
 not a standard z-buffer present, the end result looks like there is one.
 Opaque polygons, opaque volume modifiers (fog, etc), translucent polygons,
 translucent modifiers, and punch-through polygons (which can 
\begin_inset Quotes eld
\end_inset 

cut
\begin_inset Quotes erd
\end_inset 

 pieces of other polygons out, I think) must be sent to the TA, in that
 order.
 Each list is rendered in that order as well, for each tile, and so the
 more lists you send, the slower the rendering process gets.
 Opaque polygons are the fastest obviously, followed by punch-throughs,
 translucent polygons, and then the volume modifiers.
 
\layout Standard

Because of the tile system, there is no user clipping neccessary: the TA
 works backwards by intersecting polygons and volumes with each tile before
 rendering.
 The end result of all of this is that all you have to do as a user is cull
 out the completely useless polygons (if you feel like it), arrange things
 in polygon 
\begin_inset Quotes eld
\end_inset 

strips
\begin_inset Quotes erd
\end_inset 

 as much as possible, and then throw the various lists to the TA.
 Then sit back and wait for it to do its work.
\layout Standard

The PVR chip is not magic: it is powerful and can accelerate the drawing
 process to an amazing degree, but it still draws in terms of screen coordinates.
 So it is really a fancy 2D accelerator with perspective correction support
 for textures, and z-buffering.
\layout Standard

Coordinates in the PVR start at 0,0 (all coordinates are floating point
 numbers) and go to 640,480, in the normal mode.
 Any coordinates outside this will work but will be clipped.
 Z coordinates start at 0 and move out of the screen towards the viewer.
 As far as I can tell, in normal mode, it wants Z and not 1/Z (W).
 I may be wrong of course.
 I'm no 3D hardware expert.
\layout Standard

All that being said, the basic operation goes something like this:
\layout Enumerate

Setup the TA (ta_init); initialize the background plane structure
\layout Enumerate

Load any textures you may want to use
\layout Enumerate

For each frame:
\layout Itemize

Call ta_begin_render to initialize the rendering process.
\layout Itemize

Construct and send one or more polygon headers for opaque polygons, each
 followed by zero or more verteces; each vertex strip must end with an 
\begin_inset Quotes eld
\end_inset 

end of list
\begin_inset Quotes erd
\end_inset 

 marker.
\layout Itemize

Call ta_commit_eol to finish the opaque list.
\layout Itemize

Construct and send one or more polygon headers for translucent polygons
 (same process as above).
\layout Itemize

Call ta_commit_eol to finish the translucent list.
\layout Itemize

Call ta_finish_frame to finish the rendering process and wait for a vertical
 blank to flip pages.
\layout Standard

Here are the structures and functions needed to do these things:
\layout Subsection

struct pv_str ta_page_values[2]
\layout Standard

Holds all the internal rendering data for the page flipper and renderer.
 This is useful mainly if you want to do something like take a screen shot
 (you can find the current frame buffer).
\layout Subsection

bkg_poly ta_bkg
\layout Standard

The background plane polygon.
 The background plane is currently automatically a 640x480, three-point
 opaque polygon.
 I'm not even sure if you can change this.
 For the values to load into this, take a look at one of the 3D example
 programs.
 If you want to do color shifting you can change this on the fly.
\layout Subsection

poly_hdr_t
\layout Standard

A polygon header; this is always four flag long-words and four dummy words.
 The four dummy words are actually used with different types of shading
 and volume modifiers, but these are not supported yet in libdream.
 You should fill this structure directly (if you know what you're doing)
 or use ta_build_poly_hdr.
\layout Subsection

vertex_oc_t
\layout Standard

Represents a single opaque/colored vertex with floating point coordinates
 and ARGB values.
 Actually it works fine for translucent polygons also but the naming convention
 stuck.
\layout Subsection

vertex_ot_t
\layout Standard

Represents a single opaque/textured vertex with floating point coordinates
 and ARGB values.
 Actually it works fine for translucent polygons also.
\layout Subsection

int ta_curpage
\layout Standard

The current working page (out of ta_page_values above).
\layout Subsection

void ta_init()
\layout Standard

Initializes the TA and prepares for page flipped 3D.
\layout Subsection

void ta_send_queue(void *sql, int size)
\layout Standard

Sends one (or two) store queue(s) full of data to the TA.
\layout Subsection

void ta_begin_render()
\layout Standard

Call before you start drawing a frame.
\layout Subsection

void ta_commit_poly_hdr(poly_hdr_t *polyhdr)
\layout Standard

Sends one polygon header to the TA.
 This needs to be done when you want to change drawing modes; e.g., opaque
 color, opaque textured, translucent color, translucent textured.
\layout Subsection

void ta_commit_vertex(void *vertex, int size)
\layout Standard

Sends one vertex to the TA; this can be a vertex_oc_t or vertex_ot_t.
 Pass along the result of sizeof() on the vertex.
\layout Subsection

void ta_commit_eol()
\layout Standard

Sends the 
\begin_inset Quotes eld
\end_inset 

end of list
\begin_inset Quotes erd
\end_inset 

 marker to the TA.
 This ought to be used after all opaque polygons are sent, and again after
 all translucent polygons are sent.
\layout Subsection

void ta_finish_frame()
\layout Standard

Call after you've finished sending all data.
 This completes the rendering process in the alternate screen buffer and
 then waits for a vertical blank to switch to the new page.
\layout Subsection

void ta_build_poly_hdr(poly_hdr_t *target, ...)
\layout Standard

Parameters omitted for brevity: int translucent, int textureformat, int
 tw, int th, uint32 textureaddr, int filtering.
 This builds a polygon header for you so you don't have to diddle with bitfields.
 Translucent should be one of TA_OPAQUE or TA_TRANSLUCENT.
 Textureformat needs to be one of the texture format constants or TA_NO_TEXTURE.
 This includes whether it's twiddled or not (for info on twiddled textures,
 look for the PVR E3 presentation online).
 The rest of the parameters are only relevant if textureformat is not TA_NO_TEXT
URE.
 tw and th are the texture width and height, and must be powers of two between
 8 and 1024.
 Textureaddr is the address within the PVR RAM that you loaded the texture,
 and it must be aligned on an 8-byte boundary.
 Filtering should be TA_NO_FILTER or TA_BILINEAR_FILTER.
 Note that bi-linear filtering is a fairly expensive operation unless you
 store your textures in the PVR RAM in twiddled format, in which case it's
 free.
\layout Subsection

void ta_load_texture(uint32 dest, void *src, int size)
\layout Standard

Loads a texture into PVR ram at the given offset.
 
\begin_inset Quotes eld
\end_inset 

size
\begin_inset Quotes erd
\end_inset 

 must be a multiple of 4 and will be rounded up if it's not already.
 A seperate function is required because the PVR requires you to send all
 texture data to 0xa4000000, not 0xa5000000.
 This must also be done after ta_init.
\layout Subsection

void *ta_texture_map(uint32 loc)
\layout Standard

Maps a given PVR offset to a texture space.
 You should use this if you want to write directly into texture ram.
 Once again, it must be done after ta_init.
\layout Chapter

About this document
\layout Standard

This document was written in a stock LyX 1.0.0 distribution, using no fancy
 add-ons (so it ought to load ok for you if you want to try it).
 The PostScript was generated using the TeX tools that come with Debian
 2.2.
 The HTML output was produced by exporting a LaTeX file from LyX and using
 latex2html on the result.
\layout Standard

\the_end
