Japanese
SGL User's ManualPROGRAMMER'S TUTORIAL
BackForward
PROGRAMMER'S TUTORIAL

7.Polygon surface attributes


This chapter explains the surface attributes of polygons on Sega Saturn.
For polygons, "Sort" indicates the reference position to determine the display order of each polygon, "Front and back attributes" specify whether to display one side or both sides of the polygon, and a two-dimensional picture ( There are elements such as "textures" that paste bitmap data).
These are collectively called "polygon surface attributes."
By specifying the surface attributes of polygons, you can add various expressions to polygons that were previously just pictures.

7-1. Attributes

In Sega Graphic Library (SGL), the surface attributes of polygons can be specified using the ATTRIBUTE macro.
In the sample programs up to this chapter, attributes have been set implicitly without explaining the contents of each parameter in detail.
However, attributes gather important elements when working with polygons. Therefore, here we will explain in detail the meaning of each parameter of the ATTRIBUTE macro.

Listing 7-1 Attribute data
●Attribute data

ATTR attribute_label[]={ ATTRIBUTE(Plane,Sort,Texture,Color,Gouraund,Mode,Dir,Option), ...................... };

Note) The ATTRIBUTE macro is defined in “sl_def.h”.

The meaning of each parameter is as follows.

Plane: Indicates whether it is a single-sided polygon or a double-sided polygon (front and back attributes)
Sort: Indicates the representative point of the positional relationship of polygons (Z sort)
Texture: Indicates the texture name (No.) Color: Indicates the color data Gouraud: Indicates the address of the Gouraud shading table Mode: Indicates the polygon drawing mode (various mode settings)
Dir: Indicates the state of polygons and textures Option: Indicates other functions (option settings)

7-2.Plane

The first attribute parameter “Plane” indicates the front and back attributes of the polygon. The front and back attributes are attributes that indicate whether the polygon is a one-sided polygon or a double-sided polygon.
Double-sided polygons can be seen from both sides, but single-sided polygons disappear when turned to the back.
Below are the macros that can be specified for this parameter.

Table 7-1 Plane (front and back attributes)
macro Contents
Single_Plane One-sided display of polygons
Dual_Plane Double-sided display of polygons

Now, let's take a look at the sample program (Listing 7-2).
A one-sided yellow polygon rotates around the Y axis.
Since it is a single-sided polygon, the back side is not displayed.

Listing 7-2 sample_7_2: main.c
/*------------------------------------------------ ----------------------*/
/* Rotation of Single Plane Polygon */
/*------------------------------------------------ ----------------------*/
#include "sgl.h"

extern PDATA PD_PLANE;

void ss_main(void)
{
	static ANGLE ang[XYZ];
	static FIXED pos[XYZ];

	slInitSystem(TV_320x224,NULL,1);
	slPrint("Sample program 7.2" , slLocate(6,2));

	ang[X] = ang[Y] = ang[Z] = DEGtoANG(0.0);
	pos[X] = toFIXED( 0.0);
	pos[Y] = toFIXED( 0.0);
	pos[Z] = toFIXED(170.0);

	while(-1){

		slPushMatrix();
		{
			slTranslate(pos[X] , pos[Y] , pos[Z]);
			slRotX(ang[X]);
			slRotY(ang[Y]);
			slRotZ(ang[Z]);
			ang[Y] += DEGtoANG(2.0);
			slPutPolygon(&PD_PLANE);
		}
		slPopMatrix();

		slSynch();
	}
}

Look at line 27. The polygon drawing routine “slPutPolygon” is called and a pointer to the polygon data “PD_PLANE” is passed.
“PD_PLANE” is defined in the source “polygon.c” as follows.

Listing 7-3 sample_7_2: Polygon.c
#include "sgl.h"

POINT point_PLANE[] = {
	POStoFIXED(-20.0, -20.0, 0.0),
	POStoFIXED( 20.0, -20.0, 0.0),
	POStoFIXED( 20.0, 20.0, 0.0),
	POStoFIXED(-20.0, 20.0, 0.0),
};

POLYGON polygon_PLANE[] = {
	NORMAL(0.0,0.0,1.0), VERTICES(0,1,2,3),
};

