00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00087 #ifndef _libnds_background_h_
00088 #define _libnds_background_h_
00089
00090 #include <nds/ndstypes.h>
00091 #include <nds/arm9/video.h>
00092 #include <nds/arm9/sassert.h>
00093 #include <nds/memory.h>
00094 #include <nds/dma.h>
00095
00096
00097
00098
00107 typedef struct bg_scroll {
00108 u16 x;
00109 u16 y;
00110 } bg_scroll;
00111
00115 typedef struct bg_transform {
00116 s16 xdx;
00117 s16 ydx;
00118 s16 xdy;
00119 s16 ydy;
00120 s32 dx;
00121 s32 dy;
00122 } bg_transform;
00123
00127 typedef struct bg_attribute {
00128 u16 control[4];
00129 bg_scroll scroll[4];
00130 bg_transform bg2_rotation;
00131 bg_transform bg3_rotation;
00132 } bg_attribute;
00133
00135 #define MAP_BASE_SHIFT 8
00136
00137 #define TILE_BASE_SHIFT 2
00138
00139 #define BG_TILE_BASE(base) ((base) << TILE_BASE_SHIFT)
00140
00141 #define BG_MAP_BASE(base) ((base) << MAP_BASE_SHIFT)
00142
00143 #define BG_BMP_BASE(base) ((base) << MAP_BASE_SHIFT)
00144
00145 #define BG_PRIORITY(n) (n)
00146
00148 #define TILE_PALETTE(n) ((n)<<12)
00149
00150 #define TILE_FLIP_H BIT(10)
00151
00152 #define TILE_FLIP_V BIT(11)
00153
00157 typedef enum
00158 {
00159 BG_32x32 = (0 << 14),
00160 BG_64x32 = (1 << 14),
00161 BG_32x64 = (2 << 14),
00162 BG_64x64 = (3 << 14),
00164 BG_RS_16x16 = (0 << 14),
00165 BG_RS_32x32 = (1 << 14),
00166 BG_RS_64x64 = (2 << 14),
00167 BG_RS_128x128 = (3 << 14),
00169 BG_BMP8_128x128 = ((0 << 14) | BIT(7)),
00170 BG_BMP8_256x256 = ((1 << 14) | BIT(7)),
00171 BG_BMP8_512x256 = ((2 << 14) | BIT(7)),
00172 BG_BMP8_512x512 = ((3 << 14) | BIT(7)),
00173 BG_BMP8_1024x512 = BIT(14),
00174 BG_BMP8_512x1024 = 0,
00176 BG_BMP16_128x128 = ((0 << 14) | BIT(7) | BIT(2)),
00177 BG_BMP16_256x256 = ((1 << 14) | BIT(7) | BIT(2)),
00178 BG_BMP16_512x256 = ((2 << 14) | BIT(7) | BIT(2)),
00179 BG_BMP16_512x512 = ((3 << 14) | BIT(7) | BIT(2)),
00181 BG_MOSAIC_ON = (BIT(6)),
00182 BG_MOSAIC_OFF = (0),
00184 BG_PRIORITY_0 = (0),
00185 BG_PRIORITY_1 = (1),
00186 BG_PRIORITY_2 = (2),
00187 BG_PRIORITY_3 = (3),
00189 BG_WRAP_OFF = (0),
00190 BG_WRAP_ON = (1 << 13),
00192 BG_PALETTE_SLOT0 = 0,
00193 BG_PALETTE_SLOT1 = 0,
00194 BG_PALETTE_SLOT2 = BIT(13),
00195 BG_PALETTE_SLOT3 = BIT(13),
00197 BG_COLOR_256 = 0x80,
00198 BG_COLOR_16 = 0x00
00200 }BackgroundControl;
00201
00202
00212 #define BACKGROUND (*((bg_attribute *)0x04000008))
00213
00216 #define BG_OFFSET ((bg_scroll *)(0x04000010))
00217
00218 #define BG_MAP_RAM(base) ((u16*)(((base)*0x800) + 0x06000000))
00219
00220 #define BG_TILE_RAM(base) ((u16*)(((base)*0x4000) + 0x06000000))
00221
00222 #define BG_BMP_RAM(base) ((u16*)(((base)*0x4000) + 0x06000000))
00223
00224 #define CHAR_BASE_BLOCK(n) (((n)*0x4000)+ 0x06000000)
00225
00226 #define SCREEN_BASE_BLOCK(n) (((n)*0x800) + 0x06000000)
00227
00231 #define BGCTRL ( (vu16*)0x4000008)
00232
00235 #define REG_BG0CNT (*(vu16*)0x4000008)
00236
00239 #define REG_BG1CNT (*(vu16*)0x400000A)
00240
00243 #define REG_BG2CNT (*(vu16*)0x400000C)
00244
00247 #define REG_BG3CNT (*(vu16*)0x400000E)
00248
00249
00250 #define REG_BGOFFSETS ( (vu16*)0x4000010)
00251
00252 #define REG_BG0HOFS (*(vu16*)0x4000010)
00253
00254 #define REG_BG0VOFS (*(vu16*)0x4000012)
00255
00256 #define REG_BG1HOFS (*(vu16*)0x4000014)
00257
00258 #define REG_BG1VOFS (*(vu16*)0x4000016)
00259
00260 #define REG_BG2HOFS (*(vu16*)0x4000018)
00261
00262 #define REG_BG2VOFS (*(vu16*)0x400001A)
00263
00264 #define REG_BG3HOFS (*(vu16*)0x400001C)
00265
00266 #define REG_BG3VOFS (*(vu16*)0x400001E)
00267
00268 #define REG_BG2PA (*(vs16*)0x4000020)
00269
00270 #define REG_BG2PB (*(vs16*)0x4000022)
00271
00272 #define REG_BG2PC (*(vs16*)0x4000024)
00273
00274 #define REG_BG2PD (*(vs16*)0x4000026)
00275
00277 #define REG_BG2X (*(vs32*)0x4000028)
00278
00280 #define REG_BG2Y (*(vs32*)0x400002C)
00281
00282 #define REG_BG3PA (*(vs16*)0x4000030)
00283
00284 #define REG_BG3PB (*(vs16*)0x4000032)
00285
00286 #define REG_BG3PC (*(vs16*)0x4000034)
00287
00288 #define REG_BG3PD (*(vs16*)0x4000036)
00289
00291 #define REG_BG3X (*(vs32*)0x4000038)
00292
00294 #define REG_BG3Y (*(vs32*)0x400003C)
00295
00304 #define BACKGROUND_SUB (*((bg_attribute *)0x04001008))
00305
00308 #define BG_OFFSET_SUB ((bg_scroll *)(0x04001010))
00309
00310 #define BG_MAP_RAM_SUB(base) ((u16*)(((base)*0x800) + 0x06200000))
00311
00312 #define BG_TILE_RAM_SUB(base) ((u16*)(((base)*0x4000) + 0x06200000))
00313
00314 #define BG_BMP_RAM_SUB(base) ((u16*)(((base)*0x4000) + 0x06200000))
00315
00316 #define SCREEN_BASE_BLOCK_SUB(n) (((n)*0x800) + 0x06200000)
00317
00318 #define CHAR_BASE_BLOCK_SUB(n) (((n)*0x4000)+ 0x06200000)
00319
00323 #define BGCTRL_SUB ( (vu16*)0x4001008)
00324
00327 #define REG_BG0CNT_SUB (*(vu16*)0x4001008)
00328
00331 #define REG_BG1CNT_SUB (*(vu16*)0x400100A)
00332
00335 #define REG_BG2CNT_SUB (*(vu16*)0x400100C)
00336
00339 #define REG_BG3CNT_SUB (*(vu16*)0x400100E)
00340
00341 #define REG_BGOFFSETS_SUB ( (vu16*)0x4001010)
00342
00344 #define REG_BG0HOFS_SUB (*(vu16*)0x4001010)
00345
00346 #define REG_BG0VOFS_SUB (*(vu16*)0x4001012)
00347
00348 #define REG_BG1HOFS_SUB (*(vu16*)0x4001014)
00349
00350 #define REG_BG1VOFS_SUB (*(vu16*)0x4001016)
00351
00352 #define REG_BG2HOFS_SUB (*(vu16*)0x4001018)
00353
00354 #define REG_BG2VOFS_SUB (*(vu16*)0x400101A)
00355
00356 #define REG_BG3HOFS_SUB (*(vu16*)0x400101C)
00357
00358 #define REG_BG3VOFS_SUB (*(vu16*)0x400101E)
00359
00361 #define REG_BG2PA_SUB (*(vs16*)0x4001020)
00362
00363 #define REG_BG2PB_SUB (*(vs16*)0x4001022)
00364
00365 #define REG_BG2PC_SUB (*(vs16*)0x4001024)
00366
00367 #define REG_BG2PD_SUB (*(vs16*)0x4001026)
00368
00370 #define REG_BG2X_SUB (*(vs32*)0x4001028)
00371
00372 #define REG_BG2Y_SUB (*(vs32*)0x400102C)
00373
00375 #define REG_BG3PA_SUB (*(vs16*)0x4001030)
00376
00377 #define REG_BG3PB_SUB (*(vs16*)0x4001032)
00378
00379 #define REG_BG3PC_SUB (*(vs16*)0x4001034)
00380
00381 #define REG_BG3PD_SUB (*(vs16*)0x4001036)
00382
00384 #define REG_BG3X_SUB (*(vs32*)0x4001038)
00385
00386 #define REG_BG3Y_SUB (*(vs32*)0x400103C)
00387
00394
00395 typedef struct BgState
00396 {
00397 int angle;
00398 s32 centerX;
00399 s32 centerY;
00400 s32 scaleX;
00401 s32 scaleY;
00402 s32 scrollX;
00403 s32 scrollY;
00404 int size;
00405 int type;
00406 bool dirty;
00407
00408 }BgState;
00409
00410
00411
00412 extern vuint16* bgControl[8];
00413 extern bg_scroll* bgScrollTable[8];
00414 extern bg_transform* bgTransform[8];
00415 extern BgState bgState[8];
00416
00421 typedef enum
00422 {
00423 BgType_Text8bpp,
00424 BgType_Text4bpp,
00425 BgType_Rotation,
00426 BgType_ExRotation,
00427 BgType_Bmp8,
00428 BgType_Bmp16
00431 }BgType;
00432
00433
00440 typedef enum
00441 {
00442 BgSize_R_128x128 = (0 << 14),
00443 BgSize_R_256x256 = (1 << 14),
00444 BgSize_R_512x512 = (2 << 14),
00445 BgSize_R_1024x1024 = (3 << 14),
00447 BgSize_T_256x256 = (0 << 14) | (1 << 16),
00448 BgSize_T_512x256 = (1 << 14) | (1 << 16),
00449 BgSize_T_256x512 = (2 << 14) | (1 << 16),
00450 BgSize_T_512x512 = (3 << 14) | (1 << 16),
00452 BgSize_ER_128x128 = (0 << 14) | (2 << 16),
00453 BgSize_ER_256x256 = (1 << 14) | (2 << 16),
00454 BgSize_ER_512x512 = (2 << 14) | (2 << 16),
00455 BgSize_ER_1024x1024 = (3 << 14) | (2 << 16),
00457 BgSize_B8_128x128 = ((0 << 14) | BIT(7) | (3 << 16)),
00458 BgSize_B8_256x256 = ((1 << 14) | BIT(7) | (3 << 16)),
00459 BgSize_B8_512x256 = ((2 << 14) | BIT(7) | (3 << 16)),
00460 BgSize_B8_512x512 = ((3 << 14) | BIT(7) | (3 << 16)),
00461 BgSize_B8_1024x512 = (1 << 14) | (3 << 16),
00462 BgSize_B8_512x1024 = (0) | (3 << 16),
00464 BgSize_B16_128x128 = ((0 << 14) | BIT(7) | BIT(2) | (4 << 16)),
00465 BgSize_B16_256x256 = ((1 << 14) | BIT(7) | BIT(2) | (4 << 16)),
00466 BgSize_B16_512x256 = ((2 << 14) | BIT(7) | BIT(2) | (4 << 16)),
00467 BgSize_B16_512x512 = ((3 << 14) | BIT(7) | BIT(2) | (4 << 16)),
00469 }BgSize;
00470
00471
00472 #ifdef __cplusplus
00473 extern "C" {
00474 #endif
00475
00476
00477 bool bgIsText(int id);
00478 int bgInit_call(int layer, BgType type, BgSize size, int mapBase, int tileBase);
00479 int bgInitSub_call(int layer, BgType type, BgSize size, int mapBase, int tileBase);
00480
00485 void bgUpdate(void);
00486
00487 static inline
00495 void bgSetRotate(int id, int angle)
00496 {
00497 bgState[id].angle = angle;
00498
00499 bgState[id].dirty = true;
00500 }
00501
00502
00503
00504 static inline
00512 void bgRotate(int id, int angle)
00513 {
00514 sassert(!bgIsText(id), "Cannot Rotate a Text Background");
00515
00516 bgSetRotate(id, angle + bgState[id].angle);
00517 }
00518
00519 static inline
00540 void bgSet(int id, int angle, s32 sx, s32 sy, s32 scrollX, s32 scrollY, s32 rotCenterX, s32 rotCenterY)
00541 {
00542 bgState[id].scaleX = sx;
00543 bgState[id].scaleY = sy;
00544
00545 bgState[id].scrollX = scrollX;
00546 bgState[id].scrollY = scrollY;
00547
00548 bgState[id].centerX = rotCenterX;
00549 bgState[id].centerY = rotCenterY;
00550
00551 bgState[id].angle = angle;
00552
00553 bgState[id].dirty = true;
00554 }
00555
00556 static inline
00568 void bgSetRotateScale(int id, int angle, s32 sx, s32 sy)
00569 {
00570 bgState[id].scaleX = sx;
00571 bgState[id].scaleY = sy;
00572 bgState[id].angle = angle;
00573
00574 bgState[id].dirty = true;
00575 }
00576
00577 static inline
00587 void bgSetScale(int id, s32 sx, s32 sy)
00588 {
00589 sassert(!bgIsText(id), "Cannot Scale a Text Background");
00590
00591 bgState[id].scaleX = sx;
00592 bgState[id].scaleY = sy;
00593
00594 bgState[id].dirty = true;
00595 }
00596
00597 static inline
00620 int bgInit(int layer, BgType type, BgSize size, int mapBase, int tileBase)
00621 {
00622 sassert(layer >= 0 && layer <= 3, "Only layers 0 - 3 are supported");
00623 sassert(tileBase >= 0 && tileBase <= 15, "Background tile base is out of range");
00624 sassert(mapBase >=0 && mapBase <= 31, "Background Map Base is out of range");
00625 sassert(layer != 0 || !video3DEnabled(), "Background 0 is currently being used for 3D display");
00626 sassert(layer > 1 || type == BgType_Text8bpp || type == BgType_Text4bpp, "Incorrect background type for mode");
00627
00628 sassert(tileBase == 0 || type < BgType_Bmp8, "Tile base is unused for bitmaps. Can be offset using mapBase * 16KB");
00629 sassert((mapBase == 0 || type != BgType_Bmp8) || (size != BgSize_B8_512x1024 && size != BgSize_B8_1024x512), "Large Bitmaps cannot be offset");
00630
00631 return bgInit_call(layer, type, size, mapBase, tileBase);
00632 }
00633
00634 static inline
00657 int bgInitSub(int layer, BgType type, BgSize size, int mapBase, int tileBase)
00658 {
00659 sassert(layer >= 0 && layer <= 3, "Only layers 0 - 3 are supported");
00660 sassert(tileBase >= 0 && tileBase <= 15, "Background tile base is out of range");
00661 sassert(mapBase >=0 && mapBase <= 31, "Background Map Base is out of range");
00662 sassert(layer > 1 || type == BgType_Text8bpp|| type == BgType_Text4bpp , "Incorrect background type for mode");
00663 sassert(tileBase == 0 || type < BgType_Bmp8, "Tile base is unused for bitmaps. Can be offset using mapBase * 16KB");
00664 sassert((size != BgSize_B8_512x1024 && size != BgSize_B8_1024x512), "Sub Display has no large Bitmaps");
00665
00666 return bgInitSub_call(layer, type, size, mapBase, tileBase);
00667 }
00668
00669 static inline
00680 vuint16* bgSetControlBits(int id, u16 bits)
00681 {
00682 *bgControl[id] |= bits;
00683 return bgControl[id];
00684 }
00685
00686 static inline
00694 void bgClearControlBits(int id, u16 bits)
00695 {
00696 *bgControl[id] &= ~bits;
00697 }
00698
00699 static inline
00700
00701 void bgWrapOn(int id)
00702 {
00703 bgSetControlBits(id, BIT(13));
00704 }
00705
00706 static inline
00707
00708 void bgWrapOff(int id)
00709 {
00710 bgClearControlBits(id, BIT(13));
00711 }
00712 static inline
00721 void bgSetPriority(int id, unsigned int priority)
00722 {
00723 sassert(priority < 4, "Priority must be less than 4");
00724
00725 *bgControl[id] &= ~ 3;
00726 *bgControl[id] |= priority;
00727
00728 }
00729
00730 static inline
00739 void bgSetMapBase(int id, unsigned int base)
00740 {
00741 sassert(base <= 31, "Map base cannot exceed 31");
00742
00743 *bgControl[id] &= ~ (31 << MAP_BASE_SHIFT);
00744 *bgControl[id] |= base << MAP_BASE_SHIFT;
00745 }
00746
00747 static inline
00756 void bgSetTileBase(int id, unsigned int base)
00757 {
00758 sassert(base <= 15, "Tile base cannot exceed 15");
00759
00760 *bgControl[id] &= ~ (15 << TILE_BASE_SHIFT);
00761 *bgControl[id] |= base << TILE_BASE_SHIFT;
00762 }
00763
00764
00765 static inline
00778 void bgSetScrollf(int id, s32 x, s32 y)
00779 {
00780
00781 bgState[id].scrollX = x;
00782 bgState[id].scrollY = y;
00783
00784 bgState[id].dirty = true;
00785 }
00786
00787 static inline
00797 void bgSetScroll(int id, int x, int y)
00798 {
00799 bgSetScrollf(id, x << 8, y << 8);
00800 }
00801
00802
00803 static inline
00809 void bgMosaicEnable(int id)
00810 {
00811 *bgControl[id] |= BIT(6);
00812 }
00813
00814 static inline
00820 void bgMosaicDisable(int id)
00821 {
00822 *bgControl[id] &= ~BIT(6);
00823 }
00824
00825 static inline
00833 void bgSetMosaic(unsigned int dx, unsigned int dy) {
00834 sassert(dx < 16 && dy < 16, "Mosaic range is 0 to 15");
00835
00836 mosaicShadow = ( mosaicShadow & 0xff00) | (dx | (dy << 4));
00837 REG_MOSAIC = mosaicShadow;
00838
00839 }
00840
00841 static inline
00849 void bgSetMosaicSub(unsigned int dx, unsigned int dy) {
00850 sassert(dx < 16 && dy < 16, "Mosaic range is 0 to 15");
00851
00852 mosaicShadowSub = ( mosaicShadowSub & 0xff00) | (dx | (dy << 4));
00853 REG_MOSAIC_SUB = mosaicShadowSub;
00854
00855 }
00856
00857 static inline
00865 int bgGetPriority(int id)
00866 {
00867 return *bgControl[id] & 3;
00868 }
00869
00870 static inline
00880 int bgGetMapBase(int id)
00881 {
00882 return (*bgControl[id] >> MAP_BASE_SHIFT) & 31;
00883 }
00884
00885 static inline
00893 int bgGetTileBase(int id)
00894 {
00895 return (*bgControl[id] >> TILE_BASE_SHIFT) & 31;
00896 }
00897
00898 static inline
00906 u16* bgGetMapPtr(int id)
00907 {
00908 return (id < 4) ? ((u16*)BG_MAP_RAM(bgGetMapBase(id))) : ((u16*)BG_MAP_RAM_SUB(bgGetMapBase(id)));
00909 }
00910
00911 static inline
00919 u16* bgGetGfxPtr(int id)
00920 {
00921 if(bgState[id].type < BgType_Bmp8)
00922 return (id < 4) ? (u16*)(BG_TILE_RAM(bgGetTileBase(id))) : ((u16*)BG_TILE_RAM_SUB(bgGetTileBase(id)));
00923 else
00924 return (id < 4) ? (u16*)(BG_GFX + 0x2000 * (bgGetMapBase(id))) : (u16*)(BG_GFX_SUB + 0x2000 * (bgGetMapBase(id)));
00925 }
00926
00927
00928 static inline
00941 void bgScrollf(int id, s32 dx, s32 dy)
00942 {
00943 bgSetScrollf(id, bgState[id].scrollX + dx, bgState[id].scrollY + dy);
00944 }
00945
00946 static inline
00959 void bgScroll(int id, int dx, int dy)
00960 {
00961 bgScrollf(id, dx << 8, dy << 8);
00962 }
00963
00964 static inline
00970 void bgShow(int id)
00971 {
00972 if(id < 4)
00973 videoBgEnable(id);
00974 else
00975 videoBgEnableSub(id & 3);
00976 }
00977
00978 static inline
00984 void bgHide(int id)
00985 {
00986 if(id < 4)
00987 videoBgDisable(id);
00988 else
00989 videoBgDisableSub(id & 3);
00990 }
00991
00992 static inline
01005 void bgSetCenterf(int id, s32 x, s32 y)
01006 {
01007 sassert(!bgIsText(id), "Text Backgrounds have no Center of Rotation");
01008
01009 bgState[id].centerX = x;
01010 bgState[id].centerY = y;
01011
01012 bgState[id].dirty = true;
01013 }
01014
01015 static inline
01026 void bgSetCenter(int id, int x, int y)
01027 {
01028 bgSetCenterf(id, x << 8, y << 8);
01029 }
01030
01031 #ifdef __cplusplus
01032 }
01033 #endif
01034
01042 #endif