Beginnings of sprite support. gsoc2008_nds
authorDarren Alton <dalton@stevens.edu>
Sat, 16 Aug 2008 12:08:12 +0000
branchgsoc2008_nds
changeset 2693 bae97b6ac32b
parent 2692 cd8978f47849
child 2694 c1c7cb1b5a47
Beginnings of sprite support.
src/video/nds/SDL_ndsrender.c
--- a/src/video/nds/SDL_ndsrender.c	Sat Aug 16 11:16:08 2008 +0000
+++ b/src/video/nds/SDL_ndsrender.c	Sat Aug 16 12:08:12 2008 +0000
@@ -42,10 +42,10 @@
 #define SPRITE_ANGLE_MASK 0x01FF
 
 void
-NDS_OAM_Update(tOAM *oam)
+NDS_OAM_Update(tOAM *oam, int sub)
 {
     DC_FlushAll();
-    dmaCopyHalfWords(SPRITE_DMA_CHANNEL, oam->spriteBuffer, OAM,
+    dmaCopyHalfWords(SPRITE_DMA_CHANNEL, oam->spriteBuffer, sub?OAM_SUB:OAM,
                      SPRITE_COUNT * sizeof(SpriteEntry));
 }
 
@@ -62,7 +62,7 @@
 }
 
 void
-NDS_OAM_Init(tOAM *oam)
+NDS_OAM_Init(tOAM *oam, int sub)
 {
     int i;
     for(i = 0; i < SPRITE_COUNT; i++) {
@@ -74,7 +74,7 @@
         NDS_OAM_RotateSprite(&(oam->matrixBuffer[i]), 0);
     }
     swiWaitForVBlank();
-    NDS_OAM_Update(oam);
+    NDS_OAM_Update(oam, sub);
 }
 
 void