ATTR attribute_PLANE[] = {
	ATTRIBUTE(Single_Plane,SORT_CEN,No_Texture,C_RGB(31,31,0),No_Gouraud,MESHoff,sprPolygon,No_Option),
};

PDATA PD_PLANE = {
	point_PLANE , sizeof(point_PLANE)/sizeof(POINT) ,
	polygon_PLANE , sizeof(polygon_PLANE)/sizeof(POLYGON) ,
	attribute_PLANE
};

The 18th line and subsequent lines are polygon data. The 21st line is a pointer to the attribute data, so the actual data starts from the 14th line.
You can see that the first parameter is “Single_Plane”.

7-3. Sort

The second parameter “Sort” indicates the position of the Z sort on the polygon. Z-sort is a method that uses the representative point on each polygon to determine its position and context in 3D space, and is faster to calculate and draw than the Z-buffer (position is determined for each pixel on a polygon) method. The feature is that it can be done. Below are the macros that can be specified for this parameter.

Table 7-2 Sort (Z sort specification)
macro Contents
SORT_MIN Set the vertex on the polygon closest to the camera as the representative point
SORT_CEN Set the center point of the polygon as the representative point
SORT_MAX Set the point farthest from the camera as the representative point
SORT_BFR Displayed in front of the polygon registered just before

Also, if you make a diagram of this, it will look like this:

Figure 7-1 Representative points of Z sort

“SORT_BFR” is a special specification and is used when you want to display one polygon above (in front of) another polygon. Specifically, the display position of a polygon with “SORT_BFR” specified will be immediately in front of the polygon registered immediately before that polygon. However, this specification only becomes meaningful when you want to use two polygons as a group, so it is not usually used.

Due to its nature, the Z-sort method includes the possibility that the context may become incorrect depending on how representative points are taken. Take a look at the following example.

Figure 7-2 Differences in context due to representative points

If you specify the representative point as shown in the figure above, the actual screen will look like the figure below.

Figure 7-3 Actual screen

7-4.Texture

The third parameter “Texture” is a parameter required when using texture mapping. Here, specify the number of the texture actually used from the texture table registered with the function "slInitSystem".
When not using a texture, specify the macro “No_Texture”. Texture mapping is a general term for functions that paste two-dimensional graphics onto the surface of polygons. Needless to say, polygons can only represent display colors, and there are limits to their reality. However, by making full use of the texture mapping function, it is possible to express 3D objects with a higher degree of reality, such as object textures and surface patterns that could not be expressed using polygons alone.

Texture mapping for Sega Saturn and so-called texture mapping for general CG have two different characteristics, as shown in Table 7-3.

Table 7-3 Differences between Sega Saturn texture mapping and general CG texture mapping
texture mapping
For Sega Saturn For general CG
 of texture
 stakeout
It is possible to paste one texture to one polygon. A single texture can be pasted across multiple polygons.
 deformation
The texture is also transformed according to the shape of the polygon. The texture will be clipped to the shape of the polygon.

●Pasting textures

Figure 7-5 Characteristics of texture 1

note)
There is a one-to-one correspondence between textures and polygons.

Textures in general CG can be pasted across multiple polygons, but in the case of Sega Saturn, one texture is pasted in correspondence to one polygon. If you want to paste a texture that spans two or more polygons, you need to divide the texture according to each polygon as shown in Figure 7-5.

●Texture deformation
For general CG textures, if the polygon is not a rectangle (including a square), the texture will be clipped to the polygon shape. However, on the Sega Saturn, textures are not clipped and are deformed along polygons. Even if the polygon is a triangle, the entire texture will be transformed into a triangle.

Figure 7-6 Texture characteristics 2

note)
The texture transforms according to the shape of the polygon.

About texture distortion

If the polygon is a rectangle and the texture attached to it is square, the texture will be transformed into a rectangle according to the aspect ratio of the polygon. Therefore, keep in mind that the texture will be less distorted if the aspect ratio of the texture matches the aspect ratio of the polygon as much as possible.

Figure 7-7 Texture distortion

Now, let's take a look at the sample program (Listing 7-4).
A single polygon with a texture attached rotates around the Y axis.
Here, we will register two textures in advance.
One is a picture of [SONIC] (size: 64 x 64 pixels), and the other is the "AM2" mark (size: 64 x 32 pixels).

