◎飽和加算ルーチン
ピクセルフォーマットは15bpp(R5G5B5)とします。
スプライトパターンとフレームバッファのRGB値をそれぞれ加算します。
加算結果が31を越えた場合、値は31にします。
/* C言語風表記(2ピクセル処理) */
/* vram = フレームバッファへのポインタ */
/* sprite = スプライトパターンへのポインタ */
const unsigned maskA = 0x3def3def;
const unsigned maskB = 0x42104210;
/* 丸め(ラップラウンド)加算 */
tmp1 = ((col1 & maskA) + (col2 & maskA)) ^ ((col1 ^ col2) & maskB);
/* RGBの桁あふれ算出 */
tmp2 = col1 + col2 - tmp1;
output = tmp1 | (tmp2 - (tmp2>>5));
; NASM(4ピクセル処理)
;UV大文字表記は他のパイプに移動できない命令です
;edi = フレームバッファのアドレス
;edx = スプライトパターンのアドレス
;ecx = スプライトの横幅(4ピクセル単位)
;mm6 = 04210421042104210h
;mm7 = 03def3def3def3defh
movq mm0,[edx] ;n
movq mm1,[edi] ;n
LP:
movq mm2,mm0 ;u1
movq mm3,mm1 ;v1
movq mm4,mm1 ;u2
pand mm2,mm7 ;v2
pxor mm0,mm1 ;u3
pand mm3,mm7 ;v3
pand mm0,mm6 ;u4
paddw mm2,mm3 ;v4
pxor mm2,mm0 ;u5
padd mm4,mm1 ;v5
psubw mm4,mm2 ;u6
lea edi,[edi+8] ;v6
movq mm3,mm4 ;u7
psrlw mm4,5 ;v7
movq mm0,[edx+8] ;U8
psubw mm3,mm4 ;v8
movq mm1,[edi] ;U9
por mm2,mm3 ;v9
lea edx,[edx+8] ;u10
dec ecx ;v10
movq [edi-8],mm2 ;U11
jnz LP ;v11
とりあえずキャッシュが全てヒットした場合を考えます。
MMX Pentium(P55C)では、
4ピクセル当たり11クロックで処理します。
パターンをQWORDにアラインするのは当然にしても、
転送先のアドレスは表示位置によって変わってしまうので、
4ピクセル当たり17クロック程度と考えるのが妥当です。