src/video/nds/SDL_ndsrender.c
author Darren Alton <dalton@stevens.edu>
Mon, 18 Aug 2008 07:29:52 +0000
branchgsoc2008_nds
changeset 2696 0b395a60deff
parent 2695 c04a266c277a
child 2698 e1da92da346c
permissions -rw-r--r--
Timers work now.
dalton@2670
     1
/*
dalton@2670
     2
    SDL - Simple DirectMedia Layer
dalton@2670
     3
    Copyright (C) 1997-2006 Sam Lantinga
dalton@2670
     4
dalton@2670
     5
    This library is free software; you can redistribute it and/or
dalton@2670
     6
    modify it under the terms of the GNU Lesser General Public
dalton@2670
     7
    License as published by the Free Software Foundation; either
dalton@2670
     8
    version 2.1 of the License, or (at your option) any later version.
dalton@2670
     9
dalton@2670
    10
    This library is distributed in the hope that it will be useful,
dalton@2670
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
dalton@2670
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
dalton@2670
    13
    Lesser General Public License for more details.
dalton@2670
    14
dalton@2670
    15
    You should have received a copy of the GNU Lesser General Public
dalton@2670
    16
    License along with this library; if not, write to the Free Software
dalton@2670
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
dalton@2670
    18
dalton@2670
    19
    Sam Lantinga
dalton@2670
    20
    slouken@libsdl.org
dalton@2670
    21
*/
dalton@2670
    22
dalton@2670
    23
#include <stdio.h>
dalton@2670
    24
#include <stdlib.h>
dalton@2670
    25
#include <nds.h>
dalton@2688
    26
#include <nds/arm9/video.h>
dalton@2688
    27
#include <nds/arm9/sprite.h>
dalton@2688
    28
#include <nds/arm9/trig_lut.h>
dalton@2670
    29
dalton@2670
    30
#include "SDL_config.h"
dalton@2670
    31
dalton@2670
    32
#include "SDL_video.h"
dalton@2670
    33
#include "../SDL_sysvideo.h"
dalton@2670
    34
#include "../SDL_yuv_sw_c.h"
dalton@2670
    35
#include "../SDL_renderer_sw.h"
dalton@2670
    36
dalton@2690
    37
#define TRACE
dalton@2690
    38
//#define TRACE printf
dalton@2688
    39
dalton@2688
    40
/* NDS sprite-related functions */
dalton@2688
    41
#define SPRITE_DMA_CHANNEL 3
dalton@2688
    42
#define SPRITE_ANGLE_MASK 0x01FF
dalton@2688
    43
dalton@2688
    44
void
dalton@2693
    45
NDS_OAM_Update(tOAM *oam, int sub)
dalton@2688
    46
{
dalton@2688
    47
    DC_FlushAll();
dalton@2693
    48
    dmaCopyHalfWords(SPRITE_DMA_CHANNEL, oam->spriteBuffer, sub?OAM_SUB:OAM,
dalton@2688
    49
                     SPRITE_COUNT * sizeof(SpriteEntry));
dalton@2688
    50
}
dalton@2688
    51
dalton@2688
    52
void
dalton@2688
    53
NDS_OAM_RotateSprite(SpriteRotation *spriteRotation, u16 angle)
dalton@2688
    54
{
dalton@2688
    55
    s16 s = SIN[angle & SPRITE_ANGLE_MASK] >> 4;
dalton@2688
    56
    s16 c = COS[angle & SPRITE_ANGLE_MASK] >> 4;
dalton@2688
    57
dalton@2688
    58
    spriteRotation->hdx = c;
dalton@2688
    59
    spriteRotation->hdy = s;
dalton@2688
    60
    spriteRotation->vdx = -s;
dalton@2688
    61
    spriteRotation->vdy = c;
dalton@2688
    62
}
dalton@2688
    63
dalton@2688
    64
void
dalton@2693
    65
NDS_OAM_Init(tOAM *oam, int sub)
dalton@2688
    66
{
dalton@2688
    67
    int i;
dalton@2688
    68
    for(i = 0; i < SPRITE_COUNT; i++) {
dalton@2688
    69
        oam->spriteBuffer[i].attribute[0] = ATTR0_DISABLED;
dalton@2688
    70
        oam->spriteBuffer[i].attribute[1] = 0;
dalton@2688
    71
        oam->spriteBuffer[i].attribute[2] = 0;
dalton@2688
    72
    }
dalton@2688
    73
    for(i = 0; i < MATRIX_COUNT; i++) {
dalton@2688
    74
        NDS_OAM_RotateSprite(&(oam->matrixBuffer[i]), 0);
dalton@2688
    75
    }
dalton@2688
    76
    swiWaitForVBlank();
dalton@2693
    77
    NDS_OAM_Update(oam, sub);
dalton@2688
    78
}
dalton@2688
    79
dalton@2688
    80
void
dalton@2688
    81
NDS_OAM_HideSprite(SpriteEntry *spriteEntry)
dalton@2688
    82
{
dalton@2688
    83
    spriteEntry->isRotoscale = 0;
dalton@2688
    84
    spriteEntry->isHidden = 1;
dalton@2688
    85
}
dalton@2688
    86