Listing 7-4 sample_7_4: main.c
/*------------------------------------------------ ----------------------*/
/* Polygon & Texture */
/*------------------------------------------------ ----------------------*/
#include "sgl.h"

extern PDATA PD_PLANE;
extern TEXTURE tex_sample[];
extern PICTURE pic_sample[];

#define max_texture 2

void set_texture(PICTURE *pcptr , Uint32 NbPicture)
{
	TEXTURE *txptr;
 
	for(; NbPicture--> 0; pcptr++){
		txptr = tex_sample + pcptr-> texno;
		slDMACopy((void *)pcptr->pcsrc,
			(void *)(SpriteVRAM + ((txptr-> (CGadr)<< 3)),
			(Uint32)((txptr-> Hsize * txptr-> Vsize * 4) >> (pcptr-> cmode)));
	}
}

void ss_main(void)
{
	static ANGLE ang[XYZ];
	static FIXED pos[XYZ];

	slInitSystem(TV_320x224,tex_sample,1);
	set_texture(pic_sample,max_texture);
	slPrint("Sample program 7.4" , slLocate(9,2));

	ang[X] = ang[Y] = ang[Z] = DEGtoANG(0.0);
	pos[X] = toFIXED( 0.0);
	pos[Y] = toFIXED( 0.0);
	pos[Z] = toFIXED(170.0);

	while(-1){
		slPushMatrix();
		{
			slTranslate(pos[X] , pos[Y] , pos[Z]);
			slRotX(ang[X]);
			slRotY(ang[Y]);
			slRotZ(ang[Z]);
			ang[Y] += DEGtoANG(2.0);
			slPutPolygon(&PD_PLANE);
		}
		slPopMatrix();

		slSynch();
	}
}

The program flow itself is not much different from Listing 7-2.

First, pay attention to line 29.
This is an initialization routine that has been used implicitly until now, but the second parameter is different from before. Specify a pointer to the texture table to be passed to SGL here. (The actual table is defined in “texture.c”. See Listing 7-5 .) Up until now, we had not used textures, so we had assigned “NULL”.

Line 30 transfers the texture data to V-RAM.
This texture data transfer can be performed at any time after initialization, so techniques such as redrawing textures during the game can be easily performed.

The 12th line and subsequent lines are the actual texture data transfer routine.
Here, we receive the start address of the texture table and the number of registered textures. The “slDMACopy” function on line 18 uses DMA to transfer data at high speed.
The first parameter of this function is the transfer source address, the second parameter is the transfer destination address, and the third parameter is the transfer size.

[void slDMACopy ( void *src , void *dst , Uint32 cnt ) ;]
Uses the CPU's built-in DMA to perform block transfers of data
. Assign the start address of the transfer source memory area, the start address of the transfer destination memory area, and the block transfer amount (unit: bytes) to the parameters.
This function ends the transfer immediately after starting the DMA.
If you want to know when the transfer is complete, use the function “slDMAWait”.

Next, let's look at the texture data.

Listing 7-5 sample_7_4:texture.c

#include "sgl.h"
/********************************/
/* Texture Data */
/********************************/

TEXDAT sonic_64x64[]={ /* Texture data 1 */
	 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
					:
					:
				      Omitted:
};

TEXDAT am2_64x32[]={ /* Texture data 2 */
	 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
					:
					:
				      Omitted:
};

TEXTURE tex_sample[]={ /* Table to be passed to SGL */
	TEXDEF(64,64,0),
	TEXDEF(64,32,64*64*1),
};

PICTURE pic_sample[]={ /* VRAM transfer table */
	PICDEF(0,COL_32K,sonic_64x64),
	PICDEF(1,COL_32K,am2_64x32),
};

The part written by the TEXDAT macro becomes the actual texture data.
Although omitted in the above list, all data is included in the source. Note that the format of texture data is not mentioned here. Please refer to “Function Reference” in the reference manual.

The part written by the TEXTURE macro is the texture table passed to SGL.
Set the size (width x height) of each texture and the offset value from the start address of the actual texture data.

Finally, the PICTURE macro part becomes the table for VRAM transfer.
Set the texture number, color mode, and pointer to texture data.

Now, last but not least, let's take a look at the attributes of the polygon data.

Listing 7-6 sample_7_4: polygon.c

#include "sgl.h"

#define PN_SONIC 0
#define PN_AM2 1

POINT point_plane[] = {
        POStoFIXED(-40.0 , -40.0 , 0.0) ,
        POStoFIXED( 40.0 , -40.0 , 0.0) ,
        POStoFIXED( 40.0 , 40.0 , 0.0) ,
        POStoFIXED(-40.0 , 40.0 , 0.0)
};

POLYGON polygon_plane[] = {
        NORMAL(0.0,0.0,1.0), VERTICES(0 , 1 , 2 , 3)
};

ATTR attribute_plane[] = {
	ATTRIBUTE(Single_Plane, SORT_CEN, PN_SONIC, No_Palet, No_Gouraud, CL32KRGB|MESHoff, sprNoflip, No_Option),
};

PDATA PD_PLANE = {
        point_plane , sizeof(point_plane)/sizeof(POINT),
        polygon_plane, sizeof(polygon_plane)/sizeof(POLYGON),
        attribute_plane
};

The third parameter of “ATTRIBUTE” is “PN_SONIC”.
In other words, the texture "SONIC" with registration number [0] is pasted on the polygon and displayed.
Also, try changing this parameter to “PN_AM2”.
This time, the texture should change to the "AM2" mark with registration number [1].
Furthermore, by changing the first parameter “Single_Plane” to “Dual_Plane”, it is also possible to view the texture from the back side.

7-5.Color

The fourth parameter “Color” specifies the offset address to the polygon color and texture color palette.
For polygons, the color data specification method is limited to RGB Direct. The format is “C_RGB(r,g,b)”. r, g, and b indicate the three primary colors of light, and are specified as decimal numbers from 0 to 31.
For textures, the color data specification method depends on the specification in "Mode" (sixth parameter of the attribute. See " 7-7 Mode "). For 32768-color RGB mode, specify the macro “No_Palet”; for other index modes, specify the offset address to the color palette.

7-6. Gouraud

The fifth parameter “Gouraud” specifies the Gouraud table used for Gouraud shading. Gouraud shading is a term for flat shading in which the boundaries between polygons are clearly defined, and is a technique that applies shading to polygon surfaces and erases the boundaries between polygons to make them look like curved surfaces. The Sega Saturn uses the color gradation between the vertices of polygons to achieve Gouraud shading.

Figure 7-8 Gouraud shading
flat shading Gouro shading

Now, let's take a look at the sample program (Listing 7-7). A cube with Gouraud shading rotates around the Y axis.

Listing 7-7 sample_7_6: main.c

/*------------------------------------------------ ----------------------*/
/* Gouraud Shading */
/*------------------------------------------------ ----------------------*/
#include "sgl.h"

extern PDATA PD_CUBE;

#define GRoffsetTBL(r,g,b) (((b & 0x1f)<< 0) | ((g & 0x1f)<< 5) | (r & 0x1f))
#define VRAMaddr (SpriteVRAM+0x70000)

static Uint16 GRdata[6][4] = {
	{ GRoffsetTBL( 0,-16,-16) , GRoffsetTBL( 0,-16,-16) ,
	  GRoffsetTBL( 0,-16,-16) , GRoffsetTBL(-16, 15, 0) } , 
	{ GRoffsetTBL( 0,-16,-16) , GRoffsetTBL( 0,-16,-16) ,
	  GRoffsetTBL(-16, 15, 0) , GRoffsetTBL( 0,-16,-16) } , 
	{ GRoffsetTBL(-16, 15, 0) , GRoffsetTBL( 0,-16,-16) ,
	  GRoffsetTBL( 0,-16,-16) , GRoffsetTBL( 0,-16,-16) } , 
	{ GRoffsetTBL( 0,-16,-16) , GRoffsetTBL(-16, 15, 0) ,
	  GRoffsetTBL( 0,-16,-16) , GRoffsetTBL( 0,-16,-16) } , 
	{ GRoffsetTBL( 0,-16,-16) , GRoffsetTBL(-16, 15, 0) ,
	  GRoffsetTBL( 0,-16,-16) , GRoffsetTBL( 0,-16,-16) } , 
	{ GRoffsetTBL(-16, 15, 0) , GRoffsetTBL( 0,-16,-16) , 
	  GRoffsetTBL( 0,-16,-16) , GRoffsetTBL( 0,-16,-16) } 
};

void ss_main(void)
{
	static ANGLE ang[XYZ];
	static FIXED pos[XYZ];

	slInitSystem(TV_320x224,NULL,1);
	slPrint("Sample program 7.6" , slLocate(9,2));

	ang[X] = DEGtoANG(30.0);
	ang[Y] = DEGtoANG( 0.0);
	ang[Z] = DEGtoANG( 0.0);
	pos[X] = toFIXED( 0.0);
	pos[Y] = toFIXED( 0.0);
	pos[Z] = toFIXED(200.0);

	slDMACopy(GRdata,(void *)VRAMaddr,sizeof(GRdata));

	while(-1){
		slPushMatrix();
		{
			slTranslate(pos[X] , pos[Y] , pos[Z]);
			slRotX(ang[X]);
			slRotY(ang[Y]);
			slRotZ(ang[Z]);
			slPutPolygon(&PD_CUBE);
		}
		slPopMatrix();

		ang[Y] += DEGtoANG(1.0);

		slSynch();
	}
}

The routine for drawing and rotating a cube is not much different from the previous one, so I will omit the explanation. The difference is line 41, where the Gouraud table is transferred to VRAM. The idea is the same as transferring texture data, first store all the necessary tables in VRAM.

Now let's take a look at the attributes.

Listing 7-8 sample_7_6: polygon.c

#include "sgl.h"

#define GRaddr 0xe000

static POINT point_CUBE[] = {
	POStoFIXED(-20.0 , -20.0 , 20.0) ,
	POStoFIXED( 20.0 , -20.0 , 20.0) ,
	POStoFIXED( 20.0 , 20.0 , 20.0) ,
	POStoFIXED(-20.0 , 20.0 , 20.0) ,
	POStoFIXED(-20.0 , -20.0 , -20.0) ,
	POStoFIXED( 20.0 , -20.0 , -20.0) ,
	POStoFIXED( 20.0 , 20.0 , -20.0) ,
	POStoFIXED(-20.0 , 20.0 , -20.0)
};

static POLYGON polygon_CUBE[] = {
	NORMAL( 0.0 , 0.0 , 1.0), VERTICES(0 , 1 , 2 , 3),
	NORMAL(-1.0 , 0.0 , 0.0), VERTICES(4 , 0 , 3 , 7),
	NORMAL( 0.0 , 0.0 ,-1.0), VERTICES(5 , 4 , 7 , 6),
	NORMAL( 1.0 , 0.0 , 0.0), VERTICES(1 , 5 , 6 , 2),
	NORMAL( 0.0 ,-1.0 , 0.0), VERTICES(4 , 5 , 1 , 0),
	NORMAL( 0.0 , 1.0 , 0.0), VERTICES(3 , 2 , 6 , 7)
};

static ATTR attribute_CUBE[] = {
	ATTRIBUTE(Single_Plane, SORT_MIN, No_Texture, C_RGB(31,16,31), GRaddr, MESHoff|CL_Gouraud, sprPolygon,No_Option),
	ATTRIBUTE(Single_Plane, SORT_MIN, No_Texture, C_RGB(31,16,31), GRaddr+1, MESHoff|CL_Gouraud, sprPolygon,No_Option),
	ATTRIBUTE(Single_Plane, SORT_MIN, No_Texture, C_RGB(31,16,31), GRaddr+2, MESHoff|CL_Gouraud, sprPolygon,No_Option),
	ATTRIBUTE(Single_Plane, SORT_MIN, No_Texture, C_RGB(31,16,31), GRaddr+3, MESHoff|CL_Gouraud, sprPolygon,No_Option),
	ATTRIBUTE(Single_Plane, SORT_MIN, No_Texture, C_RGB(31,16,31), GRaddr+4, MESHoff|CL_Gouraud, sprPolygon,No_Option),
	ATTRIBUTE(Single_Plane, SORT_MIN, No_Texture, C_RGB(31,16,31), GRaddr+5, MESHoff|CL_Gouraud, sprPolygon,No_Option),
};

PDATA PD_CUBE = {
	point_CUBE , sizeof(point_CUBE)/sizeof(POINT),
	polygon_CUBE , sizeof(polygon_CUBE)/sizeof(POLYGON) ,
	attribute_CUBE
};

Pay attention to the attributes.
The fifth parameter “Gouraud” is set to the VRAM address where the Gouraud data was stored earlier. The VRAM address here is (relative address ÷ 8).

Please also pay attention to the 6th parameter “Mode”.
When using Gouraud shading, “CL_Gouraud” must be specified here. If you do not use Gouraud shading, please specify the macro "No_Gouraud" for the fifth parameter "Gouraud".

7-7.Mode

The sixth parameter is “Mode”.
Here you can add various conditions and settings to polygons. The macros that can be specified here are as follows.

Table 7-4 Mode
group macro Content
[1] No_Window Not subject to Window restrictions (default)
Window_In Display inside Window
Window_Out Display outside the window
[2] MESHoff Normal display (default)
MESHon Display as mesh
[3] ECdis Disable EndCode
ECenb Enable EndCode (default)
[4] SPdis Also display transparent pixels (default)
SPenb Do not display transparent pixels
[5] CL16Bnk 16-color color bank mode (default)
CL16Look 16 color lookup table
CL64Bnk 64 color color bank mode
CL128Bnk 128 color color bank mode
CL256Bnk 256 color color bank mode
CL32KRGB 32768 colors RGB mode
[6] CL_Replace Overwrite (standard) mode (default)
CL_Shadow shadow mode
CL_Half half brightness mode
CL_Trans Translucent mode
CL_Gouraud gouraud shading mode
[7] HSSon Use high speed shrink
HSSoff Do not use high speed shrink (default)
[8] MSBon Set MSB when writing to frame buffer
MSBoff Do not set MSB when writing to frame buffer (default)

You can specify one option for each group.
Please write consecutively using the or operator "|".
Omitted groups are treated as if the default was specified.

Note
All groups cannot be abbreviated. If you want to set everything to default, please specify “No_Window” as a dummy.

Group [5] is for specifying the color mode of the texture, so if you do not use the texture, be sure to set it to the default (“CL_16Bnk” or do not specify it). If you specify any other mode here, the polygons will not be displayed.

As exceptions to group [6], “CL_Gouraud |- CL_Half” and “CL_Gouraud |- CL_Trans” can be used. Please use it when you want to use semi-bright Gouraud shading or semi-transparent Gouraud shading.
If you use Gouraud shading, you need to set “CL_Gouraud” here as well as setting the 5th parameter.
When using semi-brightness, semi-transparent, and Gouraud shading, only RGB direct mode is supported for polygons and 32768-color RGB mode for textures. Please note that other settings will not display correctly.

7-8.Dir

The seventh parameter is “Dir”. Specify whether the object is a polygon or a texture, and if it is a texture, how to flip it.

Table 7-5 Dir
macro Contents
sprNoflip Display texture normally
sprHflip Flip the texture horizontally
sprVflip Flip the texture vertically
sprHVflip Flip the texture vertically and horizontally
sprPolygon display polygons
sprPolyLine display polyline
sprLine Displays a straight line using the first two points

Note
If you are not using textures for the object, do not specify “sprHflip” or “sprVflip”.
Specify “sprLine” as 4 points like other polygons (repeatedly specify the first 2 points).

7-9.Option

The last parameter is “Option”. Other settings for polygons and textures are specified here. The following five options are supported by the current SGL (Ver 3.0).

Table 7-6 Option
macro Contents
UseLight Perform light source calculations
Use Palette Indicates that polygon colors are in palette format
UseNearClip If the 4 vertices go outside the screen specified by slWindowClipLevel, they will not be displayed.
UseDepth Calculate depth cue with parallel light source
UseGouraud Performs light source calculation using real-time Gouraud (valid only with slPutPolygonX)

Multiple options can be specified using the or operator "|".

Note
If you do not want to use options, please specify the macro “No_Option”.
If you want to perform light source calculation when the polygon color is in palette format, use “UsePalette” and “UseLight” together.

Appendix: SGL library functions that appear in this chapter

In this chapter, we explained the functions in the table below.

Table 7-7 SGL library functions introduced in this chapter
functional type function name parameters function
void slDMACopy Src,dst,cnt Block transfer using CPU DMA


BackForward
SGL User's ManualPROGRAMMER'S TUTORIAL
Copyright SEGA ENTERPRISES, LTD., 1997