#21637 - jarobi - Wed Jun 02, 2004 6:36 am
I just started playing around with tile modes and decided to start with mode 2, but whenever I try to set REG_BG2CNT some other background register gets written to and my tiles display weird in that background (tile 0 only, in random places). My intent is to put tile data (8 tiles, 256 colors) in charater base 0, and my map data in screen base 1. However, when i run my program and observe the contents of the background registers, REG_BG2CNT uses the map data from the correct location, but uses charater block 2 for its tile data (which happens to be empty). The other background register that displays my tiles, is empty, therefore the map data and the tile data are in the same location, thus the random appearance of tiles. I've tried using different charater base blocks and screen base blocks to no avail. I tried switching to the background that displays funny stuff, but it displays that in background 2 instead. I noticed I was accessing map data 8 bits at a time, so I fixed that and nothing happened. Can anyone please tell me what I might be doing wrong?
Here is part of my code and header file for some insight:
Header File:
C File:
_________________
Nihongo o hanasemasen!
Here is part of my code and header file for some insight:
Header File:
Code: |
//my modifications: #define GAMEPAK_RAM *(u8*)0xE000000 //gamepak ram 64KB //setting screen mode #define MODE_0 0x0 #define MODE_1 0x1 #define MODE_2 0x2 #define MODE_3 0x3 #define MODE_4 0x4 #define MODE_5 0x5 #define BACKBUFFER 0x10 #define H_BLANK_OAM 0x20 #define OBJ_MAP_2D 0x0 #define OBJ_MAP_1D 0x40 #define FORCE_BLANK 0x80 #define BG0_ENABLE 0x100 #define BG1_ENABLE 0x200 #define BG2_ENABLE 0x400 #define BG3_ENABLE 0x800 #define OBJ_ENABLE 0x1000 #define WIN1_ENABLE 0x2000 #define WIN2_ENABLE 0x4000 #define WINOBJ_ENABLE 0x8000 #define setMode(mode) REG_DISPCNT=(mode) //height and width #define HEIGHT 160 #define WIDTH 240 #define RGB(r,g,b) (r|(g<<5)|(b<<10)) //keypad (REG_KEYPAD is address 0x4000130 -- dereferences address) #define KEY_A 1 #define KEY_B 2 #define KEY_SELECT 4 #define KEY_START 8 #define KEY_RIGHT 16 #define KEY_LEFT 32 #define KEY_UP 64 #define KEY_DOWN 128 #define KEY_R 256 #define KEY_L 512 #define KEY_PRESSED(k) (!(REG_KEYPAD & k)) //sprites //attribute 0 data #define ROTATION_FLAG 0x100 #define SIZE_DOUBLE 0x200 #define MODE_NORMAL 0x0 #define MODE_TRANSPARENT 0x400 #define MODE_WINDOWED 0x800 #define MOSAIC 0x1000 #define COLOR_16 0x0000 #define COLOR_256 0x2000 #define SQUARE 0x0 #define TALL 0x8000 #define WIDE 0x4000 //attribute 1 data #define ROT_INDEX(n) ((n & 0x1f) << 9) #define HORIZONTAL_FLIP 0x1000 #define VERTICAL_FLIP 0x2000 #define SIZE_8 0x0 #define SIZE_16 0x4000 #define SIZE_32 0x8000 #define SIZE_64 0xC000 //attribute 2 data #define PRIORITY(n) ((n & 3) << 10) #define PALETTE(n) ((n & 15) << 12) //attribute 4 and sprite data typedef struct tagOAMEntry { u16 attribute0; u16 attribute1; u16 attribute2; u16 attribute3; } OAMEntry, *pOAMEntry; typedef struct tagRotData { u16 filler1[3]; //not used u16 pa; u16 filler2[3]; //not used u16 pb; u16 filler3[3]; //not used u16 pc; u16 filler4[3]; //not used u16 pd; } RotData, *pRotData; u16 *OAM = (u16*)0x7000000; //the address of OAM OAMEntry sprites[128]; //My sprite array pRotData rotData = (pRotData)sprites; //backgrounds (tile mode) #define BG_MOSAIC_ENABLE 0x40 #define BG_COLOR_256 0x80 //256 color mode #define BG_COLOR_16 0x0 //16 color mode #define TEXTBG_SIZE_1 0x0 //256 x 256 tiles #define TEXTBG_SIZE_3 0x8000 //256 x 512 tiles #define TEXTBG_SIZE_2 0x4000 //512 x 256 tiles #define TEXTBG_SIZE_4 0xC000 //512 x 512 tiles #define ROTBG_SIZE_1 0x0 //128 x 128 tiles #define ROTBG_SIZE_2 0x4000 //256 x 256 tiles #define ROTBG_SIZE_3 0x8000 //512 x 512 tiles #define ROTBG_SIZE_4 0xC000 //1024 x 1024 tiles #define WRAP_AROUND 0x2000 //map wrap over for rotation bg's #define BG_PRIORITY(n) (n&3) //bgackground priority #define CHAR_BASE_BLOCK(n) (((n)&0x3)<<2) //used when updating BGxCNT register #define SCREEN_BASE_BLOCK(n) (((n)&0x1F)<<8) //used when updating BGxCNT register #define charBaseBlock(n) (0x6000000+(n*0x4000)) //gives address #define screenBaseBlock(n) (0x6000000+(n*0x800)) //gives address //a struct holding all the attributes of a background struct BACKGROUND { u8 bgNumber; u16 attributes; //holds attributes of background to be put in REG_BGxCNT u16 x_scroll, y_scroll; //scroll for text bg (also used for rotation bg implicitly) u32 dx, dy; //scroll for rotation bg exclusively u16 pa, pb, pc, pd; //rotation attributes }; typedef struct BACKGROUND Background; |
C File:
Code: |
#include <stdlib.h> #include "../gba.h" #include "../fixed.h" #include "../sincostable.h" #include "ship.h" #include "bgtiles_space.h" #define PALETTE_LENGTH 256 u16 *tileData_space = (u16*)charBaseBlock(0); u16 *mapData_space = (u16*)screenBaseBlock(16); u16 *bgPaletteMem = (u16*)0x5000000; u16 *objPaletteMem = (u16*)0x5000200; u16 *videoBuffer = (u16*)0x6000000; u16 *charBuffer = (u16*)0x6010000; void rotateBackground(Background *bg, s16 angle, int center_x, int center_y, Fixed scale) { center_y = (center_y * scale)>>8; center_x = (center_x * scale)>>8; bg->dx = (bg->x_scroll - (center_y*SIN[angle]) - (center_x*COS[angle])); bg->dy = (bg->y_scroll - (center_y*COS[angle]) + (center_x*SIN[angle])); bg->pa = multFixed(COS[angle], scale); bg->pb = multFixed(SIN[angle], scale); bg->pc = multFixed(-SIN[angle], scale); bg->pd = multFixed(COS[angle], scale); } void updateBackground(Background *bg) { switch(bg->bgNumber) { case 0: REG_BG0HOFS = bg->x_scroll; REG_BG0VOFS = bg->y_scroll; break; case 1: REG_BG1HOFS = bg->x_scroll; REG_BG1VOFS = bg->y_scroll; break; case 2: if(!(REG_DISPCNT & MODE_0)) { REG_BG2X = bg->dx; REG_BG2Y = bg->dy; REG_BG2PA = bg->pa; REG_BG2PB = bg->pb; REG_BG2PC = bg->pc; REG_BG2PD = bg->pd; } else { REG_BG2HOFS = bg->x_scroll; REG_BG2VOFS = bg->y_scroll; } break; case 3: if(!(REG_DISPCNT & MODE_0)) { REG_BG3X = bg->dx; REG_BG3Y = bg->dy; REG_BG3PA = bg->pa; REG_BG3PB = bg->pb; REG_BG3PC = bg->pc; REG_BG3PD = bg->pd; } else { REG_BG3HOFS = bg->x_scroll; REG_BG3VOFS = bg->y_scroll; } } } void waitForVBlank() { while (REG_VCOUNT < 160){} } void copyOAM() { int i; u16 *spritePtr = (u16*)sprites; for (i = 0; i < 128 * 4; i++) { OAM[i] = spritePtr[i]; } } void moveSprite(OAMEntry *sprite, s16 *x, s16 *y) { sprite->attribute0 &= 0xff00; sprite->attribute0 |= (*y &= 0x00ff); sprite->attribute1 &= 0xfe00; sprite->attribute1 |= (*x &= 0x01ff); } void rotateSprite(s16 rotDataIndex, s16 angle, s16 x_scale, s16 y_scale) { s16 pa, pb, pc, pd; pa = multFixed(x_scale, COS[angle]); pb = multFixed(y_scale, SIN[angle]); pc = multFixed(x_scale, -SIN[angle]); pd = multFixed(y_scale, COS[angle]); rotData[rotDataIndex].pa = pa; rotData[rotDataIndex].pb = pb; rotData[rotDataIndex].pc = pc; rotData[rotDataIndex].pd = pd; } void initSprites() { int i; for (i = 0; i < 128; i++) { sprites[i].attribute0 = 160; sprites[i].attribute1 = 240; } } int main() { int i; Background *bg2_space; setMode(MODE_2|OBJ_MAP_1D|BG2_ENABLE|OBJ_ENABLE); bg2_space->bgNumber = 2; bg2_space->attributes = ROTBG_SIZE_1|WRAP_AROUND|SCREEN_BASE_BLOCK(1)|BG_COLOR_256|CHAR_BASE_BLOCK(0)|BG_PRIORITY(3); REG_BG2CNT = bg2_space->attributes; //load obj and bg palettes for (i = 0; i < PALETTE_LENGTH; i++) { bgPaletteMem[i] = bgtiles_spacePalette[i]; objPaletteMem[i] = shipPalette[i]; } for (i = 0; i < 256; i++) { tileData_space[i] = bgtiles_spaceData[i]; } for (i = 0; i < 256/2; i++) { mapData_space[i] = 0; mapData_space[i] = 0<<8; } while (1) { waitForVBlank(); } return 0; } |
_________________
Nihongo o hanasemasen!