dalton@2688
    87
void
dalton@2688
    88
NDS_OAM_ShowSprite(SpriteEntry *spriteEntry, int affine, int double_bound)
dalton@2688
    89
{
dalton@2688
    90
    if (affine) {
dalton@2688
    91
        spriteEntry->isRotoscale = 1;
dalton@2688
    92
        spriteEntry->rsDouble = double_bound;
dalton@2688
    93
    } else {
dalton@2688
    94
        spriteEntry->isHidden = 0;
dalton@2688
    95
    }
dalton@2688
    96
}
dalton@2688
    97
dalton@2688
    98
dalton@2685
    99
/* SDL NDS renderer implementation */
dalton@2670
   100
dalton@2677
   101
static SDL_Renderer *NDS_CreateRenderer(SDL_Window * window, Uint32 flags);
dalton@2677
   102
static int NDS_ActivateRenderer(SDL_Renderer * renderer);
dalton@2677
   103
static int NDS_DisplayModeChanged(SDL_Renderer * renderer);
dalton@2677
   104
static int NDS_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
dalton@2677
   105
static int NDS_QueryTexturePixels(SDL_Renderer * renderer,
dalton@2677
   106
                                 SDL_Texture * texture, void **pixels,
dalton@2677
   107
                                 int *pitch);
dalton@2677
   108
static int NDS_SetTexturePalette(SDL_Renderer * renderer,
dalton@2677
   109
                                SDL_Texture * texture,
dalton@2677
   110
                                const SDL_Color * colors, int firstcolor,
dalton@2677
   111
                                int ncolors);
dalton@2677
   112
static int NDS_GetTexturePalette(SDL_Renderer * renderer,
dalton@2677
   113
                                SDL_Texture * texture, SDL_Color * colors,
dalton@2677
   114
                                int firstcolor, int ncolors);
dalton@2677
   115
static int NDS_SetTextureColorMod(SDL_Renderer * renderer,
dalton@2677
   116
                                 SDL_Texture * texture);
dalton@2677
   117
static int NDS_SetTextureAlphaMod(SDL_Renderer * renderer,
dalton@2677
   118
                                 SDL_Texture * texture);
dalton@2677
   119
static int NDS_SetTextureBlendMode(SDL_Renderer * renderer,
dalton@2677
   120
                                  SDL_Texture * texture);
dalton@2677
   121
static int NDS_SetTextureScaleMode(SDL_Renderer * renderer,
dalton@2677
   122
                                  SDL_Texture * texture);
dalton@2677
   123
static int NDS_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
dalton@2691
   124
                          const SDL_Rect * rect, const void *pixels,
dalton@2691
   125
                          int pitch);
dalton@2677
   126
static int NDS_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
dalton@2677
   127
                          const SDL_Rect * rect, int markDirty, void **pixels,
dalton@2677
   128
                          int *pitch);
dalton@2677
   129
static void NDS_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
dalton@2677
   130
static void NDS_DirtyTexture(SDL_Renderer * renderer,
dalton@2677
   131
                            SDL_Texture * texture, int numrects,
dalton@2677
   132
                            const SDL_Rect * rects);
dalton@2677
   133
static int NDS_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g,
dalton@2671
   134
                              Uint8 b, Uint8 a, const SDL_Rect * rect);
dalton@2677
   135
static int NDS_RenderCopy(SDL_Renderer * renderer,
dalton@2671
   136
                              SDL_Texture * texture,
dalton@2671
   137
                              const SDL_Rect * srcrect,
dalton@2671
   138
                              const SDL_Rect * dstrect);
dalton@2677
   139
static void NDS_RenderPresent(SDL_Renderer * renderer);
dalton@2677
   140
static void NDS_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
dalton@2677
   141
static void NDS_DestroyRenderer(SDL_Renderer * renderer);
dalton@2670
   142
dalton@2670
   143
dalton@2677
   144
SDL_RenderDriver NDS_RenderDriver = {
dalton@2677
   145
    NDS_CreateRenderer,
dalton@2679
   146
    {   "nds", /* char* name */
dalton@2691
   147
        (SDL_RENDERER_SINGLEBUFFER |
dalton@2691
   148
         SDL_RENDERER_ACCELERATED |
dalton@2691
   149
         SDL_RENDERER_PRESENTDISCARD |
dalton@2691
   150
         SDL_RENDERER_PRESENTVSYNC), /* u32 flags */
dalton@2679
   151
        (SDL_TEXTUREMODULATE_NONE), /* u32 mod_modes */
dalton@2690
   152
        (SDL_TEXTUREBLENDMODE_MASK), /* u32 blend_modes */
dalton@2690
   153
        (SDL_TEXTURESCALEMODE_FAST), /* u32 scale_modes */
dalton@2679
   154
        3, /* u32 num_texture_formats */
dalton@2679
   155
        {
dalton@2679
   156
            SDL_PIXELFORMAT_INDEX8,
dalton@2681
   157
            SDL_PIXELFORMAT_ABGR1555,
dalton@2681
   158
            SDL_PIXELFORMAT_BGR555,
dalton@2679
   159
        }, /* u32 texture_formats[20] */
dalton@2679
   160
        (256), /* int max_texture_width */
dalton@2679
   161
        (256), /* int max_texture_height */
dalton@2679
   162
    }
dalton@2670
   163
};
dalton@2670
   164
