00001 #ifndef _PA_Sprite
00002 #define _PA_Sprite
00003
00004 #ifdef __cplusplus
00005 extern "C" {
00006 #endif
00007
00014 #include "PA_Math.h"
00015
00016
00017 #define EWRAM_DATA __attribute__((section(".ewram")))
00018 #define EWRAM_BSS __attribute__((section(".sbss")))
00019 #define PA_Cos(angle) PA_SIN[((angle) + 128)&511]
00020 #define PA_Sin(angle) PA_SIN[((angle))&511]
00021 extern const s16 PA_SIN[512];
00022
00023 #define MAX_DRAW 16 // Maximum 16 sprites dessinables...
00024
00025
00027
00029
00030
00031 #define OBJ_SIZE_8X8 0,0
00032 #define OBJ_SIZE_16X16 0,1
00033 #define OBJ_SIZE_32X32 0,2
00034 #define OBJ_SIZE_64X64 0,3
00035 #define OBJ_SIZE_16X8 1,0
00036 #define OBJ_SIZE_32X8 1,1
00037 #define OBJ_SIZE_32X16 1,2
00038 #define OBJ_SIZE_64X32 1,3
00039 #define OBJ_SIZE_8X16 2,0
00040 #define OBJ_SIZE_8X32 2,1
00041 #define OBJ_SIZE_16X32 2,2
00042 #define OBJ_SIZE_32X64 2,3
00043
00044 typedef struct {
00045 u8 lx, ly;
00046 } PA_sizes;
00047
00048 extern const PA_sizes PA_size[3][4];
00049
00050
00051 #define BITS_16 65535
00052 #define ALL_BUT(ATR) (BITS_16 - ATR)
00053
00054 #define PA_OBJ_X 511 //511, debugging...
00055 #define PA_OBJ_Y 255
00056 #define OBJ_ROT 256
00057 #define ALL_BUT_ROTSET 49663 // Numéro du rotset
00058 #define ALL_BUT_PAL 4095
00059
00060 #define DBLSIZE 512
00061 #define N_COLORS (1 << 13)
00062 #define OBJ_MODE 3072
00063 #define OBJ_MOSAIC 4096
00064 #define OBJ_HFLIP 4096
00065 #define OBJ_VFLIP 8192
00066
00067 #define OBJ_GFX 1023
00068 #define OBJ_PRIO 3072
00069
00070 #define COLORS_256 1
00071 #define COLORS_16 0
00072
00073
00074
00075 #define MEM_DECAL 5
00076 #define NUMBER_DECAL 7
00077
00078
00079
00080
00081 typedef struct {
00082 u16 mem_block;
00083 u16 free;
00084 } mem_usage;
00085
00086 extern u16 n_free_mem[2];
00087 extern u8 used_mem[2][1024];
00088 extern u8 obj_per_gfx[2][1024];
00089 extern mem_usage free_mem[2][1024];
00090
00091 extern u16 FirstGfx[2];
00092
00093 extern const u16 PA_obj_sizes[4][3];
00094
00095 typedef struct {
00096 u16 atr0, atr1, atr2, atr3;
00097 }obj_inf;
00098 extern obj_inf PA_obj[2][128];
00099
00100 extern u8 PA_SpritePrio[2][128];
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 extern unsigned char *PA_SpriteBuffer[MAX_DRAW];
00121
00122 extern u16 *PA_SpriteAnimP[2][1024];
00123
00124
00125 #define ANIM_LOOP 0 // loop around
00126 #define ANIM_UPDOWN 1 // back and forth animation
00127
00128 #define ANIM_ONESHOT ANIM_LOOP, 1
00129 #define ANIM_INFINITE ANIM_LOOP, -1
00130
00131
00132
00133 extern s16 nspriteanims;
00134 typedef struct{
00135 s32 firstframe, lastframe, currentframe;
00136 s8 framechange;
00137 s32 time;
00138 u8 lx, ly;
00139 u8 colors;
00140 s16 speed;
00141 u8 play;
00142 u16 *gfx;
00143 u8 type;
00144 s32 ncycles;
00145 } spriteanim;
00146 extern spriteanim spriteanims[2][128];
00147
00148
00149
00150
00151
00152 extern u8 PA_SpriteExtPrio;
00153
00154
00155
00156
00157
00158
00159 #define OAM0 0x07000000
00160 #define OAM1 0x07000400
00161
00162
00175 #define PA_UpdateOAM0() DMA_Copy((void*)PA_obj, (void*)OAM0, 256, DMA_32NOW)
00176
00182 #define PA_UpdateOAM1() DMA_Copy((void*)PA_obj + 256, (void*)OAM1, 256, DMA_32NOW)
00183
00184
00185
00186
00187
00188
00195 void PA_UpdateOAM(void);
00196
00197
00219 u16 PA_CreateGfx(u8 screen, void* obj_data, u8 obj_shape, u8 obj_size, u8 color_mode);
00220
00226 void PA_ResetSpriteSys(void);
00227
00228
00229
00262 extern inline void PA_CreateSprite(u8 screen, u8 obj_number, void* obj_data, u8 obj_shape, u8 obj_size, u8 color_mode, u8 palette, s16 x, s16 y) {
00263 PA_obj[screen][obj_number].atr2 = PA_CreateGfx(screen, obj_data, obj_shape, obj_size, color_mode) + (palette << 12);
00264 PA_obj[screen][obj_number].atr0 = (y&PA_OBJ_Y) + (color_mode << 13) + (obj_shape << 14);
00265 PA_obj[screen][obj_number].atr1 = (x & PA_OBJ_X) + (obj_size << 14);
00266 };
00267
00318 extern inline void PA_CreateSpriteEx(u8 screen, u8 obj_number, void* obj_data, u8 obj_shape, u8 obj_size, u8 color_mode, u8 palette, u8 obj_mode, u8 mosaic, u8 hflip, u8 vflip, u8 prio, u8 dblsize, s16 x, s16 y) {
00319 PA_obj[screen][obj_number].atr2 = PA_CreateGfx(screen, obj_data, obj_shape, obj_size, color_mode) + (prio << 10) + (palette << 12);
00320 PA_obj[screen][obj_number].atr0 = (y&PA_OBJ_Y) + (dblsize << 9) + (obj_mode << 10) + (mosaic << 12) + ((color_mode) << 13) + (obj_shape << 14);
00321 PA_obj[screen][obj_number].atr1 = (x & PA_OBJ_X) + (hflip << 12) + (vflip << 13) + (obj_size << 14);
00322 };
00323
00324
00325
00326
00327
00369 extern inline void PA_Create16bitSpriteEx(u8 screen, u8 obj_number, void* obj_data, u8 obj_shape, u8 obj_size, u8 mosaic, u8 hflip, u8 vflip, u8 prio, u8 dblsize, s16 x, s16 y){
00370 PA_obj[screen][obj_number].atr2 = PA_CreateGfx(screen, obj_data, obj_shape, obj_size, 2) + (prio << 10) + (15 << 12);
00371 PA_obj[screen][obj_number].atr0 = (y&PA_OBJ_Y) + (dblsize << 9) + (3 << 10) + (mosaic << 12) + (0 << 13) + (obj_shape << 14);
00372 PA_obj[screen][obj_number].atr1 = (x & PA_OBJ_X) + (hflip << 12) + (vflip << 13) + (obj_size << 14);
00373 }
00374
00375
00376
00377
00404 extern inline void PA_Create16bitSpriteFromGfx(u8 screen, u8 obj_number, u16 gfx, u8 obj_shape, u8 obj_size, s16 x, s16 y){
00405 PA_obj[screen][obj_number].atr2 = gfx + (15 << 12);
00406 PA_obj[screen][obj_number].atr0 = (y&PA_OBJ_Y) + (3 << 10) + (obj_shape << 14);
00407 PA_obj[screen][obj_number].atr1 = (x & PA_OBJ_X) + (obj_size << 14);
00408 }
00409
00410
00411
00412
00413
00440 extern inline void PA_Create16bitSprite(u8 screen, u8 obj_number, void* obj_data, u8 obj_shape, u8 obj_size, s16 x, s16 y){
00441 PA_Create16bitSpriteEx(screen, obj_number, obj_data, obj_shape, obj_size, 0, 0, 0, 0, 0, x, y);
00442 }
00443
00444
00445
00446
00479 extern inline void PA_CreateSpriteFromGfx(u8 screen, u8 obj_number, u16 obj_gfx, u8 obj_shape, u8 obj_size, u8 color_mode, u8 palette, s16 x, s16 y) {
00480 PA_obj[screen][obj_number].atr2 = obj_gfx + (palette << 12);
00481 PA_obj[screen][obj_number].atr0 = (y&PA_OBJ_Y) + (color_mode << 13) + (obj_shape << 14);
00482 PA_obj[screen][obj_number].atr1 = (x & PA_OBJ_X) + (obj_size << 14);
00483 ++obj_per_gfx[screen][obj_gfx];
00484 };
00485
00536 extern inline void PA_CreateSpriteExFromGfx(u8 screen, u8 obj_number, u16 obj_gfx, u8 obj_shape, u8 obj_size, u8 color_mode, u8 palette, u8 obj_mode, u8 mosaic, u8 hflip, u8 vflip, u8 prio, u8 dblsize, s16 x, s16 y) {
00537 PA_obj[screen][obj_number].atr2 = obj_gfx + (prio << 10) + (palette << 12);
00538 PA_obj[screen][obj_number].atr0 = (y&PA_OBJ_Y) + (dblsize << 9) + (obj_mode << 10) + (mosaic << 12) + (color_mode << 13) + (obj_shape << 14);
00539 PA_obj[screen][obj_number].atr1 = (x & PA_OBJ_X) + (hflip << 12) + (vflip << 13) + (obj_size << 14);
00540 ++obj_per_gfx[screen][obj_gfx];
00541 };
00542
00543
00558 #define PA_UpdateSpriteGfx(screen, obj_number, obj_data) PA_UpdateGfx(screen, PA_GetSpriteGfx(screen, obj_number), obj_data)
00559
00577 extern inline void PA_UpdateGfx(u8 screen, u16 gfx_number, void *obj_data) {
00578 DMA_Copy((obj_data), (void*)(SPRITE_GFX1 + (0x200000 * (screen)) + ((gfx_number) << NUMBER_DECAL)), (used_mem[screen][gfx_number] << MEM_DECAL), DMA_32NOW);
00579
00580 }
00581
00582
00598 extern inline void PA_UpdateGfxAndMem(u8 screen, u8 gfx_number, void *obj_data){
00599 DMA_Copy((obj_data), (void*)(SPRITE_GFX1 + (0x200000 * (screen)) + ((gfx_number) << NUMBER_DECAL)), (used_mem[screen][gfx_number] << MEM_DECAL), DMA_32NOW);
00600 PA_SpriteAnimP[screen][gfx_number] = (u16*)obj_data;
00601 }
00602
00603
00604
00605
00617 void PA_DeleteGfx(u8 screen, u16 obj_gfx);
00618
00619
00631 void PA_DeleteSprite(u8 screen, u8 obj_number);
00632
00633
00649 #define PA_SetSpriteRotEnable(screen, sprite, rotset) {PA_obj[screen][sprite].atr0 |= OBJ_ROT; PA_obj[screen][sprite].atr1 = (PA_obj[screen][sprite].atr1 & ALL_BUT_ROTSET) + ((rotset) << 9);}
00650
00662 #define PA_SetSpriteRotDisable(screen, sprite) {PA_obj[screen][sprite].atr0 &= ALL_BUT(OBJ_ROT); PA_obj[screen][sprite].atr1 &= ALL_BUT_ROTSET;}
00663
00664
00686 extern inline void PA_SetRotset(u8 screen, u8 rotset, s16 angle, u16 zoomx, u16 zoomy) {
00687 u8 obj_num = (rotset << 2);
00688 PA_obj[screen][obj_num].atr3 = (PA_Cos(angle) * zoomx) >> 8;
00689 PA_obj[screen][obj_num + 1].atr3 = (-PA_Sin(angle) * zoomy) >> 8;
00690 PA_obj[screen][obj_num + 2].atr3 = (PA_Sin(angle) * zoomx) >> 8;
00691 PA_obj[screen][obj_num + 3].atr3 = (PA_Cos(angle) * zoomy) >> 8;
00692 }
00693
00708 extern inline void PA_SetRotsetNoZoom(u8 screen, u8 rotset, s16 angle) {
00709 u8 obj_num = (rotset << 2);
00710 PA_obj[screen][obj_num].atr3 = PA_Cos(angle);
00711 PA_obj[screen][obj_num + 1].atr3 = -PA_Sin(angle);
00712 PA_obj[screen][obj_num + 2].atr3 = PA_Sin(angle);
00713 PA_obj[screen][obj_num + 3].atr3 = PA_Cos(angle);
00714 }
00715
00733 extern inline void PA_SetRotsetNoAngle(u8 screen, u8 rotset, u16 zoomx, u16 zoomy) {
00734 u8 obj_num = (rotset << 2);
00735 PA_obj[screen][obj_num].atr3 = zoomx;
00736 PA_obj[screen][obj_num + 1].atr3 = 0;
00737 PA_obj[screen][obj_num + 2].atr3 = 0;
00738 PA_obj[screen][obj_num + 3].atr3 = zoomy;
00739 }
00740
00741
00742
00743
00744
00745
00746
00763 #define PA_SetSpriteX(screen, obj, x) PA_obj[screen][obj].atr1 = (PA_obj[screen][obj].atr1 & ALL_BUT(PA_OBJ_X)) + ((x) & PA_OBJ_X)
00764
00777 #define PA_GetSpriteX(screen, obj) (PA_obj[screen][obj].atr1 & (PA_OBJ_X))
00778
00779
00794 #define PA_SetSpriteY(screen, obj, y) PA_obj[screen][obj].atr0 = (PA_obj[screen][obj].atr0 & ALL_BUT(PA_OBJ_Y)) + ((y) & PA_OBJ_Y)
00795
00808 #define PA_GetSpriteY(screen, obj) (PA_obj[screen][obj].atr0 & PA_OBJ_Y)
00809
00810
00811
00829 extern inline void PA_SetSpriteXY(u8 screen, u8 sprite, s16 x, s16 y) {
00830 PA_SetSpriteX(screen, sprite, x);
00831 PA_SetSpriteY(screen, sprite, y);
00832 }
00833
00834
00835
00850 #define PA_SetSpritePal(screen, obj, pal) PA_obj[screen][obj].atr2 = (PA_obj[screen][obj].atr2 & ALL_BUT_PAL) + ((pal) << 12)
00851
00863 #define PA_GetSpritePal(screen, obj) (PA_obj[screen][obj].atr2 >> 12)
00864
00865
00880 #define PA_SetSpriteDblsize(screen, obj, dblsize) PA_obj[screen][obj].atr0 = (PA_obj[screen][obj].atr0 & ALL_BUT(DBLSIZE)) + ((dblsize) << 9)
00881
00893 #define PA_GetSpriteDblsize(screen, obj) ((PA_obj[screen][obj].atr0 & DBLSIZE) >> 9)
00894
00895
00910 #define PA_SetSpriteColors(screen, sprite, n_colors) PA_obj[screen][sprite].atr0 = (PA_obj[screen][sprite].atr0 & ALL_BUT(N_COLORS)) + ((n_colors) << 13)
00911
00923 #define PA_GetSpriteColors(screen, sprite) ((PA_obj[screen][sprite].atr0 & N_COLORS) >> 13)
00924
00925
00926
00941 #define PA_SetSpriteMode(screen, sprite, obj_mode) PA_obj[screen][sprite].atr0 = (PA_obj[screen][sprite].atr0 & ALL_BUT(OBJ_MODE)) + ((obj_mode) << 10)
00942
00954 #define PA_GetSpriteMode(screen, obj) ((PA_obj[screen][obj].atr0 & OBJ_MODE) >> 10)
00955
00956
00971 #define PA_SetSpriteMosaic(screen, obj, mosaic) PA_obj[screen][obj].atr0 = (PA_obj[screen][obj].atr0 & ALL_BUT(OBJ_MOSAIC)) + ((mosaic) << 12)
00972
00984 #define PA_GetSpriteMosaic(screen, obj) ((PA_obj[screen][obj].atr0 & OBJ_MOSAIC) >> 12)
00985
00986
00987
01002 #define PA_SetSpriteHflip(screen, obj, hflip) PA_obj[screen][obj].atr1 = (PA_obj[screen][obj].atr1 & ALL_BUT(OBJ_HFLIP)) + ((hflip) << 12)
01003
01015 #define PA_GetSpriteHflip(screen, obj) ((PA_obj[screen][obj].atr1 & OBJ_HFLIP) >> 12)
01016
01017
01032 #define PA_SetSpriteVflip(screen, obj, vflip) PA_obj[screen][obj].atr1 = (PA_obj[screen][obj].atr1 & ALL_BUT(OBJ_VFLIP)) + ((vflip) << 13)
01033
01045 #define PA_GetSpriteVflip(screen, obj) ((PA_obj[screen][obj].atr1 & OBJ_VFLIP) >> 13)
01046
01047
01062 #define PA_SetSpriteGfx(screen, obj, gfx) PA_obj[screen][obj].atr2 = (PA_obj[screen][obj].atr2 & ALL_BUT(OBJ_GFX)) + ((gfx) & OBJ_GFX)
01063
01075 #define PA_GetSpriteGfx(screen, obj) (PA_obj[screen][obj].atr2 & OBJ_GFX)
01076
01077
01078
01093 #define PA_SetSpritePrio(screen, obj, prio) PA_obj[screen][obj].atr2 = (PA_obj[screen][obj].atr2 & ALL_BUT(OBJ_PRIO)) + ((prio) << 10)
01094
01106 #define PA_GetSpritePrio(screen, obj) ((PA_obj[screen][obj].atr2 & OBJ_PRIO) >> 10)
01107
01108
01120 #define PA_GetSpriteLx(screen, sprite) PA_size[PA_obj[screen][sprite].atr0 >> 14][PA_obj[screen][sprite].atr1 >> 14].lx
01121
01122
01134 #define PA_GetSpriteLy(screen, sprite)PA_size[PA_obj[screen][sprite].atr0 >> 14][PA_obj[screen][sprite].atr1 >> 14].ly
01135
01136
01151 #define PA_CloneSprite(screen, obj, target) {PA_obj[screen][obj].atr0 = PA_obj[screen][target].atr0; PA_obj[screen][obj].atr1 = PA_obj[screen][target].atr1; PA_obj[screen][obj].atr2 = PA_obj[screen][target].atr2; ++obj_per_gfx[screen][PA_GetSpriteGfx(screen, target)];}
01152
01153
01154
01155
01156
01157
01158
01159
01183 extern inline void PA_SetSpriteAnimEx(u8 screen, u8 sprite, u8 lx, u8 ly, u8 ncolors, s16 animframe){
01184 u16 gfx = PA_GetSpriteGfx(screen, sprite);
01185
01186 PA_UpdateGfx(screen, gfx, (void*)(PA_SpriteAnimP[screen][gfx] + (animframe * (lx * ly) >> (2 - ncolors))));
01187 }
01188
01203 extern inline void PA_SetSpriteAnim(u8 screen, u8 sprite, s16 animframe){
01204 PA_SetSpriteAnimEx(screen, sprite, PA_GetSpriteLx(screen, sprite), PA_GetSpriteLy(screen, sprite), PA_GetSpriteColors(screen, sprite), animframe);
01205 }
01206
01207
01208
01235 void PA_StartSpriteAnimEx(u8 screen, u8 sprite, s16 firstframe, s16 lastframe, s16 speed, u8 type, s16 ncycles);
01236
01237
01238
01239
01260 extern inline void PA_StartSpriteAnim(u8 screen, u8 sprite, s16 firstframe, s16 lastframe, s16 speed){
01261 PA_StartSpriteAnimEx(screen, sprite, firstframe, lastframe, speed, ANIM_INFINITE);
01262 }
01263
01264
01265
01266
01278 extern inline void PA_StopSpriteAnim(u8 screen, u8 sprite)
01279 {
01280 if (spriteanims[screen][sprite].play) nspriteanims--;
01281 spriteanims[screen][sprite].play = 0;
01282 }
01283
01298 extern inline void PA_SetSpriteAnimFrame(u8 screen, u8 sprite, u16 frame)
01299 {
01300 if(spriteanims[screen][sprite].currentframe != frame){
01301 PA_SetSpriteAnimEx(screen, sprite, spriteanims[screen][sprite].lx, spriteanims[screen][sprite].ly, spriteanims[screen][sprite].colors, spriteanims[screen][sprite].currentframe);
01302 spriteanims[screen][sprite].currentframe = frame;
01303 }
01304 }
01305
01306
01318 extern inline u16 PA_GetSpriteAnimFrame(u8 screen, u8 sprite)
01319 {
01320 return spriteanims[screen][sprite].currentframe;
01321 }
01322
01323
01324
01339 extern inline void PA_SetSpriteAnimSpeed(u8 screen, u8 sprite, s16 speed)
01340 {
01341 spriteanims[screen][sprite].speed = speed;
01342 }
01343
01355 extern inline u16 PA_GetSpriteAnimSpeed(u8 screen, u8 sprite)
01356 {
01357 return spriteanims[screen][sprite].speed;
01358 }
01359
01360
01375 extern inline void PA_SetSpriteNCycles(u8 screen, u8 sprite, s16 NCycles)
01376 {
01377 spriteanims[screen][sprite].ncycles = NCycles;
01378 }
01379
01380
01381
01393 extern inline u16 PA_GetSpriteNCycles(u8 screen, u8 sprite)
01394 {
01395 return spriteanims[screen][sprite].speed;
01396 }
01397
01398
01399
01400
01401
01416 extern inline void PA_SpriteAnimPause(u8 screen, u8 sprite, u8 pause)
01417 {
01418 if (pause&&spriteanims[screen][sprite].play) nspriteanims--;
01419 else if ((!pause)&&(!spriteanims[screen][sprite].play)) nspriteanims++;
01420 spriteanims[screen][sprite].play = !pause;
01421 }
01422
01423
01424
01425
01426
01427
01448 extern inline void PA_SetSpritePixel(u8 screen, u8 sprite, u8 x, u8 y, u8 color){
01449 u8 hsize = spriteanims[screen][sprite].lx>>3;
01450
01451 s32 pos = (x >> 3) + ((y >> 3) * hsize);
01452 x&=7; y&=7;
01453
01454 pos = (pos << 5) + (x >> 1) + (y << 2);
01455
01456 u16 pixel = spriteanims[screen][sprite].gfx[pos];
01457
01458 if (x&1){
01459 spriteanims[screen][sprite].gfx[pos] = (color << 8) | (pixel&0x00FF);
01460 }
01461 else {
01462 spriteanims[screen][sprite].gfx[pos] = color | (pixel&0xFF00);
01463 }
01464 }
01465
01466
01484 extern inline u8 PA_GetSpritePixel(u8 screen, u8 sprite, u8 x, u8 y) {
01485 u8 hsize = spriteanims[screen][sprite].lx>>3;
01486
01487 s32 pos = (x >> 3) + ((y >> 3) * hsize);
01488 x&=7; y&=7;
01489
01490 pos = (pos << 5) + (x >> 1) + (y << 2);
01491
01492 u16 pixel = spriteanims[screen][sprite].gfx[pos];
01493
01494 if (x&1){
01495 return ((pixel>>8)&255);
01496 }
01497 else {
01498 return (pixel&255);
01499 }
01500 }
01501
01502
01514 void PA_InitSpriteDraw(u8 screen, u8 sprite);
01515
01516
01517
01523 extern inline void PA_InitAllSpriteDraw(void){
01524 u8 i, j;
01525 for (j = 0; j < 2; j++)
01526 for (i = 0; i < 128; i++)
01527 PA_InitSpriteDraw(j, i);
01528 }
01529
01530
01531
01532
01541 void PA_InitSpriteExtPrio(u8 SpritePrio);
01542
01543 extern inline void PA_SetSPriteExtPrio(u8 screen, u8 sprite, u8 prio){
01544 PA_SpritePrio[screen][sprite] = prio;
01545 }
01546
01547
01548
01549
01551
01552
01553
01554
01555
01556 void PA_UpdateSpriteAnims(void);
01557
01558
01559
01560
01561
01562
01563 #ifdef __cplusplus
01564 }
01565 #endif
01566
01567
01568
01569
01570 #endif
01571
01572