More NDS video driver work.
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2006 Sam Lantinga
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "SDL_config.h"
29 #include "SDL_video.h"
30 #include "../SDL_sysvideo.h"
31 #include "../SDL_yuv_sw_c.h"
32 #include "../SDL_renderer_sw.h"
35 /* SDL surface based renderer implementation */
37 static SDL_Renderer *NDS_CreateRenderer(SDL_Window * window, Uint32 flags);
38 static int NDS_ActivateRenderer(SDL_Renderer * renderer);
39 static int NDS_DisplayModeChanged(SDL_Renderer * renderer);
40 static int NDS_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
41 static int NDS_QueryTexturePixels(SDL_Renderer * renderer,
42 SDL_Texture * texture, void **pixels,
44 static int NDS_SetTexturePalette(SDL_Renderer * renderer,
45 SDL_Texture * texture,
46 const SDL_Color * colors, int firstcolor,
48 static int NDS_GetTexturePalette(SDL_Renderer * renderer,
49 SDL_Texture * texture, SDL_Color * colors,
50 int firstcolor, int ncolors);
51 static int NDS_SetTextureColorMod(SDL_Renderer * renderer,
52 SDL_Texture * texture);
53 static int NDS_SetTextureAlphaMod(SDL_Renderer * renderer,
54 SDL_Texture * texture);
55 static int NDS_SetTextureBlendMode(SDL_Renderer * renderer,
56 SDL_Texture * texture);
57 static int NDS_SetTextureScaleMode(SDL_Renderer * renderer,
58 SDL_Texture * texture);
59 static int NDS_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
60 const SDL_Rect * rect, const void *pixels,
62 static int NDS_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
63 const SDL_Rect * rect, int markDirty, void **pixels,
65 static void NDS_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
66 static void NDS_DirtyTexture(SDL_Renderer * renderer,
67 SDL_Texture * texture, int numrects,
68 const SDL_Rect * rects);
69 static int NDS_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g,
70 Uint8 b, Uint8 a, const SDL_Rect * rect);
71 static int NDS_RenderCopy(SDL_Renderer * renderer,
72 SDL_Texture * texture,
73 const SDL_Rect * srcrect,
74 const SDL_Rect * dstrect);
75 static void NDS_RenderPresent(SDL_Renderer * renderer);
76 static void NDS_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
77 static void NDS_DestroyRenderer(SDL_Renderer * renderer);
80 SDL_RenderDriver NDS_RenderDriver = {
82 { "nds", /* char* name */
83 (SDL_RENDERER_SINGLEBUFFER|SDL_RENDERER_ACCELERATED), /* u32 flags */
84 (SDL_TEXTUREMODULATE_NONE), /* u32 mod_modes */
85 (SDL_TEXTUREBLENDMODE_NONE), /* u32 blend_modes */
86 (SDL_TEXTURESCALEMODE_NONE), /* u32 scale_modes */
87 3, /* u32 num_texture_formats */
89 SDL_PIXELFORMAT_INDEX8,
90 SDL_PIXELFORMAT_RGB555,
91 SDL_PIXELFORMAT_RGB565
92 }, /* u32 texture_formats[20] */
93 (256), /* int max_texture_width */
94 (256), /* int max_texture_height */
107 enum { NDSTX_BG, NDSTX_SPR } type;
109 struct { int w, h, pitch, bpp; } dim;
114 /* this is mainly hackish testing/debugging stuff to get cleaned up soon
115 anything named sdlds_blah shouldn't make it into the stable version
121 /* hack to get the proper colors until I actually get BGR555 to work right */
122 u16 Rmask = 0x7C00, Bmask = 0x001F, GAmask = 0x83E0, r, b;
123 r = (c & Rmask) >> 10;
124 b = (c & Bmask) << 10;
125 return (c & GAmask) | r | b;
129 sdlds_print_pixfmt_info(SDL_PixelFormat * f)
133 printf("bpp: %d\nRGBA: %x %x %x %x\n",
134 f->BitsPerPixel, f->Rmask, f->Gmask, f->Bmask, f->Amask);
138 sdlds_print_surface_info(SDL_Surface * s)
142 printf("flags: %x\nsize: %dx%d, pitch: %d\nlocked: %d, refcount: %d\n",
143 s->flags, s->w, s->h, s->pitch, s->locked, s->refcount);
144 sdlds_print_pixfmt_info(s->format);
147 /* again the above shouldn't make it into the stable version */
150 NDS_CreateRenderer(SDL_Window * window, Uint32 flags)
152 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
153 SDL_DisplayMode *displayMode = &display->current_mode;
154 SDL_Renderer *renderer;
155 NDS_RenderData *data;
158 Uint32 Rmask, Gmask, Bmask, Amask;
159 /* Uint32 Rmask = 0x7C00, Gmask = 0x03E0, Bmask = 0x001F, Amask = 0x8000;
160 Uint32 Rmask = 0x001F, Gmask = 0x03E0, Bmask = 0x7C00, Amask = 0x8000;
163 /* hard coded this to BGR555 for now */
164 if (!SDL_PixelFormatEnumToMasks(SDL_PIXELFORMAT_BGR555, &bpp,
165 &Rmask, &Gmask, &Bmask, &Amask)) {
166 SDL_SetError("Unknown display format");
170 renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
176 data = (NDS_RenderData *) SDL_malloc(sizeof(*data));
178 NDS_DestroyRenderer(renderer);
184 renderer->RenderFill = NDS_RenderFill;
185 renderer->RenderCopy = NDS_RenderCopy;
186 renderer->RenderPresent = NDS_RenderPresent;
187 renderer->DestroyRenderer = NDS_DestroyRenderer;
188 renderer->info.name = NDS_RenderDriver.info.name;
189 renderer->info.flags = 0;
190 renderer->window = window->id;
191 renderer->driverdata = data;
192 renderer->CreateTexture = NDS_CreateTexture;
193 renderer->QueryTexturePixels = NDS_QueryTexturePixels;
194 renderer->SetTexturePalette = NDS_SetTexturePalette;
195 renderer->GetTexturePalette = NDS_GetTexturePalette;
196 renderer->SetTextureColorMod = NDS_SetTextureColorMod;
197 renderer->SetTextureAlphaMod = NDS_SetTextureAlphaMod;
198 renderer->SetTextureBlendMode = NDS_SetTextureBlendMode;
199 renderer->SetTextureScaleMode = NDS_SetTextureScaleMode;
200 renderer->UpdateTexture = NDS_UpdateTexture;
201 renderer->LockTexture = NDS_LockTexture;
202 renderer->UnlockTexture = NDS_UnlockTexture;
203 renderer->DirtyTexture = NDS_DirtyTexture;
204 renderer->DestroyTexture = NDS_DestroyTexture;
206 renderer->info.mod_modes = NDS_RenderDriver.info.mod_modes;
207 renderer->info.blend_modes = NDS_RenderDriver.info.blend_modes;
208 renderer->info.scale_modes = NDS_RenderDriver.info.scale_modes;
209 renderer->info.num_texture_formats =
210 NDS_RenderDriver.info.num_texture_formats;
211 SDL_memcpy(renderer->info.texture_formats,
212 NDS_RenderDriver.info.texture_formats,
213 sizeof(renderer->info.texture_formats));;
214 renderer->info.max_texture_width = NDS_RenderDriver.info.max_texture_width;
215 renderer->info.max_texture_height =
216 NDS_RenderDriver.info.max_texture_height;
218 /*data->fb = (u16*)0x06020000;*/
219 data->bg = &BACKGROUND;
220 data->bg_taken[2] = data->bg_taken[3] = 0;
227 NDS_ActivateRenderer(SDL_Renderer * renderer)
229 NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
230 /* stub. TODO: figure out what needs to be done, if anything. */
235 NDS_DisplayModeChanged(SDL_Renderer * renderer)
237 NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
238 /* stub. TODO: figure out what needs to be done */
243 NDS_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
245 NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
246 NDS_TextureData *txdat = NULL;
247 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
248 SDL_SetError("Unsupported texture format");
252 Uint32 Rmask, Gmask, Bmask, Amask;
254 if (!SDL_PixelFormatEnumToMasks
255 (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
256 SDL_SetError("Unknown texture format");
259 /* conditional statements on w/h to place it as bg/sprite */
260 /*if(texture->w <= 64 && texture->h <= 64) {
261 sprites not implemented yet. elegant, I know.
262 } else*/ if(texture->w <= 256 && texture->h <= 256) {
264 if(!data->bg_taken[2]) {
266 data->bg->bg2_rotation.xdx = 0x100;
267 data->bg->bg2_rotation.xdy = 0;
268 data->bg->bg2_rotation.ydx = 0;
269 data->bg->bg2_rotation.ydy = 0x100;
270 data->bg->bg2_rotation.centerX = 0;
271 data->bg->bg2_rotation.centerY = 0;
272 } else if(!data->bg_taken[3]) {
274 data->bg->bg3_rotation.xdx = 0x100;
275 data->bg->bg3_rotation.xdy = 0;
276 data->bg->bg3_rotation.ydx = 0;
277 data->bg->bg3_rotation.ydy = 0x100;
278 data->bg->bg3_rotation.centerX = 0;
279 data->bg->bg3_rotation.centerY = 0;
282 data->bg->control[whichbg] = (bpp == 8) ?
283 BG_BMP8_256x256 : BG_BMP16_256x256;
284 data->bg->scroll[whichbg].x = 0;
285 data->bg->scroll[whichbg].y = 0;
286 texture->driverdata = SDL_calloc(1, sizeof(NDS_TextureData));
287 txdat = (NDS_TextureData*)texture->driverdata;
288 txdat->type = NDSTX_BG;
289 txdat->hw_index = whichbg;
290 txdat->dim.w = texture->w;
291 txdat->dim.h = texture->h;
292 txdat->dim.pitch = 256 * (bpp/8);
293 txdat->dim.bpp = bpp;
294 txdat->vram = (u16*)(data->sub ?
295 BG_BMP_RAM_SUB(whichbg) : BG_BMP_RAM(whichbg));
297 SDL_SetError("Out of NDS backgrounds.");
300 SDL_SetError("Texture too big for NDS hardware.");
304 if (!texture->driverdata) {
311 NDS_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
312 void **pixels, int *pitch)
314 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
315 SDL_SetError("Unsupported texture format");
318 NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
320 *pixels = txdat->vram;
321 *pitch = txdat->dim.pitch;
327 NDS_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
328 const SDL_Color * colors, int firstcolor, int ncolors)
330 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
331 SDL_SetError("YUV textures don't have a palette");
334 NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
335 /* TODO: mess with 8-bit modes and/or 16-color palette modes */
341 NDS_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
342 SDL_Color * colors, int firstcolor, int ncolors)
344 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
345 SDL_SetError("YUV textures don't have a palette");
348 NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
349 /* TODO: mess with 8-bit modes and/or 16-color palette modes */
355 NDS_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
357 /* stub. TODO: figure out what needs to be done, if anything */
362 NDS_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
364 /* stub. TODO: figure out what needs to be done, if anything */
369 NDS_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
371 /* stub. TODO: figure out what needs to be done, if anything */
376 NDS_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
378 /* stub. TODO: figure out what needs to be done.
379 (NDS hardware scaling is nearest neighbor.) */
384 NDS_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
385 const SDL_Rect * rect, const void *pixels, int pitch)
387 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
388 SDL_SetError("Unsupported texture format");
391 NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
395 /* IMPORTANT! copy the new pixels into the sprite or bg. */
396 src = (Uint8 *) pixels;
398 (Uint8 *) txdat->vram + rect->y * txdat->dim.pitch +
399 rect->x * (txdat->dim.bpp/8);
400 length = rect->w * (txdat->dim.bpp/8);
401 for (row = 0; row < rect->h; ++row) {
402 SDL_memcpy(dst, src, length);
404 dst += txdat->dim.pitch;
411 NDS_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
412 const SDL_Rect * rect, int markDirty, void **pixels,
415 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
416 SDL_SetError("Unsupported texture format");
419 NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
421 *pixels = (void *) ((u8 *)txdat->vram + rect->y * txdat->dim.pitch
422 + rect->x * (txdat->dim.bpp/8));
423 *pitch = txdat->dim.pitch;
429 NDS_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
431 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
432 SDL_SetError("Unsupported texture format");
437 NDS_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
438 int numrects, const SDL_Rect * rects)
443 NDS_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b,
444 Uint8 a, const SDL_Rect * rect)
446 NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
447 SDL_Rect real_rect = *rect;
451 /* TODO: make a single-color sprite and stretch it.
452 color = RGB15(r>>3,g>>3,b>>3);
453 for (i = real_rect.x; i < real_rect.x+real_rect.w; ++i) {
454 for (j = real_rect.y; j < real_rect.y+real_rect.h; ++j) {
455 data->fb[(j + real_rect.y) * 256 + i + real_rect.x] =
463 NDS_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
464 const SDL_Rect * srcrect, const SDL_Rect * dstrect)
466 NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
467 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
468 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
471 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
472 SDL_Surface *target = data->screens[data->current_screen];
474 (Uint8 *) target->pixels + dstrect->y * target->pitch +
475 dstrect->x * target->format->BytesPerPixel;
476 return SDL_SW_CopyYUVToRGB((SDL_SW_YUVTexture *) texture->driverdata,
477 srcrect, display->current_mode.format,
478 dstrect->w, dstrect->h, pixels,
481 SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
482 SDL_Surface *target = data->screens[data->current_screen];
483 SDL_Rect real_srcrect = *srcrect;
484 SDL_Rect real_dstrect = *dstrect;
485 return SDL_LowerBlit(surface, &real_srcrect, target, &real_dstrect);
493 NDS_RenderPresent(SDL_Renderer * renderer)
495 NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
496 /* Send the data to the display TODO */
498 /* Update the flipping chain, if any */
499 if (renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) {
505 NDS_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
507 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
508 SDL_SetError("Unsupported texture format");
510 /* free anything else allocated for texture */
511 SDL_free(texture->driverdata);
516 NDS_DestroyRenderer(SDL_Renderer * renderer)
518 NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
519 /*SDL_Window *window = SDL_GetWindowFromID(renderer->window);
520 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);*/
524 /* TODO: free anything relevant. */
525 /*for (i = 0; i < SDL_arraysize(data->texture); ++i) {
526 if (data->texture[i]) {
527 DestroyTexture(data->renderer, data->texture[i]);
530 if (data->surface.format) {
531 SDL_SetSurfacePalette(&data->surface, NULL);
532 SDL_FreeFormat(data->surface.format);
534 if (display->palette) {
535 SDL_DelPaletteWatch(display->palette, DisplayPaletteChanged,
538 SDL_FreeDirtyRects(&data->dirty);*/
544 /* vi: set ts=4 sw=4 expandtab: */