Beginnings of sprite support. gsoc2008_nds
authorDarren Alton <dalton@stevens.edu>
Sat, 16 Aug 2008 12:08:12 +0000
branchgsoc2008_nds
changeset 2693bae97b6ac32b
parent 2692 cd8978f47849
child 2694 c1c7cb1b5a47
Beginnings of sprite support.
src/video/nds/SDL_ndsrender.c
     1.1 --- a/src/video/nds/SDL_ndsrender.c	Sat Aug 16 11:16:08 2008 +0000
     1.2 +++ b/src/video/nds/SDL_ndsrender.c	Sat Aug 16 12:08:12 2008 +0000
     1.3 @@ -42,10 +42,10 @@
     1.4  #define SPRITE_ANGLE_MASK 0x01FF
     1.5  
     1.6  void
     1.7 -NDS_OAM_Update(tOAM *oam)
     1.8 +NDS_OAM_Update(tOAM *oam, int sub)
     1.9  {
    1.10      DC_FlushAll();
    1.11 -    dmaCopyHalfWords(SPRITE_DMA_CHANNEL, oam->spriteBuffer, OAM,
    1.12 +    dmaCopyHalfWords(SPRITE_DMA_CHANNEL, oam->spriteBuffer, sub?OAM_SUB:OAM,
    1.13                       SPRITE_COUNT * sizeof(SpriteEntry));
    1.14  }
    1.15  
    1.16 @@ -62,7 +62,7 @@
    1.17  }
    1.18  
    1.19  void
    1.20 -NDS_OAM_Init(tOAM *oam)
    1.21 +NDS_OAM_Init(tOAM *oam, int sub)
    1.22  {
    1.23      int i;
    1.24      for(i = 0; i < SPRITE_COUNT; i++) {
    1.25 @@ -74,7 +74,7 @@
    1.26          NDS_OAM_RotateSprite(&(oam->matrixBuffer[i]), 0);
    1.27      }
    1.28      swiWaitForVBlank();
    1.29 -    NDS_OAM_Update(oam);
    1.30 +    NDS_OAM_Update(oam, sub);
    1.31  }
    1.32  
    1.33  void
    1.34 @@ -173,7 +173,7 @@
    1.35  typedef struct
    1.36  {
    1.37      enum { NDSTX_BG, NDSTX_SPR } type; /* represented in a bg or sprite. */
    1.38 -    int hw_index; /* sprite: index in the OAM.  bg: 2 or 3. */
    1.39 +    int hw_index; /* sprite: index in the OAM. /  bg: 2 or 3. */
    1.40      struct
    1.41      {
    1.42          int hdx, hdy, vdx, vdy; /* affine transformation, used for scaling. */
    1.43 @@ -209,6 +209,11 @@
    1.44          case SDL_PIXELFORMAT_BGR555:
    1.45              /* okay */
    1.46              break;
    1.47 +        case SDL_PIXELFORMAT_RGB555:
    1.48 +        case SDL_PIXELFORMAT_RGB565:
    1.49 +        case SDL_PIXELFORMAT_ARGB1555:
    1.50 +            /* we'll take these too for now */
    1.51 +            break;
    1.52          default:
    1.53              printf("DEBUG: wrong display format!\n");
    1.54              break;
    1.55 @@ -272,7 +277,8 @@
    1.56          data->bg = &BACKGROUND_SUB;
    1.57      }
    1.58      data->bg_taken[2] = data->bg_taken[3] = 0;
    1.59 -    NDS_OAM_Init(&(data->oam_copy)); /* init sprites. */
    1.60 +
    1.61 +    NDS_OAM_Init(&(data->oam_copy), data->sub); /* init sprites. */
    1.62  
    1.63      TRACE("-NDS_CreateRenderer\n");
    1.64      return renderer;
    1.65 @@ -313,30 +319,39 @@
    1.66      /* conditional statements on w/h to place it as bg/sprite
    1.67         depending on which one it fits. */
    1.68      if(texture->w <= 64 && texture->h <= 64) {
    1.69 -        /* TODO: implement sprites similar to how BG's are.
    1.70 -           they have a similar affine transformation matrix
    1.71 -           (hdx,hdy,vdx,vdy) as the backgrounds, so it should
    1.72 -           be similar enough to handle with the same driverdata. */
    1.73 +        int whichspr = -1;
    1.74          printf("Tried to make a sprite.\n");
    1.75          txdat->type = NDSTX_SPR;
    1.76 +        for(i = 0; i < SPRITE_COUNT; ++i) {
    1.77 +            if(data->oam_copy.spriteBuffer[i].attribute[0] & ATTR0_DISABLED) {
    1.78 +                whichspr = i;
    1.79 +                break;
    1.80 +            }
    1.81 +        }
    1.82 +        if(whichspr >= 0) {
    1.83 +            SpriteEntry *sprent = &(data->oam_copy.spriteBuffer[whichspr]);
    1.84 +
    1.85 +            texture->driverdata = SDL_calloc(1, sizeof(NDS_TextureData));
    1.86 +            txdat = (NDS_TextureData*)texture->driverdata;
    1.87 +            if(!txdat) {
    1.88 +                SDL_OutOfMemory();
    1.89 +                return -1;
    1.90 +            }
    1.91 +
    1.92 +            sprent->objMode = OBJMODE_BITMAP;
    1.93 +            sprent->posX = 0; sprent->posY = 0;
    1.94 +            sprent->colMode = OBJCOLOR_16; /* OBJCOLOR_256 for INDEX8 */
    1.95 +            if(whichspr < MATRIX_COUNT) {
    1.96 +                sprent->isRotoscale = 1;
    1.97 +                sprent->rsMatrixIdx = whichspr;
    1.98 +            }
    1.99 +        }
   1.100      } else if(texture->w <= 256 && texture->h <= 256) {
   1.101          int whichbg = -1, base = 0;
   1.102          if(!data->bg_taken[2]) {
   1.103              whichbg = 2;
   1.104 -            data->bg->bg2_rotation.xdx = 0x100;
   1.105 -            data->bg->bg2_rotation.xdy = 0;
   1.106 -            data->bg->bg2_rotation.ydx = 0;
   1.107 -            data->bg->bg2_rotation.ydy = 0x100;
   1.108 -            data->bg->bg2_rotation.centerX = 0;
   1.109 -            data->bg->bg2_rotation.centerY = 0;
   1.110          } else if(!data->bg_taken[3]) {
   1.111              whichbg = 3;
   1.112 -            data->bg->bg3_rotation.xdx = 0x100;
   1.113 -            data->bg->bg3_rotation.xdy = 0;
   1.114 -            data->bg->bg3_rotation.ydx = 0;
   1.115 -            data->bg->bg3_rotation.ydy = 0x100;
   1.116 -            data->bg->bg3_rotation.centerX = 0;
   1.117 -            data->bg->bg3_rotation.centerY = 0;
   1.118              base = 4;
   1.119          }
   1.120          if(whichbg >= 0) {
   1.121 @@ -362,7 +377,7 @@
   1.122              txdat->hw_index = whichbg;
   1.123              txdat->dim.hdx = 0x100; txdat->dim.hdy = 0;
   1.124              txdat->dim.vdx = 0;     txdat->dim.vdy = 0x100;
   1.125 -            txdat->dim.pitch = 256 * ((bpp+1)/8);
   1.126 +            txdat->dim.pitch = texture->w * ((bpp+1)/8);
   1.127              txdat->dim.bpp = bpp;
   1.128              txdat->vram_pixels = (u16*)(data->sub ?
   1.129                  BG_BMP_RAM_SUB(base) : BG_BMP_RAM(base));
   1.130 @@ -405,7 +420,7 @@
   1.131      Uint8 *src, *dst;
   1.132      int row; size_t length;
   1.133      TRACE("+NDS_UpdateTexture\n");
   1.134 -    if(!texture) { printf("OH BOY!!!\n"); return -1; }
   1.135 +
   1.136      txdat = (NDS_TextureData *) texture->driverdata;
   1.137  
   1.138      src = (Uint8 *) pixels;
   1.139 @@ -413,10 +428,15 @@
   1.140          (Uint8 *) txdat->vram_pixels + rect->y * txdat->dim.pitch +
   1.141          rect->x * ((txdat->dim.bpp+1)/8);
   1.142      length = rect->w * ((txdat->dim.bpp+1)/8);
   1.143 -    for (row = 0; row < rect->h; ++row) {
   1.144 -        SDL_memcpy(dst, src, length);
   1.145 -        src += pitch;
   1.146 -        dst += txdat->dim.pitch;
   1.147 +
   1.148 +    if(rect->w == texture->w) {
   1.149 +        dmaCopy(src, dst, length*rect->h);
   1.150 +    } else {
   1.151 +        for (row = 0; row < rect->h; ++row) {
   1.152 +            dmaCopy(src, dst, length);
   1.153 +            src += pitch;
   1.154 +            dst += txdat->dim.pitch;
   1.155 +        }
   1.156      }
   1.157  
   1.158      TRACE("-NDS_UpdateTexture\n");
   1.159 @@ -429,17 +449,12 @@
   1.160                 int *pitch)
   1.161  {
   1.162      NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
   1.163 -    int i;
   1.164      TRACE("+NDS_LockTexture\n");
   1.165 -    if (markDirty) {
   1.166 -        printf("wanted to mark dirty\n");
   1.167 -        /* TODO: figure out how to handle this! */
   1.168 -        /*SDL_AddDirtyRect(&txdat->dirty, rect);*/
   1.169 -    }
   1.170  
   1.171      *pixels = (void *) ((u8 *)txdat->vram_pixels + rect->y
   1.172                          * txdat->dim.pitch + rect->x * ((txdat->dim.bpp+1)/8));
   1.173      *pitch = txdat->dim.pitch;
   1.174 +
   1.175      TRACE("-NDS_LockTexture\n");
   1.176      return 0;
   1.177  }
   1.178 @@ -448,8 +463,6 @@
   1.179  NDS_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   1.180  {
   1.181      TRACE("+NDS_UnlockTexture\n");
   1.182 -    /* TODO: should I be doing something here, somehow, now that the pixels
   1.183 -             should have been "written" between LockTexture and this? */
   1.184      TRACE("-NDS_UnlockTexture\n");
   1.185  }
   1.186  
   1.187 @@ -499,16 +512,29 @@
   1.188  
   1.189      TRACE("+NDS_RenderCopy\n");
   1.190      if(txdat->type == NDSTX_BG) {
   1.191 -        bg_rotation *tmpbg = (txdat->hw_index == 2) ?
   1.192 +        bg_rotation *bgrot = (txdat->hw_index == 2) ?
   1.193              &(data->bg->bg2_rotation) : &(data->bg->bg3_rotation);
   1.194 -        tmpbg->xdx = txdat->dim.hdx;
   1.195 -        tmpbg->xdy = txdat->dim.hdy;
   1.196 -        tmpbg->ydx = txdat->dim.vdx;
   1.197 -        tmpbg->ydy = txdat->dim.vdy;
   1.198 -        tmpbg->centerX = 0;
   1.199 -        tmpbg->centerY = 0;
   1.200 +        bgrot->xdx = txdat->dim.hdx;
   1.201 +        bgrot->xdy = txdat->dim.hdy;
   1.202 +        bgrot->ydx = txdat->dim.vdx;
   1.203 +        bgrot->ydy = txdat->dim.vdy;
   1.204 +        bgrot->centerX = 0;
   1.205 +        bgrot->centerY = 0;
   1.206 +
   1.207 +        data->bg->scroll[txdat->hw_index].x = dstrect->x;
   1.208 +        data->bg->scroll[txdat->hw_index].y = dstrect->y;
   1.209      } else {
   1.210 -        /* sprites not implemented yet */
   1.211 +        /* sprites not fully implemented yet */
   1.212 +        SpriteEntry *spr = &(data->oam_copy.spriteBuffer[txdat->hw_index]);
   1.213 +        spr->posX = dstrect->x;
   1.214 +        spr->posY = dstrect->y;
   1.215 +        if(txdat->hw_index < MATRIX_COUNT) {
   1.216 +            SpriteRotation *sprot = &(data->oam_copy.matrixBuffer[txdat->hw_index]);
   1.217 +            sprot->hdx = txdat->dim.hdx;
   1.218 +            sprot->hdy = txdat->dim.hdy;
   1.219 +            sprot->vdx = txdat->dim.vdx;
   1.220 +            sprot->vdy = txdat->dim.vdy;
   1.221 +        }
   1.222          printf("tried to RenderCopy a sprite.\n");
   1.223      }
   1.224      TRACE("-NDS_RenderCopy\n");
   1.225 @@ -523,19 +549,10 @@
   1.226      NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
   1.227      SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   1.228      SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   1.229 -    int i;
   1.230 +
   1.231      TRACE("+NDS_RenderPresent\n");
   1.232 -
   1.233 -    {
   1.234 -        SDL_Texture * tx = display->textures[i];
   1.235 -        NDS_TextureData * txdat = (NDS_TextureData*)tx->driverdata;
   1.236 -        /* Send the data to the display TODO :
   1.237 -           shouldn't it already be there at this point?  from lock/unlock
   1.238 -           giving it the direct address in VRAM of the bg's.
   1.239 -           I guess set the BG's and sprites "visible" flags here,
   1.240 -           if applicable. */
   1.241 -    }
   1.242 -
   1.243 +    /* update sprites */
   1.244 +    NDS_OAM_Update(&(data->oam_copy), data->sub);
   1.245      /* vsync for NDS */
   1.246      if (renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) {
   1.247          swiWaitForVBlank();
   1.248 @@ -547,14 +564,10 @@
   1.249  NDS_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   1.250  {
   1.251      TRACE("+NDS_DestroyTexture\n");
   1.252 -    if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
   1.253 -        SDL_SetError("Unsupported texture format");
   1.254 -    } else {
   1.255 -        /* free anything else allocated for texture */
   1.256 -        NDS_TextureData *txdat = texture->driverdata;
   1.257 -        /*SDL_FreeDirtyRects(&txdat->dirty);*/
   1.258 -        SDL_free(txdat);
   1.259 -    }
   1.260 +    /* free anything else allocated for texture */
   1.261 +    NDS_TextureData *txdat = texture->driverdata;
   1.262 +    /*SDL_FreeDirtyRects(&txdat->dirty);*/
   1.263 +    SDL_free(txdat);
   1.264      TRACE("-NDS_DestroyTexture\n");
   1.265  }
   1.266  
   1.267 @@ -569,20 +582,15 @@
   1.268      TRACE("+NDS_DestroyRenderer\n");
   1.269      if (data) {
   1.270          /* TODO: free anything else relevant. */
   1.271 -        /*for (i = 0; i < SDL_arraysize(data->texture); ++i) {
   1.272 -            if (data->texture[i]) {
   1.273 -                DestroyTexture(data->renderer, data->texture[i]);
   1.274 -            }
   1.275 -        }
   1.276 -        if (data->surface.format) {
   1.277 +        /*if (data->surface.format) {
   1.278              SDL_SetSurfacePalette(&data->surface, NULL);
   1.279              SDL_FreeFormat(data->surface.format);
   1.280          }
   1.281          if (display->palette) {
   1.282              SDL_DelPaletteWatch(display->palette, DisplayPaletteChanged,
   1.283                                  data);
   1.284 -        }
   1.285 -        SDL_FreeDirtyRects(&data->dirty);*/
   1.286 +        }*/
   1.287 +        /*SDL_FreeDirtyRects(&data->dirty);*/
   1.288          SDL_free(data);
   1.289      }
   1.290      SDL_free(renderer);