Some video cleanups for better readability
This commit is contained in:
parent
f5490a1996
commit
2391496432
|
@ -171,6 +171,8 @@ typedef enum
|
|||
REG_HALTCNT = 0x180
|
||||
} hardware_register;
|
||||
|
||||
#define REG_BGxCNT(n) (REG_BG0CNT + (n))
|
||||
|
||||
#define FLASH_DEVICE_UNDEFINED 0x00
|
||||
#define FLASH_DEVICE_MACRONIX_64KB 0x1C
|
||||
#define FLASH_DEVICE_AMTEL_64KB 0x3D
|
||||
|
|
162
video.c
162
video.c
|
@ -24,6 +24,10 @@ u16* gba_screen_pixels = NULL;
|
|||
#define get_screen_pixels() gba_screen_pixels
|
||||
#define get_screen_pitch() GBA_SCREEN_PITCH
|
||||
|
||||
typedef struct {
|
||||
u16 attr0, attr1, attr2, attr3;
|
||||
} t_oam;
|
||||
|
||||
static void render_scanline_conditional_tile(u32 start, u32 end, u16 *scanline,
|
||||
u32 enable_flags, u32 dispcnt, u32 bldcnt, const tile_layer_render_struct
|
||||
*layer_renderers);
|
||||
|
@ -863,7 +867,7 @@ static void render_scanline_text_base_normal(u32 layer,
|
|||
u32 start, u32 end, void *scanline)
|
||||
{
|
||||
render_scanline_extra_variables_base_normal(text);
|
||||
u32 bg_control = read_ioreg(REG_BG0CNT + layer);
|
||||
u32 bg_control = read_ioreg(REG_BGxCNT(layer));
|
||||
u32 map_size = (bg_control >> 14) & 0x03;
|
||||
u32 map_width = map_widths[map_size];
|
||||
u32 horizontal_offset =
|
||||
|
@ -1050,7 +1054,7 @@ static void render_scanline_text_transparent_normal(u32 layer,
|
|||
u32 start, u32 end, void *scanline)
|
||||
{
|
||||
render_scanline_extra_variables_transparent_normal(text);
|
||||
u32 bg_control = read_ioreg(REG_BG0CNT + layer);
|
||||
u32 bg_control = read_ioreg(REG_BGxCNT(layer));
|
||||
u32 map_size = (bg_control >> 14) & 0x03;
|
||||
u32 map_width = map_widths[map_size];
|
||||
u32 horizontal_offset =
|
||||
|
@ -1236,7 +1240,7 @@ static void render_scanline_text_base_color16(u32 layer,
|
|||
u32 start, u32 end, void *scanline)
|
||||
{
|
||||
render_scanline_extra_variables_base_color16(text);
|
||||
u32 bg_control = read_ioreg(REG_BG0CNT + layer);
|
||||
u32 bg_control = read_ioreg(REG_BGxCNT(layer));
|
||||
u32 map_size = (bg_control >> 14) & 0x03;
|
||||
u32 map_width = map_widths[map_size];
|
||||
u32 horizontal_offset =
|
||||
|
@ -1421,7 +1425,7 @@ static void render_scanline_text_transparent_color16(u32 layer,
|
|||
u32 start, u32 end, void *scanline)
|
||||
{
|
||||
render_scanline_extra_variables_transparent_color16(text);
|
||||
u32 bg_control = read_ioreg(REG_BG0CNT + layer);
|
||||
u32 bg_control = read_ioreg(REG_BGxCNT(layer));
|
||||
u32 map_size = (bg_control >> 14) & 0x03;
|
||||
u32 map_width = map_widths[map_size];
|
||||
u32 horizontal_offset =
|
||||
|
@ -1606,7 +1610,7 @@ static void render_scanline_text_base_color32(u32 layer,
|
|||
u32 start, u32 end, void *scanline)
|
||||
{
|
||||
render_scanline_extra_variables_base_color32(text);
|
||||
u32 bg_control = read_ioreg(REG_BG0CNT + layer);
|
||||
u32 bg_control = read_ioreg(REG_BGxCNT(layer));
|
||||
u32 map_size = (bg_control >> 14) & 0x03;
|
||||
u32 map_width = map_widths[map_size];
|
||||
u32 horizontal_offset =
|
||||
|
@ -1791,7 +1795,7 @@ static void render_scanline_text_transparent_color32(u32 layer,
|
|||
u32 start, u32 end, void *scanline)
|
||||
{
|
||||
render_scanline_extra_variables_transparent_color32(text);
|
||||
u32 bg_control = read_ioreg(REG_BG0CNT + layer);
|
||||
u32 bg_control = read_ioreg(REG_BGxCNT(layer));
|
||||
u32 map_size = (bg_control >> 14) & 0x03;
|
||||
u32 map_width = map_widths[map_size];
|
||||
u32 horizontal_offset =
|
||||
|
@ -1978,7 +1982,7 @@ static void render_scanline_text_base_alpha(u32 layer,
|
|||
u32 start, u32 end, void *scanline)
|
||||
{
|
||||
render_scanline_extra_variables_base_alpha(text);
|
||||
u32 bg_control = read_ioreg(REG_BG0CNT + layer);
|
||||
u32 bg_control = read_ioreg(REG_BGxCNT(layer));
|
||||
u32 map_size = (bg_control >> 14) & 0x03;
|
||||
u32 map_width = map_widths[map_size];
|
||||
u32 horizontal_offset =
|
||||
|
@ -2161,7 +2165,7 @@ static void render_scanline_text_transparent_alpha(u32 layer,
|
|||
u32 start, u32 end, void *scanline)
|
||||
{
|
||||
render_scanline_extra_variables_transparent_alpha(text);
|
||||
u32 bg_control = read_ioreg(REG_BG0CNT + layer);
|
||||
u32 bg_control = read_ioreg(REG_BGxCNT(layer));
|
||||
u32 map_size = (bg_control >> 14) & 0x03;
|
||||
u32 map_width = map_widths[map_size];
|
||||
u32 horizontal_offset =
|
||||
|
@ -2532,7 +2536,7 @@ void render_scanline_affine_##combine_op##_##alpha_op(u32 layer, \
|
|||
u32 start, u32 end, void *scanline) \
|
||||
{ \
|
||||
render_scanline_extra_variables_##combine_op##_##alpha_op(affine); \
|
||||
u32 bg_control = read_ioreg(REG_BG0CNT + layer); \
|
||||
u32 bg_control = read_ioreg(REG_BGxCNT(layer)); \
|
||||
u32 current_pixel; \
|
||||
s32 source_x, source_y; \
|
||||
u32 pixel_x, pixel_y; \
|
||||
|
@ -3141,6 +3145,12 @@ static const u32 obj_width_table[] =
|
|||
static const u32 obj_height_table[] =
|
||||
{ 8, 16, 32, 64, 8, 8, 16, 32, 16, 32, 32, 64 };
|
||||
|
||||
static const u8 obj_dim_table[3][4][2] = {
|
||||
{ {8, 8}, {16, 16}, {32, 32}, {64, 64} },
|
||||
{ {16, 8}, {32, 8}, {32, 16}, {64, 32} },
|
||||
{ {8, 16}, {8, 32}, {16, 32}, {32, 64} }
|
||||
};
|
||||
|
||||
static u8 obj_priority_list[5][160][128];
|
||||
static u8 obj_priority_count[5][160];
|
||||
static u8 obj_alpha_count[160];
|
||||
|
@ -3344,43 +3354,53 @@ render_scanline_obj_builder(copy, copy_tile, 2D, no_partial_alpha);
|
|||
render_scanline_obj_builder(copy, copy_bitmap, 1D, no_partial_alpha);
|
||||
render_scanline_obj_builder(copy, copy_bitmap, 2D, no_partial_alpha);
|
||||
|
||||
#define OBJ_MOD_NORMAL 0
|
||||
#define OBJ_MOD_SEMITRAN 1
|
||||
#define OBJ_MOD_WINDOW 2
|
||||
#define OBJ_MOD_INVALID 3
|
||||
|
||||
|
||||
// Goes through the object list in the OAM (from #127 to #0) and adds objects
|
||||
// into a sorted list by priority for the current row.
|
||||
// Invisible objects are discarded.
|
||||
static void order_obj(u32 video_mode)
|
||||
{
|
||||
s32 obj_num, row;
|
||||
s32 obj_x, obj_y;
|
||||
u32 obj_size, obj_mode;
|
||||
s32 obj_width, obj_height;
|
||||
u32 obj_priority;
|
||||
u32 obj_attribute_0, obj_attribute_1, obj_attribute_2;
|
||||
u16 *oam_ptr = oam_ram + 508;
|
||||
s32 obj_num;
|
||||
u32 row;
|
||||
t_oam *oam_base = (t_oam*)oam_ram;
|
||||
|
||||
memset(obj_priority_count, 0, sizeof(obj_priority_count));
|
||||
memset(obj_alpha_count, 0, sizeof(obj_alpha_count));
|
||||
|
||||
for(obj_num = 127; obj_num >= 0; obj_num--, oam_ptr -= 4)
|
||||
for(obj_num = 127; obj_num >= 0; obj_num--)
|
||||
{
|
||||
obj_attribute_0 = eswap16(oam_ptr[0]);
|
||||
obj_attribute_2 = eswap16(oam_ptr[2]);
|
||||
obj_size = obj_attribute_0 & 0xC000;
|
||||
obj_priority = (obj_attribute_2 >> 10) & 0x03;
|
||||
obj_mode = (obj_attribute_0 >> 10) & 0x03;
|
||||
t_oam *oam_ptr = &oam_base[obj_num];
|
||||
u16 obj_attr0 = eswap16(oam_ptr->attr0);
|
||||
// Bit 9 disables regular sprites. Used as double bit for affine ones.
|
||||
bool visible = (obj_attr0 & 0x0300) != 0x0200;
|
||||
if (visible) {
|
||||
u16 obj_shape = obj_attr0 >> 14;
|
||||
u32 obj_mode = (obj_attr0 >> 10) & 0x03;
|
||||
|
||||
if(((obj_attribute_0 & 0x0300) != 0x0200) && (obj_size != 0xC000) &&
|
||||
(obj_mode != 3) && ((video_mode < 3) ||
|
||||
((obj_attribute_2 & 0x3FF) >= 512)))
|
||||
// Prohibited shape and mode
|
||||
bool invalid = (obj_shape == 0x3) || (obj_mode == OBJ_MOD_INVALID);
|
||||
if (!invalid) {
|
||||
u16 obj_attr1 = eswap16(oam_ptr->attr1);
|
||||
u16 obj_attr2 = eswap16(oam_ptr->attr2);
|
||||
u32 obj_priority = (obj_attr2 >> 10) & 0x03;
|
||||
|
||||
if (((video_mode < 3) || ((obj_attr2 & 0x3FF) >= 512)))
|
||||
{
|
||||
obj_y = obj_attribute_0 & 0xFF;
|
||||
// Calculate object size (from size and shape attr bits)
|
||||
u16 obj_size = (obj_attr1 >> 14);
|
||||
s32 obj_height = obj_dim_table[obj_shape][obj_size][1];
|
||||
s32 obj_width = obj_dim_table[obj_shape][obj_size][0];
|
||||
s32 obj_y = obj_attr0 & 0xFF;
|
||||
|
||||
if(obj_y > 160)
|
||||
obj_y -= 256;
|
||||
|
||||
obj_attribute_1 = eswap16(oam_ptr[1]);
|
||||
obj_size = ((obj_size >> 12) & 0x0C) | (obj_attribute_1 >> 14);
|
||||
obj_height = obj_height_table[obj_size];
|
||||
obj_width = obj_width_table[obj_size];
|
||||
|
||||
if(obj_attribute_0 & 0x200)
|
||||
// Double size for affine sprites with double bit set
|
||||
if(obj_attr0 & 0x200)
|
||||
{
|
||||
obj_height *= 2;
|
||||
obj_width *= 2;
|
||||
|
@ -3388,40 +3408,39 @@ static void order_obj(u32 video_mode)
|
|||
|
||||
if(((obj_y + obj_height) > 0) && (obj_y < 160))
|
||||
{
|
||||
obj_x = (s32)(obj_attribute_1 << 23) >> 23;
|
||||
s32 obj_x = (s32)(obj_attr1 << 23) >> 23;
|
||||
|
||||
if(((obj_x + obj_width) > 0) && (obj_x < 240))
|
||||
{
|
||||
if(obj_y < 0)
|
||||
{
|
||||
obj_height += obj_y;
|
||||
obj_y = 0;
|
||||
}
|
||||
// Clip Y coord and height to the 0..159 interval
|
||||
u32 starty = MAX(obj_y, 0);
|
||||
u32 endy = MIN(obj_y + obj_height, 160);
|
||||
|
||||
if((obj_y + obj_height) >= 160)
|
||||
obj_height = 160 - obj_y;
|
||||
|
||||
if(obj_mode == 1)
|
||||
{
|
||||
for(row = obj_y; row < obj_y + obj_height; row++)
|
||||
switch (obj_mode) {
|
||||
case OBJ_MOD_SEMITRAN:
|
||||
for(row = starty; row < endy; row++)
|
||||
{
|
||||
u32 cur_cnt = obj_priority_count[obj_priority][row];
|
||||
obj_priority_list[obj_priority][row][cur_cnt] = obj_num;
|
||||
obj_priority_count[obj_priority][row] = cur_cnt + 1;
|
||||
// Mark the row as having semi-transparent objects
|
||||
obj_alpha_count[row] = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(obj_mode == 2)
|
||||
break;
|
||||
case OBJ_MOD_WINDOW:
|
||||
obj_priority = 4;
|
||||
|
||||
for(row = obj_y; row < obj_y + obj_height; row++)
|
||||
/* fallthrough */
|
||||
case OBJ_MOD_NORMAL:
|
||||
// Add the object to the list.
|
||||
for(row = starty; row < endy; row++)
|
||||
{
|
||||
u32 cur_cnt = obj_priority_count[obj_priority][row];
|
||||
obj_priority_list[obj_priority][row][cur_cnt] = obj_num;
|
||||
obj_priority_count[obj_priority][row] = cur_cnt + 1;
|
||||
}
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3432,29 +3451,31 @@ static void order_obj(u32 video_mode)
|
|||
u32 layer_order[16];
|
||||
u32 layer_count;
|
||||
|
||||
static void order_layers(u32 layer_flags)
|
||||
// Sorts active BG/OBJ layers and generates an ordered list of layers.
|
||||
// Things are drawn back to front, so lowest priority goes first.
|
||||
static void order_layers(u32 layer_flags, u32 vcnt)
|
||||
{
|
||||
s32 priority, layer_number;
|
||||
bool obj_enabled = (layer_flags & 0x10);
|
||||
s32 priority;
|
||||
|
||||
layer_count = 0;
|
||||
|
||||
for(priority = 3; priority >= 0; priority--)
|
||||
{
|
||||
for(layer_number = 3; layer_number >= 0; layer_number--)
|
||||
bool anyobj = obj_priority_count[priority][vcnt] > 0;
|
||||
s32 lnum;
|
||||
|
||||
for(lnum = 3; lnum >= 0; lnum--)
|
||||
{
|
||||
if(((layer_flags >> layer_number) & 1) &&
|
||||
((read_ioreg(REG_BG0CNT + layer_number) & 0x03) == priority))
|
||||
if(((layer_flags >> lnum) & 1) &&
|
||||
((read_ioreg(REG_BGxCNT(lnum)) & 0x03) == priority))
|
||||
{
|
||||
layer_order[layer_count] = layer_number;
|
||||
layer_count++;
|
||||
layer_order[layer_count++] = lnum;
|
||||
}
|
||||
}
|
||||
|
||||
if((obj_priority_count[priority][read_ioreg(REG_VCOUNT)] > 0)
|
||||
&& (layer_flags & 0x10))
|
||||
{
|
||||
layer_order[layer_count] = priority | 0x04;
|
||||
layer_count++;
|
||||
}
|
||||
if(obj_enabled && anyobj)
|
||||
layer_order[layer_count++] = priority | 0x04;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4448,7 +4469,16 @@ static void render_scanline_window_##type(u16 *scanline, u32 dispcnt) \
|
|||
render_scanline_window_builder(tile);
|
||||
render_scanline_window_builder(bitmap);
|
||||
|
||||
static const u32 active_layers[6] = { 0x1F, 0x17, 0x1C, 0x14, 0x14, 0x14 };
|
||||
static const u8 active_layers[] = {
|
||||
0x1F, // Mode 0, Tile BG0-3 and OBJ
|
||||
0x17, // Mode 1, Tile BG0-2 and OBJ
|
||||
0x1C, // Mode 2, Tile BG2-3 and OBJ
|
||||
0x14, // Mode 3, BMP BG2 and OBJ
|
||||
0x14, // Mode 4, BMP BG2 and OBJ
|
||||
0x14, // Mode 5, BMP BG2 and OBJ
|
||||
0, // Unused
|
||||
0,
|
||||
};
|
||||
|
||||
void update_scanline(void)
|
||||
{
|
||||
|
@ -4466,7 +4496,7 @@ void update_scanline(void)
|
|||
reg[OAM_UPDATED] = 0;
|
||||
}
|
||||
|
||||
order_layers((dispcnt >> 8) & active_layers[video_mode]);
|
||||
order_layers((dispcnt >> 8) & active_layers[video_mode], vcount);
|
||||
|
||||
if(skip_next_frame)
|
||||
return;
|
||||
|
|
Loading…
Reference in New Issue