First and foremost, there are references in the document to copywritten materials. These materials are summarized later in the document. All references to copywritten materials are copyright their respective owners.
This document is divided up into 4 major segments, each covering a different aspect of developing software for the Sega Dreamcast. These segments are: Introduction, Using KOS, Using libronin, and Writing your own library.
The first requirement in starting to write software is to know the C or C++ language. If you do not know the C or C++ language it is recommended that you stop reading this document and proceed directly to learning how to read/write C or C++.
In order to develop software for the Sega Dreamcast it is required that you have a correctly configured GCC compiler for the SH4 and ARM processors. This section documents what and how to build each component and where you can download pre-built versions of the libraries and or compilers.
When developing on a Windows system you have two options for your development environment. The first option is to use Cygwin. While this option is the most common it has been reported that you have the ability to use a pre-compiled version of the tool-chain available http://www.kpit.com/products/support.htm
If you choose to not use the pre-built tool-chain above you should download and install the Cygwin environment on your PC. Once you have a working Cygwin environment you should then follow the UNIX instructions below for using a ``build script'' to download, build, and install the compiler for you. This is the fastest/easiest way to get up and running on a Windows system with Cygwin
On UNIX based systems it is extremely simple to build the tool-chain. It is best to use a compilation script that will generate both the SH4 and ARM compilers for you. There are many of these available on the net, they all work about the same and as such I am not going to go into much documentation other than provide links to them:
In order to test your software on the Sega Dreamcast you must send it over the serial cable, broadband adapter/LAN adapter, or burn it to a CD-R/CD-RW.
Andrew Kieschnick is the author of many tools that are in heavy use today. These tools include both dc-tool and dc-load. dc-tool is the serial upload slave and dc-load is the Broadband adapter upload slave. You can download the latest version of dc-tool or dc-load from the following site:
http://www.cerc.utexas.edu/andrewk/dc/
Marcus wrote one of the first tools for sending your program over to the Sega Dreamcast. This tool is available from:
http://mc.pp.se/dc/serslave.html
To purchase a pre-built cable please visit one of the following links:
Building your own serial cable can be a fun project. There are a handful of sites that will teach you how to build a cable from a NeoGeo Pocket to Dreamcast link cable and also a couple on how to use two video cables to create a serial cable.
While a serial cable is the most ideal solution, and most economical for most people, the Broadband Adapter/LAN Adapter will also work for sending programs to the Dreamcast. The added bonus of using a Broadband Adapter/LAN Adapter is that you have added speed, 10Mbps vs 56kbps. While the speed is a nice thing, the price of a Broadband/LAN Adapter will likely make this option a bit out of range for most people. The typical price for the Broadband Adapter/LAN Adapter is anywhere from $60 to $150 USD. Many people do not make any distinguishment between the Broadband Adapter and the LAN Adapter but there are some fairly major differences.
If you are still inclined to purchase a Broadband Adapter/LAN Adapter then you will want to purchase one from the following links:
KOS is one of the more complete solutions for developers wanting to write software for the Sega Dreamcast. While there are a few missing features this is by far the fastest way for many people to get some software to work on the Sega Dreamcast.
KOS can be obtained in source form in two ways:
Binaries are available from http://sourceforge.net/projects/cadcdev/under the ``files'' section. Simply download the ``stable'' version you are interested in, extract and then start working with it. More information on this will be given in the next segment.
KOS has to be one of the easiest libraries to configure. There is a shell script which you can run in either Cygwin or on any UNIX system. The script will require a few modifications to tailor it to your system. Below is a listing of the variables that you will likely need to modify:
The first program you will likely create will be a hello world program. Here is the source code you would write and an example of its usage:
#include <kos.h>; KOS_INIT_FLAGS(INIT_DEFAULT); int main(int argc, char **argv) { printf("\nHello world!\n\n"); return 0; }
The output of this program should be nothing to the the TV screen but it should print ``Hello world!'' to your console window which started the program.
KOS includes a fairly large set of example programs so examples of KOS' usage is not being done in this document except for the example above.
libronin is a derivative effort of the DreamSNES team to produce a second library which provides functionality to developers for writting software for the Sega Dreamcast. libronin has two forms, libronin.a and libronin-noserial.a. The libronin.a is best suited for development and testing of your software, however, when you release your software to the general public it is advised that you use the libronin-noserial.a file as it will render a faster program in the end due to not having serial output enabled.
The binaries are currently all that is publicly distributed. These can be obtained from:
http://peter.bortas.org/scumm/
This section will be broken down to many smaller pieces which will go over specifics of the library.
The first example program to be created is as always a hello world program:
#include ``ronin/ronin.h'' /* This is the default entry point for your program */ int main(int argc, char **argv) { serial_init(57600); usleep(200000); report("\nHello world!\n\n"); return 0; }
The ``serial_init(57600);'' line will initialize the serial port for read/write at 57600 bps. After you initialize the serial port it is mandatory that you sleep for at least two seconds to ensure stability of the line. The ``report'' call is essentially just a call to ``printf(<string>);'' except that it is sent across the serial line to the PC. This also is short circuited when you are not using the serial version of libronin.
In this example we will initialize and read from the cdrom the contents of the root directory.
#include ``ronin/ronin.h'' /* This is the default entry point for your program */ int main(int argc, char **argv) { serial_init(57600); usleep(200000); cdfs_init(); DIR *dir = opendir(``/''); if(dir != null) { struct dirent *ent; ent = readdir(dir); while(ent != null) { reportf(``File is: %s [%u]\r\n'', ent->d_name,ent->d_size); ent = readdir(dir); } closedir(dir); } return 0; }
The call to ``cdfs_init();'' will initialize the cdrom functions within the libronin library. The call to ``opendir(<path>)'', ``readdir(<DIR>)'', ``closedir(<DIR>)'' are all identical to that of the same calls on a linux/POSIX system. The path you pass to ``opendir(<path>)'' starts at the root of the cdrom. Be sure to check the return values from ``opendir(<path>)'' and ``readir(<DIR>)'' as exceptions can be thrown with invalid pointer accesses.
In this example we will begin to use the Tile Accelerator to put a colored box on the screen.
#include ``ronin/ronin.h'' /* This is the default entry point for your program */ int render_solid_box(float x1, float y1, float x2, float y2, int color) { struct polygon_list poly; struct packed_colour_vertex_list vert; // Initialize to some sane values: it is an opaque colored polygon, no texture. poly.cmd = TA_CMD_POLYGON | TA_CMD_POLYGON_TYPE_OPAQUE | TA_CMD_POLYGON_STRIPLENGTH_2 | TA_CMD_POLYGON_PACKED_COLOUR | TA_CMD_POLYGON_GOURAUD_SHADING; poly.mode1 = TA_POLYMODE1_Z_ALWAYS | TA_POLYMODE1_NO_Z_UPDATE; poly.mode2 = TA_POLYMODE2_BLEND_SRC | TA_POLYMODE2_FOG_DISABLED; // Default the texture to no texture poly.texture = 0; // Set the polygon color to 0 (black) poly.red = poly.green = poly.blue = poly.alpha = 0; // Commit this polygon to the Tile Accelerator ta_commit_list(&poly); // Default the vertex information to something sensable. vertex.cmd = TA_CMD_VERTEX; vertex.ocolour = 0; vertex.z = 0.5; vertex.u = 0.0; vertex.v = 0.0; vertex.colour = color; // submit the upper left corner vertex.x = x1; vertex.y = y1; ta_commit_list(&vertex); // submit the upper right corner vertex.x = x2; ta_commit_list(&vertex); // submit the lower left corner vertex.x = x1; vertex.y = y2; ta_commit_list(&vertex); // submit the lower right corner vertex.x = x2; vertex.cmd |= TA_CMD_VERTEX_EOS; ta_commit_list(&vertex); } /* This is the default entry point for your program */ int main(int argc, char **argv) { serial_init(57600); usleep(200000); dc_setup_ta(); for(;;) { ta_sync(); ta_begin_frame(); // begin opaque poly list render_solid_box(20.0, 20.0, 620.0, 460.0, 0xFFFFFFFF); // render a white box to the screen ta_commit_end(); // begin translucent poly list commit_dummy_transpoly(); ta_commit_end(); // commit the frame to the Tile Accelerator ta_commit_frame(); } return 0; }
The ``dc_setup_ta()'' call will initialize and configure the libronin library for using the Tile Accelerator chip in the Sega Dreamcast. The call to ``ta_sync()'' will ensure the Tile Accelerator is ready for a new frame of data to be written. The call to ``ta_begin_frame()'' initializes the frame buffers for the lists of opaque and transparent polygons which are to be rendered.
When you use the Tile Accelerator it is mandatory that you do not send it an empty list. It is rare that you will not have at least one opaque polygon during a given frame so there is no function provided for submitting an empty polygon for the opaque list, however, in the case of translucent polygons there is a function ``commit_dummy_transpoly()'' which will generate and submit an empty translucent polygon.
libronin has one drawback on it that KOS doesn't have, macros for the directions, buttons, etc on the controller. Other than this the maple implementation is very solid and works flawlessly for every application I could think of.. Here are the defines you will need to have to make life and code easier to handle:
/* Buttons bitfield defines */ #define CONT_C (1 << 0) #define CONT_B (1 << 1) #define CONT_A (1 << 2) #define CONT_START (1 << 3) #define CONT_DPAD_UP (1 << 4) #define CONT_DPAD_DOWN (1 << 5) #define CONT_DPAD_LEFT (1 << 6) #define CONT_DPAD_RIGHT (1 << 7) #define CONT_Z (1 << 8) #define CONT_Y (1 << 9) #define CONT_X (1 << 10) #define CONT_D (1 << 11) #define CONT_DPAD2_UP (1 << 12) #define CONT_DPAD2_DOWN (1 << 13) #define CONT_DPAD2_LEFT (1 << 14) #define CONT_DPAD2_RIGHT (1 << 15)
Without these defines you will end up having to use cryptic code like : ``if(buttons & 4) do something''. Now with these defines you can write it as ``if (buttons & CONT_A) do something''
Here is an example using the above defines to read controller input:
/* This is the default entry point for your program */ int main(int argc, char **argv) { int mask, i; struct mapledev *pads; serial_init(57600); usleep(200000); maple_init(); for(;;) { mask = getimask(); setimask(15); pads = get_locked_pads(); for(i = 0; i < 4; i++) { if(pads[i]->func & MAPLE_FUNC_CONTROLLER) { int buttons = pads[i]->cond.controller.buttons; reportf(``Controller %u state:\r\n'', i); reportf(``UP: %u DOWN: %u LEFT: %u RIGHT: %u\r\n'', buttons & CONT_DPAD_UP, buttons & CONT_DPAD_DOWN, buttons & CONT_DPAD_LEFT, buttons & CONT_DPAD_RIGHT); reportf(``UP2: %u DOWN2: %u LEFT2: %u RIGHT2: %u\r\n'', buttons & CONT_DPAD2_UP, buttons & CONT_DPAD2_DOWN, buttons & CONT_DPAD2_LEFT, buttons & CONT_DPAD2_RIGHT); reportf(``A: %u B: %u X: %u Y: %u\r\n'', buttons & CONT_A, buttons & CONT_B, buttons & CONT_X, buttons & CONT_Y); } } setimask(mask); } }
The above example is a fairly simple example showing how you would read the state of the controllers and dump it to the console. The usage of ``setimask'' and ``getimask'' is required to ensure that we are not interrupted while we have the pad struct locked.
This section of the doc is not available at this time. More information will be given shortly.
This section of the doc is not available at this time. More information will be given shortly.
Writing your own library to drive the Sega Dreamcast hardware is somewhat difficult and long process of developing re-usable pieces of code that do direct hardware interaction. This is generally not recommended for beginning developers but more for the advanced developers who have lots of system level knowledge and/or have access to documentation which provides accurate information regarding the hardware. Some documentation is available from:
http://mc.pp.se/dc/hw.html
There are many references within this document to copywritten materials, this section lists the references and who owns the copywrite for the references.