comparison src/video/nds/SDL_ndsrender.c @ 2693:bae97b6ac32b gsoc2008_nds

Beginnings of sprite support.
author Darren Alton <dalton@stevens.edu>
date Sat, 16 Aug 2008 12:08:12 +0000
parents cd8978f47849
children c1c7cb1b5a47
comparison
equal deleted inserted replaced
2692:cd8978f47849 2693:bae97b6ac32b
40 /* NDS sprite-related functions */ 40 /* NDS sprite-related functions */
41 #define SPRITE_DMA_CHANNEL 3 41 #define SPRITE_DMA_CHANNEL 3
42 #define SPRITE_ANGLE_MASK 0x01FF 42 #define SPRITE_ANGLE_MASK 0x01FF
43 43
44 void 44 void
45 NDS_OAM_Update(tOAM *oam) 45 NDS_OAM_Update(tOAM *oam, int sub)
46 { 46 {
47 DC_FlushAll(); 47 DC_FlushAll();
48 dmaCopyHalfWords(SPRITE_DMA_CHANNEL, oam->spriteBuffer, OAM, 48 dmaCopyHalfWords(SPRITE_DMA_CHANNEL, oam->spriteBuffer, sub?OAM_SUB:OAM,
49 SPRITE_COUNT * sizeof(SpriteEntry)); 49 SPRITE_COUNT * sizeof(SpriteEntry));
50 } 50 }
51 51
52 void 52 void
53 NDS_OAM_RotateSprite(SpriteRotation *spriteRotation, u16 angle) 53 NDS_OAM_RotateSprite(SpriteRotation *spriteRotation, u16 angle)
60 spriteRotation->vdx = -s; 60 spriteRotation->vdx = -s;
61 spriteRotation->vdy = c; 61 spriteRotation->vdy = c;
62 } 62 }
63 63
64 void 64 void
65 NDS_OAM_Init(tOAM *oam) 65 NDS_OAM_Init(tOAM *oam, int sub)
66 { 66 {
67 int i; 67 int i;
68 for(i = 0; i < SPRITE_COUNT; i++) { 68 for(i = 0; i < SPRITE_COUNT; i++) {
69 oam->spriteBuffer[i].attribute[0] = ATTR0_DISABLED; 69 oam->spriteBuffer[i].attribute[0] = ATTR0_DISABLED;
70 oam->spriteBuffer[i].attribute[1] = 0; 70 oam->spriteBuffer[i].attribute[1] = 0;
72 } 72 }
73 for(i = 0; i < MATRIX_COUNT; i++) { 73 for(i = 0; i < MATRIX_COUNT; i++) {
74 NDS_OAM_RotateSprite(&(oam->matrixBuffer[i]), 0); 74 NDS_OAM_RotateSprite(&(oam->matrixBuffer[i]), 0);
75 } 75 }
76 swiWaitForVBlank(); 76 swiWaitForVBlank();
77 NDS_OAM_Update(oam); 77 NDS_OAM_Update(oam, sub);
78 } 78 }
79 79
80 void 80 void
81 NDS_OAM_HideSprite(SpriteEntry *spriteEntry) 81 NDS_OAM_HideSprite(SpriteEntry *spriteEntry)
82 { 82 {
171 } NDS_RenderData; 171 } NDS_RenderData;
172 172
173 typedef struct 173 typedef struct
174 { 174 {
175 enum { NDSTX_BG, NDSTX_SPR } type; /* represented in a bg or sprite. */ 175 enum { NDSTX_BG, NDSTX_SPR } type; /* represented in a bg or sprite. */
176 int hw_index; /* sprite: index in the OAM. bg: 2 or 3. */ 176 int hw_index; /* sprite: index in the OAM. / bg: 2 or 3. */
177 struct 177 struct
178 { 178 {
179 int hdx, hdy, vdx, vdy; /* affine transformation, used for scaling. */ 179 int hdx, hdy, vdx, vdy; /* affine transformation, used for scaling. */
180 int pitch, bpp; /* some useful info */ 180 int pitch, bpp; /* some useful info */
181 } dim; 181 } dim;
206 switch(displayMode->format) { 206 switch(displayMode->format) {
207 case SDL_PIXELFORMAT_INDEX8: 207 case SDL_PIXELFORMAT_INDEX8:
208 case SDL_PIXELFORMAT_ABGR1555: 208 case SDL_PIXELFORMAT_ABGR1555:
209 case SDL_PIXELFORMAT_BGR555: 209 case SDL_PIXELFORMAT_BGR555:
210 /* okay */ 210 /* okay */
211 break;
212 case SDL_PIXELFORMAT_RGB555:
213 case SDL_PIXELFORMAT_RGB565:
214 case SDL_PIXELFORMAT_ARGB1555:
215 /* we'll take these too for now */
211 break; 216 break;
212 default: 217 default:
213 printf("DEBUG: wrong display format!\n"); 218 printf("DEBUG: wrong display format!\n");
214 break; 219 break;
215 } 220 }
270 data->bg = &BACKGROUND; 275 data->bg = &BACKGROUND;
271 } else { 276 } else {
272 data->bg = &BACKGROUND_SUB; 277 data->bg = &BACKGROUND_SUB;
273 } 278 }
274 data->bg_taken[2] = data->bg_taken[3] = 0; 279 data->bg_taken[2] = data->bg_taken[3] = 0;
275 NDS_OAM_Init(&(data->oam_copy)); /* init sprites. */ 280
281 NDS_OAM_Init(&(data->oam_copy), data->sub); /* init sprites. */
276 282
277 TRACE("-NDS_CreateRenderer\n"); 283 TRACE("-NDS_CreateRenderer\n");
278 return renderer; 284 return renderer;
279 } 285 }
280 286
311 } 317 }
312 318
313 /* conditional statements on w/h to place it as bg/sprite 319 /* conditional statements on w/h to place it as bg/sprite
314 depending on which one it fits. */ 320 depending on which one it fits. */
315 if(texture->w <= 64 && texture->h <= 64) { 321 if(texture->w <= 64 && texture->h <= 64) {
316 /* TODO: implement sprites similar to how BG's are. 322 int whichspr = -1;
317 they have a similar affine transformation matrix
318 (hdx,hdy,vdx,vdy) as the backgrounds, so it should
319 be similar enough to handle with the same driverdata. */
320 printf("Tried to make a sprite.\n"); 323 printf("Tried to make a sprite.\n");
321 txdat->type = NDSTX_SPR; 324 txdat->type = NDSTX_SPR;
325 for(i = 0; i < SPRITE_COUNT; ++i) {
326 if(data->oam_copy.spriteBuffer[i].attribute[0] & ATTR0_DISABLED) {
327 whichspr = i;
328 break;
329 }
330 }
331 if(whichspr >= 0) {
332 SpriteEntry *sprent = &(data->oam_copy.spriteBuffer[whichspr]);
333
334 texture->driverdata = SDL_calloc(1, sizeof(NDS_TextureData));
335 txdat = (NDS_TextureData*)texture->driverdata;
336 if(!txdat) {
337 SDL_OutOfMemory();
338 return -1;
339 }
340
341 sprent->objMode = OBJMODE_BITMAP;
342 sprent->posX = 0; sprent->posY = 0;
343 sprent->colMode = OBJCOLOR_16; /* OBJCOLOR_256 for INDEX8 */
344 if(whichspr < MATRIX_COUNT) {
345 sprent->isRotoscale = 1;
346 sprent->rsMatrixIdx = whichspr;
347 }
348 }
322 } else if(texture->w <= 256 && texture->h <= 256) { 349 } else if(texture->w <= 256 && texture->h <= 256) {
323 int whichbg = -1, base = 0; 350 int whichbg = -1, base = 0;
324 if(!data->bg_taken[2]) { 351 if(!data->bg_taken[2]) {
325 whichbg = 2; 352 whichbg = 2;
326 data->bg->bg2_rotation.xdx = 0x100;
327 data->bg->bg2_rotation.xdy = 0;
328 data->bg->bg2_rotation.ydx = 0;
329 data->bg->bg2_rotation.ydy = 0x100;
330 data->bg->bg2_rotation.centerX = 0;
331 data->bg->bg2_rotation.centerY = 0;
332 } else if(!data->bg_taken[3]) { 353 } else if(!data->bg_taken[3]) {
333 whichbg = 3; 354 whichbg = 3;
334 data->bg->bg3_rotation.xdx = 0x100;
335 data->bg->bg3_rotation.xdy = 0;
336 data->bg->bg3_rotation.ydx = 0;
337 data->bg->bg3_rotation.ydy = 0x100;
338 data->bg->bg3_rotation.centerX = 0;
339 data->bg->bg3_rotation.centerY = 0;
340 base = 4; 355 base = 4;
341 } 356 }
342 if(whichbg >= 0) { 357 if(whichbg >= 0) {
343 texture->driverdata = SDL_calloc(1, sizeof(NDS_TextureData)); 358 texture->driverdata = SDL_calloc(1, sizeof(NDS_TextureData));
344 txdat = (NDS_TextureData*)texture->driverdata; 359 txdat = (NDS_TextureData*)texture->driverdata;
360 375
361 txdat->type = NDSTX_BG; 376 txdat->type = NDSTX_BG;
362 txdat->hw_index = whichbg; 377 txdat->hw_index = whichbg;
363 txdat->dim.hdx = 0x100; txdat->dim.hdy = 0; 378 txdat->dim.hdx = 0x100; txdat->dim.hdy = 0;
364 txdat->dim.vdx = 0; txdat->dim.vdy = 0x100; 379 txdat->dim.vdx = 0; txdat->dim.vdy = 0x100;
365 txdat->dim.pitch = 256 * ((bpp+1)/8); 380 txdat->dim.pitch = texture->w * ((bpp+1)/8);
366 txdat->dim.bpp = bpp; 381 txdat->dim.bpp = bpp;
367 txdat->vram_pixels = (u16*)(data->sub ? 382 txdat->vram_pixels = (u16*)(data->sub ?
368 BG_BMP_RAM_SUB(base) : BG_BMP_RAM(base)); 383 BG_BMP_RAM_SUB(base) : BG_BMP_RAM(base));
369 384
370 /*txdat->size = txdat->dim.pitch * texture->h;*/ 385 /*txdat->size = txdat->dim.pitch * texture->h;*/
403 { 418 {
404 NDS_TextureData *txdat; 419 NDS_TextureData *txdat;
405 Uint8 *src, *dst; 420 Uint8 *src, *dst;
406 int row; size_t length; 421 int row; size_t length;
407 TRACE("+NDS_UpdateTexture\n"); 422 TRACE("+NDS_UpdateTexture\n");
408 if(!texture) { printf("OH BOY!!!\n"); return -1; } 423
409 txdat = (NDS_TextureData *) texture->driverdata; 424 txdat = (NDS_TextureData *) texture->driverdata;
410 425
411 src = (Uint8 *) pixels; 426 src = (Uint8 *) pixels;
412 dst = 427 dst =
413 (Uint8 *) txdat->vram_pixels + rect->y * txdat->dim.pitch + 428 (Uint8 *) txdat->vram_pixels + rect->y * txdat->dim.pitch +
414 rect->x * ((txdat->dim.bpp+1)/8); 429 rect->x * ((txdat->dim.bpp+1)/8);
415 length = rect->w * ((txdat->dim.bpp+1)/8); 430 length = rect->w * ((txdat->dim.bpp+1)/8);
416 for (row = 0; row < rect->h; ++row) { 431
417 SDL_memcpy(dst, src, length); 432 if(rect->w == texture->w) {
418 src += pitch; 433 dmaCopy(src, dst, length*rect->h);
419 dst += txdat->dim.pitch; 434 } else {
435 for (row = 0; row < rect->h; ++row) {
436 dmaCopy(src, dst, length);
437 src += pitch;
438 dst += txdat->dim.pitch;
439 }
420 } 440 }
421 441
422 TRACE("-NDS_UpdateTexture\n"); 442 TRACE("-NDS_UpdateTexture\n");
423 return 0; 443 return 0;
424 } 444 }
427 NDS_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, 447 NDS_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
428 const SDL_Rect * rect, int markDirty, void **pixels, 448 const SDL_Rect * rect, int markDirty, void **pixels,
429 int *pitch) 449 int *pitch)
430 { 450 {
431 NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata; 451 NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
432 int i;
433 TRACE("+NDS_LockTexture\n"); 452 TRACE("+NDS_LockTexture\n");
434 if (markDirty) {
435 printf("wanted to mark dirty\n");
436 /* TODO: figure out how to handle this! */
437 /*SDL_AddDirtyRect(&txdat->dirty, rect);*/
438 }
439 453
440 *pixels = (void *) ((u8 *)txdat->vram_pixels + rect->y 454 *pixels = (void *) ((u8 *)txdat->vram_pixels + rect->y
441 * txdat->dim.pitch + rect->x * ((txdat->dim.bpp+1)/8)); 455 * txdat->dim.pitch + rect->x * ((txdat->dim.bpp+1)/8));
442 *pitch = txdat->dim.pitch; 456 *pitch = txdat->dim.pitch;
457
443 TRACE("-NDS_LockTexture\n"); 458 TRACE("-NDS_LockTexture\n");
444 return 0; 459 return 0;
445 } 460 }
446 461
447 static void 462 static void
448 NDS_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) 463 NDS_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
449 { 464 {
450 TRACE("+NDS_UnlockTexture\n"); 465 TRACE("+NDS_UnlockTexture\n");
451 /* TODO: should I be doing something here, somehow, now that the pixels
452 should have been "written" between LockTexture and this? */
453 TRACE("-NDS_UnlockTexture\n"); 466 TRACE("-NDS_UnlockTexture\n");
454 } 467 }
455 468
456 static void 469 static void
457 NDS_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, 470 NDS_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
497 int bpp = SDL_BYTESPERPIXEL(texture->format); 510 int bpp = SDL_BYTESPERPIXEL(texture->format);
498 int pitch = txdat->dim.pitch; 511 int pitch = txdat->dim.pitch;
499 512
500 TRACE("+NDS_RenderCopy\n"); 513 TRACE("+NDS_RenderCopy\n");
501 if(txdat->type == NDSTX_BG) { 514 if(txdat->type == NDSTX_BG) {
502 bg_rotation *tmpbg = (txdat->hw_index == 2) ? 515 bg_rotation *bgrot = (txdat->hw_index == 2) ?
503 &(data->bg->bg2_rotation) : &(data->bg->bg3_rotation); 516 &(data->bg->bg2_rotation) : &(data->bg->bg3_rotation);
504 tmpbg->xdx = txdat->dim.hdx; 517 bgrot->xdx = txdat->dim.hdx;
505 tmpbg->xdy = txdat->dim.hdy; 518 bgrot->xdy = txdat->dim.hdy;
506 tmpbg->ydx = txdat->dim.vdx; 519 bgrot->ydx = txdat->dim.vdx;
507 tmpbg->ydy = txdat->dim.vdy; 520 bgrot->ydy = txdat->dim.vdy;
508 tmpbg->centerX = 0; 521 bgrot->centerX = 0;
509 tmpbg->centerY = 0; 522 bgrot->centerY = 0;
523
524 data->bg->scroll[txdat->hw_index].x = dstrect->x;
525 data->bg->scroll[txdat->hw_index].y = dstrect->y;
510 } else { 526 } else {
511 /* sprites not implemented yet */ 527 /* sprites not fully implemented yet */
528 SpriteEntry *spr = &(data->oam_copy.spriteBuffer[txdat->hw_index]);
529 spr->posX = dstrect->x;
530 spr->posY = dstrect->y;
531 if(txdat->hw_index < MATRIX_COUNT) {
532 SpriteRotation *sprot = &(data->oam_copy.matrixBuffer[txdat->hw_index]);
533 sprot->hdx = txdat->dim.hdx;
534 sprot->hdy = txdat->dim.hdy;
535 sprot->vdx = txdat->dim.vdx;
536 sprot->vdy = txdat->dim.vdy;
537 }
512 printf("tried to RenderCopy a sprite.\n"); 538 printf("tried to RenderCopy a sprite.\n");
513 } 539 }
514 TRACE("-NDS_RenderCopy\n"); 540 TRACE("-NDS_RenderCopy\n");
515 541
516 return 0; 542 return 0;
521 NDS_RenderPresent(SDL_Renderer * renderer) 547 NDS_RenderPresent(SDL_Renderer * renderer)
522 { 548 {
523 NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata; 549 NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
524 SDL_Window *window = SDL_GetWindowFromID(renderer->window); 550 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
525 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); 551 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
526 int i; 552
527 TRACE("+NDS_RenderPresent\n"); 553 TRACE("+NDS_RenderPresent\n");
528 554 /* update sprites */
529 { 555 NDS_OAM_Update(&(data->oam_copy), data->sub);
530 SDL_Texture * tx = display->textures[i];
531 NDS_TextureData * txdat = (NDS_TextureData*)tx->driverdata;
532 /* Send the data to the display TODO :
533 shouldn't it already be there at this point? from lock/unlock
534 giving it the direct address in VRAM of the bg's.
535 I guess set the BG's and sprites "visible" flags here,
536 if applicable. */
537 }
538
539 /* vsync for NDS */ 556 /* vsync for NDS */
540 if (renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) { 557 if (renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) {
541 swiWaitForVBlank(); 558 swiWaitForVBlank();
542 } 559 }
543 TRACE("-NDS_RenderPresent\n"); 560 TRACE("-NDS_RenderPresent\n");
545 562
546 static void 563 static void
547 NDS_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) 564 NDS_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
548 { 565 {
549 TRACE("+NDS_DestroyTexture\n"); 566 TRACE("+NDS_DestroyTexture\n");
550 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { 567 /* free anything else allocated for texture */
551 SDL_SetError("Unsupported texture format"); 568 NDS_TextureData *txdat = texture->driverdata;
552 } else { 569 /*SDL_FreeDirtyRects(&txdat->dirty);*/
553 /* free anything else allocated for texture */ 570 SDL_free(txdat);
554 NDS_TextureData *txdat = texture->driverdata;
555 /*SDL_FreeDirtyRects(&txdat->dirty);*/
556 SDL_free(txdat);
557 }
558 TRACE("-NDS_DestroyTexture\n"); 571 TRACE("-NDS_DestroyTexture\n");
559 } 572 }
560 573
561 static void 574 static void
562 NDS_DestroyRenderer(SDL_Renderer * renderer) 575 NDS_DestroyRenderer(SDL_Renderer * renderer)
567 int i; 580 int i;
568 581
569 TRACE("+NDS_DestroyRenderer\n"); 582 TRACE("+NDS_DestroyRenderer\n");
570 if (data) { 583 if (data) {
571 /* TODO: free anything else relevant. */ 584 /* TODO: free anything else relevant. */
572 /*for (i = 0; i < SDL_arraysize(data->texture); ++i) { 585 /*if (data->surface.format) {
573 if (data->texture[i]) {
574 DestroyTexture(data->renderer, data->texture[i]);
575 }
576 }
577 if (data->surface.format) {
578 SDL_SetSurfacePalette(&data->surface, NULL); 586 SDL_SetSurfacePalette(&data->surface, NULL);
579 SDL_FreeFormat(data->surface.format); 587 SDL_FreeFormat(data->surface.format);
580 } 588 }
581 if (display->palette) { 589 if (display->palette) {
582 SDL_DelPaletteWatch(display->palette, DisplayPaletteChanged, 590 SDL_DelPaletteWatch(display->palette, DisplayPaletteChanged,
583 data); 591 data);
584 } 592 }*/
585 SDL_FreeDirtyRects(&data->dirty);*/ 593 /*SDL_FreeDirtyRects(&data->dirty);*/
586 SDL_free(data); 594 SDL_free(data);
587 } 595 }
588 SDL_free(renderer); 596 SDL_free(renderer);
589 TRACE("-NDS_DestroyRenderer\n"); 597 TRACE("-NDS_DestroyRenderer\n");
590 } 598 }