Japanese
SGL User's ManualSupplementary manual
SGL REFERENCE/SGL Supplementary Manual

■About event registration and execution

The execution list will be cleared when you execute slInitEvent (), so you must register the events you want to execute in the list.
Use slSetEvent () or slSetEventNext () to register events.

    void *eventtbl[] = {
        init_camera ,
        init_player1 ,
        init_player2 ,
        init_enemyctrl
    };

    void InitGame(){
        void **evrdptr;
        EVENT *evptr;
        int cnt;

        slInitEvent (); /* Initialize event management variables */
        evrptr = eventtbl;
        for(cnt = sizeof(eventtbl) / sizeof(void *) ; cnt--> 0 ;){
            evptr = slSetEvent (*evrptr++);
        }
        slSetSprTVMode ( TV_320x224 );
    }

    void Game(){
        slExecuteEvent (); /* Execute event */
        slSynch (); /* Polygon data output and video display synchronization */
    }

The event is executed each time you call the slExecuteEvent () function.
Each event is basically executed in the order in which it is registered.
The first registered event is defined in the system's EventTop variable, and from this point, the event pointer is defined in the EventNow variable and the processing function for each event is called. Define the processing function in the following format.

  void function( EVENT *evptr){
        ... /* Event processing */
  }

  When writing in assembly language, use _function:
        ... ; Event processing ; Event pointer is set in r4 register rts
        nop

When an event ends, we put the next pointer in the event's structure into the EventNow variable, and similarly execute the processing function. These are repeated until the next pointer is NULL.

  EventTop: ----+
                 |
                 |   +------------------+
                 +-->| *work = NULL     |
                     | *before = NULL   |
                +--  | *next            |
                |    | *exad()          |
                |    |  user[]          |
                |    +------------------+
                |
                |    +------------------+       +------------------+
                +--> | *work            |  ---> | *next            | -+
                     | *before          |       |                  |  |
                +--  | *next            |       |                  |  |
                |    | *exad()          |       +------------------+  |
                |    |  user[]          |   +-------------------------+
                |    +------------------+   |
                |                           |   +------------------+
                |    +------------------+   +-> | *next = NULL     | 
  EventLast: ---+--> | *work            |       |                  |
                     | *before          |       |                  |
                     | *next = NULL     |       +------------------+
                     | *exad()          |
                     |  user[]          |
                     +------------------+

The EventLast variable defines a pointer to the last event to be executed and is used when adding events.
For a user to use RAM, define a struct for the user and cast the event RAM's user[] to that struct.

example)
    typedef struct rob{
        FIXED posX , posY , posZ ;
        ANGLE angX , angY , angZ ;
        PDATA *pat;
    } ROBOT ; /* This structure must not exceed 112 bytes */

    void rob_control( EVENT *evptr){
        ROBOT *rbptr ;

        rbptr = (ROBOT *)evptr-> user ;
        rbptr-> posX = to_fixed(0);
        rbptr-> posY = to_fixed(0);
        rbptr-> posZ = to_fixed(0);
        rbptr-> pat = &PD_Robot;
    }

Workpieces can be linked and held using a list of pointers.
When moving multiple characters in one event, use work to secure RAM.

    typedef struct road{
        struct road *next;
        FIXED posX , posY , posZ ;
        PDATA *pat;
    }ROAD;

    typedef struct rdat{
        Sint16 px , py , pz ;
        Uint16 pn ;
    } ROAD_DAT ;

    ROAD_DAT roadtbl[] = {
        { 0 , 0 , 0 , PN_ROAD} ,
        { 0 , 0 , 100 , PN_ROAD} ,
        { 0 , 0 , 200 , PN_ROAD}
    };

    void InitRoadControl( EVENT *evptr){
        WORK *wkptr;
        ROAD *rdptr;
        ROAD_DAT *rdtptr;
        int cnt;

        rdptr = (ROAD *)evptr ;
        rdtptr = roadtbl;
        for(cnt = sizeof(roadtbl) / sizeof(ROAD_DAT) ; cnt--> 0 ;){
            if((wkptr = slGetWork ()) == NULL ){
                break ;
            }
            rdptr-> next = (ROAD *)wkptr ; /* The first pointer is */
                                                /* Enter work on event */
            rdptr = (ROAD *)wkptr ;
            rdptr-> posX = rdtptr-> px<< 16 ; /* position */
            rdptr-> posY = rdtptr-> py>> 16;
            rdptr-> posZ = rdtptr-> pz>> 16;
            rdptr-> pat = pattbl[rdptr-> pn] ; /* Pattern data */
            rdtptr++;
        }
        rdptr-> next = NULL ; /* End mark */
        evptr-> exad = (void *)RoadControl;
    }