@@ -173,7 +173,7 @@
 typedef struct
 {
     enum { NDSTX_BG, NDSTX_SPR } type; /* represented in a bg or sprite. */
-    int hw_index; /* sprite: index in the OAM.  bg: 2 or 3. */
+    int hw_index; /* sprite: index in the OAM. /  bg: 2 or 3. */
     struct
     {
         int hdx, hdy, vdx, vdy; /* affine transformation, used for scaling. */
@@ -209,6 +209,11 @@
         case SDL_PIXELFORMAT_BGR555:
             /* okay */
             break;
+        case SDL_PIXELFORMAT_RGB555:
+        case SDL_PIXELFORMAT_RGB565:
+        case SDL_PIXELFORMAT_ARGB1555:
+            /* we'll take these too for now */
+            break;
         default:
             printf("DEBUG: wrong display format!\n");
             break;
@@ -272,7 +277,8 @@
         data->bg = &BACKGROUND_SUB;
     }
     data->bg_taken[2] = data->bg_taken[3] = 0;
-    NDS_OAM_Init(&(data->oam_copy)); /* init sprites. */
+
+    NDS_OAM_Init(&(data->oam_copy), data->sub); /* init sprites. */
 
     TRACE("-NDS_CreateRenderer\n");
     return renderer;
@@ -313,30 +319,39 @@
     /* conditional statements on w/h to place it as bg/sprite
        depending on which one it fits. */
     if(texture->w <= 64 && texture->h <= 64) {
-        /* TODO: implement sprites similar to how BG's are.
-           they have a similar affine transformation matrix
-           (hdx,hdy,vdx,vdy) as the backgrounds, so it should
-           be similar enough to handle with the same driverdata. */
+        int whichspr = -1;
         printf("Tried to make a sprite.\n");
         txdat->type = NDSTX_SPR;
+        for(i = 0; i < SPRITE_COUNT; ++i) {
+            if(data->oam_copy.spriteBuffer[i].attribute[0] & ATTR0_DISABLED) {
+                whichspr = i;
+                break;
+            }
+        }
+        if(whichspr >= 0) {
+            SpriteEntry *sprent = &(data->oam_copy.spriteBuffer[whichspr]);
+
+            texture->driverdata = SDL_calloc(1, sizeof(NDS_TextureData));
+            txdat = (NDS_TextureData*)texture->driverdata;
+            if(!txdat) {
+                SDL_OutOfMemory();
+                return -1;
+            }
+
+            sprent->objMode = OBJMODE_BITMAP;
+            sprent->posX = 0; sprent->posY = 0;
+            sprent->colMode = OBJCOLOR_16; /* OBJCOLOR_256 for INDEX8 */
+            if(whichspr < MATRIX_COUNT) {
+                sprent->isRotoscale = 1;
+                sprent->rsMatrixIdx = whichspr;
+            }
+        }
     } else if(texture->w <= 256 && texture->h <= 256) {
         int whichbg = -1, base = 0;
         if(!data->bg_taken[2]) {
             whichbg = 2;
-            data->bg->bg2_rotation.xdx = 0x100;
-            data->bg->bg2_rotation.xdy = 0;
-            data->bg->bg2_rotation.ydx = 0;
-            data->bg->bg2_rotation.ydy = 0x100;
-            data->bg->bg2_rotation.centerX = 0;
-            data->bg->bg2_rotation.centerY = 0;
         } else if(!data->bg_taken[3]) {
             whichbg = 3;
-            data->bg->bg3_rotation.xdx = 0x100;
-            data->bg->bg3_rotation.xdy = 0;
-            data->bg->bg3_rotation.ydx = 0;
-            data->bg->bg3_rotation.ydy = 0x100;
-            data->bg->bg3_rotation.centerX = 0;
-            data->bg->bg3_rotation.centerY = 0;
             base = 4;
         }
         if(whichbg >= 0) {
@@ -362,7 +377,7 @@
             txdat->hw_index = whichbg;
             txdat->dim.hdx = 0x100; txdat->dim.hdy = 0;
             txdat->dim.vdx = 0;     txdat->dim.vdy = 0x100;
-            txdat->dim.pitch = 256 * ((bpp+1)/8);
+            txdat->dim.pitch = texture->w * ((bpp+1)/8);
             txdat->dim.bpp = bpp;
             txdat->vram_pixels = (u16*)(data->sub ?
                 BG_BMP_RAM_SUB(base) : BG_BMP_RAM(base));
@@ -405,7 +420,7 @@
     Uint8 *src, *dst;
     int row; size_t length;
     TRACE("+NDS_UpdateTexture\n");
-    if(!texture) { printf("OH BOY!!!\n"); return -1; }
+
     txdat = (NDS_TextureData *) texture->driverdata;
 
     src = (Uint8 *) pixels;
@@ -413,10 +428,15 @@
         (Uint8 *) txdat->vram_pixels + rect->y * txdat->dim.pitch +
         rect->x * ((txdat->dim.bpp+1)/8);
     length = rect->w * ((txdat->dim.bpp+1)/8);
-    for (row = 0; row < rect->h; ++row) {
-        SDL_memcpy(dst, src, length);
-        src += pitch;
-        dst += txdat->dim.pitch;
+
+    if(rect->w == texture->w) {
+        dmaCopy(src, dst, length*rect->h);
+    } else {
+        for (row = 0; row < rect->h; ++row) {
+            dmaCopy(src, dst, length);
+            src += pitch;
+            dst += txdat->dim.pitch;
+        }
     }
 
     TRACE("-NDS_UpdateTexture\n");
@@ -429,17 +449,12 @@
                int *pitch)
 {
     NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
-    int i;
     TRACE("+NDS_LockTexture\n");
-    if (markDirty) {
-        printf("wanted to mark dirty\n");
-        /* TODO: figure out how to handle this! */
-        /*SDL_AddDirtyRect(&txdat->dirty, rect);*/
-    }
 
     *pixels = (void *) ((u8 *)txdat->vram_pixels + rect->y
                         * txdat->dim.pitch + rect->x * ((txdat->dim.bpp+1)/8));
     *pitch = txdat->dim.pitch;
+
     TRACE("-NDS_LockTexture\n");
     return 0;
 }
@@ -448,8 +463,6 @@
 NDS_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
 {
     TRACE("+NDS_UnlockTexture\n");
-    /* TODO: should I be doing something here, somehow, now that the pixels
-             should have been "written" between LockTexture and this? */
     TRACE("-NDS_UnlockTexture\n");
 }
 
@@ -499,16 +512,29 @@
 
     TRACE("+NDS_RenderCopy\n");
     if(txdat->type == NDSTX_BG) {
-        bg_rotation *tmpbg = (txdat->hw_index == 2) ?
+        bg_rotation *bgrot = (txdat->hw_index == 2) ?
             &(data->bg->bg2_rotation) : &(data->bg->bg3_rotation);
-        tmpbg->xdx = txdat->dim.hdx;
-        tmpbg->xdy = txdat->dim.hdy;
-        tmpbg->ydx = txdat->dim.vdx;
-        tmpbg->ydy = txdat->dim.vdy;
-        tmpbg->centerX = 0;
-        tmpbg->centerY = 0;
+        bgrot->xdx = txdat->dim.hdx;
+        bgrot->xdy = txdat->dim.hdy;
+        bgrot->ydx = txdat->dim.vdx;
+        bgrot->ydy = txdat->dim.vdy;
+        bgrot->centerX = 0;
+        bgrot->centerY = 0;
+
+        data->bg->scroll[txdat->hw_index].x = dstrect->x;
+        data->bg->scroll[txdat->hw_index].y = dstrect->y;
     } else {
-        /* sprites not implemented yet */
+        /* sprites not fully implemented yet */
+        SpriteEntry *spr = &(data->oam_copy.spriteBuffer[txdat->hw_index]);
+        spr->posX = dstrect->x;
+        spr->posY = dstrect->y;
+        if(txdat->hw_index < MATRIX_COUNT) {
+            SpriteRotation *sprot = &(data->oam_copy.matrixBuffer[txdat->hw_index]);
+            sprot->hdx = txdat->dim.hdx;
+            sprot->hdy = txdat->dim.hdy;
+            sprot->vdx = txdat->dim.vdx;
+            sprot->vdy = txdat->dim.vdy;
+        }
         printf("tried to RenderCopy a sprite.\n");
     }
     TRACE("-NDS_RenderCopy\n");
@@ -523,19 +549,10 @@
     NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
-    int i;
+
     TRACE("+NDS_RenderPresent\n");
-
-    {
-        SDL_Texture * tx = display->textures[i];
-        NDS_TextureData * txdat = (NDS_TextureData*)tx->driverdata;
-        /* Send the data to the display TODO :
-           shouldn't it already be there at this point?  from lock/unlock
-           giving it the direct address in VRAM of the bg's.
-           I guess set the BG's and sprites "visible" flags here,
-           if applicable. */
-    }
-
+    /* update sprites */
+    NDS_OAM_Update(&(data->oam_copy), data->sub);
     /* vsync for NDS */
     if (renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) {
         swiWaitForVBlank();
@@ -547,14 +564,10 @@
 NDS_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
 {
     TRACE("+NDS_DestroyTexture\n");
-    if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
-        SDL_SetError("Unsupported texture format");
-    } else {
-        /* free anything else allocated for texture */
-        NDS_TextureData *txdat = texture->driverdata;
-        /*SDL_FreeDirtyRects(&txdat->dirty);*/
-        SDL_free(txdat);
-    }
+    /* free anything else allocated for texture */
+    NDS_TextureData *txdat = texture->driverdata;
+    /*SDL_FreeDirtyRects(&txdat->dirty);*/
+    SDL_free(txdat);
     TRACE("-NDS_DestroyTexture\n");
 }
 
@@ -569,20 +582,15 @@
     TRACE("+NDS_DestroyRenderer\n");
     if (data) {
         /* TODO: free anything else relevant. */
-        /*for (i = 0; i < SDL_arraysize(data->texture); ++i) {
-            if (data->texture[i]) {
-                DestroyTexture(data->renderer, data->texture[i]);
-            }
-        }
-        if (data->surface.format) {
+        /*if (data->surface.format) {
             SDL_SetSurfacePalette(&data->surface, NULL);
             SDL_FreeFormat(data->surface.format);
         }
         if (display->palette) {
             SDL_DelPaletteWatch(display->palette, DisplayPaletteChanged,
                                 data);
-        }
-        SDL_FreeDirtyRects(&data->dirty);*/
+        }*/
+        /*SDL_FreeDirtyRects(&data->dirty);*/
         SDL_free(data);
     }
     SDL_free(renderer);