dalton@2670
   165
typedef struct
dalton@2670
   166
{
dalton@2688
   167
    bg_attribute *bg; /* backgrounds */
dalton@2688
   168
    tOAM oam_copy; /* sprites */
dalton@2679
   169
    u8 bg_taken[4];
dalton@2679
   170
    int sub;
dalton@2677
   171
} NDS_RenderData;
dalton@2670
   172
dalton@2678
   173
typedef struct
dalton@2678
   174
{
dalton@2690
   175
    enum { NDSTX_BG, NDSTX_SPR } type; /* represented in a bg or sprite. */
dalton@2693
   176
    int hw_index; /* sprite: index in the OAM. /  bg: 2 or 3. */
dalton@2690
   177
    struct
dalton@2690
   178
    {
dalton@2690
   179
        int hdx, hdy, vdx, vdy; /* affine transformation, used for scaling. */
dalton@2690
   180
        int pitch, bpp; /* some useful info */
dalton@2690
   181
    } dim;
dalton@2690
   182
    u16 *vram_pixels; /* where the pixel data is stored (a pointer into VRAM) */
dalton@2690
   183
    u16 *vram_palette; /* where the palette data is stored if it's indexed.*/
dalton@2690
   184
    /*int size;*/
dalton@2678
   185
} NDS_TextureData;
dalton@2672
   186
dalton@2672
   187
dalton@2672
   188
dalton@2670
   189
SDL_Renderer *
dalton@2677
   190
NDS_CreateRenderer(SDL_Window * window, Uint32 flags)
dalton@2670
   191
{
dalton@2670
   192
    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
dalton@2670
   193
    SDL_DisplayMode *displayMode = &display->current_mode;
dalton@2670
   194
    SDL_Renderer *renderer;
dalton@2677
   195
    NDS_RenderData *data;
dalton@2670
   196
    int i, n;
dalton@2688
   197
    int bpp;
dalton@2673
   198
    Uint32 Rmask, Gmask, Bmask, Amask;
dalton@2688
   199
dalton@2690
   200
    TRACE("+NDS_CreateRenderer\n");
dalton@2688
   201
    if (!SDL_PixelFormatEnumToMasks(displayMode->format, &bpp,
dalton@2673
   202
                                    &Rmask, &Gmask, &Bmask, &Amask)) {
dalton@2673
   203
        SDL_SetError("Unknown display format");
dalton@2673
   204
        return NULL;
dalton@2673
   205
    }
dalton@2688
   206
    switch(displayMode->format) {
dalton@2688
   207
        case SDL_PIXELFORMAT_INDEX8:
dalton@2688
   208
        case SDL_PIXELFORMAT_ABGR1555:
dalton@2688
   209
        case SDL_PIXELFORMAT_BGR555:
dalton@2688
   210
            /* okay */
dalton@2688
   211
            break;
dalton@2693
   212
        case SDL_PIXELFORMAT_RGB555:
dalton@2693
   213
        case SDL_PIXELFORMAT_RGB565:
dalton@2693
   214
        case SDL_PIXELFORMAT_ARGB1555:
dalton@2693
   215
            /* we'll take these too for now */
dalton@2693
   216
            break;
dalton@2688
   217
        default:
dalton@2688
   218
            printf("DEBUG: wrong display format!\n");
dalton@2688
   219
            break;
dalton@2688
   220
    }
dalton@2670
   221
dalton@2670
   222
    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
dalton@2670
   223
    if (!renderer) {
dalton@2670
   224
        SDL_OutOfMemory();
dalton@2670
   225
        return NULL;
dalton@2670
   226
    }
dalton@2670
   227
dalton@2677
   228
    data = (NDS_RenderData *) SDL_malloc(sizeof(*data));
dalton@2670
   229
    if (!data) {
dalton@2677
   230
        NDS_DestroyRenderer(renderer);
dalton@2670
   231
        SDL_OutOfMemory();
dalton@2670
   232
        return NULL;
dalton@2670
   233
    }
dalton@2670
   234
    SDL_zerop(data);
dalton@2670
   235
dalton@2677
   236
    renderer->RenderFill = NDS_RenderFill;
dalton@2677
   237
    renderer->RenderCopy = NDS_RenderCopy;
dalton@2677
   238
    renderer->RenderPresent = NDS_RenderPresent;
dalton@2677
   239
    renderer->DestroyRenderer = NDS_DestroyRenderer;
dalton@2677
   240
    renderer->info.name = NDS_RenderDriver.info.name;
dalton@2670
   241
    renderer->info.flags = 0;
dalton@2670
   242
    renderer->window = window->id;
dalton@2670
   243
    renderer->driverdata = data;
dalton@2679
   244
    renderer->CreateTexture = NDS_CreateTexture;
dalton@2679
   245
    renderer->QueryTexturePixels = NDS_QueryTexturePixels;
dalton@2679
   246
    renderer->SetTexturePalette = NDS_SetTexturePalette;
dalton@2679
   247
    renderer->GetTexturePalette = NDS_GetTexturePalette;
dalton@2679
   248
    renderer->SetTextureColorMod = NDS_SetTextureColorMod;
dalton@2679
   249
    renderer->SetTextureAlphaMod = NDS_SetTextureAlphaMod;
dalton@2679
   250
    renderer->SetTextureBlendMode = NDS_SetTextureBlendMode;
dalton@2679
   251
    renderer->SetTextureScaleMode = NDS_SetTextureScaleMode;
dalton@2679
   252
    renderer->UpdateTexture = NDS_UpdateTexture;
dalton@2679
   253
    renderer->LockTexture = NDS_LockTexture;
dalton@2679
   254
    renderer->UnlockTexture = NDS_UnlockTexture;
dalton@2679
   255
    renderer->DirtyTexture = NDS_DirtyTexture;
dalton@2679
   256
    renderer->DestroyTexture = NDS_DestroyTexture;
dalton@2670
   257
dalton@2679
   258
    renderer->info.mod_modes = NDS_RenderDriver.info.mod_modes;
dalton@2679
   259
    renderer->info.blend_modes = NDS_RenderDriver.info.blend_modes;
dalton@2679
   260
    renderer->info.scale_modes = NDS_RenderDriver.info.scale_modes;
dalton@2679
   261
    renderer->info.num_texture_formats =
dalton@2679
   262
        NDS_RenderDriver.info.num_texture_formats;
dalton@2679
   263
    SDL_memcpy(renderer->info.texture_formats,
dalton@2679
   264
               NDS_RenderDriver.info.texture_formats,
dalton@2690
   265
               sizeof(renderer->info.texture_formats));
dalton@2690
   266
    renderer->info.max_texture_width =
dalton@2690
   267
        NDS_RenderDriver.info.max_texture_width;
dalton@2679
   268
    renderer->info.max_texture_height =
dalton@2679
   269
        NDS_RenderDriver.info.max_texture_height;
dalton@2670
   270
dalton@2688
   271
    data->sub = 0; /* TODO: this is hard-coded to the "main" screen.
dalton@2688
   272
                            figure out how to detect whether to set it to
dalton@2688
   273
                            "sub" screen.  window->id, perhaps? */
dalton@2690
   274
    if(!data->sub) {
dalton@2690
   275
        data->bg = &BACKGROUND;
dalton@2690
   276
    } else {
dalton@2690
   277
        data->bg = &BACKGROUND_SUB;
dalton@2690
   278
    }
dalton@2690
   279
    data->bg_taken[2] = data->bg_taken[3] = 0;
dalton@2693
   280
dalton@2693
   281
    NDS_OAM_Init(&(data->oam_copy), data->sub); /* init sprites. */
dalton@2672
   282
dalton@2690
   283
    TRACE("-NDS_CreateRenderer\n");
dalton@2670
   284
    return renderer;
dalton@2670
   285
}
dalton@2670
   286