■Precautions when changing the clock

◆RAM guaranteed at clock change

◆RAM not guaranteed during clock change

Therefore, it is necessary to reinitialize memory which is not guaranteed after a clock change.
In particular, if there is data in LOW-RAM or SOUND RAM before the clock change, the validity of that data is not guaranteed, so be sure to reload the data.
From SGL 3.10, if a clock change occurs in slInitSystem , a dummy empty loop will be registered to keep the MC68000 running, so be sure to reload the sound driver after the clock change.
Also, slInitSystem returns each status and register to their initial state, so please reinitialize each parameter in the user program.

■About initializing the BSS area and system variable area

When programming in C language, an area called BSS is always reserved. When using an uninitialized variable in a program, a part of this memory space called BSS is allocated for that variable.
Normally, when defining an uninitialized variable in a program, the prerequisite is to assign some value to it later, but in very rare cases, it may be used as is. (This kind of operation is usually a programming error) In that case, the operation is often performed assuming 0. If an undefined value is written in this area, the behavior will become undefined if you use the uninitialized variable as is, creating a breeding ground for bugs. Therefore, in the SGL sample program, the program link saturn/sample/common/cinit.c is used to clear the BSS area to 0.
This is why the SGL sample starts with ss_main, and the main function performs these initializations.
The same is true for the "system variable area" used within SGL; in this case, depending on the BOOT ROM, a stack may be set in a location that overlaps with this area, making the contents undefined. Some people may think that everything is initialized by the SGL function slInitSystem , but in reality, not all areas are initialized by this function, and in some cases, the SGL function There is also a possibility that an undefined value may be referenced.
Since this "system variable area" is cleared to 0 in "cinit.c" above, the above two problems can be resolved by linking this file. If you do not link this file in your program, be sure to initialize these files.
Furthermore, this cinit.c had a bug until recently, and the "system variable area" could not be initialized, so your cinit.c

        /* 3.SGL System Variable Clear */
        for( dst = (Uint8 *)SystemWork, i = 0;i < SystemSize; i++) {
                *dst = 0;
        }

If so, please change it as shown below.

        /* 3.SGL System Variable Clear */
        for( dst = (Uint8 *)SystemWork, i = 0;i < SystemSize; i++) {
                *dst++ = 0;
                /* ^^ */
        }

■ About blanking interrupt processing

The blanking start interrupt transfers scroll data, executes the DMA transfer table created by slTransferEntry , and executes the user function registered by slIntFunction[a]. Of these, scroll data transfer can be prohibited using the PauseFlag variable.

PauseFlag is a Uint8 type flag variable, and if it is other than 0, it works to prohibit the above transfer.

The blanking end interrupt performs mode switching such as erase write and frame change of the sprite frame buffer, DMA transfer of sprite data, fetching of peripheral data, and subtraction of the interrupt wait counter. Of these, parts related to sprites can be prohibited using the PauseFlag above.

■ About FRT used in SGL

SGL uses FRT (free running timer) to issue commands to SMPC. The FRT frequency division ratio at this time is 128, and changing this on the user side is prohibited.
This is because, in order to prevent SMPC requests from being made during the 300μs period after V-Blank In when access to the SMPC is prohibited, a wait for that time is applied to the FRT.

■ About calculation libraries and system libraries

