GBA Exploration Diary (2)
Obj and Oam
Obj refers to the wizard of one by one, or the picture of the small piece of small block in GBA. It is actually almost the BG. It is just some. It is also a layer. For example, the RPG game in GBA likes to put One of the characters are implemented with OBJ. Of course, it is also very convenient to see the control of BG from GBA Explore Diary (-). The difference between OBJ and BG is the size.
Set display mode
If you have to use OBJ in your program,
When setting the display mode, you need to add DISP_OBJ_ON and DISP_OBJ_CHAR_1D_MAP to
* (vu16 *) REG_DISPCNT = DISP_MODE_1 | DISP_OBJ_ON | DISP_OBJ_CHAR_1D_MAP;
#define disp_obj_char_1d_map 0x0040 // Obj Character Data 1D MApping
#define DISP_OBJ_ON 0X1000 // Obj On
Let's take a look at how the OBJ is implemented in GBA.
The first thing to explain is that OBJ is displayed in GBA, which is also made up by a small piece of 8x8, like BG.
There are 12 sizes below.
0000: 8 x 8 1000: 8 x 16
0001: 16 x 161: 8 x 32
0010: 32 x 32 1010: 16 x 32
0011: 64 x 64 1011: 32 x 64
0100: 16 x 8
0101: 32 x 8
0110: 32 x 16
0111: 64 x 32
OBJ's data division three parts.
CHARACTER
It is the same as the BG's data format, which is image data of 8x8 small tiles. And you can also convert the OBJ's character by converting BG. Therefore, the data structure of BG and OBJ is basically the same. But all OBJ's CHARACTER cannot exceed 32K.
256 colors of Obj can have 512 Characters, each of the Characters accounts for 8 * 8 = 64bytes. The 16-color Characters can have 1024. Each Character accounts for 8 * 8/2 = 32bytes. It seems to be 256 Character than a BG. Many? But BG can have multiple, different BGs can have different Characters, and all OBJ can only share this 512 Charater.
2.Palette
The palette is not used, which supports a 256-color palette or 16 16-color palette as a BG.
3.oam
OAM is an abbreviation of Obj AttribURE Memory. It is the data section of the OBJ attribute. For example, the location of the OBJ, the size and other data parts are placed here. Each OAM accounts for 8 bytes, OAM is from 07000000H to 070003ffh 1024 = 8 * 128, so the total of OAM can have 128.
How to create an OBJ?
I said that I can use the tool of converting BG to convert OBJ.
Previous conversion BG I recommend using BMP2Map.exe in AGBLIB, similarly, convert OBJ also uses BMP2Map.exe tools.
For example, put the Character Data into the number of sprite_gfx, put the Palette in sprite_pal. (There is no Map Data in the OBJ, you can convert Map Data when your conversion is converted, but it is not used later)
Then write in the program:
DmaArrayCopy (3, sprite_gfx, obj_mode1_vram, 32);
DmaArrayCopy (3, Sprite_Pal, Obj_pltt, 32);
Copy sprite_gfx, sprite_pal to the specified memory.
Here is the OBJ_MODE1_VRAM and OBJ_PLTT two memory addresses
Still look at how to define them in Agblib.
#define pltt 0x05000000 // Palette Ram # define plt_end (PLTT 0x400)
#define BG_PLTT (PLTT 0x0) // BG Palette Ram
#define BG_PLTT_END (PLTT 0x200)
#define obj_pltt (PLTT 0x200) // Obj Palette Ram
#define obj_pltt_end (PLTT 0x400)
#define vram 0x06000000 // vram
#define vram_end (vram 0x18000)
#define bg_vram (vram 0x0) // BG Character / Screen Ram
#define obj_mode0_vram (VRAM 0x10000) // Obj Character RAM
#DEFINE OBJ_MODE1_VRAM (VRAM 0x10000)
#DEFINE OBJ_MODE2_VRAM (VRAM 0x10000)
#define obj_mode3_vram (vram 0x14000)
#DEFINE OBJ_MODE4_VRAM (vram 0x14000)
#define obj_mode5_vram (vram 0x14000)
#DEFINE OBJ_VRAM_END (VRAM 0x18000)
Here I put the address in the BG contains recent, you can compare the address in BG and OBJ.
Then set up OAM (OBJ AttribURE Memory).
Here first, how do you say this OAM's data structure in the official document.
Specially pointed out that Character Name in the above table refers to the reference of this OBJ's starting character.
I will introduce two mid methods to set.
The first method is very intuitive and it is very simple. This is what I saw online.
First define the data structure
TypeDef struct tagoamentry
{
U16 Attribute0;
U16 attribute1;
U16 attribute2;
U16 attribute3;
} OAMENTRY, * POAMENTRY;
// attribute0 #defines
#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 0x4000
#define wide 0x8000
// attribute1 #defines
#define Rotdata (N) ((n) << 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
// atribute2 #defines
#define priority (n) ((n) << 10)
#define palette (n) ((n) << 12)
Then write the code:
OAMENTRY SPRITES [128]; // Here you define a total of 128 OBJ, but we only use the first one.
Void initializesprites ()
{
U16 loop;
For (loop = 0; loop <128; loop )
{
Sprites [loop] .attribute0 = 160; // y to> 159
Sprites [loop] .attribute1 = 240; // x to> 239
}
}
Void Copyoam ()
{
U16 loop;
U16 * TEMP;
U16 * _OAM = (u16 *) 0x7000000;
Temp = (u16 *) sprites;
For (loop = 0; loop <128 * 4; loop )
{
_Oam [loop] = TEMP [loop];
}
}
U16 spritey = 100;
U16 spritex = 100;
Initializesprites ();
Sprites [0] .attribute0 = color_256 | Square | Spritey;
Sprites [0] .attribute1 = size_16 | spritex;
Sprites [0] .attribute2 = 0 | priority (0);
Since this OBJ's character is written from the first address of OBJ_MODE1_VRAM, it should be 0. So Sprites [0] .attribute2 = 0 | priority (0);
Since the 16-color OBJ and 256 colors of the GBA are the same for the address of Characters. So, whether it is 16 colors or 256 colors of OBJ, their starting character, should be the vram character name of Obj * 32 (although 256 colors under 64bytes).
For example, take a look at the example below:
If you transfer 256 colors of the address of the CHARACTER DATA to OBJ_MODE1_VRAM N * 32
DmaArrayCopy (3, sprite_gfx, obj_mode1_vram n * 32, 32);
Then the character name in Attribute2 in its corresponding attribute is N.
Sprites [0] .attribute2 = n; n ranges 0-1023
For Attribute3, we are now not available now.
Next, write Sprites to OAM
To constantly update OAM in the main loop of the program
While (1)
{
// Waiting for image buffer synchronization
Waitsync ();
Copyoam ();
}
The second method is the method used in agblib.
For example, I want to display one is OBJ
Directly define one
VU32 BG_OAM_BUFFER [2];
Then you have to write Character and Palette data into
DmaArrayCopy (3, sprite_gfx, obj_mode1_vram, 32);
DmaArrayCopy (3, Sprite_Pal, Obj_pltt, 32);
Write like this when setting OAM
BG_OAM_BUFFER [0] = OAM_COLOR_256 | OAM_SQUARE | OAM_SIZE_16X16
| (100) << OAM_H_POS_SHIFT
| (72) << OAM_V_POS_SHIFT;
BG_OAM_BUFFER [1] = 0x0400;
The definition of the macro above is given below:
#define OAM_V_POS_SHIFT 0
#define OAM_H_POS_SHIFT 16
#define oam_color_16 0x00000000 // SELECT 16
#define oam_color_256 0x00002000 // SELECT 256 Colors
#define oam_size_8x8 0x00000000 // OBJ 8 x 8 DOT
#define oam_size_16x16 0x40000000 // OBJ 16 x 16 DOT
#define oam_size_32x32 0x80000000 // Obj 32 x 32 DOT
#define oam_size_64x64 0xc0000000 // Obj 64 x 64 Dot
#define oam_size_16x8 0x00004000 // Obj 16 x 8 DOT
#define oam_size_32x8 0x40004000 // Obj 32 x 8 Dot
#define oam_size_32x16 0x80004000 // Obj 32 x 16 Dot
#define oam_size_64x32 0xc0004000 // Obj 64 x 32 DOT
#define oam_size_8x16 0x00008000 // OBJ 8 x 16 DOT
#define oam_size_8x32 0x40008000 // Obj 8 x 32 Dot
#define oam_size_16x32 0x80008000 // Obj 16 x 32 Dot
#define oam_size_32x64 0xc0008000 // Obj 32 x 64 DOT
You can see.
BG_OAM_BUFFER [0] is actually the set of Attribute0, Attribute1 of the first method.
BG_OAM_BUFFER [1] is the collection of Attribute2, Attribute3 of the first method.
The same is then constantly updating the OAM in the program living cycle.
While (1)
{
DMACOPY (3, BG_OAM_BUFFER, OAM, 8, 32);
}
This is the definition of OAM:
#define oam 0x07000000 // oam # define oam_end (oam 0x400)