ndiddy's SGL questions

I've been at this for hours and can't seem to figure it out. 1x1 backgrounds work fine but 2x2 ones seem to cause random graphical corruption onscreen. I'm using Sega's official map editor if that's an issue. Here's my main.c file (if anyone wants a full source code dump, reply saying so):
Code:
/*----------------------------------------------------------------------*/
/*    Pad Control                            */
/*----------------------------------------------------------------------*/
#include    "sgl.h"
#include    "sega_sys.h"

#include "structs.h"
#include "assetrefs.h"

#define        NBG1_CEL_ADR        ( VDP2_VRAM_A0 )
#define        NBG1_MAP_ADR        ( VDP2_VRAM_B0 )
#define        NBG1_COL_ADR        ( VDP2_COLRAM )
#define        BACK_COL_ADR        ( VDP2_VRAM_A1 + 0x1fffe )

#define NUM_SPRITES 200
SPRITE_INFO sprites[NUM_SPRITES];
const SPR_ATTR DEFAULT_ATTR = SPR_ATTRIBUTE(0,No_Palet,No_Gouraud,CL32KRGB|SPenb|ECdis,sprNoflip);
int numDispSprites = 1;

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

void handleInput(void)
{
    Uint16 data = ~Smpc_Peripheral[0].data;
    if (data & PER_DGT_KR)
        sprites[0].pos[X] += toFIXED(1.0);
    else if (data & PER_DGT_KL)
        sprites[0].pos[X] -= toFIXED(1.0);
    if (data & PER_DGT_KU)
        sprites[0].pos[Y] -= toFIXED(1.0);
    else if (data & PER_DGT_KD)
        sprites[0].pos[Y] += toFIXED(1.0);
    if (data & PER_DGT_TA)
        sprites[0].pos[S] += toFIXED(0.1);
    if (data & PER_DGT_TB)
        sprites[0].pos[S] -= toFIXED(0.1);
    if (data & PER_DGT_TL)
        sprites[0].ang += DEGtoANG(1.0);
    if (data & PER_DGT_TR)
        sprites[0].ang -= DEGtoANG(1.0);
}

void initSprites(void)
{
    int i;
    for (i = 0; i < NUM_SPRITES; i++) {
        sprites[i].pos[X] = toFIXED(192.0); //start offscreen (160 + sprite width)
        sprites[i].pos[Y] = toFIXED(0.0);
        sprites[i].pos[Z] = toFIXED(169);
        sprites[i].pos[S] = toFIXED(1.0);
        sprites[i].ang = DEGtoANG(0.0);
        // {t,(a)|(((d)>>24)&0xc0),c,g,(d)&0x0f3f}
        sprites[i].attr = DEFAULT_ATTR;
    }
}

void dispSprites(void)
{
    int i;
    for (i = 0; i < numDispSprites; i++) {
        // sprites[i].pos[X] = toFIXED((slRandom() % 320) - 160);
        // sprites[i].pos[Y] = toFIXED((slRandom() % 224) - 112);
        slDispSprite(sprites[i].pos, &sprites[i].attr, sprites[i].ang);
    }
}
void ss_main(void)
{
    slInitSystem(TV_320x224,tex_sprites,1);
    slTVOff();
    set_sprite(pic_sprites, 3, tex_sprites);
    initSprites();
  
    slColRAMMode(CRM16_1024);
    slBack1ColSet((void *)BACK_COL_ADR , 0);
  
    slCharNbg1(COL_TYPE_256, CHAR_SIZE_2x2);
    slPageNbg1((void *)NBG1_CEL_ADR, 0, PNB_1WORD|CN_12BIT);
    slPlaneNbg1(PL_SIZE_1x1);
    slMapNbg1((void *)NBG1_MAP_ADR , (void *)NBG1_MAP_ADR , (void *)NBG1_MAP_ADR , (void *)NBG1_MAP_ADR);
    //Cel2VRAM(cel_map1, (void *)NBG1_CEL_ADR, 3 * 64 * 4);
    memcpy((void *)cel_map1, (void *)NBG1_CEL_ADR, 768);
    Map2VRAM(map_map1, (void *)NBG1_MAP_ADR, 32, 32, 1, 0);
    //memcpy((void *)map_map1, (void *)NBG1_MAP_ADR, 32 * sizeof(Uint16));
    memcpy((void *)pal_map1, (void *)NBG1_COL_ADR, 256 * sizeof(Uint16));
  
    slScrPosNbg1(toFIXED(0.0), toFIXED(0.0));
    slScrAutoDisp(NBG0ON | NBG1ON);
    slTVOn();
    sprites[0].pos[X] = toFIXED(0.0);
    while(1) {
        handleInput();
        dispSprites();
        slSynch();
    }
}

And here's what I get if I run it:
QdWaYa9.png


Here's what the map it should be displaying looks like:
i095Yuv.png


Any help would be appreciated. If I set the character size to 1x1 and keep everything else the same, backgrounds do work and the garbage goes away, although obviously it only shows parts of tiles.
 
Solved the issue by moving the background to a rotating one (idk how that fixed it, it's magic i guess)
Code for anyone in the future who has a similar issue:

Code:
/*----------------------------------------------------------------------*/
/*    Pad Control                            */
/*----------------------------------------------------------------------*/
#include    "sgl.h"
#include    "sega_sys.h"

#include "structs.h"
#include "assetrefs.h"

#define        RBG0_CEL_ADR        VDP2_VRAM_A0
#define        RBG0_MAP_ADR        VDP2_VRAM_B0
#define        RBG0_COL_ADR        ( VDP2_COLRAM + 0x00200 )
#define        RBG0_PAR_ADR        ( VDP2_VRAM_A1 + 0x1fe00 )
#define        BACK_COL_ADR        ( VDP2_VRAM_A1 + 0x1fffe )

#define NUM_SPRITES 200
SPRITE_INFO sprites[NUM_SPRITES];
const SPR_ATTR DEFAULT_ATTR = SPR_ATTRIBUTE(0,No_Palet,No_Gouraud,CL32KRGB|SPenb|ECdis,sprNoflip);
int numDispSprites = 1;

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

void handleInput(void)
{
    Uint16 data = ~Smpc_Peripheral[0].data;
    if (data & PER_DGT_KR)
        sprites[0].pos[X] += toFIXED(1.0);
    else if (data & PER_DGT_KL)
        sprites[0].pos[X] -= toFIXED(1.0);
    if (data & PER_DGT_KU)
        sprites[0].pos[Y] -= toFIXED(1.0);
    else if (data & PER_DGT_KD)
        sprites[0].pos[Y] += toFIXED(1.0);
    if (data & PER_DGT_TA)
        sprites[0].pos[S] += toFIXED(0.1);
    if (data & PER_DGT_TB)
        sprites[0].pos[S] -= toFIXED(0.1);
    if (data & PER_DGT_TL)
        sprites[0].ang += DEGtoANG(1.0);
    if (data & PER_DGT_TR)
        sprites[0].ang -= DEGtoANG(1.0);
}

void initSprites(void)
{
    int i;
    for (i = 0; i < NUM_SPRITES; i++) {
        sprites[i].pos[X] = toFIXED(192.0); //start offscreen (160 + sprite width)
        sprites[i].pos[Y] = toFIXED(0.0);
        sprites[i].pos[Z] = toFIXED(169);
        sprites[i].pos[S] = toFIXED(1.0);
        sprites[i].ang = DEGtoANG(0.0);
        // {t,(a)|(((d)>>24)&0xc0),c,g,(d)&0x0f3f}
        sprites[i].attr = DEFAULT_ATTR;
    }
}

void dispSprites(void)
{
    int i;
    for (i = 0; i < numDispSprites; i++) {
        // sprites[i].pos[X] = toFIXED((slRandom() % 320) - 160);
        // sprites[i].pos[Y] = toFIXED((slRandom() % 224) - 112);
        slDispSprite(sprites[i].pos, &sprites[i].attr, sprites[i].ang);
    }
}
void ss_main(void)
{
    slInitSystem(TV_320x224,tex_sprites,1);
    slTVOff();
    set_sprite(pic_sprites, 3, tex_sprites);
    initSprites();
   
    slColRAMMode(CRM16_2048);
    slBack1ColSet((void *)BACK_COL_ADR , 0);
   
    slRparaInitSet((void *)RBG0_PAR_ADR);
    slCharRbg0(COL_TYPE_256, CHAR_SIZE_2x2);
    slPageRbg0((void *)RBG0_CEL_ADR, 0, PNB_1WORD|CN_12BIT);
    slPlaneRA(PL_SIZE_1x1);
    sl1MapRA((void *)RBG0_MAP_ADR);
    slOverRA(2);
    Cel2VRAM(cel_map1, (void *)RBG0_CEL_ADR, 3 * 64 * 4);
    //memcpy((void *)cel_map1, (void *)RBG0_CEL_ADR, 768);
    Map2VRAM(map_map1, (void *)RBG0_MAP_ADR, 32, 32, 1, 0);
    //memcpy((void *)map_map1, (void *)NBG1_MAP_ADR, 32 * sizeof(Uint16));
    memcpy((void *)pal_map1, (void *)RBG0_COL_ADR, 256 * sizeof(Uint16));
   
    slDispCenterR(toFIXED(160.0) , toFIXED(112.0));
    slLookR(toFIXED(128.0) , toFIXED(64.0));
   
    slScrAutoDisp(NBG0ON | RBG0ON);
    slTVOn();
    sprites[0].pos[X] = toFIXED(0.0);
    while(1) {
        handleInput();
        dispSprites();
        slSynch();
    }
}
 
Let's try to figure out why it doesn't display under normal backgrounds.

What does the *Debug/VDP2* Window say about the backgrounds?
 
Let's try to figure out why it doesn't display under normal backgrounds.

What does the *Debug/VDP2* Window say about the backgrounds?
Thanks for the help, but I think it's because my "memcpy" way of copying textures to VRAM didn't work as well as Sega's example code (transplanted using "CEL2VRAM" into my original code and it seems to work). If you know about SGL, I was wondering if it's possible to get semi-transparent backgrounds using it. The manual mentions semi-transparent sprites, but nothing about semi-transparent backgrounds. Also, what's the best way to get the reciprocal of a FIXED number (16.16 fixed-point)? ((1<<16)/scale)<<16 sorta works but cuts off the decimal so it's obviously not that useful (I want to do this because the background scaling parameter is the reciprocal of the scaling factor, while the sprite scaling factor is just the scaling factor so you need to take the reciprocal to scale the background along with the sprite).
 
Last edited:
So it works now with normal backgrounds?

You'll have to actually divide it. It's no different than with floats. I believe there is some division function available to you. If you know you need the reciprocal of the scaling factor.

As for transparency, you'll need multiple backgrounds, but I'm unsure what the functions in SGL would enable the hardware feature.
 
Thanks for the help, I got it working (for future reference, the division function is slDivFX). By the way, I'm having some really weird issue with my sprite handler function, where this:

Code:
void dispSprites(void)
{
    int i;
    FIXED spriteScale = slDivFX(scale, toFIXED(1.0)); //reciprocal
    FIXED spritePos[XYZS];
    for (i = 0; i < numDispSprites; i++) {
        spritePos[X] = slMulFX(sprites[i].pos[X] - screenX, spriteScale);
        spritePos[Y] = slMulFX(sprites[i].pos[Y] - screenY, spriteScale);
        slPrintFX(spritePos[X], slLocate(0,4));
        slPrintFX(spritePos[Y], slLocate(0,5));
        slPrintFX(spriteScale, slLocate(0,6));
        spritePos[S] = spriteScale;
        slDispSprite(spritePos, &sprites[i].attr, sprites[i].ang);
    }
}

works fine, but removing the slPrintFX(spriteScale, slLocate(0,6)); line makes sprites not display at all (it doesn't even send a command to VDP1). Is the compiler optimizing away the variable assignment for some reason, or is there some other issue I don't see?
 
Found the issue a while ago, turns out that adding angles calculated by Deg2Ang (e.g. angle += Deg2Ang(10)) doesn't work (my guess is that there's a rounding error or something), so now I just store the degrees instead of the SGL angle format and do the degree to angle calculation in the sprite drawing loop, which does work.
 
Found the issue a while ago, turns out that adding angles calculated by Deg2Ang (e.g. angle += Deg2Ang(10)) doesn't work (my guess is that there's a rounding error or something), so now I just store the degrees instead of the SGL angle format and do the degree to angle calculation in the sprite drawing loop, which does work.
I just noticed that in your first post you used a 1024 CRAM mode instead of 2048 like in the other post.
I think with the 1024 mode you need to store the palette in a special manner, like have the upper 2 k mirror the other 2 k of color data, but I never tried it so I could be wrong.
 
Other question: is there a way to set priorities for specific sprites? I see the "slPrioritySprX" functions in SL_DEF.H but I don't know how to determine which "groups" the sprites go into, unless it literally means sprites 0-7.
 
There are 16 sprite types, and each has a set number of bits designated for priority index (into the sprite registers) and other features (in CMDCOLR). The sprite priority registers 0 to 7 are different priorities you can set to.

For example, you have sprite type 0, and you set sprite register 0 to 3, and sprite register 1 to 7. By default, VDP1 will set the priority to all your primitives to 3. If in another command table, you set the right bits to index to sprite register 1, that command table will have a priority of 7.

Confusing? Needlessly complicated? Flexible and useful? Yes, yes, no.
 
There are 16 sprite types, and each has a set number of bits designated for priority index (into the sprite registers) and other features (in CMDCOLR). The sprite priority registers 0 to 7 are different priorities you can set to.

For example, you have sprite type 0, and you set sprite register 0 to 3, and sprite register 1 to 7. By default, VDP1 will set the priority to all your primitives to 3. If in another command table, you set the right bits to index to sprite register 1, that command table will have a priority of 7.

Confusing? Needlessly complicated? Flexible and useful? Yes, yes, no.
Essentially what I'm trying to do is use up a background layer for a transparent character (the game's running at 320x224 so it would be obvious if I simply used a mesh on the sprite), but I also want to animate certain features on that character using sprites. I know it's possible to do this with the Saturn hardware, but I'd like to keep using SGL (I'm far enough along that porting the game over to SBL or something would be a pain). With SGL, you seem to only have one command table, and add to it by giving the slDispSprite function the sprite position, SPR_ATTR structure, and angle. It looks like you can use the sprite's Z coordinate for some sorting within the sprite layer, but I don't know if you can put sprites above other layers using it.
 
Essentially what I'm trying to do is use up a background layer for a transparent character (the game's running at 320x224 so it would be obvious if I simply used a mesh on the sprite), but I also want to animate certain features on that character using sprites. I know it's possible to do this with the Saturn hardware, but I'd like to keep using SGL (I'm far enough along that porting the game over to SBL or something would be a pain). With SGL, you seem to only have one command table, and add to it by giving the slDispSprite function the sprite position, SPR_ATTR structure, and angle. It looks like you can use the sprite's Z coordinate for some sorting within the sprite layer, but I don't know if you can put sprites above other layers using it.
it's in your attribute color that you can set the priority.
Make sure you are using color bank sprites.

Try something (pseudo code) such as :

Sint32 v = dist >> 24; //Just one example, if you distance is in fixed point format.
if (v>7) v=7;
else if (v<0) v=0;
for (i=0; i<curPol->nbPolygon; ++i)
{ curPol->attbl.colno &= (~(7<<11));
curPol->attbl.colno |= (v<<11);
}

Edit : that modifies your color calculation ratio. Depending on your sprite type, just flip the priority bit. Say bit 14 then you could just flip it so that your sprite becomes sprite 1, which is registered as having priority 3. If your color calculation condition is <= 4, then your will have transparency.
 
Last edited:
Back
Top