The numbers used in the library are based on the use of:

Fixed-point data such as position, trigonometric functions, etc.:
Upper 16 bits are integer part, lower 16 bits are decimal part, total 32 bits (signed) Type name FIXED

example)
When representing 16.5
0x0010_8000
  ━━━━ ━━━━
   ↑     ↑  
   │     └──Decimal part
   └────────Integer part

The coordinates are the X-axis in the left-right direction (plus means to the right), the Y-axis in the up-down direction (plus means down), and the Z-axis in the depth direction (plus means back).

Angle: 360 degrees expressed in 16 bits
Type name ANGLE

example)
90.0゜ : 0x4000
45.0゜ : 0x2000
22.5゜ : 0x1000
11.25°: 0x0800

If you create a rotation matrix, the positive direction of the angle will be a right rotation about the axis.

queue :
FIXED values are used. It is a 3 x 4 matrix, and its arrangement in memory is as follows.
    M00 , M01 , M02 ,
    M10 , M11 , M12 ,
    M20 , M21 , M22 ,
    M30 , M31 , M32

■Peripheral library overview

◆Now you can understand everything! Peripheral control sample program
  void main()
  {
    slInitSystem ( TV_320x224 , NULL , 1 );
    {
      slSetLanguage ( SMPC_JAPAN );
      slSetSoundOutput ( SMPC_SOUND_STEREO );
      ( void ) slSetSmpcMemory ();
    }

    {
      SmpcDateTime *dt = &( Smpc_Status -> rtc );

      dt-> year = 0x1999;
      dt-> month = SMPC_FRI | SMPC_DEC ;
      dt-> date = 0x31;
      dt-> hour = 0x23;
      dt-> minute = 0x59;
      dt-> second = 0x59;
      ( void ) slSetDateTime ();
    }

    ( void ) slResetDisable ();

    while( TRUE ) {
      if( slCheckReset () == SMPC_RES_ON ) {
      ( void ) slClearReset ();
      break;
    }

    if( Per_Connect1 ) {
      PerDigital *pad;

      pad = Smpc_Peripheral + 0;
      if( !( pad-> data & PER_DGT_ST ) ) break;
    }
    slSynch ();
  }

  ( void ) slResetEnable ();
  ( void ) slIntBackCancel ();

  while( TRUE ) slSynch ();
}

■Prohibited moves when using the library,
Example of execution failure due to function call procedure

☆Calls from slave SH2 are prohibited.
Since the internal work area is not reserved for the cache-through area, the operation will be undefined.
In particular, exclusive control is not performed properly, causing problems such as SMPC deadlock.

☆ After executing " slGetPeripheral " and " slGetStatus ", if the following function is called and an Intoback command is being executed, the execution will fail.
This occurs because the SMPC command request in wait mode assumes that the command cache is not used.
      slNMIRequestWait
      slResetDisableWait
      slResetEnableWait
      slSetDateTimeWait
      slSetSmpcMemoryWait

To avoid the above execution failure, call " slIntBackCancel " and issue the command in the next frame.

The following function will fail even if the intoback command is not being executed.
This is because SMPC prohibits issuing the Intoback command in any state other than the initial setting state.

      slSetPortDir1 ,2
      slSetPortExt1 ,2
      slSetPortSelect1 ,2

To avoid the above execution failure, you can call " slIntBackCancel ".

  ◆ After executing " slIntBackCancel ", if the following conditions are set,
     Calling " slGetPeripheral " fails.

     For ports set to SMPC control mode with " slSetPortSelect1 ,2", output settings were made with " slSetPortDir1 ,2".
     External latch input was enabled with " slSetPortExt1,2 ".

In any of the above cases, or if both are set.

This is because SMPC prohibits issuing the Intoback command in any state other than the initial setting state.
Set both ports 1 and 2 to SH2 direct mode with " slSetPortSelect1 ,2".