dalton@2670
   287
static int
dalton@2678
   288
NDS_ActivateRenderer(SDL_Renderer * renderer)
dalton@2678
   289
{
dalton@2678
   290
    NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
dalton@2690
   291
    TRACE("!NDS_ActivateRenderer\n");
dalton@2678
   292
    return 0;
dalton@2678
   293
}
dalton@2678
   294
dalton@2678
   295
static int
dalton@2678
   296
NDS_DisplayModeChanged(SDL_Renderer * renderer)
dalton@2678
   297
{
dalton@2678
   298
    NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
dalton@2690
   299
    TRACE("!NDS_DisplayModeChanged\n");
dalton@2678
   300
    return 0;
dalton@2678
   301
}
dalton@2678
   302
dalton@2678
   303
static int
dalton@2678
   304
NDS_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
dalton@2678
   305
{
dalton@2678
   306
    NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
dalton@2679
   307
    NDS_TextureData *txdat = NULL;
dalton@2682
   308
    int i;
dalton@2688
   309
    int bpp;
dalton@2688
   310
    Uint32 Rmask, Gmask, Bmask, Amask;
dalton@2688
   311
dalton@2690
   312
    TRACE("+NDS_CreateTexture\n");
dalton@2688
   313
    if (!SDL_PixelFormatEnumToMasks
dalton@2688
   314
        (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
dalton@2688
   315
        SDL_SetError("Unknown texture format");
dalton@2678
   316
        return -1;
dalton@2678
   317
    }
dalton@2678
   318
dalton@2688
   319
    /* conditional statements on w/h to place it as bg/sprite
dalton@2688
   320
       depending on which one it fits. */
dalton@2688
   321
    if(texture->w <= 64 && texture->h <= 64) {
dalton@2693
   322
        int whichspr = -1;
dalton@2688
   323
        printf("Tried to make a sprite.\n");
dalton@2690
   324
        txdat->type = NDSTX_SPR;
dalton@2693
   325
        for(i = 0; i < SPRITE_COUNT; ++i) {
dalton@2693
   326
            if(data->oam_copy.spriteBuffer[i].attribute[0] & ATTR0_DISABLED) {
dalton@2693
   327
                whichspr = i;
dalton@2693
   328
                break;
dalton@2693
   329
            }
dalton@2693
   330
        }
dalton@2693
   331
        if(whichspr >= 0) {
dalton@2693
   332
            SpriteEntry *sprent = &(data->oam_copy.spriteBuffer[whichspr]);
dalton@2695
   333
            int maxside = texture->w > texture->h ? texture->w : texture->h;
dalton@2695
   334
            int pitch;
dalton@2693
   335
dalton@2693
   336
            texture->driverdata = SDL_calloc(1, sizeof(NDS_TextureData));
dalton@2693
   337
            txdat = (NDS_TextureData*)texture->driverdata;
dalton@2693
   338
            if(!txdat) {
dalton@2693
   339
                SDL_OutOfMemory();
dalton@2693
   340
                return -1;
dalton@2693
   341
            }
dalton@2693
   342
dalton@2693
   343
            sprent->objMode = OBJMODE_BITMAP;
dalton@2693
   344
            sprent->posX = 0; sprent->posY = 0;
dalton@2693
   345
            sprent->colMode = OBJCOLOR_16; /* OBJCOLOR_256 for INDEX8 */
dalton@2694
   346
dalton@2694
   347
            /* the first 32 sprites get transformation matrices.
dalton@2694
   348
               first come, first served */
dalton@2693
   349
            if(whichspr < MATRIX_COUNT) {
dalton@2693
   350
                sprent->isRotoscale = 1;
dalton@2693
   351
                sprent->rsMatrixIdx = whichspr;
dalton@2693
   352
            }
dalton@2694
   353
dalton@2695
   354
            /* containing shape (square or 2:1 rectangles) */
dalton@2694
   355
            sprent->objShape = OBJSHAPE_SQUARE;
dalton@2694
   356
            if(texture->w/2 >= texture->h) {
dalton@2694
   357
                sprent->objShape = OBJSHAPE_WIDE;
dalton@2694
   358
            } else if(texture->h/2 >= texture->w) {
dalton@2694
   359
                sprent->objShape = OBJSHAPE_TALL;
dalton@2694
   360
            }
dalton@2695
   361
dalton@2695
   362
            /* size in pixels */
dalton@2695
   363
            /* FIXME: "pitch" is hardcoded for 2bytes per pixel. */
dalton@2695
   364
            sprent->objSize = OBJSIZE_64;
dalton@2695
   365
            pitch = 128;
dalton@2695
   366
            if(maxside <= 8) {
dalton@2695
   367
                sprent->objSize = OBJSIZE_8;
dalton@2695
   368
                pitch = 16;
dalton@2695
   369
            } else if(maxside <= 16) {
dalton@2695
   370
                sprent->objSize = OBJSIZE_16;
dalton@2695
   371
                pitch = 32;
dalton@2695
   372
            } else if(maxside <= 32) {
dalton@2695
   373
                sprent->objSize = OBJSIZE_32;
dalton@2695
   374
                pitch = 64;
dalton@2695
   375
            }
dalton@2695
   376
dalton@2695
   377
            /* FIXME: this is hard-coded and will obviously only work for one
dalton@2695
   378
               sprite-texture.  tells it to look at the beginning of SPRITE_GFX
dalton@2695
   379
               for its pixels. */
dalton@2695
   380
            sprent->tileIdx = 0;
dalton@2695
   381
dalton@2695
   382
            /* now for the texture data */
dalton@2695
   383
            txdat->type = NDSTX_SPR;
dalton@2695
   384
            txdat->hw_index = whichspr;
dalton@2695
   385
            txdat->dim.hdx = 0x100; txdat->dim.hdy = 0;
dalton@2695
   386
            txdat->dim.vdx = 0;     txdat->dim.vdy = 0x100;
dalton@2695
   387
            txdat->dim.pitch = pitch;
dalton@2695
   388
            txdat->dim.bpp = bpp;
dalton@2695
   389
            txdat->vram_pixels = (u16*)(data->sub ?
dalton@2695
   390
                SPRITE_GFX_SUB : SPRITE_GFX); /* FIXME: use tileIdx*boundary
dalton@2695
   391
                                                 to point to proper location */
dalton@2694
   392
        } else {
dalton@2694
   393
            SDL_SetError("Out of NDS sprites.");
dalton@2693
   394
        }
dalton@2688
   395
    } else if(texture->w <= 256 && texture->h <= 256) {
dalton@2690
   396
        int whichbg = -1, base = 0;
dalton@2688
   397
        if(!data->bg_taken[2]) {
dalton@2688
   398
            whichbg = 2;
dalton@2688
   399
        } else if(!data->bg_taken[3]) {
dalton@2688
   400
            whichbg = 3;
dalton@2690
   401
            base = 4;
dalton@2688
   402
        }
dalton@2688
   403
        if(whichbg >= 0) {
dalton@2690
   404
            texture->driverdata = SDL_calloc(1, sizeof(NDS_TextureData));
dalton@2690
   405
            txdat = (NDS_TextureData*)texture->driverdata;
dalton@2690
   406
            if(!txdat) {
dalton@2690
   407
                SDL_OutOfMemory();
dalton@2690
   408
                return -1;
dalton@2690
   409
            }
dalton@2690
   410
dalton@2695
   411
            /* this is hard-coded to being 256x256 ABGR1555 for now. */
dalton@2688
   412
            data->bg->control[whichbg] = (bpp == 8) ?
dalton@2688
   413
                BG_BMP8_256x256 : BG_BMP16_256x256;
dalton@2690
   414
dalton@2690
   415
            data->bg->control[whichbg] |= BG_BMP_BASE(base);
dalton@2690
   416
dalton@2688
   417
            data->bg->scroll[whichbg].x = 0;
dalton@2688
   418
            data->bg->scroll[whichbg].y = 0;
dalton@2690
   419
dalton@2688
   420
            txdat->type = NDSTX_BG;
dalton@2688
   421
            txdat->hw_index = whichbg;
dalton@2688
   422
            txdat->dim.hdx = 0x100; txdat->dim.hdy = 0;
dalton@2688
   423
            txdat->dim.vdx = 0;     txdat->dim.vdy = 0x100;
dalton@2695
   424
            txdat->dim.pitch = 512;
dalton@2688
   425
            txdat->dim.bpp = bpp;
dalton@2690
   426
            txdat->vram_pixels = (u16*)(data->sub ?
dalton@2690
   427
                BG_BMP_RAM_SUB(base) : BG_BMP_RAM(base));
dalton@2691
   428
dalton@2690
   429
            /*txdat->size = txdat->dim.pitch * texture->h;*/
dalton@2688
   430
        } else {
dalton@2688
   431
            SDL_SetError("Out of NDS backgrounds.");
dalton@2688
   432
        }
dalton@2688
   433
    } else {
dalton@2688
   434
        SDL_SetError("Texture too big for NDS hardware.");
dalton@2688
   435
    }
dalton@2688
   436
dalton@2690
   437
    TRACE("-NDS_CreateTexture\n");
dalton@2678
   438
    if (!texture->driverdata) {
dalton@2678
   439
        return -1;
dalton@2678
   440
    }
dalton@2688
   441
dalton@2678
   442
    return 0;
dalton@2678
   443
}
dalton@2678
   444
dalton@2678
   445
static int
dalton@2678
   446
NDS_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
dalton@2678
   447
                      void **pixels, int *pitch)
