Mercurial > sdl-ios-xcode
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 } |