This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_ndsrender.c
557 lines (502 loc) · 18.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2006 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include <stdio.h>
#include <stdlib.h>
#include <nds.h>
#include "SDL_config.h"
#include "SDL_video.h"
#include "../SDL_sysvideo.h"
#include "../SDL_yuv_sw_c.h"
#include "../SDL_renderer_sw.h"
35
/* SDL NDS renderer implementation */
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
static SDL_Renderer *NDS_CreateRenderer(SDL_Window * window, Uint32 flags);
static int NDS_ActivateRenderer(SDL_Renderer * renderer);
static int NDS_DisplayModeChanged(SDL_Renderer * renderer);
static int NDS_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
static int NDS_QueryTexturePixels(SDL_Renderer * renderer,
SDL_Texture * texture, void **pixels,
int *pitch);
static int NDS_SetTexturePalette(SDL_Renderer * renderer,
SDL_Texture * texture,
const SDL_Color * colors, int firstcolor,
int ncolors);
static int NDS_GetTexturePalette(SDL_Renderer * renderer,
SDL_Texture * texture, SDL_Color * colors,
int firstcolor, int ncolors);
static int NDS_SetTextureColorMod(SDL_Renderer * renderer,
SDL_Texture * texture);
static int NDS_SetTextureAlphaMod(SDL_Renderer * renderer,
SDL_Texture * texture);
static int NDS_SetTextureBlendMode(SDL_Renderer * renderer,
SDL_Texture * texture);
static int NDS_SetTextureScaleMode(SDL_Renderer * renderer,
SDL_Texture * texture);
static int NDS_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, const void *pixels,
int pitch);
static int NDS_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, int markDirty, void **pixels,
int *pitch);
static void NDS_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
static void NDS_DirtyTexture(SDL_Renderer * renderer,
SDL_Texture * texture, int numrects,
const SDL_Rect * rects);
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
73
74
SDL_Texture * texture,
const SDL_Rect * srcrect,
const SDL_Rect * dstrect);
75
76
77
static void NDS_RenderPresent(SDL_Renderer * renderer);
static void NDS_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
static void NDS_DestroyRenderer(SDL_Renderer * renderer);
78
79
80
81
SDL_RenderDriver NDS_RenderDriver = {
NDS_CreateRenderer,
82
83
84
85
86
87
88
89
{ "nds", /* char* name */
(SDL_RENDERER_SINGLEBUFFER|SDL_RENDERER_ACCELERATED), /* u32 flags */
(SDL_TEXTUREMODULATE_NONE), /* u32 mod_modes */
(SDL_TEXTUREBLENDMODE_NONE), /* u32 blend_modes */
(SDL_TEXTURESCALEMODE_NONE), /* u32 scale_modes */
3, /* u32 num_texture_formats */
{
SDL_PIXELFORMAT_INDEX8,
90
91
SDL_PIXELFORMAT_ABGR1555,
SDL_PIXELFORMAT_BGR555,
92
93
94
95
}, /* u32 texture_formats[20] */
(256), /* int max_texture_width */
(256), /* int max_texture_height */
}
96
97
98
99
};
typedef struct
{
100
101
bg_attribute *bg;
u8 bg_taken[4];
102
/* todo for sprites: pSpriteRotation and pSpriteEntry. pointers to OAM */
103
int sub;
104
} NDS_RenderData;
105
106
107
108
typedef struct
{
enum { NDSTX_BG, NDSTX_SPR } type;
109
int hw_index;
110
struct { int hdx, hdy, vdx, vdy, pitch, bpp; } dim;
111
112
u16 *vram;
} NDS_TextureData;
113
114
115
116
117
118
119
/* this is mainly hackish testing/debugging stuff to get cleaned up soon
anything named sdlds_blah shouldn't make it into the stable version
*/
u16
120
121
122
sdlds_rgb2bgr(u16 c)
{
/* hack to get the proper colors until I actually get BGR555 to work right */
123
124
125
126
127
128
u16 Rmask = 0x7C00, Bmask = 0x001F, GAmask = 0x83E0, r, b;
r = (c & Rmask) >> 10;
b = (c & Bmask) << 10;
return (c & GAmask) | r | b;
}
129
/* again the above shouldn't make it into the stable version */
130
131
SDL_Renderer *
132
NDS_CreateRenderer(SDL_Window * window, Uint32 flags)
133
134
135
136
{
SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
SDL_DisplayMode *displayMode = &display->current_mode;
SDL_Renderer *renderer;
137
NDS_RenderData *data;
138
int i, n;
139
int bpp = 15;
140
141
Uint32 Rmask, Gmask, Bmask, Amask;
/* Uint32 Rmask = 0x7C00, Gmask = 0x03E0, Bmask = 0x001F, Amask = 0x8000;
142
Uint32 Rmask = 0x001F, Gmask = 0x03E0, Bmask = 0x7C00, Amask = 0x8000;
143
*/
144
printf("+NDS_CreateRenderer\n");
145
146
147
148
149
150
151
/* hard coded this to BGR555 for now */
if (!SDL_PixelFormatEnumToMasks(SDL_PIXELFORMAT_BGR555, &bpp,
&Rmask, &Gmask, &Bmask, &Amask)) {
SDL_SetError("Unknown display format");
return NULL;
}
152
153
154
155
156
157
158
renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
SDL_OutOfMemory();
return NULL;
}
159
data = (NDS_RenderData *) SDL_malloc(sizeof(*data));
160
if (!data) {
161
NDS_DestroyRenderer(renderer);
162
163
164
165
166
SDL_OutOfMemory();
return NULL;
}
SDL_zerop(data);
167
168
169
170
171
renderer->RenderFill = NDS_RenderFill;
renderer->RenderCopy = NDS_RenderCopy;
renderer->RenderPresent = NDS_RenderPresent;
renderer->DestroyRenderer = NDS_DestroyRenderer;
renderer->info.name = NDS_RenderDriver.info.name;
172
173
174
renderer->info.flags = 0;
renderer->window = window->id;
renderer->driverdata = data;
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
renderer->CreateTexture = NDS_CreateTexture;
renderer->QueryTexturePixels = NDS_QueryTexturePixels;
renderer->SetTexturePalette = NDS_SetTexturePalette;
renderer->GetTexturePalette = NDS_GetTexturePalette;
renderer->SetTextureColorMod = NDS_SetTextureColorMod;
renderer->SetTextureAlphaMod = NDS_SetTextureAlphaMod;
renderer->SetTextureBlendMode = NDS_SetTextureBlendMode;
renderer->SetTextureScaleMode = NDS_SetTextureScaleMode;
renderer->UpdateTexture = NDS_UpdateTexture;
renderer->LockTexture = NDS_LockTexture;
renderer->UnlockTexture = NDS_UnlockTexture;
renderer->DirtyTexture = NDS_DirtyTexture;
renderer->DestroyTexture = NDS_DestroyTexture;
renderer->info.mod_modes = NDS_RenderDriver.info.mod_modes;
renderer->info.blend_modes = NDS_RenderDriver.info.blend_modes;
renderer->info.scale_modes = NDS_RenderDriver.info.scale_modes;
renderer->info.num_texture_formats =
NDS_RenderDriver.info.num_texture_formats;
SDL_memcpy(renderer->info.texture_formats,
NDS_RenderDriver.info.texture_formats,
sizeof(renderer->info.texture_formats));;
renderer->info.max_texture_width = NDS_RenderDriver.info.max_texture_width;
renderer->info.max_texture_height =
NDS_RenderDriver.info.max_texture_height;
/*data->fb = (u16*)0x06020000;*/
data->bg = &BACKGROUND;
data->bg_taken[2] = data->bg_taken[3] = 0;
data->sub = 0;
205
206
printf("-NDS_CreateRenderer\n");
207
208
209
return renderer;
}
210
211
212
213
214
static int
NDS_ActivateRenderer(SDL_Renderer * renderer)
{
NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
/* stub. TODO: figure out what needs to be done, if anything. */
215
printf("!NDS_ActivateRenderer\n");
216
217
218
219
220
221
222
223
return 0;
}
static int
NDS_DisplayModeChanged(SDL_Renderer * renderer)
{
NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
/* stub. TODO: figure out what needs to be done */
224
printf("!NDS_DisplayModeChanged\n");
225
226
227
228
229
230
231
return 0;
}
static int
NDS_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{
NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
232
NDS_TextureData *txdat = NULL;
233
int i;
234
printf("+NDS_CreateTexture\n");
235
236
237
238
239
240
241
242
243
244
245
246
if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
SDL_SetError("Unsupported texture format");
return -1;
} else {
int bpp;
Uint32 Rmask, Gmask, Bmask, Amask;
if (!SDL_PixelFormatEnumToMasks
(texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
SDL_SetError("Unknown texture format");
return -1;
}
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
/* conditional statements on w/h to place it as bg/sprite */
/*if(texture->w <= 64 && texture->h <= 64) {
sprites not implemented yet. elegant, I know.
} else*/ if(texture->w <= 256 && texture->h <= 256) {
int whichbg = -1;
if(!data->bg_taken[2]) {
whichbg = 2;
} else if(!data->bg_taken[3]) {
whichbg = 3;
}
if(whichbg >= 0) {
data->bg->control[whichbg] = (bpp == 8) ?
BG_BMP8_256x256 : BG_BMP16_256x256;
data->bg->scroll[whichbg].x = 0;
data->bg->scroll[whichbg].y = 0;
texture->driverdata = SDL_calloc(1, sizeof(NDS_TextureData));
txdat = (NDS_TextureData*)texture->driverdata;
txdat->type = NDSTX_BG;
txdat->hw_index = whichbg;
266
267
txdat->dim.hdx = 0x100; txdat->dim.hdy = 0;
txdat->dim.vdx = 0; txdat->dim.vdy = 0x100;
268
269
270
271
txdat->dim.pitch = 256 * (bpp/8);
txdat->dim.bpp = bpp;
txdat->vram = (u16*)(data->sub ?
BG_BMP_RAM_SUB(whichbg) : BG_BMP_RAM(whichbg));
272
for(i = 0; i < 60; ++i) swiWaitForVBlank();
273
274
} else {
SDL_SetError("Out of NDS backgrounds.");
275
printf("ran out.\n");
276
277
278
279
}
} else {
SDL_SetError("Texture too big for NDS hardware.");
}
280
281
}
282
printf("-NDS_CreateTexture\n");
283
284
285
286
287
288
289
290
291
292
if (!texture->driverdata) {
return -1;
}
return 0;
}
static int
NDS_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
void **pixels, int *pitch)
{
293
printf("+NDS_QueryTexturePixels\n");
294
295
296
297
298
299
300
301
if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
SDL_SetError("Unsupported texture format");
return -1;
} else {
NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
*pixels = txdat->vram;
*pitch = txdat->dim.pitch;
302
printf("-NDS_QueryTexturePixels\n");
303
304
305
306
307
308
309
310
return 0;
}
}
static int
NDS_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, const void *pixels, int pitch)
{
311
printf("+NDS_UpdateTexture\n");
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
SDL_SetError("Unsupported texture format");
return -1;
} else {
NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
Uint8 *src, *dst;
int row;
size_t length;
/* IMPORTANT! copy the new pixels into the sprite or bg. */
src = (Uint8 *) pixels;
dst =
(Uint8 *) txdat->vram + rect->y * txdat->dim.pitch +
rect->x * (txdat->dim.bpp/8);
length = rect->w * (txdat->dim.bpp/8);
for (row = 0; row < rect->h; ++row) {
SDL_memcpy(dst, src, length);
src += pitch;
329
dst += txdat->dim.pitch;
330
}
331
printf("-NDS_UpdateTexture\n");
332
333
334
335
336
337
338
339
340
return 0;
}
}
static int
NDS_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, int markDirty, void **pixels,
int *pitch)
{
341
printf("+NDS_LockTexture\n");
342
343
344
345
346
347
if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
SDL_SetError("Unsupported texture format");
return -1;
} else {
NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
348
if (markDirty) {
349
printf("wanted to mark dirty\n");
350
/*SDL_AddDirtyRect(&txdat->dirty, rect);*/
351
352
}
353
354
355
*pixels = (void *) ((u8 *)txdat->vram + rect->y * txdat->dim.pitch
+ rect->x * (txdat->dim.bpp/8));
*pitch = txdat->dim.pitch;
356
printf(" pixels = %08x\n", (u32)*pixels);
357
printf("-NDS_LockTexture\n");
358
359
360
361
362
363
364
365
366
367
return 0;
}
}
static void
NDS_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{
if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
SDL_SetError("Unsupported texture format");
}
368
printf("+NDS_UnlockTexture\n-NDS_UnlockTexture\n");
369
370
371
372
373
374
}
static void
NDS_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
int numrects, const SDL_Rect * rects)
{ /* stub */
375
printf("!NDS_DirtyTexture\n");
376
377
}
378
static int
379
NDS_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b,
380
Uint8 a, const SDL_Rect * rect)
381
{
382
NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
383
SDL_Rect real_rect = *rect;
384
385
386
u16 color;
int i, j;
387
printf("+NDS_RenderFill\n");
388
/* TODO: make a single-color sprite and stretch it.
389
390
391
392
393
394
color = RGB15(r>>3,g>>3,b>>3);
for (i = real_rect.x; i < real_rect.x+real_rect.w; ++i) {
for (j = real_rect.y; j < real_rect.y+real_rect.h; ++j) {
data->fb[(j + real_rect.y) * 256 + i + real_rect.x] =
0x8000 | color;
}
395
}*/
396
printf("-NDS_RenderFill\n");
397
return 0;
398
}
399
400
static int
401
NDS_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
402
const SDL_Rect * srcrect, const SDL_Rect * dstrect)
403
{
404
NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
405
406
407
NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
// SDL_Window *window = SDL_GetWindowFromID(renderer->window);
// SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
408
int i;
409
410
int bpp = SDL_BYTESPERPIXEL(texture->format);
int pitch = txdat->dim.pitch;
411
printf("+NDS_RenderCopy\n");
412
413
414
415
416
417
418
419
420
421
422
if(txdat->type == NDSTX_BG) {
bg_rotation *tmpbg = (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;
} else {
/* sprites not implemented yet */
423
}
424
printf(" txdat->hw_index = %d\n", txdat->hw_index);
425
printf("-NDS_RenderCopy\n");
426
return 0;
427
428
}
429
430
static void
431
NDS_RenderPresent(SDL_Renderer * renderer)
432
{
433
434
NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
/* Send the data to the display TODO */
435
436
/* shouldn't it already be there at this point?
I guess set the BG's and sprites "visible" flags here. */
437
printf("+NDS_RenderPresent\n");
438
439
/* vsync for NDS */
440
441
if (renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) {
swiWaitForVBlank();
442
}
443
printf("-NDS_RenderPresent\n");
444
445
}
446
447
448
static void
NDS_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{
449
printf("+NDS_DestroyTexture\n");
450
451
452
if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
SDL_SetError("Unsupported texture format");
} else {
453
/* free anything else allocated for texture */
454
NDS_TextureData *txdat = texture->driverdata;
455
/*SDL_FreeDirtyRects(&txdat->dirty);*/
456
SDL_free(txdat);
457
}
458
printf("-NDS_DestroyTexture\n");
459
460
}
461
static void
462
NDS_DestroyRenderer(SDL_Renderer * renderer)
463
{
464
NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
465
466
/*SDL_Window *window = SDL_GetWindowFromID(renderer->window);
SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);*/
467
468
int i;
469
printf("+NDS_DestroyRenderer\n");
470
if (data) {
471
472
/* TODO: free anything relevant. */
/*for (i = 0; i < SDL_arraysize(data->texture); ++i) {
473
474
if (data->texture[i]) {
DestroyTexture(data->renderer, data->texture[i]);
475
}
476
477
478
479
480
481
482
483
484
}
if (data->surface.format) {
SDL_SetSurfacePalette(&data->surface, NULL);
SDL_FreeFormat(data->surface.format);
}
if (display->palette) {
SDL_DelPaletteWatch(display->palette, DisplayPaletteChanged,
data);
}
485
SDL_FreeDirtyRects(&data->dirty);*/
486
487
488
SDL_free(data);
}
SDL_free(renderer);
489
printf("-NDS_DestroyRenderer\n");
490
491
}
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
static int
NDS_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Color * colors, int firstcolor, int ncolors)
{
printf("+NDS_SetTexturePalette\n");
if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
SDL_SetError("YUV textures don't have a palette");
return -1;
} else {
NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
/* TODO: mess with 8-bit modes and/or 16-color palette modes */
printf("-NDS_SetTexturePalette\n");
return 0;
}
}
static int
NDS_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
SDL_Color * colors, int firstcolor, int ncolors)
{
printf("+NDS_GetTexturePalette\n");
if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
SDL_SetError("YUV textures don't have a palette");
return -1;
} else {
NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
printf("-NDS_GetTexturePalette\n");
/* TODO: mess with 8-bit modes and/or 16-color palette modes */
return 0;
}
}
static int
NDS_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
{
printf("!NDS_SetTextureColorMod\n");
/* stub. TODO: figure out what needs to be done, if anything */
return 0;
}
static int
NDS_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
{
printf("!NDS_SetTextureAlphaMod\n");
/* stub. TODO: figure out what needs to be done, if anything */
return 0;
}
static int
NDS_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
{
printf("!NDS_SetTextureBlendMode\n");
/* stub. TODO: figure out what needs to be done, if anything */
return 0;
}
static int
NDS_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
{
printf("!NDS_SetTextureScaleMode\n");
/* stub. TODO: figure out what needs to be done.
(NDS hardware scaling is nearest neighbor.) */
return 0;
}
557
/* vi: set ts=4 sw=4 expandtab: */