next_inactive up previous


Cryptic Allusion Libdream 0.95 / Programmer's Manual

(c)2000 Dan Potter


Contents

Legal

``Sega'' and ``Dreamcast'' 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.

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.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ``Software''), 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:

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

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.

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.

1. Getting Started

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 what Libdream is, please take a look at the README file in the root of the package directory.

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!

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.

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.

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 ``MAKE=gmake gmake'' (in bash parlance). Cygwin users ought to be able to use ``make'' and have it compile ok.

If you'd like to compile just the examples and skip the libdream step, then edit Makefile.config like before, but change into ``examples'' 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_disable before dc_setup if you want to run them using a CDR.

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 ``include'' and ``lib'' subdirectories of the libdream root.

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

2. A Basic Libdream Program

A libdream program is pretty simple and straightforward - you should have a ``main'', which is called ``main'' if you're using a default crt0, or ``dc_main'' 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.

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.

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.

The basic normal call looks something like this:

dc_setup(DM_640x480, PM_RGB565);
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.

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 assumptions 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).

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 ``examples'' directory off the libdream root.

3. The Subsystems

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. _;

3.1 Data Types

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 ``int'', but counts are usually ``uint32''. Functions that can return errors generally return them as a negative int, and success as a zero int. Strings are stored as ``char *''. Indivudual characters are generally ``int''.

3.2 Serial (serial.c)

The serial system accesses the ``SCIF'' (serial communications interface w/FIFO) of the SH-4 CPU. This port of the CPU is attached to the external ``Serial I/O'' port of the Dreamcast.

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

3.2.1 void serial_disable()

Disables serial access through the serial module; all serial output will be discarded and serial input will always return ``no character available''. 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.

3.2.2 void serial_init(int baud)

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

3.2.3 void serial_write(int c)

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().

3.2.4 void serial_flush()

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

3.2.5 void serial_write_buffer(uint8 *data, int len)

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

3.2.6 void serial_write_str(char *str)

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

3.2.7 int serial_read()

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

3.2.8 int serial_printf(char *fmt, ...)

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.

3.3 Basic Video (video.c)

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 ``TA'' module. The basic usage of the video system is to call vid_init with the desired parameters, and then use one of the ``vram'' pointers to access video memory.

The following variables and functions are available in basic video:

3.3.1 uint32 *vram_l

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 =).

3.3.2 uint32 *vram_s

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.

3.3.3 int vram_config

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

3.3.4 int vram_size

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

3.3.5 int vid_cable_type

Stores the cable_type parameter to the video init function below.

3.3.6 int vid_check_cable()

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

3.3.7 int vid_init(int cable_type, int disp_mode, int pixel_mode)

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.

3.3.8 void vid_set_start(uint32 start)

Set the ``start address'' register, which governs where in the frame buffer the output picture comes from. This can be used for ``double buffering'', but it will most commonly be used during 3D acceleration.

3.3.9 void vid_border_color(int r, int g, int b)

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).

3.3.10 void vid_clear(int r, int g, int b)

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.

3.3.11 void vid_empty()

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.

3.3.12 void vid_waitvbl()

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 ``tearing'' or other artifacts. It's also generally when you want to switch start addresses.

3.4 BIOS Fonts (biosfont.c)

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.

The following functions are available:

3.4.1 void* bfont_find_char(int ch)

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

3.4.2 void bfont_draw(uint16 *buffer, int bufwidth, int c)

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').

3.4.3 void bfont_draw_str(uint16 *buffer, int bufwidth, char *str)

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

3.5 PC Fonts (font.c)

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.

3.6 Sound Processor Unit (spu.c)

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 ``s3mplay'' on the Cryptic Allusion DCDev site (see README).

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

3.6.1 SMP_BASE

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).

3.6.2 void snd_ram_write_wait()

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.

3.6.3 void snd_load_arm(void *src, int size)

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

3.6.4 void snd_stop_arm()

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

3.6.5 void snd_init()

Initialize the SPU: disable the ARM7 and clear sound memory.

3.6.6 void snd_load(void *src, int dest, int len)

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.

3.7 CD-Rom Access (cdfs.c)

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

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 =).

The following functions are available:

3.7.1 uint32 iso_open(const char *path, int oflag)

Open a file on the CD, using absolute path ``path'', with open flags ``oflag''. Note that in the current system, ``path'' must use forward slashes for path seperators (but can mix upper and lower case freely with no troubles), and ``oflag'' must be O_RDONLY or (O_RDONLY | O_DIR). A file descriptor will be returned, or a zero on error.

3.7.2 void iso_close(uint32 fd)

Close the file referenced by the given file descriptor.

3.7.3 int iso_read(uint32 fd, void *buf, int count)

Read ``nbyte'' bytes from the file referenced by ``fd'', into buffer ``buf''. 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.

3.7.4 long iso_lseek(uint32 fd, long offset, int whence)

Seek in file ``fd'' by ``offset'' bytes, relative to ``whence''. ``whence'' is one of the standard STDIO constants: SEEK_SET, SEEK_CUR, SEEK_END. ``offset'' may be positive or negative depending on the usage. The new file location will be returned.

3.7.5 long iso_tell(uint32 fd)

Returns the current file pointer within ``fd''.

3.7.6 dirent_t *iso_readdir(uint32 dirfd)

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.