This is because SMPC prohibits issuing an intoback command that returns only peripheral data when both port selects are in SH2 direct mode, regardless of port input/output settings.

  ◆ After executing " slIntBackCancel ", if the following conditions are set,
     Calling " slGetStatus " fails.

     For ports set to SMPC control mode with " slSetPortSelect1 ,2", output settings were made with " slSetPortDir1 ,2".
     External latch input was enabled with " slSetPortExt1,2 ".

In any of the above cases, or if both are set.
This is because SMPC prohibits issuing the Intoback command in any state other than the initial setting state.

◆ Limit performance
☆ Maximum number of caching commands... 31
☆ Maximum peripheral data size... 15 bytes * 30 ports

Supports data acquisition in 15-byte mode from peripheral devices released as of April 1, 1995 and peripheral devices released in the future.

Data can be acquired in 255-byte mode by registering user-defined buffer addresses to the system variables " Smpc_Status " and " Smpc_Peripheral ".
However, library support is required to perform device-specific data conversion operations.

■About issuing sound function commands and success or failure.

The sound driver has 8 command buffers.
Each time a command is requested to be issued, SGL's sound functions first transfer it to the library's internal buffer instead of sending it to the driver's buffer.
When the slSndFlush function or slSynch function is called, it is transferred to the command buffer using CPU-DMA.
Additionally, timing flag handshaking is used to communicate with the sound driver, and before DMA transfer of buffer data, the data is transferred after waiting until the timing flag of the sound driver becomes 0.
Generally, when a sound function does not succeed, it occurs when there are insufficient pronunciation management numbers or PCM channels.

■ About polygon data

The polygon data used by slPutPolygon () has the following format.

    .data.l        point_tbl     ; Table of vertex coordinates
    .data.l        NbPoint       ; Number of vertices to calculate
    .data.l        polygon_tbl   ; Table of normal vectors and vertex numbers for each polygon
    .data.l        NbPolygon     ; Number of polygons to calculate
    .data.l        attribute_tbl ; Table of attributes for each polygon

 point_tbl:
    .data.l        X,Y,Z                ; Coordinate data of vertex number 0
    .data.l        X,Y,Z                ; Coordinate data of vertex number 1
        ...
    .data.l        X,Y,Z                ; Coordinate data of vertex number NbPoint - 1

When creating a table in C language, the POINT type is declared and the above data table can be created by using the POStoFIXED macro.

example)
        static POINT point_CUBE[] = {
            POStoFIXED(-80,-80,-80),
            POStoFIXED( 80,-80,-80),
            POStoFIXED( 80, 80,-80),
            POStoFIXED(-80, 80,-80),

            POStoFIXED( 80,-80, 80),
            POStoFIXED(-80,-80, 80),
            POStoFIXED(-80, 80, 80),
            POStoFIXED( 80, 80, 80)
        } ;

 polygon_tbl:
    .data.l        Nx,Ny,Nz     ; Normal vector of polygon number 0
    .data.w        P0,P1,P2,P3  ; Vertex number used for polygon number 0
        (For triangular polygons, P2 and P3 will be the same number)
        ...
    .data.l        Nx,Ny,Nz     ; Normal vector of polygon number NbPolygon - 1
    .data.w        P0,P1,P2,P3  ; Number of the vertex used in polygon number NbPolygon - 1

When creating a table in C language, the POLYGON type is declared and the above data table can be created by using the POStoFIXED macro.

example)
        static POLYGON polygon_CUBE[] = {
            {POStoFIXED( 0 , 0 ,-1) , { 0 , 1 , 2 , 3}} ,
                |__ |__
            {POStoFIXED( 1 , 0 , 0) , { 1 , 4 , 7 , 2}} ,
            {POStoFIXED(-1 , 0 , 0) , { 5 , 0 , 3 , 6}} ,
            {POStoFIXED( 0 ,-1 , 0) , { 4 , 1 , 0 , 5}} ,
            {POStoFIXED( 0 , 1 , 0) , { 2 , 7 , 6 , 3}} ,
            {POStoFIXED( 0 , 0 , 1) , { 4 , 5 , 6 , 7}} ,
        } ;

 attribute_tbl:
    .data.b        RevCheck     ; Specify either the flag Single_Plane or Dual_Plane
                                ; to indicate whether to display the face that has become the back side due to front/back determination.
    .data.b        SortMode     ; Declare the calculation method for the position used as the sorting standard and the use of optional
                                ; functions. One of SORT_CEN, SORT_MIN, SORT_MAX, or SORT_BFR.
        SORT_CEN : Uses the average of the four specified Z positions as the sorting criterion
        SORT_MIN : Use the smallest Z position among 4 points
        SORT_MAX : Use the largest Z position among 4 points
        SORT_BFR : Use the Z position of the most recently displayed polygon
                                ; The polygon will always be displayed in front of the previous polygon. Specify the following options in addition to
                                ; these. Specify multiple UseTexture, UseLight, UseClip options. can do.
        UseTexture : Specify this when using a texture (deformed sprite).
        UseLight : The color of the polygon is offset by the inner product of the light source
                                ; vector and the normal vector to express brightness and darkness. Cannot be used at the same time as UseTexture.
        UseClip : When using large polygons, use this when the display position overflows and
                                ; cannot be displayed correctly.
    .data.w        TextNum      ; When using a texture, use it as a character registration number.
    .data.w        DispMode  ; Specifies the polygon display mode. The display modes that can be specified are as follows:
        MSBon : Set only the most significant bit to 1 when writing to the frame buffer. (Shadows to sprites usually use this)
        HSSon : High speed shrink enabled
        HSSoff: High speed shrink disabled (default)
        Window_In : Display inside the specified window.
        Window_Out : Display outside the window.
        No_Window : (default) Displays without being affected by the window.
        MESHon : Display as a mesh.
        MESHoff : (default) Normal display.
        ECdis : Disable end code when using textures.
        ECenb : (default) Enable end code when using textures.
        SPdis : When using textures, disable spaces (display in palette 0 colors).
                                ; However, if the data written to the frame buffer becomes 0000, it will not be displayed, so please
                                ; adjust the priority etc. values so that it does not become 0000.
        SPenb : (default) Enable spacing when using textures.

        CL16Bnk  : (default) Texture color mode is 16-color color bank method
                  にします。
        CL16Look : 16-color lookup table method for texture color mode
                   にします。
        CL64Bnk  : Set the texture color mode to 64-color color bank method.
        CL128Bnk : Set the texture color mode to 128-color color bank method.
        CL256Bnk : Set the texture color mode to 256-color color bank method.
        CL32KRGB : Set the texture color mode to RGB with 32000 colors.

        CL_Replace : (default) Set to rewrite mode.
        CL_Trans   : Display semi-transparent.
        CL_Half    : Displays at half brightness.
        CL_Shadow  : Displays shadow.
        CL_Gouraud : Specifies Gouraud shading.

        Specify one display mode for each group.

    .data.w        Color         ; Specify the display color. If it is affected by the light source, or if you specify a display mode
                                 ; other than CL_Replace, it must be in RGB mode. Also, when using a texture and
                                 ; in CL32KRGB mode, the specification here will be ignored.

    .data.w        GouraudTable  ; Specifies the Gouraud shading table. If CL_Gouraud is specified, it specifies the offset
                                 ; position of the Gouraud shading table. Specify the offset position by setting SpriteVRAM (0x25c00000) to 0 and
                                 ; incrementing it by 1 every 8 bytes. For example, if you have data at 0x25c12000:
                                 ;   ( 0x25c12000 - 0x25c00000 ) / 0x08 = 0x2400

    .data.w        Function      ; Specifies the sprite display function. Specifies whether to display as polygons, textures, or
                                 ; polylines. To specify, choose one from the following six options:
        sprNoflip  : Show texture.
        sprHflip   : Displays the texture by flipping it horizontally.
        sprVflip   : Displays the texture by flipping it vertically.
        sprHVflip  : Displays the texture flipped both vertically and horizontally.
        sprPolygon : Display as polygons.
        sprPolyLine: Displays polylines (polygon outlines only).

    When creating a table in C language, the ATTR type is declared and the above data table can be created by using
    the ATTRIBUTE macro.
  example)
        static ATTR attr_CUBE[] = {
            ATTRIBUTE( Single_Plane, SORT_MIN, No_Texture, CD_MediumGreen,
                      No_Gouraud, Window_In, sprPolygon, UseLight ),
            ATTRIBUTE( Single_Plane, SORT_MIN, No_Texture, CD_MediumBlue,
                      No_Gouraud, Window_In, sprPolygon, UseLight ),
            ATTRIBUTE( Single_Plane, SORT_MIN, No_Texture, CD_MediumMagenta,
                      No_Gouraud, Window_In, sprPolygon, UseLight ),
            ATTRIBUTE( Single_Plane, SORT_MIN, No_Texture, CD_MediumWhite,
                      No_Gouraud, Window_In, sprPolygon, UseLight ),
            ATTRIBUTE( Single_Plane, SORT_MIN, No_Texture, CD_MediumYellow,
                      No_Gouraud, Window_In, sprPolygon, UseLight ),
            ATTRIBUTE( Single_Plane, SORT_MIN, No_Texture, CD_MediumRed,
                      No_Gouraud, Window_In, sprPolygon, UseLight )
        };

■ About attributes for sprite display functions

The attribute table used by slPutSprite () and slDispSprite () is almost the same as the one for polygons above, but the first two pieces of data are missing.
If you create this table in C, the SPR_ATTR type is declared and you can use the SPR_ATTRIBUTE macro.

example)
        SPR_ATTR attr_AM2Logo = {
            SPR_ATTRIBUTE (PN_AM2_Logo,CL_AM2_Logo, No_Gouraud , Window_In | ECdis ,
                sprNoflip | _ZmCB )
        };

_ZmCB specifies which position of the sprite the position points to, and the following nine are defined.
     _ZmLT      _ZmCT        _ZmRT
           +-------+-------+
           |       |       |
     _ZmLC +----_ZmCC------+ _ZmRC
           |       |       |
           +-------+-------+
     _ZmLB      _ZmCB        _ZmRB

■ Sprite display sample

 #define        CGtop                 0x10000
 #define        TEXTBL(hs,vs,cga)     {hs , vs , (cga)>>3 , ((hs)&0x1f8)>>5|(vs)}
 #define        AdjCG(cga,hs,vs,col)  ((cga + (((hs)*(vs)*4)>>(col)) + 0x1f) & 0x7ffe0)
 #define        PICTBL(txno,cmod,cga) {txno , cmod , cga}
 #define        CL_Triangle           0x00

 static const Uint16 triangle[] = {
   0x0000,0x0001,0x1000,0x0000,        /* Sprite character data */
   0x0000,0x0012,0x2100,0x0000,
   0x0000,0x0123,0x3210,0x0000,
   0x0000,0x1234,0x4321,0x0000,
   0x0001,0x2344,0x4432,0x1000,
   0x0012,0x3333,0x3333,0x2100,
   0x0122,0x2222,0x2222,0x2210,
   0x1111,0x1111,0x1111,0x1111
 };

 enum patn {
   PN_Triangle,                        /* sprite pattern number       */
   Max_Texture,                        /* Total number of patterns    */
   Max_Picture = Max_Texture           /* Total number of characters  */
 };

 enum cga {                                /* character address */
   CG_Triangle = CGtop,
   CG_Next = AdjCG( CG_Triangle, 16, 8, COL_16 )
 };

 TEXTURE form_tbl[] = {         /* pattern size data */
   TEXTBL( 16, 8, CG_Triangle )
 };

 PICTURE pic_tbl[] = {                          /* character definition table */
   PICTBL( PN_Triangle, COL_16, triangle )
 };

 static const Sint16 Triangle_Color[] = {                   /* color data */
                    RGB( 0, 0,31), RGB( 0, 0, 29 ), RGB( 0, 0, 27 ),
   RGB( 0, 0, 25 ), RGB( 0, 0,23), RGB( 0, 0, 21 ), RGB( 0, 0, 19 ),
   RGB( 0, 0, 17 ), RGB( 0, 0,15), RGB( 0, 0, 13 ), RGB( 0, 0, 11 ),
   RGB( 0, 0, 9  ), RGB( 0, 0,7),  RGB( 0, 0, 5 ),  RGB( 0, 0, 3 )
 };

 typedef struct{                        /* Color definition structure */
   Sint16 *src;
   void   *dst;
   Sint16  size;
 } COLMAP;

 static const COLMAP ctrns_list[] = {  /* color definition table */
   { Triangle_Color,
     ( void* )( VDP2_COLRAM + ( CL_Triangle + 1 ) * 2 ),
     sizeof( Triangle_Color )
   }
 };

 extern TEXTURE * FormTbl ;

 /*                                                */
 /*  Character data transfer                       */
 /*                                                */

 void SetTexture( PICTURE *pcptr, Uint32 NbPicture ) {
   TEXTURE *txptr;

   for( ; NbPicture-- > 0 ; pcptr++ ) {
     txptr = FormTbl + pcptr->texno ;
     slDMACopy( pcptr->pcsrc,
                ( void * )( SpriteVRAM + ( ( txptr->CGadr ) >> 3 ) ),
                ( txptr->Hsize * txptr->Vsize * 4 ) >> ( pcptr->cmode ) );
   }
 }

 /*                                                */
 /*  Color data transfer                           */
 /*                                                */

 void SetColor(){
   COLMAP      *cmptr ;
   Sint16       cnt ;

   slTVOff() ;
   cmptr= ctrns_list ;
   for ( cnt = sizeof( ctrns_list ) / sizeof( COLMAP ) ; cnt-- > 0 ; cmptr++ ){
    slDMACopy( cmptr->src, cmptr->dst, cmptr->size );
   }
   slTVOn();
 }

 /*  Sample character display position */
   FIXED tpos[] = { toFIXED(1.0), toFIXED(2.0), toFIXED(2.0), toFIXED(4.0)};
 /*                 |             |             |             |_ Display scale (specify toFIXED(ORIGINAL) for same size) */
 /*              X position     Y position    Y position     */

 /*  sample character data */
   SPR_ATTR tattr = SPR_ATTRIBUTE(PN_Triangle,CL_Triangle,No_Gouraud,CL16Bnk,sprNoflip|_ZmCC);
 /*                               |           |           |          |       |         |__ Rotation center position */
 /*                               |           |           |          |       |__ No character reversal */
 /*                               |           |           |          |__ 16 colors color bank mode  */
 /*                               |           |           |___ Do not use Gouraud shading */
 /*                      pattern number   color bank number */

 main() {
   ANGLE        ang = DEGtoANG (0.0);

   *( Uint32 * )( 0x06002500 ) = ( Uint32 )( 0x060007f0 );
   /* Apparently, during a clock change, the 68K for sound reads the switch data and prepares the data at the address set here,
      but it doesn't seem to be working properly, so for now I'll put an address with unpressed data 0xFFFF. */

   slInitSystem( TV_320x224, form_tbl, 1 ); /* System initialization */
   SetTexture( pic_tbl, Max_Picture );      /* Set of character data */
   SetColor();                              /* Set of color data */
   while( -1 ) {
     slDispSprite( tpos, &tattr, ang );     /* Registering sprites */
     ang += DEGtoANG ( 3.0 );
     slSynch();                             /* Sprite output with synchronization to screen display */
   }
 }

■Real-time Gouro usage procedure

The following four processes are required to realize real-time Gouraud.

(1) Add the following three to the attribute table
  1. Specify " CL_Gouraud " for MODE.
  2. Specify the storage location of the glow table in GOURAUD.
  3. Specify " UseGouraud " in OPTION.
example
     ATTRIBUTE( Single_Plane , SORT_CEN , 0, 0xffa0, 0xe000,
            CL16Look | MESHoff | CL_Gouraud , sprNoflip , UseGouraud )

(2) Specifying normal vector
Specify the normal vector of each vertex and the polygon model data table called " XPDATA "
Example>
         VECTOR gr_point[] = { /* Vertex normal vector data */
           toFIXED (-0.873), toFIXED ( 0.436), toFIXED ( 0.217),
           toFIXED (-0.873), toFIXED (-0.436), toFIXED (0.217),
                                :
                                :
         };
         XPDATA PD_BOX = {                            /* Model table specification */
           point_BOX,                                 /* Vertex position data table */
           sizeof( point_BOX ) / sizeof( POINT ),     /* Number of vertices */
           polygon_BOX,                               /* Polygon definition table */
           sizeof( polygon_BOX ) /sizeof( POLYGON ),  /* Number of polygons */
           attribute_BOX2,                            /* Polygon attribute table */
           gr_point                                   /* Vertex normal vector data */
         };

(3) Initialization of real-time Gouraud program
(a) Specify the position and size of the Gouraud table to be used
example
       slInitGouraud ( ( GOURAUDTBL * ) gr_tab, ( Uint32 )300, 0xe000, addr );

(b) Register Gouraud program in V blank
example
       slIntFunction ( slGouraudTblCopy );

(4) Specifying light source vector
example
         FIXED light[ XYZ ];
         light[ X ] = toFIXED ( 1.0 );
         light[ Y ] = toFIXED ( 0.0 );
         light[ Z ] = toFIXED ( 0.0 );
         slPutPolygonX ( &PD_BOXx, ( FIXED * )light );

(5) Actual program usage example
example
 static GOURAUDTBL gr_tab[300];

 void ss_main( void )
 {
   FIXED light[ XYZ ];
          :
   /* Initialize real-time glow program */
   slInitGouraud ( ( GOURAUDTBL * ) gr_tab, ( Uint32 )300, 0xe000, addr );
   slGouraudTblCopy ();
   slSynch ();
               :
   light[ X ] = toFIXED ( 1.0 );
   light[ Y ] = toFIXED ( 0.0 );
   light[ Z ] = toFIXED ( 0.0 );
   while( 1 )
   {
           :
     slPushMatrix ();
     {
        :
       /**/
       slPutPolygonX ( &PD_BOX, ( FIXED * )light );
     }
     slPopMatrix ();
     slSynch ();
   }
 }

■Near clipping

If you specify " UseNearClip " in the OPTION of the attribute table, near clipping processing will be performed. " UseClip " has been replaced by " UseNearClip " since Ver3.0 due to the addition of the same function.

example
  ATTRIBUTE ( Single_Plane , SORT_CEN , 1, No_Palet , No_Gouraud , 
              CL32KRGB | MESHoff , sprNoflip , UseNearClip );

■Differences between SGL Ver2.1x and SGL Ver3.00

(1) Change of light source calculation method for flat shading
The light source calculation method for flat shading has been changed as follows.
Light source calculation method up to Ver2.1x>
Angle between light source and surface →0------45------90-----135-----180
Gouraud table                          →31-----16-------0-------0-------0
Light source calculation method from Ver3.0>
Angle between light source and surface →0------45------90-----135-----180
Gouraud table                          →31-----24------16-------8-------0

(2) Changing the size of the coloring data table due to the influence of the light source
By adding a function to light source processing, the size of the color data table (CLOfsfBuf) area has been increased.

32×32 (0x400) to 32×32×3 (0xC00)

It has been changed to.

Therefore, change sglarea.o in the saturn/sgl/lib directory where the initial value was set, and change the user customization.

saturn\sgl\sample\workarea

Files such as workarea.c in the directory have also been changed in the calculation part. Be sure to change this when migrating from SGL Ver2.1x.

(3) Delete UseClip option
The attribute option UseClip has been replaced with UseNearClip due to the addition of functions in SGL Ver3.0.
SGL User's ManualSupplementary manual
Copyright SEGA ENTERPRISES, LTD., 1997