📄 sprite_a.cpp
字号:
/* 精灵是一个带有透明色的 16/15-bit Bitmap,
任何操作都过滤透明色,并带有Alpha混合,
目前Alpha混合仅支持九级
所有函数都尽可能使用MMX指令, 为提高速度宽度应设为4的倍数
使用前应调用InitSprite( ), 以完成初始化任务 !
只能在具有MMX技术的CPU上运行 !
*/
#include "gl.h"
//#include "gengine.h"
#include "sprite.h"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
// 透明色, 放入mm7
DWORD dwColorKey;
QWORD qwColorKey;
//
DWORD dwAlphaMask1, dwAlphaMask2, dwAlphaMask4;
QWORD qwAlphaMask1, qwAlphaMask2, qwAlphaMask4;
static Bitmap* bmp; //for test
SpriteBlitAlphaFunc spriteBlitAlpha[9];
SpriteBlitBetaFunc spriteBlitBeta[9];
SpriteBlitAlphaFunc SpriteBlitAlpha;
SpriteBlitBetaFunc SpriteBlitBeta;
int InitSprite( void )
{
if( screenInfo.colorDepth == 16 ){
dwColorKey = 0xf81ff81f;
qwColorKey = 0xf81ff81ff81ff81f;
dwAlphaMask1 = 0x18e318e3; // 1/8
dwAlphaMask2 = 0x39e739e7; // 1/4
dwAlphaMask4 = 0x7bef7bef; // 1/2
qwAlphaMask1 = 0x18e318e318e318e3;
qwAlphaMask2 = 0x39e739e739e739e7;
qwAlphaMask4 = 0x7bef7bef7bef7bef;
}
else if( screenInfo.colorDepth == 15 ){
dwColorKey = 0x7c1f7c1f;
qwColorKey = 0x7c1f7c1f7c1f7c1f;
dwAlphaMask1 = 0x0c630c63;
dwAlphaMask2 = 0x1ce71ce7;
dwAlphaMask4 = 0x3def3def;
qwAlphaMask1 = 0x0c630c630c630c63;
qwAlphaMask2 = 0x1ce71ce71ce71ce7;
qwAlphaMask4 = 0x3def3def3def3def;
}
else
return -1;
if( cpu.mmx ){
spriteBlitAlpha[0] = SpriteBlitAlpha0MMX;
spriteBlitAlpha[1] = SpriteBlitAlpha1MMX;
spriteBlitAlpha[2] = SpriteBlitAlpha2MMX;
spriteBlitAlpha[3] = SpriteBlitAlpha3MMX;
spriteBlitAlpha[4] = SpriteBlitAlpha4MMX;
spriteBlitAlpha[5] = SpriteBlitAlpha5MMX;
spriteBlitAlpha[6] = SpriteBlitAlpha6MMX;
spriteBlitAlpha[7] = SpriteBlitAlpha7MMX;
spriteBlitAlpha[8] = SpriteBlitAlpha8MMX;
spriteBlitBeta[0] = SpriteBlitBeta0MMX;
spriteBlitBeta[1] = SpriteBlitBeta1MMX;
spriteBlitBeta[2] = SpriteBlitBeta2MMX;
spriteBlitBeta[3] = SpriteBlitBeta3MMX;
spriteBlitBeta[4] = SpriteBlitBeta4MMX;
spriteBlitBeta[5] = SpriteBlitBeta5MMX;
spriteBlitBeta[6] = SpriteBlitBeta6MMX;
spriteBlitBeta[7] = SpriteBlitBeta7MMX;
spriteBlitBeta[8] = SpriteBlitBeta8MMX;
}
SpriteBlitAlpha = spriteBlitAlpha[7];
SpriteBlitBeta = spriteBlitBeta[7];
bmp = LoadTga( "test.tga", NULL );
if( bmp == NULL )
return -1;
return 0;
}
void SpriteSetDrawMode( int mode, DWORD degree )
{
degree = ((degree >> 5) >= 8)? 8 : (degree >> 5 )+1;
if( mode & Bitmap::AlphaMode )
SpriteBlitAlpha = spriteBlitAlpha[degree];
else
SpriteBlitBeta = spriteBlitBeta[degree];
}
void SpriteBlitAlpha0MMX( Bitmap* dest, int x, int y, Bitmap* src )
{
}
void SpriteBlitAlpha1MMX( Bitmap* dest, int x, int y, Bitmap* src )
{
SPRITE_CLIP;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 0
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
movq mm6, qwAlphaMask1;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 1
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
// do 1/8 alpha blend;
psrlw mm1, 3;
psrlw mm4, 3;
pand mm1, mm6;
pand mm4, mm6;
paddw mm1, mm3;
movq mm5, mm2;
psubw mm1, mm4;
pand mm3, mm5;
pandn mm2, mm1;
sub ecx, 4;
por mm2, mm3;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 2
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
shr ax, 3;
mov bx, dx;
and ax, word ptr dwAlphaMask1;
shr dx, 3;
add ax, bx;
and dx, word ptr dwAlphaMask1;
sub ax, dx;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 3
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
}
void SpriteBlitAlpha2MMX( Bitmap* dest, int x, int y, Bitmap* src )
{
SPRITE_CLIP;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 0
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
movq mm6, qwAlphaMask2;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 1
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
// do 1/4 alpha blend;
psrlw mm1, 2;
psrlw mm4, 2;
pand mm1, mm6;
pand mm4, mm6;
paddw mm1, mm3;
movq mm5, mm2;
psubw mm1, mm4;
pand mm3, mm5;
pandn mm2, mm1;
sub ecx, 4;
por mm2, mm3;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 2
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
shr ax, 2;
mov bx, dx;
and ax, word ptr dwAlphaMask2;
shr dx, 2;
add ax, bx;
and dx, word ptr dwAlphaMask2;
sub ax, dx;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 3
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
}
void SpriteBlitAlpha3MMX( Bitmap* dest, int x, int y, Bitmap* src )
{
SPRITE_CLIP;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 0
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
movq mm6, qwAlphaMask2; // 1/4
movq mm5, qwAlphaMask1; // 1/8
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 1
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
// do 3/8 alpha blend;
psrlw mm1, 2;
psrlw mm3, 2;
pand mm1, mm6;
pand mm3, mm6;
paddw mm1, mm3;
movq mm0, mm1;
psrlq mm1, 1;
paddw mm3, mm0;
pand mm1, mm5;
movq mm0, mm2;
paddw mm1, mm3;
pand mm0, mm4;
pandn mm2, mm1;
sub ecx, 4;
por mm2, mm0;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 2
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
shr ax, 2;
shr dx, 2;
and ax, word ptr dwAlphaMask2;
mov bx, ax;
and dx, word ptr dwAlphaMask2;
shr bx, 1;
add ax, dx;
and bx, word Ptr dwAlphaMask1;
shr dx, 1;
add ax, bx;
and dx, word ptr dwAlphaMask1;
add ax, dx;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 3
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
}
void SpriteBlitAlpha4MMX( Bitmap* dest, int x, int y, Bitmap* src )
{
SPRITE_CLIP;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 0
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
movq mm6, qwAlphaMask4; // 1/2
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 1
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
// do 1/2 alpha blend;
psrlw mm0, 1;
movq mm5, mm2;
psrlw mm4, 1;
pand mm0, mm6;
pand mm4, mm6;
pand mm3, mm5;
paddw mm0, mm4;
pandn mm2, mm0;
sub ecx, 4;
por mm2, mm3;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 2
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
shr ax, 1;
mov bx, word ptr dwAlphaMask4;
shr dx, 1;
and ax, bx;
and dx, bx;
add ax, dx;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 3
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
}
void SpriteBlitAlpha5MMX( Bitmap* dest, int x, int y, Bitmap* src )
{
SPRITE_CLIP;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 0
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
movq mm6, qwAlphaMask2; // 1/4
movq mm5, qwAlphaMask1; // 1/8
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 1
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
// do 5/8 alpha blend;
psrlq mm0, 2;
psrlq mm3, 2;
pand mm0, mm6;
pand mm0, mm6;
paddd mm3, mm0;
movq mm1, mm3;
psrlq mm3, 1;
paddd mm1, mm0;
pand mm3, mm5;
movq mm0, mm2;
paddd mm1, mm3;
pandn mm2, mm1;
pand mm4, mm0;
sub ecx, 4;
por mm2, mm4;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 2
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
shr ax, 1;
mov bx, word ptr dwAlphaMask4;
shr dx, 1;
and ax, bx;
and dx, bx;
add ax, dx;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 3
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
}
void SpriteBlitAlpha6MMX( Bitmap* dest, int x, int y, Bitmap* src )
{
SPRITE_CLIP;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 0
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
movq mm6, qwAlphaMask2;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 1
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
// do 3/4 alpha blend;
psrlw mm4, 2;
psrlw mm1, 2;
pand mm4, mm6;
pand mm1, mm6;
paddw mm0, mm4;
movq mm5, mm2;
psubw mm0, mm1;
pand mm3, mm5;
pandn mm2, mm0;
sub ecx, 4;
por mm2, mm3;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 2
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
mov bx, ax;
shr dx, 2;
shr bx, 2;
and dx, word ptr dwAlphaMask2;
and bx, word ptr dwAlphaMask2;
sub ax, bx;
add ax, dx;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 3
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
}
void SpriteBlitAlpha7MMX( Bitmap* dest, int x, int y, Bitmap* src )
{
SPRITE_CLIP;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 0
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
movq mm6, qwAlphaMask1;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 1
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
// do 3/4 alpha blend;
psrlw mm4, 3;
psrlw mm1, 3;
pand mm4, mm6;
pand mm1, mm6;
paddw mm0, mm4;
movq mm5, mm2;
psubw mm0, mm1;
pand mm3, mm5;
pandn mm2, mm0;
sub ecx, 4;
por mm2, mm3;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 2
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
mov bx, ax;
shr dx, 3;
shr bx, 3;
and dx, word ptr dwAlphaMask1;
and bx, word ptr dwAlphaMask1;
add ax, dx;
sub ax, bx;
#define _SPRITE_BLIT_ALPHA_MMX_HEAD 3
#include "sprite.hpp"
#undef _SPRITE_BLIT_ALPHA_MMX_HEAD
}
void SpriteBlitAlpha8MMX( Bitmap* dest, int x, int y, Bitmap* src )
{
SPRITE_CLIP;
int spitch = src->pitch - w*2;
char* sline = src->line[sy] + sx*2;
int dpitch = dest->pitch - w*2;
char* dline = dest->line[y] + x*2;
__asm{
mov esi, sline;
mov edi, dline;
cld;
movq mm7, qwColorKey;
mov edx, spitch;
mov ecx, w;
mov bx, word ptr dwColorKey;
line_begin:
ALIGN 4;
cmp ecx, 4;
jl line_tail;
movq mm0, [esi];
movq mm3, [edi];
movq mm2, mm0;
movq mm1, mm0;
pcmpeqw mm2, mm7;
pcmpeqw mm1, mm7;
pand mm2, mm3;
pandn mm1, mm0;
sub ecx, 4;
por mm2, mm1;
add esi, 8;
movq [edi], mm2;
add edi, 8;
jmp line_begin;
line_tail:
jecxz next_line;
next_pixel:
lodsw;
dec ecx;
cmp ax, bx;
je trans_pixel;
stosw;
test ecx, ecx;
jnz next_pixel;
jmp next_line;
trans_pixel:
add edi, 2;
test ecx, ecx;
jnz next_pixel;
next_line:
add edi, dpitch;
add esi, edx;
mov ecx, w;
dec h;
jnz line_begin;
emms;
}
}
int testSprite( void )
{
// screen->Clear( 0,0,640,480, 0x808000 );
/* if( LockScreen() != 0 )
return -1;
for( int i=0; i<5; i++ ){
SpriteBlitBeta9MMX( screen, 0, i*96, bmp, 255 );
SpriteBlitAlpha2MMX( screen, 128, i*96, bmp );
SpriteBlitAlpha2MMX( screen, 256, i*96, bmp );
SpriteBlitAlpha2MMX( screen, 384, i*96, bmp );
SpriteBlitAlpha2MMX( screen, 512, i*96, bmp );
}
return UnlockScreen();*/
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -