Implement text background affine rendering
This commit is contained in:
parent
c2964e386a
commit
11f56eb1d1
2 changed files with 184 additions and 319 deletions
|
@ -177,6 +177,10 @@ typedef enum
|
|||
#define REG_WINxV(n) (REG_WIN0V + (n))
|
||||
#define REG_BGxHOFS(n) (REG_BG0HOFS + ((n) * 2))
|
||||
#define REG_BGxVOFS(n) (REG_BG0VOFS + ((n) * 2))
|
||||
#define REG_BGxPA(n) (REG_BG2PA + ((n)-2)*8)
|
||||
#define REG_BGxPB(n) (REG_BG2PB + ((n)-2)*8)
|
||||
#define REG_BGxPC(n) (REG_BG2PC + ((n)-2)*8)
|
||||
#define REG_BGxPD(n) (REG_BG2PD + ((n)-2)*8)
|
||||
|
||||
#define FLASH_DEVICE_UNDEFINED 0x00
|
||||
#define FLASH_DEVICE_MACRONIX_64KB 0x1C
|
||||
|
|
499
video.cc
499
video.cc
|
@ -685,55 +685,6 @@ static void render_scanline_conditional_bitmap(u32 start, u32 end, u16 *scanline
|
|||
#define render_scanline_dest_copy_bitmap u16
|
||||
|
||||
|
||||
// If rendering a scanline that is not a target A then there's no point in
|
||||
// keeping what's underneath it because it can't blend with it.
|
||||
|
||||
#define render_scanline_skip_alpha(bg_type, combine_op) \
|
||||
if((pixel_combine & 0x00000200) == 0) \
|
||||
{ \
|
||||
render_scanline_##bg_type##_##combine_op##_color32(layer, \
|
||||
start, end, scanline); \
|
||||
return; \
|
||||
} \
|
||||
|
||||
|
||||
#define render_scanline_extra_variables_base_normal(bg_type) \
|
||||
u16 *palette = palette_ram_converted \
|
||||
|
||||
|
||||
#define render_scanline_extra_variables_base_alpha(bg_type) \
|
||||
u32 bg_combine = color_combine_mask(5); \
|
||||
u32 pixel_combine = color_combine_mask(layer) | (bg_combine << 16); \
|
||||
render_scanline_skip_alpha(bg_type, base) \
|
||||
|
||||
#define render_scanline_extra_variables_base_color() \
|
||||
u32 bg_combine = color_combine_mask(5); \
|
||||
u32 pixel_combine = color_combine_mask(layer) \
|
||||
|
||||
#define render_scanline_extra_variables_base_color16(bg_type) \
|
||||
render_scanline_extra_variables_base_color() \
|
||||
|
||||
#define render_scanline_extra_variables_base_color32(bg_type) \
|
||||
render_scanline_extra_variables_base_color() \
|
||||
|
||||
|
||||
#define render_scanline_extra_variables_transparent_normal(bg_type) \
|
||||
render_scanline_extra_variables_base_normal(bg_type) \
|
||||
|
||||
#define render_scanline_extra_variables_transparent_alpha(bg_type) \
|
||||
u32 pixel_combine = color_combine_mask(layer); \
|
||||
render_scanline_skip_alpha(bg_type, transparent) \
|
||||
|
||||
#define render_scanline_extra_variables_transparent_color() \
|
||||
u32 pixel_combine = color_combine_mask(layer) \
|
||||
|
||||
#define render_scanline_extra_variables_transparent_color16(bg_type) \
|
||||
render_scanline_extra_variables_transparent_color() \
|
||||
|
||||
#define render_scanline_extra_variables_transparent_color32(bg_type) \
|
||||
render_scanline_extra_variables_transparent_color() \
|
||||
|
||||
|
||||
static const u32 map_widths[] = { 256, 512, 256, 512 };
|
||||
|
||||
typedef enum
|
||||
|
@ -762,15 +713,15 @@ static inline void render_tile_Nbpp(u32 layer,
|
|||
// tile_base already points to the right tile-line vertical offset
|
||||
const u8 *tile_ptr = &tile_base[(tile & 0x3FF) * (is8bpp ? 64 : 32)];
|
||||
|
||||
// On vertical flip, apply the mirror offset
|
||||
if (tile & 0x800)
|
||||
tile_ptr += vertical_pixel_flip;
|
||||
|
||||
// Calculate combine masks. These store 2 bits of info: 1st and 2nd target.
|
||||
// If set, the current pixel belongs to a layer that is 1st or 2nd target.
|
||||
u32 bg_comb = color_combine_mask(5);
|
||||
u32 px_comb = color_combine_mask(layer);
|
||||
|
||||
// On vertical flip, apply the mirror offset
|
||||
if (tile & 0x800)
|
||||
tile_ptr += vertical_pixel_flip;
|
||||
|
||||
if (is8bpp) {
|
||||
// Each byte is a color, mapped to a palete. 8 bytes can be read as 64bit
|
||||
u64 tilepix = eswap64(*(u64*)tile_ptr);
|
||||
|
@ -817,6 +768,17 @@ template<typename stype, rendtype rdtype, bool transparent>
|
|||
static void render_scanline_text(u32 layer,
|
||||
u32 start, u32 end, void *scanline)
|
||||
{
|
||||
// TODO: Move this to the caller since it makes more sense
|
||||
// If the layer is *NOT* first target, we will not combine with previous layer anyway
|
||||
// so we can "drop" the mixing bit
|
||||
if (rdtype == ALPHA && transparent) {
|
||||
bool first_target = (read_ioreg(REG_BLDCNT) >> layer) & 1;
|
||||
if (!first_target) {
|
||||
render_scanline_text<stype, COLOR32, true>(layer, start, end, scanline);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
u32 bg_control = read_ioreg(REG_BGxCNT(layer));
|
||||
u16 vcount = read_ioreg(REG_VCOUNT);
|
||||
u32 map_size = (bg_control >> 14) & 0x03;
|
||||
|
@ -954,62 +916,6 @@ static void render_scanline_text(u32 layer,
|
|||
}
|
||||
}
|
||||
|
||||
// Temporary functions
|
||||
static void render_scanline_text_base_normal(u32 layer,
|
||||
u32 start, u32 end, void *scanline)
|
||||
{
|
||||
render_scanline_text<u16, NORMAL, false>(layer, start, end, scanline);
|
||||
}
|
||||
|
||||
static void render_scanline_text_transparent_normal(u32 layer,
|
||||
u32 start, u32 end, void *scanline)
|
||||
{
|
||||
render_scanline_text<u16, NORMAL, true>(layer, start, end, scanline);
|
||||
}
|
||||
|
||||
static void render_scanline_text_base_color16(u32 layer,
|
||||
u32 start, u32 end, void *scanline)
|
||||
{
|
||||
render_scanline_text<u16, COLOR16, false>(layer, start, end, scanline);
|
||||
}
|
||||
|
||||
static void render_scanline_text_transparent_color16(u32 layer,
|
||||
u32 start, u32 end, void *scanline)
|
||||
{
|
||||
render_scanline_text<u16, COLOR16, true>(layer, start, end, scanline);
|
||||
}
|
||||
|
||||
static void render_scanline_text_base_color32(u32 layer,
|
||||
u32 start, u32 end, void *scanline)
|
||||
{
|
||||
render_scanline_text<u32, COLOR32, false>(layer, start, end, scanline);
|
||||
}
|
||||
|
||||
static void render_scanline_text_transparent_color32(u32 layer,
|
||||
u32 start, u32 end, void *scanline)
|
||||
{
|
||||
render_scanline_text<u32, COLOR32, true>(layer, start, end, scanline);
|
||||
}
|
||||
|
||||
static void render_scanline_text_base_alpha(u32 layer,
|
||||
u32 start, u32 end, void *scanline)
|
||||
{
|
||||
render_scanline_text<u32, ALPHA, false>(layer, start, end, scanline);
|
||||
}
|
||||
|
||||
static void render_scanline_text_transparent_alpha(u32 layer,
|
||||
u32 start, u32 end, void *scanline)
|
||||
{
|
||||
// TODO: Move this to the caller since it makes more sense
|
||||
// If the layer is *NOT* first target, we will not combine with previous layer anyway
|
||||
// so we can "drop" the mixing bit
|
||||
bool first_target = (read_ioreg(REG_BLDCNT) >> layer) & 1;
|
||||
if (!first_target)
|
||||
render_scanline_text_transparent_color32(layer, start, end, scanline);
|
||||
else
|
||||
render_scanline_text<u32, ALPHA, true>(layer, start, end, scanline);
|
||||
}
|
||||
|
||||
|
||||
s32 affine_reference_x[2];
|
||||
s32 affine_reference_y[2];
|
||||
|
@ -1029,232 +935,187 @@ void video_reload_counters()
|
|||
affine_reference_y[1] = signext28(read_ioreg32(REG_BG3Y_L));
|
||||
}
|
||||
|
||||
#define affine_render_bg_pixel_normal() \
|
||||
current_pixel = palette_ram_converted[0] \
|
||||
|
||||
#define affine_render_bg_pixel_alpha() \
|
||||
current_pixel = bg_combine \
|
||||
template<typename dsttype, rendtype rdtype, bool transparent>
|
||||
static inline void render_pixel_8bpp(u32 layer,
|
||||
dsttype *dest_ptr, u32 px, u32 py, const u8 *tile_base, const u8 *map_base, u32 map_size
|
||||
) {
|
||||
// Pitch represents the log2(number of tiles per row) (from 16 to 128)
|
||||
u32 map_pitch = map_size + 4;
|
||||
// Given coords (px,py) in the background space, find the tile.
|
||||
u32 mapoff = (px / 8) + ((py / 8) << map_pitch);
|
||||
// Each tile is 8x8, so 64 bytes each.
|
||||
const u8 *tile_ptr = &tile_base[map_base[mapoff] * tile_size_8bpp];
|
||||
// Read the 8bit color within the tile.
|
||||
u8 pval = tile_ptr[(px % 8) + ((py % 8) * 8)];
|
||||
|
||||
#define affine_render_bg_pixel_color16() \
|
||||
affine_render_bg_pixel_alpha() \
|
||||
// Calculate combine masks. These store 2 bits of info: 1st and 2nd target.
|
||||
// If set, the current pixel belongs to a layer that is 1st or 2nd target.
|
||||
u32 bg_comb = color_combine_mask(5);
|
||||
u32 px_comb = color_combine_mask(layer);
|
||||
|
||||
#define affine_render_bg_pixel_color32() \
|
||||
affine_render_bg_pixel_alpha() \
|
||||
// Combine mask is different if we are rendering the backdrop color
|
||||
u16 combflg = pval ? px_comb : bg_comb;
|
||||
// Alhpa mode stacks previous value (unless rendering the first layer)
|
||||
if (!transparent || pval) {
|
||||
if (rdtype == NORMAL)
|
||||
*dest_ptr = palette_ram_converted[pval];
|
||||
else if (rdtype == COLOR16 || rdtype == COLOR32)
|
||||
*dest_ptr = pval | combflg; // Add combine flags
|
||||
else if (rdtype == ALPHA)
|
||||
// Stack pixels on top of the pixel value and combine flags
|
||||
*dest_ptr = pval | combflg | ((transparent ? *dest_ptr : bg_comb) << 16);
|
||||
}
|
||||
}
|
||||
|
||||
#define affine_render_bg_pixel_base(alpha_op) \
|
||||
affine_render_bg_pixel_##alpha_op() \
|
||||
template<typename dsttype, rendtype rdtype>
|
||||
static inline void render_bdrop_pixel_8bpp(dsttype *dest_ptr) {
|
||||
// Calculate combine masks. These store 2 bits of info: 1st and 2nd target.
|
||||
// If set, the current pixel belongs to a layer that is 1st or 2nd target.
|
||||
u32 bg_comb = color_combine_mask(5);
|
||||
u32 pval = 0;
|
||||
|
||||
#define affine_render_bg_pixel_transparent(alpha_op) \
|
||||
// Alhpa mode stacks previous value (unless rendering the first layer)
|
||||
if (rdtype == NORMAL)
|
||||
*dest_ptr = palette_ram_converted[pval];
|
||||
else if (rdtype == COLOR16 || rdtype == COLOR32)
|
||||
*dest_ptr = pval | bg_comb; // Add combine flags
|
||||
else if (rdtype == ALPHA)
|
||||
// Stack pixels on top of the pixel value and combine flags
|
||||
*dest_ptr = pval | bg_comb | (bg_comb << 16);
|
||||
// FIXME: Do we need double bg_comb? I do not think so!
|
||||
}
|
||||
|
||||
#define affine_render_bg_pixel_copy(alpha_op) \
|
||||
// Affine background rendering logic.
|
||||
// wrap extends the background infinitely, otherwise transparent/backdrop fill
|
||||
// rotate indicates if there's any rotation (optimized version for no-rotation)
|
||||
template <typename dsttype, rendtype rdtype, bool transparent, bool wrap, bool rotate>
|
||||
static inline void render_affine_background(
|
||||
u32 layer, u32 start, u32 cnt, const u8 *map_base,
|
||||
u32 map_size, const u8 *tile_base, dsttype *dst_ptr) {
|
||||
|
||||
#define affine_render_bg_base(alpha_op) \
|
||||
dest_ptr[0] = current_pixel
|
||||
s32 dx = (s16)read_ioreg(REG_BGxPA(layer));
|
||||
s32 dy = (s16)read_ioreg(REG_BGxPC(layer));
|
||||
|
||||
#define affine_render_bg_transparent(alpha_op) \
|
||||
s32 source_x = affine_reference_x[layer - 2] + (start * dx);
|
||||
s32 source_y = affine_reference_y[layer - 2] + (start * dy);
|
||||
|
||||
#define affine_render_bg_copy(alpha_op) \
|
||||
// Maps are squared, four sizes available (128x128 to 1024x1024)
|
||||
u32 width_height = 128 << map_size;
|
||||
|
||||
#define affine_render_bg_remainder_base(alpha_op) \
|
||||
affine_render_bg_pixel_##alpha_op(); \
|
||||
for(; i < end; i++) \
|
||||
{ \
|
||||
affine_render_bg_base(alpha_op); \
|
||||
advance_dest_ptr_base(1); \
|
||||
} \
|
||||
if (wrap) {
|
||||
// In wrap mode the entire space is covered, since it "wraps" at the edges
|
||||
while (cnt--) {
|
||||
u32 pixel_x = (u32)(source_x >> 8) & (width_height-1);
|
||||
u32 pixel_y = (u32)(source_y >> 8) & (width_height-1);
|
||||
|
||||
#define affine_render_bg_remainder_transparent(alpha_op) \
|
||||
// Lookup pixel and draw it.
|
||||
render_pixel_8bpp<dsttype, rdtype, transparent>(
|
||||
layer, dst_ptr++, pixel_x, pixel_y, tile_base, map_base, map_size);
|
||||
|
||||
#define affine_render_bg_remainder_copy(alpha_op) \
|
||||
// Move to the next pixel, update coords accordingly
|
||||
source_x += dx;
|
||||
if (rotate)
|
||||
source_y += dy;
|
||||
}
|
||||
} else {
|
||||
|
||||
#define affine_render_next(combine_op) \
|
||||
source_x += dx; \
|
||||
source_y += dy; \
|
||||
advance_dest_ptr_##combine_op(1) \
|
||||
// Early optimization if Y-coord is out completely for this line.
|
||||
// (if there's no rotation Y coord remains identical throughout the line).
|
||||
bool is_y_out = !rotate && ((u32)(source_y >> 8)) >= width_height;
|
||||
|
||||
#define affine_render_scale_offset() \
|
||||
tile_base += ((pixel_y % 8) * 8); \
|
||||
map_base += (pixel_y / 8) << map_pitch \
|
||||
if (!is_y_out) {
|
||||
// Draw backdrop pixels if necessary until we reach the background edge.
|
||||
// TODO: on non-base cases this could perhaps be calculated in O(1)?
|
||||
while (cnt) {
|
||||
// Draw backdrop pixels if they lie outside of the background.
|
||||
u32 pixel_x = (u32)(source_x >> 8), pixel_y = (u32)(source_y >> 8);
|
||||
|
||||
#define affine_render_scale_pixel(combine_op, alpha_op) \
|
||||
map_offset = (pixel_x / 8); \
|
||||
if(map_offset != last_map_offset) \
|
||||
{ \
|
||||
tile_ptr = tile_base + (map_base[map_offset] * 64); \
|
||||
last_map_offset = map_offset; \
|
||||
} \
|
||||
tile_ptr = tile_base + (map_base[(pixel_x / 8)] * 64); \
|
||||
current_pixel = tile_ptr[(pixel_x % 8)]; \
|
||||
tile_8bpp_draw_##combine_op(0, none, 0, alpha_op); \
|
||||
affine_render_next(combine_op) \
|
||||
// Stop once we find a pixel that is actually *inside* the map.
|
||||
if (pixel_x < width_height && pixel_y < width_height)
|
||||
break;
|
||||
|
||||
#define affine_render_scale(combine_op, alpha_op) \
|
||||
{ \
|
||||
pixel_y = source_y >> 8; \
|
||||
u32 i = 0; \
|
||||
affine_render_bg_pixel_##combine_op(alpha_op); \
|
||||
if((u32)pixel_y < (u32)width_height) \
|
||||
{ \
|
||||
affine_render_scale_offset(); \
|
||||
for(; i < end; i++) \
|
||||
{ \
|
||||
pixel_x = source_x >> 8; \
|
||||
\
|
||||
if((u32)pixel_x < (u32)width_height) \
|
||||
{ \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
affine_render_bg_##combine_op(alpha_op); \
|
||||
affine_render_next(combine_op); \
|
||||
} \
|
||||
\
|
||||
for(; i < end; i++) \
|
||||
{ \
|
||||
pixel_x = source_x >> 8; \
|
||||
\
|
||||
if((u32)pixel_x >= (u32)width_height) \
|
||||
break; \
|
||||
\
|
||||
affine_render_scale_pixel(combine_op, alpha_op); \
|
||||
} \
|
||||
} \
|
||||
affine_render_bg_remainder_##combine_op(alpha_op); \
|
||||
} \
|
||||
// Draw a "transparent" pixel if we are the base layer.
|
||||
if (!transparent)
|
||||
render_bdrop_pixel_8bpp<dsttype, rdtype>(dst_ptr);
|
||||
|
||||
#define affine_render_scale_wrap(combine_op, alpha_op) \
|
||||
{ \
|
||||
u32 wrap_mask = width_height - 1; \
|
||||
pixel_y = (source_y >> 8) & wrap_mask; \
|
||||
if((u32)pixel_y < (u32)width_height) \
|
||||
{ \
|
||||
affine_render_scale_offset(); \
|
||||
for(i = 0; i < end; i++) \
|
||||
{ \
|
||||
pixel_x = (source_x >> 8) & wrap_mask; \
|
||||
affine_render_scale_pixel(combine_op, alpha_op); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
dst_ptr++;
|
||||
source_x += dx;
|
||||
if (rotate)
|
||||
source_y += dy;
|
||||
cnt--;
|
||||
}
|
||||
|
||||
// Draw background pixels by looking them up in the map
|
||||
while (cnt) {
|
||||
u32 pixel_x = (u32)(source_x >> 8), pixel_y = (u32)(source_y >> 8);
|
||||
|
||||
// Check if we run out of background pixels, stop drawing.
|
||||
if (pixel_x >= width_height || pixel_y >= width_height)
|
||||
break;
|
||||
|
||||
// Lookup pixel and draw it.
|
||||
render_pixel_8bpp<dsttype, rdtype, transparent>(
|
||||
layer, dst_ptr++, pixel_x, pixel_y, tile_base, map_base, map_size);
|
||||
|
||||
// Move to the next pixel, update coords accordingly
|
||||
cnt--;
|
||||
source_x += dx;
|
||||
if (rotate)
|
||||
source_y += dy;
|
||||
}
|
||||
}
|
||||
|
||||
// Complete the line on the right, if we ran out over the bg edge.
|
||||
// Only necessary for the base layer, otherwise we can safely finish.
|
||||
if (!transparent)
|
||||
while (cnt--)
|
||||
render_bdrop_pixel_8bpp<dsttype, rdtype>(dst_ptr++);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define affine_render_rotate_pixel(combine_op, alpha_op) \
|
||||
map_offset = (pixel_x / 8) + ((pixel_y / 8) << map_pitch); \
|
||||
if(map_offset != last_map_offset) \
|
||||
{ \
|
||||
tile_ptr = tile_base + (map_base[map_offset] * 64); \
|
||||
last_map_offset = map_offset; \
|
||||
} \
|
||||
\
|
||||
current_pixel = tile_ptr[(pixel_x % 8) + ((pixel_y % 8) * 8)]; \
|
||||
tile_8bpp_draw_##combine_op(0, none, 0, alpha_op); \
|
||||
affine_render_next(combine_op) \
|
||||
// Renders affine backgrounds. These differ substantially from non-affine
|
||||
// ones. Tile maps are byte arrays (instead of 16 bit), limiting the map to
|
||||
// 256 different tiles (with no flip bits and just one single 256 color pal).
|
||||
|
||||
#define affine_render_rotate(combine_op, alpha_op) \
|
||||
{ \
|
||||
affine_render_bg_pixel_##combine_op(alpha_op); \
|
||||
for(i = 0; i < end; i++) \
|
||||
{ \
|
||||
pixel_x = source_x >> 8; \
|
||||
pixel_y = source_y >> 8; \
|
||||
\
|
||||
if(((u32)pixel_x < (u32)width_height) && \
|
||||
((u32)pixel_y < (u32)width_height)) \
|
||||
{ \
|
||||
break; \
|
||||
} \
|
||||
affine_render_bg_##combine_op(alpha_op); \
|
||||
affine_render_next(combine_op); \
|
||||
} \
|
||||
\
|
||||
for(; i < end; i++) \
|
||||
{ \
|
||||
pixel_x = source_x >> 8; \
|
||||
pixel_y = source_y >> 8; \
|
||||
\
|
||||
if(((u32)pixel_x >= (u32)width_height) || \
|
||||
((u32)pixel_y >= (u32)width_height)) \
|
||||
{ \
|
||||
affine_render_bg_remainder_##combine_op(alpha_op); \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
affine_render_rotate_pixel(combine_op, alpha_op); \
|
||||
} \
|
||||
} \
|
||||
template<typename dsttype, rendtype rdtype, bool transparent>
|
||||
static void render_scanline_affine(u32 layer,
|
||||
u32 start, u32 end, void *scanline)
|
||||
{
|
||||
u32 bg_control = read_ioreg(REG_BGxCNT(layer));
|
||||
u32 map_size = (bg_control >> 14) & 0x03;
|
||||
|
||||
#define affine_render_rotate_wrap(combine_op, alpha_op) \
|
||||
{ \
|
||||
u32 wrap_mask = width_height - 1; \
|
||||
for(i = 0; i < end; i++) \
|
||||
{ \
|
||||
pixel_x = (source_x >> 8) & wrap_mask; \
|
||||
pixel_y = (source_y >> 8) & wrap_mask; \
|
||||
\
|
||||
affine_render_rotate_pixel(combine_op, alpha_op); \
|
||||
} \
|
||||
} \
|
||||
// Char block base pointer
|
||||
u32 base_block = (bg_control >> 8) & 0x1F;
|
||||
u8 *map_base = &vram[base_block * 2048];
|
||||
// The tilemap base is selected via bgcnt (16KiB chunks)
|
||||
u32 tilecntrl = (bg_control >> 2) & 0x03;
|
||||
u8 *tile_base = &vram[tilecntrl * 16*1024];
|
||||
|
||||
dsttype *dest_ptr = ((dsttype*)scanline) + start;
|
||||
|
||||
// Build affine background renderers.
|
||||
bool has_rotation = read_ioreg(REG_BGxPC(layer)) != 0;
|
||||
bool has_wrap = (bg_control >> 13) & 1;
|
||||
|
||||
#define render_scanline_affine_builder(combine_op, alpha_op) \
|
||||
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_BGxCNT(layer)); \
|
||||
u32 current_pixel; \
|
||||
s32 source_x, source_y; \
|
||||
u32 pixel_x, pixel_y; \
|
||||
u32 layer_offset = (layer - 2) * 8; \
|
||||
s32 dx, dy; \
|
||||
u32 map_size = (bg_control >> 14) & 0x03; \
|
||||
u32 width_height = 1 << (7 + map_size); \
|
||||
u32 map_pitch = map_size + 4; \
|
||||
u8 *map_base = vram + (((bg_control >> 8) & 0x1F) * (1024 * 2)); \
|
||||
u8 *tile_base = vram + (((bg_control >> 2) & 0x03) * (1024 * 16)); \
|
||||
u8 *tile_ptr = NULL; \
|
||||
u32 map_offset, last_map_offset = (u32)-1; \
|
||||
u32 i; \
|
||||
render_scanline_dest_##alpha_op *dest_ptr = \
|
||||
((render_scanline_dest_##alpha_op *)scanline) + start; \
|
||||
\
|
||||
dx = (s16)read_ioreg(REG_BG2PA + layer_offset); \
|
||||
dy = (s16)read_ioreg(REG_BG2PC + layer_offset); \
|
||||
source_x = affine_reference_x[layer - 2] + (start * dx); \
|
||||
source_y = affine_reference_y[layer - 2] + (start * dy); \
|
||||
\
|
||||
end -= start; \
|
||||
\
|
||||
switch(((bg_control >> 12) & 0x02) | (dy != 0)) \
|
||||
{ \
|
||||
case 0x00: \
|
||||
affine_render_scale(combine_op, alpha_op); \
|
||||
break; \
|
||||
\
|
||||
case 0x01: \
|
||||
affine_render_rotate(combine_op, alpha_op); \
|
||||
break; \
|
||||
\
|
||||
case 0x02: \
|
||||
affine_render_scale_wrap(combine_op, alpha_op); \
|
||||
break; \
|
||||
\
|
||||
case 0x03: \
|
||||
affine_render_rotate_wrap(combine_op, alpha_op); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
|
||||
render_scanline_affine_builder(base, normal);
|
||||
render_scanline_affine_builder(transparent, normal);
|
||||
render_scanline_affine_builder(base, color16);
|
||||
render_scanline_affine_builder(transparent, color16);
|
||||
render_scanline_affine_builder(base, color32);
|
||||
render_scanline_affine_builder(transparent, color32);
|
||||
render_scanline_affine_builder(base, alpha);
|
||||
render_scanline_affine_builder(transparent, alpha);
|
||||
// Four specialized versions for faster rendering on specific cases like
|
||||
// scaling only or non-wrapped backgrounds.
|
||||
if (has_wrap) {
|
||||
if (has_rotation)
|
||||
render_affine_background<dsttype, rdtype, transparent, true, true>(
|
||||
layer, start, end - start, map_base, map_size, tile_base, dest_ptr);
|
||||
else
|
||||
render_affine_background<dsttype, rdtype, transparent, true, false>(
|
||||
layer, start, end - start, map_base, map_size, tile_base, dest_ptr);
|
||||
} else {
|
||||
if (has_rotation)
|
||||
render_affine_background<dsttype, rdtype, transparent, false, true>(
|
||||
layer, start, end - start, map_base, map_size, tile_base, dest_ptr);
|
||||
else
|
||||
render_affine_background<dsttype, rdtype, transparent, false, false>(
|
||||
layer, start, end - start, map_base, map_size, tile_base, dest_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define bitmap_render_pixel_mode3(alpha_op) \
|
||||
|
@ -1422,14 +1283,14 @@ render_scanline_bitmap_builder(mode5, normal, 160, 128);
|
|||
|
||||
#define tile_layer_render_functions(type) \
|
||||
{ \
|
||||
render_scanline_##type##_base_normal, \
|
||||
render_scanline_##type##_transparent_normal, \
|
||||
render_scanline_##type##_base_alpha, \
|
||||
render_scanline_##type##_transparent_alpha, \
|
||||
render_scanline_##type##_base_color16, \
|
||||
render_scanline_##type##_transparent_color16, \
|
||||
render_scanline_##type##_base_color32, \
|
||||
render_scanline_##type##_transparent_color32 \
|
||||
render_scanline_##type<u16, NORMAL, false>, \
|
||||
render_scanline_##type<u16, NORMAL, true>, \
|
||||
render_scanline_##type<u32, ALPHA, false>, \
|
||||
render_scanline_##type<u32, ALPHA, true>, \
|
||||
render_scanline_##type<u16, COLOR16, false>, \
|
||||
render_scanline_##type<u16, COLOR16, true>, \
|
||||
render_scanline_##type<u32, COLOR32, false>, \
|
||||
render_scanline_##type<u32, COLOR32, true>, \
|
||||
} \
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue