src/video/nds/SDL_ndsrender.c
changeset 2735 204be4fc2726
child 2810 27cb878a278e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/video/nds/SDL_ndsrender.c	Wed Aug 27 15:10:03 2008 +0000
     1.3 @@ -0,0 +1,660 @@
     1.4 +/*
     1.5 +    SDL - Simple DirectMedia Layer
     1.6 +    Copyright (C) 1997-2006 Sam Lantinga
     1.7 +
     1.8 +    This library is free software; you can redistribute it and/or
     1.9 +    modify it under the terms of the GNU Lesser General Public
    1.10 +    License as published by the Free Software Foundation; either
    1.11 +    version 2.1 of the License, or (at your option) any later version.
    1.12 +
    1.13 +    This library is distributed in the hope that it will be useful,
    1.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.16 +    Lesser General Public License for more details.
    1.17 +
    1.18 +    You should have received a copy of the GNU Lesser General Public
    1.19 +    License along with this library; if not, write to the Free Software
    1.20 +    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    1.21 +
    1.22 +    Sam Lantinga
    1.23 +    slouken@libsdl.org
    1.24 +*/
    1.25 +
    1.26 +#include <stdio.h>
    1.27 +#include <stdlib.h>
    1.28 +#include <nds.h>
    1.29 +#include <nds/arm9/video.h>
    1.30 +#include <nds/arm9/sprite.h>
    1.31 +#include <nds/arm9/trig_lut.h>
    1.32 +
    1.33 +#include "SDL_config.h"
    1.34 +
    1.35 +#include "SDL_video.h"
    1.36 +#include "../SDL_sysvideo.h"
    1.37 +#include "../SDL_yuv_sw_c.h"
    1.38 +#include "../SDL_renderer_sw.h"
    1.39 +
    1.40 +/* NDS sprite-related functions */
    1.41 +#define SPRITE_DMA_CHANNEL 3
    1.42 +#define SPRITE_ANGLE_MASK 0x01FF
    1.43 +
    1.44 +void
    1.45 +NDS_OAM_Update(tOAM * oam, int sub)
    1.46 +{
    1.47 +    DC_FlushAll();
    1.48 +    dmaCopyHalfWords(SPRITE_DMA_CHANNEL, oam->spriteBuffer,
    1.49 +                     sub ? OAM_SUB : OAM, SPRITE_COUNT * sizeof(SpriteEntry));
    1.50 +}
    1.51 +
    1.52 +void
    1.53 +NDS_OAM_RotateSprite(SpriteRotation * spriteRotation, u16 angle)
    1.54 +{
    1.55 +    s16 s = SIN[angle & SPRITE_ANGLE_MASK] >> 4;
    1.56 +    s16 c = COS[angle & SPRITE_ANGLE_MASK] >> 4;
    1.57 +
    1.58 +    spriteRotation->hdx = c;
    1.59 +    spriteRotation->hdy = s;
    1.60 +    spriteRotation->vdx = -s;
    1.61 +    spriteRotation->vdy = c;
    1.62 +}
    1.63 +
    1.64 +void
    1.65 +NDS_OAM_Init(tOAM * oam, int sub)
    1.66 +{
    1.67 +    int i;
    1.68 +    for (i = 0; i < SPRITE_COUNT; i++) {
    1.69 +        oam->spriteBuffer[i].attribute[0] = ATTR0_DISABLED;
    1.70 +        oam->spriteBuffer[i].attribute[1] = 0;
    1.71 +        oam->spriteBuffer[i].attribute[2] = 0;
    1.72 +    }
    1.73 +    for (i = 0; i < MATRIX_COUNT; i++) {
    1.74 +        NDS_OAM_RotateSprite(&(oam->matrixBuffer[i]), 0);
    1.75 +    }
    1.76 +    swiWaitForVBlank();
    1.77 +    NDS_OAM_Update(oam, sub);
    1.78 +}
    1.79 +
    1.80 +void
    1.81 +NDS_OAM_HideSprite(SpriteEntry * spriteEntry)
    1.82 +{
    1.83 +    spriteEntry->isRotoscale = 0;
    1.84 +    spriteEntry->isHidden = 1;
    1.85 +}
    1.86 +
    1.87 +void
    1.88 +NDS_OAM_ShowSprite(SpriteEntry * spriteEntry, int affine, int double_bound)
    1.89 +{
    1.90 +    if (affine) {
    1.91 +        spriteEntry->isRotoscale = 1;
    1.92 +        spriteEntry->rsDouble = double_bound;
    1.93 +    } else {
    1.94 +        spriteEntry->isHidden = 0;
    1.95 +    }
    1.96 +}
    1.97 +
    1.98 +
    1.99 +/* SDL NDS renderer implementation */
   1.100 +
   1.101 +static SDL_Renderer *NDS_CreateRenderer(SDL_Window * window, Uint32 flags);
   1.102 +static int NDS_ActivateRenderer(SDL_Renderer * renderer);
   1.103 +static int NDS_DisplayModeChanged(SDL_Renderer * renderer);
   1.104 +static int NDS_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
   1.105 +static int NDS_QueryTexturePixels(SDL_Renderer * renderer,
   1.106 +                                  SDL_Texture * texture, void **pixels,
   1.107 +                                  int *pitch);
   1.108 +static int NDS_SetTexturePalette(SDL_Renderer * renderer,
   1.109 +                                 SDL_Texture * texture,
   1.110 +                                 const SDL_Color * colors, int firstcolor,
   1.111 +                                 int ncolors);
   1.112 +static int NDS_GetTexturePalette(SDL_Renderer * renderer,
   1.113 +                                 SDL_Texture * texture, SDL_Color * colors,
   1.114 +                                 int firstcolor, int ncolors);
   1.115 +static int NDS_SetTextureColorMod(SDL_Renderer * renderer,
   1.116 +                                  SDL_Texture * texture);
   1.117 +static int NDS_SetTextureAlphaMod(SDL_Renderer * renderer,
   1.118 +                                  SDL_Texture * texture);
   1.119 +static int NDS_SetTextureBlendMode(SDL_Renderer * renderer,
   1.120 +                                   SDL_Texture * texture);
   1.121 +static int NDS_SetTextureScaleMode(SDL_Renderer * renderer,
   1.122 +                                   SDL_Texture * texture);
   1.123 +static int NDS_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   1.124 +                             const SDL_Rect * rect, const void *pixels,
   1.125 +                             int pitch);
   1.126 +static int NDS_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   1.127 +                           const SDL_Rect * rect, int markDirty,
   1.128 +                           void **pixels, int *pitch);
   1.129 +static void NDS_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
   1.130 +static void NDS_DirtyTexture(SDL_Renderer * renderer,
   1.131 +                             SDL_Texture * texture, int numrects,
   1.132 +                             const SDL_Rect * rects);
   1.133 +static int NDS_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g,
   1.134 +                          Uint8 b, Uint8 a, const SDL_Rect * rect);
   1.135 +static int NDS_RenderCopy(SDL_Renderer * renderer,
   1.136 +                          SDL_Texture * texture,
   1.137 +                          const SDL_Rect * srcrect, const SDL_Rect * dstrect);
   1.138 +static void NDS_RenderPresent(SDL_Renderer * renderer);
   1.139 +static void NDS_DestroyTexture(SDL_Renderer * renderer,
   1.140 +                               SDL_Texture * texture);
   1.141 +static void NDS_DestroyRenderer(SDL_Renderer * renderer);
   1.142 +
   1.143 +
   1.144 +SDL_RenderDriver NDS_RenderDriver = {
   1.145 +    NDS_CreateRenderer,
   1.146 +    {"nds",                     /* char* name */
   1.147 +     (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_PRESENTVSYNC),  /* u32 flags */
   1.148 +     (SDL_TEXTUREMODULATE_NONE),        /* u32 mod_modes */
   1.149 +     (SDL_TEXTUREBLENDMODE_MASK),       /* u32 blend_modes */
   1.150 +     (SDL_TEXTURESCALEMODE_FAST),       /* u32 scale_modes */
   1.151 +     3,                         /* u32 num_texture_formats */
   1.152 +     {
   1.153 +      SDL_PIXELFORMAT_INDEX8,
   1.154 +      SDL_PIXELFORMAT_ABGR1555,
   1.155 +      SDL_PIXELFORMAT_BGR555,
   1.156 +      },                        /* u32 texture_formats[20] */
   1.157 +     (256),                     /* int max_texture_width */
   1.158 +     (256),                     /* int max_texture_height */
   1.159 +     }
   1.160 +};
   1.161 +
   1.162 +typedef struct
   1.163 +{
   1.164 +    bg_attribute *bg;           /* backgrounds */
   1.165 +    tOAM oam_copy;              /* sprites */
   1.166 +    u8 bg_taken[4];
   1.167 +    int sub;
   1.168 +} NDS_RenderData;
   1.169 +
   1.170 +typedef struct
   1.171 +{
   1.172 +    enum
   1.173 +    { NDSTX_BG, NDSTX_SPR } type;       /* represented in a bg or sprite. */
   1.174 +    int hw_index;               /* sprite: index in the OAM. /  bg: 2 or 3. */
   1.175 +    struct
   1.176 +    {
   1.177 +        int hdx, hdy, vdx, vdy; /* affine transformation, used for scaling. */
   1.178 +        int pitch, bpp;         /* some useful info */
   1.179 +    } dim;
   1.180 +    u16 *vram_pixels;           /* where the pixel data is stored (a pointer into VRAM) */
   1.181 +    u16 *vram_palette;          /* where the palette data is stored if it's indexed. */
   1.182 +    /*int size; */
   1.183 +} NDS_TextureData;
   1.184 +
   1.185 +
   1.186 +
   1.187 +SDL_Renderer *
   1.188 +NDS_CreateRenderer(SDL_Window * window, Uint32 flags)
   1.189 +{
   1.190 +    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   1.191 +    SDL_DisplayMode *displayMode = &display->current_mode;
   1.192 +    SDL_Renderer *renderer;
   1.193 +    NDS_RenderData *data;
   1.194 +    int i, n;
   1.195 +    int bpp;
   1.196 +    Uint32 Rmask, Gmask, Bmask, Amask;
   1.197 +
   1.198 +    if (!SDL_PixelFormatEnumToMasks(displayMode->format, &bpp,
   1.199 +                                    &Rmask, &Gmask, &Bmask, &Amask)) {
   1.200 +        SDL_SetError("Unknown display format");
   1.201 +        return NULL;
   1.202 +    }
   1.203 +    switch (displayMode->format) {
   1.204 +    case SDL_PIXELFORMAT_INDEX8:
   1.205 +    case SDL_PIXELFORMAT_ABGR1555:
   1.206 +    case SDL_PIXELFORMAT_BGR555:
   1.207 +        /* okay */
   1.208 +        break;
   1.209 +    case SDL_PIXELFORMAT_RGB555:
   1.210 +    case SDL_PIXELFORMAT_RGB565:
   1.211 +    case SDL_PIXELFORMAT_ARGB1555:
   1.212 +        /* we'll take these too for now */
   1.213 +        break;
   1.214 +    default:
   1.215 +        SDL_SetError("Warning: wrong display format for NDS!\n");
   1.216 +        break;
   1.217 +    }
   1.218 +
   1.219 +    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
   1.220 +    if (!renderer) {
   1.221 +        SDL_OutOfMemory();
   1.222 +        return NULL;
   1.223 +    }
   1.224 +
   1.225 +    data = (NDS_RenderData *) SDL_malloc(sizeof(*data));
   1.226 +    if (!data) {
   1.227 +        NDS_DestroyRenderer(renderer);
   1.228 +        SDL_OutOfMemory();
   1.229 +        return NULL;
   1.230 +    }
   1.231 +    SDL_zerop(data);
   1.232 +
   1.233 +    renderer->RenderFill = NDS_RenderFill;
   1.234 +    renderer->RenderCopy = NDS_RenderCopy;
   1.235 +    renderer->RenderPresent = NDS_RenderPresent;
   1.236 +    renderer->DestroyRenderer = NDS_DestroyRenderer;
   1.237 +    renderer->info.name = NDS_RenderDriver.info.name;
   1.238 +    renderer->info.flags = 0;
   1.239 +    renderer->window = window->id;
   1.240 +    renderer->driverdata = data;
   1.241 +    renderer->CreateTexture = NDS_CreateTexture;
   1.242 +    renderer->QueryTexturePixels = NDS_QueryTexturePixels;
   1.243 +    renderer->SetTexturePalette = NDS_SetTexturePalette;
   1.244 +    renderer->GetTexturePalette = NDS_GetTexturePalette;
   1.245 +    renderer->SetTextureColorMod = NDS_SetTextureColorMod;
   1.246 +    renderer->SetTextureAlphaMod = NDS_SetTextureAlphaMod;
   1.247 +    renderer->SetTextureBlendMode = NDS_SetTextureBlendMode;
   1.248 +    renderer->SetTextureScaleMode = NDS_SetTextureScaleMode;
   1.249 +    renderer->UpdateTexture = NDS_UpdateTexture;
   1.250 +    renderer->LockTexture = NDS_LockTexture;
   1.251 +    renderer->UnlockTexture = NDS_UnlockTexture;
   1.252 +    renderer->DirtyTexture = NDS_DirtyTexture;
   1.253 +    renderer->DestroyTexture = NDS_DestroyTexture;
   1.254 +
   1.255 +    renderer->info.mod_modes = NDS_RenderDriver.info.mod_modes;
   1.256 +    renderer->info.blend_modes = NDS_RenderDriver.info.blend_modes;
   1.257 +    renderer->info.scale_modes = NDS_RenderDriver.info.scale_modes;
   1.258 +    renderer->info.num_texture_formats =
   1.259 +        NDS_RenderDriver.info.num_texture_formats;
   1.260 +    SDL_memcpy(renderer->info.texture_formats,
   1.261 +               NDS_RenderDriver.info.texture_formats,
   1.262 +               sizeof(renderer->info.texture_formats));
   1.263 +    renderer->info.max_texture_width =
   1.264 +        NDS_RenderDriver.info.max_texture_width;
   1.265 +    renderer->info.max_texture_height =
   1.266 +        NDS_RenderDriver.info.max_texture_height;
   1.267 +
   1.268 +    data->sub = 0;              /* TODO: this is hard-coded to the "main" screen.
   1.269 +                                   figure out how to detect whether to set it to
   1.270 +                                   "sub" screen.  window->id, perhaps? */
   1.271 +    if (!data->sub) {
   1.272 +        data->bg = &BACKGROUND;
   1.273 +    } else {
   1.274 +        data->bg = &BACKGROUND_SUB;
   1.275 +    }
   1.276 +    data->bg_taken[2] = data->bg_taken[3] = 0;
   1.277 +
   1.278 +    NDS_OAM_Init(&(data->oam_copy), data->sub); /* init sprites. */
   1.279 +
   1.280 +    return renderer;
   1.281 +}
   1.282 +
   1.283 +static int
   1.284 +NDS_ActivateRenderer(SDL_Renderer * renderer)
   1.285 +{
   1.286 +    NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
   1.287 +
   1.288 +    return 0;
   1.289 +}
   1.290 +
   1.291 +static int
   1.292 +NDS_DisplayModeChanged(SDL_Renderer * renderer)
   1.293 +{
   1.294 +    NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
   1.295 +
   1.296 +    return 0;
   1.297 +}
   1.298 +
   1.299 +static int
   1.300 +NDS_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   1.301 +{
   1.302 +    NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
   1.303 +    NDS_TextureData *txdat = NULL;
   1.304 +    int i;
   1.305 +    int bpp;
   1.306 +    Uint32 Rmask, Gmask, Bmask, Amask;
   1.307 +
   1.308 +    if (!SDL_PixelFormatEnumToMasks
   1.309 +        (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
   1.310 +        SDL_SetError("Unknown texture format");
   1.311 +        return -1;
   1.312 +    }
   1.313 +
   1.314 +    /* conditional statements on w/h to place it as bg/sprite
   1.315 +       depending on which one it fits. */
   1.316 +    if (texture->w <= 64 && texture->h <= 64) {
   1.317 +        int whichspr = -1;
   1.318 +        printf("Tried to make a sprite.\n");
   1.319 +        txdat->type = NDSTX_SPR;
   1.320 +        for (i = 0; i < SPRITE_COUNT; ++i) {
   1.321 +            if (data->oam_copy.spriteBuffer[i].attribute[0] & ATTR0_DISABLED) {
   1.322 +                whichspr = i;
   1.323 +                break;
   1.324 +            }
   1.325 +        }
   1.326 +        if (whichspr >= 0) {
   1.327 +            SpriteEntry *sprent = &(data->oam_copy.spriteBuffer[whichspr]);
   1.328 +            int maxside = texture->w > texture->h ? texture->w : texture->h;
   1.329 +            int pitch;
   1.330 +
   1.331 +            texture->driverdata = SDL_calloc(1, sizeof(NDS_TextureData));
   1.332 +            txdat = (NDS_TextureData *) texture->driverdata;
   1.333 +            if (!txdat) {
   1.334 +                SDL_OutOfMemory();
   1.335 +                return -1;
   1.336 +            }
   1.337 +
   1.338 +            sprent->objMode = OBJMODE_BITMAP;
   1.339 +            sprent->posX = 0;
   1.340 +            sprent->posY = 0;
   1.341 +            sprent->colMode = OBJCOLOR_16;      /* OBJCOLOR_256 for INDEX8 */
   1.342 +
   1.343 +            /* the first 32 sprites get transformation matrices.
   1.344 +               first come, first served */
   1.345 +            if (whichspr < MATRIX_COUNT) {
   1.346 +                sprent->isRotoscale = 1;
   1.347 +                sprent->rsMatrixIdx = whichspr;
   1.348 +            }
   1.349 +
   1.350 +            /* containing shape (square or 2:1 rectangles) */
   1.351 +            sprent->objShape = OBJSHAPE_SQUARE;
   1.352 +            if (texture->w / 2 >= texture->h) {
   1.353 +                sprent->objShape = OBJSHAPE_WIDE;
   1.354 +            } else if (texture->h / 2 >= texture->w) {
   1.355 +                sprent->objShape = OBJSHAPE_TALL;
   1.356 +            }
   1.357 +
   1.358 +            /* size in pixels */
   1.359 +            /* FIXME: "pitch" is hardcoded for 2bytes per pixel. */
   1.360 +            sprent->objSize = OBJSIZE_64;
   1.361 +            pitch = 128;
   1.362 +            if (maxside <= 8) {
   1.363 +                sprent->objSize = OBJSIZE_8;
   1.364 +                pitch = 16;
   1.365 +            } else if (maxside <= 16) {
   1.366 +                sprent->objSize = OBJSIZE_16;
   1.367 +                pitch = 32;
   1.368 +            } else if (maxside <= 32) {
   1.369 +                sprent->objSize = OBJSIZE_32;
   1.370 +                pitch = 64;
   1.371 +            }
   1.372 +
   1.373 +            /* FIXME: this is hard-coded and will obviously only work for one
   1.374 +               sprite-texture.  tells it to look at the beginning of SPRITE_GFX
   1.375 +               for its pixels. */
   1.376 +            sprent->tileIdx = 0;
   1.377 +
   1.378 +            /* now for the texture data */
   1.379 +            txdat->type = NDSTX_SPR;
   1.380 +            txdat->hw_index = whichspr;
   1.381 +            txdat->dim.hdx = 0x100;
   1.382 +            txdat->dim.hdy = 0;
   1.383 +            txdat->dim.vdx = 0;
   1.384 +            txdat->dim.vdy = 0x100;
   1.385 +            txdat->dim.pitch = pitch;
   1.386 +            txdat->dim.bpp = bpp;
   1.387 +            txdat->vram_pixels = (u16 *) (data->sub ? SPRITE_GFX_SUB : SPRITE_GFX);     /* FIXME: use tileIdx*boundary
   1.388 +                                                                                           to point to proper location */
   1.389 +        } else {
   1.390 +            SDL_SetError("Out of NDS sprites.");
   1.391 +        }
   1.392 +    } else if (texture->w <= 256 && texture->h <= 256) {
   1.393 +        int whichbg = -1, base = 0;
   1.394 +        if (!data->bg_taken[2]) {
   1.395 +            whichbg = 2;
   1.396 +        } else if (!data->bg_taken[3]) {
   1.397 +            whichbg = 3;
   1.398 +            base = 4;
   1.399 +        }
   1.400 +        if (whichbg >= 0) {
   1.401 +            texture->driverdata = SDL_calloc(1, sizeof(NDS_TextureData));
   1.402 +            txdat = (NDS_TextureData *) texture->driverdata;
   1.403 +            if (!txdat) {
   1.404 +                SDL_OutOfMemory();
   1.405 +                return -1;
   1.406 +            }
   1.407 +
   1.408 +            /* this is hard-coded to being 256x256 ABGR1555 for now. */
   1.409 +            data->bg->control[whichbg] = (bpp == 8) ?
   1.410 +                BG_BMP8_256x256 : BG_BMP16_256x256;
   1.411 +
   1.412 +            data->bg->control[whichbg] |= BG_BMP_BASE(base);
   1.413 +
   1.414 +            data->bg->scroll[whichbg].x = 0;
   1.415 +            data->bg->scroll[whichbg].y = 0;
   1.416 +
   1.417 +            txdat->type = NDSTX_BG;
   1.418 +            txdat->hw_index = whichbg;
   1.419 +            txdat->dim.hdx = 0x100;
   1.420 +            txdat->dim.hdy = 0;
   1.421 +            txdat->dim.vdx = 0;
   1.422 +            txdat->dim.vdy = 0x100;
   1.423 +            txdat->dim.pitch = 512;
   1.424 +            txdat->dim.bpp = bpp;
   1.425 +            txdat->vram_pixels = (u16 *) (data->sub ?
   1.426 +                                          BG_BMP_RAM_SUB(base) :
   1.427 +                                          BG_BMP_RAM(base));
   1.428 +
   1.429 +            /*txdat->size = txdat->dim.pitch * texture->h; */
   1.430 +        } else {
   1.431 +            SDL_SetError("Out of NDS backgrounds.");
   1.432 +        }
   1.433 +    } else {
   1.434 +        SDL_SetError("Texture too big for NDS hardware.");
   1.435 +    }
   1.436 +
   1.437 +    if (!texture->driverdata) {
   1.438 +        return -1;
   1.439 +    }
   1.440 +
   1.441 +    return 0;
   1.442 +}
   1.443 +
   1.444 +static int
   1.445 +NDS_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
   1.446 +                       void **pixels, int *pitch)
   1.447 +{
   1.448 +    NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
   1.449 +    *pixels = txdat->vram_pixels;
   1.450 +    *pitch = txdat->dim.pitch;
   1.451 +    return 0;
   1.452 +}
   1.453 +
   1.454 +static int
   1.455 +NDS_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   1.456 +                  const SDL_Rect * rect, const void *pixels, int pitch)
   1.457 +{
   1.458 +    NDS_TextureData *txdat;
   1.459 +    Uint8 *src, *dst;
   1.460 +    int row;
   1.461 +    size_t length;
   1.462 +
   1.463 +    txdat = (NDS_TextureData *) texture->driverdata;
   1.464 +
   1.465 +    src = (Uint8 *) pixels;
   1.466 +    dst =
   1.467 +        (Uint8 *) txdat->vram_pixels + rect->y * txdat->dim.pitch +
   1.468 +        rect->x * ((txdat->dim.bpp + 1) / 8);
   1.469 +    length = rect->w * ((txdat->dim.bpp + 1) / 8);
   1.470 +
   1.471 +    if (rect->w == texture->w) {
   1.472 +        dmaCopy(src, dst, length * rect->h);
   1.473 +    } else {
   1.474 +        for (row = 0; row < rect->h; ++row) {
   1.475 +            dmaCopy(src, dst, length);
   1.476 +            src += pitch;
   1.477 +            dst += txdat->dim.pitch;
   1.478 +        }
   1.479 +    }
   1.480 +
   1.481 +    return 0;
   1.482 +}
   1.483 +
   1.484 +static int
   1.485 +NDS_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   1.486 +                const SDL_Rect * rect, int markDirty, void **pixels,
   1.487 +                int *pitch)
   1.488 +{
   1.489 +    NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
   1.490 +
   1.491 +    *pixels = (void *) ((u8 *) txdat->vram_pixels + rect->y
   1.492 +                        * txdat->dim.pitch +
   1.493 +                        rect->x * ((txdat->dim.bpp + 1) / 8));
   1.494 +    *pitch = txdat->dim.pitch;
   1.495 +
   1.496 +    return 0;
   1.497 +}
   1.498 +
   1.499 +static void
   1.500 +NDS_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   1.501 +{
   1.502 +    /* stub! */
   1.503 +}
   1.504 +
   1.505 +static void
   1.506 +NDS_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   1.507 +                 int numrects, const SDL_Rect * rects)
   1.508 +{
   1.509 +    /* stub! */
   1.510 +}
   1.511 +
   1.512 +static int
   1.513 +NDS_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b,
   1.514 +               Uint8 a, const SDL_Rect * rect)
   1.515 +{
   1.516 +    NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
   1.517 +    SDL_Rect real_rect = *rect;
   1.518 +    u16 color;
   1.519 +    int i, j;
   1.520 +
   1.521 +    color = RGB8(r, g, b);      /* <-- macro in libnds that makes an ARGB1555 pixel */
   1.522 +    /* TODO: make a single-color sprite and stretch it.
   1.523 +       calculate the "HDX" width modifier of the sprite by:
   1.524 +       let S be the actual sprite's width (like, 32 pixels for example)
   1.525 +       let R be the rectangle's width (maybe 50 pixels)
   1.526 +       HDX = (R<<8) / S;
   1.527 +       (it's fixed point, hence the bit shift.  same goes for vertical.
   1.528 +       be sure to use 32-bit int's for the bit shift before the division!)
   1.529 +     */
   1.530 +
   1.531 +    return 0;
   1.532 +}
   1.533 +
   1.534 +static int
   1.535 +NDS_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   1.536 +               const SDL_Rect * srcrect, const SDL_Rect * dstrect)
   1.537 +{
   1.538 +    NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
   1.539 +    NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
   1.540 +    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   1.541 +    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   1.542 +    int i;
   1.543 +    int bpp = SDL_BYTESPERPIXEL(texture->format);
   1.544 +    int pitch = txdat->dim.pitch;
   1.545 +
   1.546 +    if (txdat->type == NDSTX_BG) {
   1.547 +        bg_rotation *bgrot = (txdat->hw_index == 2) ?
   1.548 +            &(data->bg->bg2_rotation) : &(data->bg->bg3_rotation);
   1.549 +        bgrot->xdx = txdat->dim.hdx;
   1.550 +        bgrot->xdy = txdat->dim.hdy;
   1.551 +        bgrot->ydx = txdat->dim.vdx;
   1.552 +        bgrot->ydy = txdat->dim.vdy;
   1.553 +        bgrot->centerX = 0;
   1.554 +        bgrot->centerY = 0;
   1.555 +
   1.556 +        data->bg->scroll[txdat->hw_index].x = dstrect->x;
   1.557 +        data->bg->scroll[txdat->hw_index].y = dstrect->y;
   1.558 +    } else {
   1.559 +        /* sprites not fully implemented yet */
   1.560 +        SpriteEntry *spr = &(data->oam_copy.spriteBuffer[txdat->hw_index]);
   1.561 +        spr->posX = dstrect->x;
   1.562 +        spr->posY = dstrect->y;
   1.563 +        if (txdat->hw_index < MATRIX_COUNT && spr->isRotoscale) {
   1.564 +            SpriteRotation *sprot =
   1.565 +                &(data->oam_copy.matrixBuffer[txdat->hw_index]);
   1.566 +            sprot->hdx = txdat->dim.hdx;
   1.567 +            sprot->hdy = txdat->dim.hdy;
   1.568 +            sprot->vdx = txdat->dim.vdx;
   1.569 +            sprot->vdy = txdat->dim.vdy;
   1.570 +        }
   1.571 +    }
   1.572 +
   1.573 +    return 0;
   1.574 +}
   1.575 +
   1.576 +
   1.577 +static void
   1.578 +NDS_RenderPresent(SDL_Renderer * renderer)
   1.579 +{
   1.580 +    NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
   1.581 +    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   1.582 +    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   1.583 +
   1.584 +    /* update sprites */
   1.585 +    NDS_OAM_Update(&(data->oam_copy), data->sub);
   1.586 +    /* vsync for NDS */
   1.587 +    if (renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) {
   1.588 +        swiWaitForVBlank();
   1.589 +    }
   1.590 +}
   1.591 +
   1.592 +static void
   1.593 +NDS_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   1.594 +{
   1.595 +    NDS_TextureData *txdat = texture->driverdata;
   1.596 +    /* free anything else allocated for texture */
   1.597 +    SDL_free(txdat);
   1.598 +}
   1.599 +
   1.600 +static void
   1.601 +NDS_DestroyRenderer(SDL_Renderer * renderer)
   1.602 +{
   1.603 +    NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
   1.604 +    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   1.605 +    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   1.606 +    int i;
   1.607 +
   1.608 +    if (data) {
   1.609 +        /* free anything else relevant if anything else is allocated. */
   1.610 +        SDL_free(data);
   1.611 +    }
   1.612 +    SDL_free(renderer);
   1.613 +}
   1.614 +
   1.615 +static int
   1.616 +NDS_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
   1.617 +                      const SDL_Color * colors, int firstcolor, int ncolors)
   1.618 +{
   1.619 +    NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
   1.620 +    /* set 8-bit modes in the background control registers
   1.621 +       for backgrounds, BGn_CR |= BG_256_COLOR */
   1.622 +
   1.623 +    return 0;
   1.624 +}
   1.625 +
   1.626 +static int
   1.627 +NDS_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
   1.628 +                      SDL_Color * colors, int firstcolor, int ncolors)
   1.629 +{
   1.630 +    NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
   1.631 +    /* stub! */
   1.632 +    return 0;
   1.633 +}
   1.634 +
   1.635 +static int
   1.636 +NDS_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
   1.637 +{
   1.638 +    /* stub! */
   1.639 +    return 0;
   1.640 +}
   1.641 +
   1.642 +static int
   1.643 +NDS_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
   1.644 +{
   1.645 +    /* stub! */
   1.646 +    return 0;
   1.647 +}
   1.648 +
   1.649 +static int
   1.650 +NDS_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
   1.651 +{
   1.652 +    /* stub! */
   1.653 +    return 0;
   1.654 +}
   1.655 +
   1.656 +static int
   1.657 +NDS_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
   1.658 +{
   1.659 +    /* stub! (note: NDS hardware scaling is nearest neighbor.) */
   1.660 +    return 0;
   1.661 +}
   1.662 +
   1.663 +/* vi: set ts=4 sw=4 expandtab: */