dalton@2678
   448
{
dalton@2688
   449
    NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
dalton@2690
   450
    TRACE("+NDS_QueryTexturePixels\n");
dalton@2690
   451
    *pixels = txdat->vram_pixels;
dalton@2688
   452
    *pitch = txdat->dim.pitch;
dalton@2690
   453
    TRACE("-NDS_QueryTexturePixels\n");
dalton@2688
   454
    return 0;
dalton@2678
   455
}
dalton@2678
   456
dalton@2678
   457
static int
dalton@2685
   458
NDS_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
dalton@2685
   459
                 const SDL_Rect * rect, const void *pixels, int pitch)
dalton@2685
   460
{
dalton@2691
   461
    NDS_TextureData *txdat;
dalton@2688
   462
    Uint8 *src, *dst;
dalton@2688
   463
    int row; size_t length;
dalton@2690
   464
    TRACE("+NDS_UpdateTexture\n");
dalton@2693
   465
dalton@2691
   466
    txdat = (NDS_TextureData *) texture->driverdata;
dalton@2688
   467
dalton@2688
   468
    src = (Uint8 *) pixels;
dalton@2688
   469
    dst =
dalton@2690
   470
        (Uint8 *) txdat->vram_pixels + rect->y * txdat->dim.pitch +
dalton@2691
   471
        rect->x * ((txdat->dim.bpp+1)/8);
dalton@2691
   472
    length = rect->w * ((txdat->dim.bpp+1)/8);
dalton@2693
   473
dalton@2693
   474
    if(rect->w == texture->w) {
dalton@2693
   475
        dmaCopy(src, dst, length*rect->h);
dalton@2693
   476
    } else {
dalton@2693
   477
        for (row = 0; row < rect->h; ++row) {
dalton@2693
   478
            dmaCopy(src, dst, length);
dalton@2693
   479
            src += pitch;
dalton@2693
   480
            dst += txdat->dim.pitch;
dalton@2693
   481
        }
dalton@2685
   482
    }
dalton@2688
   483
dalton@2690
   484
    TRACE("-NDS_UpdateTexture\n");
dalton@2688
   485
    return 0;
dalton@2685
   486
}
dalton@2685
   487
dalton@2685
   488
static int
dalton@2685
   489
NDS_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
dalton@2685
   490
               const SDL_Rect * rect, int markDirty, void **pixels,
dalton@2685
   491
               int *pitch)
dalton@2685
   492
{
dalton@2688
   493
    NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
dalton@2690
   494
    TRACE("+NDS_LockTexture\n");
dalton@2685
   495
dalton@2690
   496
    *pixels = (void *) ((u8 *)txdat->vram_pixels + rect->y
dalton@2691
   497
                        * txdat->dim.pitch + rect->x * ((txdat->dim.bpp+1)/8));
dalton@2688
   498
    *pitch = txdat->dim.pitch;
dalton@2693
   499
dalton@2690
   500
    TRACE("-NDS_LockTexture\n");
dalton@2688
   501
    return 0;
dalton@2685
   502
}
dalton@2685
   503
dalton@2685
   504
static void
dalton@2685
   505
NDS_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
dalton@2685
   506
{
dalton@2690
   507
    TRACE("+NDS_UnlockTexture\n");
dalton@2690
   508
    TRACE("-NDS_UnlockTexture\n");
dalton@2685
   509
}
dalton@2685
   510
dalton@2685
   511
static void
dalton@2685
   512
NDS_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
dalton@2685
   513
                int numrects, const SDL_Rect * rects)