3.7.7 int cdrom_init() int iso_init()

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

3.8 Timer Counters (timer.c)

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.

The following defines and functions are available:

3.8.1 TMU0, TMU1, TMU2, WDT

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

3.8.2 int timer_prime(int which, uint32 speed)

Primes a timer, but does not start it. ``which'' is one of the timer constants, and ``speed'' is a times per second rate which the counter will bottom out. So if you set speed to ``1'', then the timer will hit bottom after one second, and start counting again. Returns 0 for success.

3.8.3 int timer_start(int which)

Starts the requested timer counting (after priming it).

3.8.4 int timer_stop(int which)

Stops the requested timer.

3.8.5 uint32 timer_count(int which)

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.

3.8.6 int timer_clear(int which)

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.

3.8.7 void timer_sleep(int ms)

Uses TMU0 to sleep for the given number of milliseconds.

3.8.8 int timer_init()

Setup timers (enable and stop all).

3.9 Maple Access (maple.c)

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.

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.

The following functions are available:

3.9.1 void maple_init(int quiet)

Initialize the maple bus; if ``quiet'' is non-zero, then the bus scan will not produce any output.

3.9.2 void maple_shutdown()

Shut down all maple bus operations.

3.9.3 uint8 maple_create_addr(uint8 port, uint8 unit)

Create a maple address for the given port and unit.

3.9.4 int maple_docmd_block(...)

Parameters omitted for topic brevity: int8 cmd, uint8 addr, uint8 datalen, void *data, maple_frame_t retframe. This is the main ``work horse'' of the maple system. ``cmd'' should be one of the maple command constants in maple.h; ``addr'' should be created with maple_create_addr (or one of the maple_*_addr functions below); ``datalen'' is the length of the extra data (beyond what's in the frame header), ``data'' is a pointer to extra data (if any) that goes after the frame header; and ``retframe'' 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.

3.9.5 int maple_rescan_bus(int quiet)

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 ``quiet'' is non-zero, it produces no output.

3.9.6 uint8 maple_device_addr(int code)

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

3.9.7 uint8 maple_*_addr()

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.

3.10 Maple Peripheral Support Modules

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! =)

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.

3.10.1 int cont_get_cond(uint8 addr, cont_cond_t *cond)

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

3.10.2 int kbd_get_cond(uint8 addr, kbd_cond_t *cond)

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.

3.10.3 int vmu_draw_lcd(uint8 addr, void *bitmap)

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.

3.10.4 int vmu_block_read(uint8 addr, uint16 blocknum, uint8 *buffer)

Read the requested block of the VMU's flash ram and put it in ``buffer''.

3.10.5 int vmu_block_write(uint8 addr, uint16 blocknum, uint8 *buffer)

Take what's in ``buffer'' and write it to the requested block of the VMU's flash ram.

3.10.6 int mouse_get_cond(uint8 addr, mouse_cond_t *cond)

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

3.11 Tile Accelerator (ta.c)

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.

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 ``display list'' describing what is to be displayed on the screen, and doing internal z-buffering. 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 ``cut'' 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.

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 ``strips'' as much as possible, and then throw the various lists to the TA. Then sit back and wait for it to do its work.

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.

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.

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

  1. Setup the TA (ta_init); initialize the background plane structure
  2. Load any textures you may want to use
  3. For each frame:
Here are the structures and functions needed to do these things:

3.11.1 struct pv_str ta_page_values[2]

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).

3.11.2 bkg_poly ta_bkg

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.

3.11.3 poly_hdr_t

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.

3.11.4 vertex_oc_t

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.

3.11.5 vertex_ot_t

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

3.11.6 int ta_curpage

The current working page (out of ta_page_values above).

3.11.7 void ta_init()

Initializes the TA and prepares for page flipped 3D.

3.11.8 void ta_send_queue(void *sql, int size)

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

3.11.9 void ta_begin_render()

Call before you start drawing a frame.

3.11.10 void ta_commit_poly_hdr(poly_hdr_t *polyhdr)

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.

3.11.11 void ta_commit_vertex(void *vertex, int size)

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.

3.11.12 void ta_commit_eol()

Sends the ``end of list'' marker to the TA. This ought to be used after all opaque polygons are sent, and again after all translucent polygons are sent.

3.11.13 void ta_finish_frame()

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.

3.11.14 void ta_build_poly_hdr(poly_hdr_t *target, ...)

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_TEXTURE. 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.

3.11.15 void ta_load_texture(uint32 dest, void *src, int size)

Loads a texture into PVR ram at the given offset. ``size'' 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.

3.11.16 void *ta_texture_map(uint32 loc)

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.

4. About this document

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.

About this document ...

Cryptic Allusion Libdream 0.95 / Programmer's Manual

This document was generated using the LaTeX2HTML translator Version 99.2beta8 (1.42)

Copyright © 1993, 1994, 1995, 1996, Nikos Drakos, Computer Based Learning Unit, University of Leeds.
Copyright © 1997, 1998, 1999, Ross Moore, Mathematics Department, Macquarie University, Sydney.

The command line arguments were:
latex2html -no_subdir -split 0 -show_section_numbers /usr/local/home/dan/prj/dc/programs/libdream/docs/libdream.tex

The translation was initiated by Dan Potter on 2000-12-27


next_inactive up previous
Dan Potter 2000-12-27