quickerNES/core/Nes_Ppu_Sprites.h

132 lines
3.4 KiB
C

int sprite_2 = sprite [2];
// pixels
ptrdiff_t next_row = this->scanline_row_bytes;
uint8_t* out = this->scanline_pixels + sprite [3] +
(top_minus_one + skip - begin_minus_one) * next_row;
cache_t const* lines = get_sprite_tile( sprite );
int dir = 1;
uint8_t* scanlines = this->sprite_scanlines + 1 + top_minus_one + skip;
if ( sprite_2 & 0x80 )
{
// vertical flip
out -= next_row;
out += visible * next_row;
next_row = -next_row;
dir = -1;
scanlines += visible - 1;
#if CLIPPED
int height = this->sprite_height();
skip = height - skip - visible;
#endif
}
// attributes
unsigned long offset = (sprite_2 & 3) * 0x04040404 + (this->palette_offset + 0x10101010);
unsigned long const mask = 0x03030303 + zero;
unsigned long const maskgen = 0x80808080 + zero;
#define DRAW_PAIR( shift ) { \
int sprite_count = *scanlines; \
CALC_FOUR( ((unaligned_uint32_t*) out) [0].val, (line >> (shift + 4)), out0 ) \
CALC_FOUR( ((unaligned_uint32_t*) out) [1].val, (line >> shift), out1 ) \
if ( sprite_count < this->max_sprites ) { \
((unaligned_uint32_t*) out) [0].val = out0; \
((unaligned_uint32_t*) out) [1].val = out1; \
} \
if ( CLIPPED ) visible--; \
out += next_row; \
*scanlines = sprite_count + 1; \
scanlines += dir; \
if ( CLIPPED && !visible ) break; \
}
if ( !(sprite_2 & 0x20) )
{
// front
unsigned long const maskgen2 = 0x7f7f7f7f + zero;
#define CALC_FOUR( in, line, out ) \
unsigned long out; \
{ \
unsigned long bg = in; \
unsigned long sp = line & mask; \
unsigned long bgm = maskgen2 + ((bg >> 4) & mask); \
unsigned long spm = (maskgen - sp) & maskgen2; \
unsigned long m = (bgm & spm) >> 2; \
out = (bg & ~m) | ((sp + offset) & m); \
}
#if CLIPPED
lines += skip >> 1;
unsigned long line = *lines++;
if ( skip & 1 )
goto front_skip;
while ( true )
{
DRAW_PAIR( 0 )
front_skip:
DRAW_PAIR( 2 )
line = *lines++;
}
#else
for ( int n = visible >> 1; n--; )
{
unsigned long line = *lines++;
DRAW_PAIR( 0 )
DRAW_PAIR( 2 )
}
#endif
#undef CALC_FOUR
}
else
{
// behind
unsigned long const omask = 0x20202020 + zero;
unsigned long const bg_or = 0xc3c3c3c3 + zero;
#define CALC_FOUR( in, line, out ) \
unsigned long out; \
{ \
unsigned long bg = in; \
unsigned long sp = line & mask; \
unsigned long bgm = maskgen - (bg & mask); \
unsigned long spm = maskgen - sp; \
out = (bg & (bgm | bg_or)) | (spm & omask) | \
(((offset & spm) + sp) & ~(bgm >> 2)); \
}
#if CLIPPED
lines += skip >> 1;
unsigned long line = *lines++;
if ( skip & 1 )
goto back_skip;
while ( true )
{
DRAW_PAIR( 0 )
back_skip:
DRAW_PAIR( 2 )
line = *lines++;
}
#else
for ( int n = visible >> 1; n--; )
{
unsigned long line = *lines++;
DRAW_PAIR( 0 )
DRAW_PAIR( 2 )
}
#endif
#undef CALC_FOUR
}
#undef CLIPPED
#undef DRAW_PAIR