• Rise from your gwave!

How to get 2x2 char sized tile backgrounds working under SGL?

Discussion in 'Saturn Dev' started by ndiddy, Jun 11, 2018.

  1. ndiddy

    ndiddy New Member

    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:
    [​IMG]

    Here's what the map it should be displaying looks like:
    [​IMG]

    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.
     
  2. ndiddy

    ndiddy New Member

    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();
        }
    }
    
    
     
  3. mrkotfw

    mrkotfw New Member

    Let's try to figure out why it doesn't display under normal backgrounds.

    What does the *Debug/VDP2* Window say about the backgrounds?
     
  4. ndiddy

    ndiddy New Member

    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: Jun 12, 2018
  5. mrkotfw

    mrkotfw New Member

    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.
     
  6. ndiddy

    ndiddy New Member

    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?
     

Share This Page