dalton@2688
   514
{
dalton@2688
   515
    /* stub */
dalton@2690
   516
    TRACE("!NDS_DirtyTexture\n");
dalton@2685
   517
}
dalton@2685
   518
dalton@2685
   519
static int
dalton@2685
   520
NDS_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b,
dalton@2685
   521
                   Uint8 a, const SDL_Rect * rect)
dalton@2685
   522
{
dalton@2685
   523
    NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
dalton@2685
   524
    SDL_Rect real_rect = *rect;
dalton@2685
   525
    u16 color;
dalton@2685
   526
    int i, j;
dalton@2685
   527
dalton@2690
   528
    TRACE("+NDS_RenderFill\n");
dalton@2688
   529
    color = RGB8(r,g,b); /* <-- macro in libnds that makes an ARGB1555 pixel */
dalton@2685
   530
    /* TODO: make a single-color sprite and stretch it.
dalton@2688
   531
       calculate the "HDX" width modifier of the sprite by:
dalton@2688
   532
         let S be the actual sprite's width (like, 32 pixels for example)
dalton@2688
   533
         let R be the rectangle's width (maybe 50 pixels)
dalton@2688
   534
         HDX = (R<<8) / S;
dalton@2688
   535
         (it's fixed point, hence the bit shift.  same goes for vertical.
dalton@2688
   536
         be sure to use 32-bit int's for the bit shift before the division!)
dalton@2688
   537
     */
dalton@2688
   538
dalton@2690
   539
    TRACE("-NDS_RenderFill\n");
dalton@2685
   540
    return 0;
dalton@2685
   541
}
dalton@2685
   542
dalton@2685
   543
static int
dalton@2685
   544
NDS_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
dalton@2685
   545
                   const SDL_Rect * srcrect, const SDL_Rect * dstrect)
dalton@2685
   546
{
dalton@2685
   547
    NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
dalton@2685
   548
    NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
dalton@2687
   549
    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
dalton@2687
   550
    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
dalton@2685
   551
    int i;
dalton@2685
   552
    int bpp = SDL_BYTESPERPIXEL(texture->format);
dalton@2685
   553
    int pitch = txdat->dim.pitch;
dalton@2690
   554
dalton@2690
   555
    TRACE("+NDS_RenderCopy\n");
dalton@2685
   556
    if(txdat->type == NDSTX_BG) {
dalton@2693
   557
        bg_rotation *bgrot = (txdat->hw_index == 2) ?
dalton@2685
   558
            &(data->bg->bg2_rotation) : &(data->bg->bg3_rotation);
dalton@2693
   559
        bgrot->xdx = txdat->dim.hdx;
dalton@2693
   560
        bgrot->xdy = txdat->dim.hdy;
dalton@2693
   561
        bgrot->ydx = txdat->dim.vdx;
dalton@2693
   562
        bgrot->ydy = txdat->dim.vdy;
dalton@2693
   563
        bgrot->centerX = 0;
dalton@2693
   564
        bgrot->centerY = 0;
dalton@2693
   565
dalton@2693
   566
        data->bg->scroll[txdat->hw_index].x = dstrect->x;
dalton@2693
   567
        data->bg->scroll[txdat->hw_index].y = dstrect->y;
dalton@2685
   568
    } else {
dalton@2693
   569
        /* sprites not fully implemented yet */
dalton@2693
   570
        SpriteEntry *spr = &(data->oam_copy.spriteBuffer[txdat->hw_index]);
dalton@2693
   571
        spr->posX = dstrect->x;
dalton@2693
   572
        spr->posY = dstrect->y;
dalton@2695
   573
        if(txdat->hw_index < MATRIX_COUNT && spr->isRotoscale) {
dalton@2693
   574
            SpriteRotation *sprot = &(data->oam_copy.matrixBuffer[txdat->hw_index]);
dalton@2693
   575
            sprot->hdx = txdat->dim.hdx;
dalton@2693
   576
            sprot->hdy = txdat->dim.hdy;
dalton@2693
   577
            sprot->vdx = txdat->dim.vdx;
dalton@2693
   578
            sprot->vdy = txdat->dim.vdy;
dalton@2693
   579
        }
dalton@2691
   580
        printf("tried to RenderCopy a sprite.\n");
dalton@2685
   581
    }
dalton@2690
   582
    TRACE("-NDS_RenderCopy\n");
dalton@2690
   583
dalton@2685
   584
    return 0;
dalton@2685
   585
}
dalton@2685
   586
dalton@2685
   587
dalton@2685
   588
static void
dalton@2685
   589
NDS_RenderPresent(SDL_Renderer * renderer)
dalton@2685
   590
{
dalton@2685
   591
    NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
dalton@2687
   592
    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
dalton@2687
   593
    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
dalton@2693
   594
dalton@2690
   595
    TRACE("+NDS_RenderPresent\n");
dalton@2693
   596
    /* update sprites */
dalton@2693
   597
    NDS_OAM_Update(&(data->oam_copy), data->sub);
dalton@2685
   598
    /* vsync for NDS */
dalton@2685
   599
    if (renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) {
dalton@2685
   600
        swiWaitForVBlank();
dalton@2685
   601
    }
dalton@2690
   602
    TRACE("-NDS_RenderPresent\n");
dalton@2685
   603
}
dalton@2685
   604
dalton@2685
   605
static void
dalton@2685
   606
NDS_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
dalton@2685
   607
{
dalton@2695
   608
    NDS_TextureData *txdat = texture->driverdata;
dalton@2690
   609
    TRACE("+NDS_DestroyTexture\n");
dalton@2693
   610
    /* free anything else allocated for texture */
dalton@2693
   611
    /*SDL_FreeDirtyRects(&txdat->dirty);*/
dalton@2693
   612
    SDL_free(txdat);
dalton@2690
   613
    TRACE("-NDS_DestroyTexture\n");
dalton@2685
   614
}
dalton@2685
   615
dalton@2685
   616
static void
dalton@2685
   617
NDS_DestroyRenderer(SDL_Renderer * renderer)
dalton@2685
   618
{
dalton@2685
   619
    NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
dalton@2695
   620
    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
dalton@2695
   621
    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
dalton@2685
   622
    int i;
dalton@2685
   623
dalton@2690
   624
    TRACE("+NDS_DestroyRenderer\n");
dalton@2685
   625
    if (data) {
dalton@2688
   626
        /* TODO: free anything else relevant. */
dalton@2693
   627
        /*if (data->surface.format) {
dalton@2685
   628
            SDL_SetSurfacePalette(&data->surface, NULL);
dalton@2685
   629
            SDL_FreeFormat(data->surface.format);
dalton@2685
   630
        }
dalton@2685
   631
        if (display->palette) {
dalton@2685
   632
            SDL_DelPaletteWatch(display->palette, DisplayPaletteChanged,
dalton@2685
   633
                                data);
dalton@2693
   634
        }*/
dalton@2693
   635
        /*SDL_FreeDirtyRects(&data->dirty);*/
dalton@2685
   636
        SDL_free(data);
dalton@2685
   637
    }
dalton@2685
   638
    SDL_free(renderer);
dalton@2690
   639
    TRACE("-NDS_DestroyRenderer\n");
dalton@2685
   640
}
dalton@2685
   641
dalton@2685
   642
static int
dalton@2678
   643
NDS_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
dalton@2678
   644
                     const SDL_Color * colors, int firstcolor, int ncolors)
dalton@2678
   645
{
dalton@2688
   646
    NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
dalton@2690
   647
    TRACE("+NDS_SetTexturePalette\n");
dalton@2688
   648
    /* set 8-bit modes in the background control registers
dalton@2688
   649
       for backgrounds, BGn_CR |= BG_256_COLOR */
dalton@2690
   650
    TRACE("-NDS_SetTexturePalette\n");
dalton@2688
   651
    return 0;
dalton@2678
   652
}
dalton@2678
   653
dalton@2678
   654
static int
dalton@2678
   655
NDS_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
dalton@2678
   656
                     SDL_Color * colors, int firstcolor, int ncolors)
dalton@2678
   657
{
dalton@2695
   658
    NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
dalton@2696
   659
    TRACE("!NDS_GetTexturePalette\n");
dalton@2688
   660
    return 0;
dalton@2678
   661
}
dalton@2678
   662
dalton@2678
   663
static int
dalton@2678
   664
NDS_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
dalton@2678
   665
{
dalton@2690
   666
    TRACE("!NDS_SetTextureColorMod\n");
dalton@2688
   667
    /* stub! */
dalton@2678
   668
    return 0;
dalton@2678
   669
}
dalton@2678
   670
dalton@2678
   671
static int
dalton@2678
   672
NDS_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
dalton@2678
   673
{
dalton@2690
   674
    TRACE("!NDS_SetTextureAlphaMod\n");
dalton@2688
   675
    /* stub! */
dalton@2678
   676
    return 0;
dalton@2678
   677
}
dalton@2678
   678
dalton@2678
   679
static int
dalton@2678
   680
NDS_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
dalton@2678
   681
{
dalton@2690
   682
    TRACE("!NDS_SetTextureBlendMode\n");
dalton@2688
   683
    /* stub! */
dalton@2678
   684
    return 0;
dalton@2678
   685
}
dalton@2678
   686
dalton@2678
   687
static int
dalton@2678
   688
NDS_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
dalton@2678
   689
{
dalton@2690
   690
    TRACE("!NDS_SetTextureScaleMode\n");
dalton@2688
   691
    /* stub! (note: NDS hardware scaling is nearest neighbor.) */
dalton@2678
   692
    return 0;
dalton@2678
   693
}
dalton@2678
   694
dalton@2670
   695
/* vi: set ts=4 sw=4 expandtab: */