1568 lines
31 KiB
NASM
1568 lines
31 KiB
NASM
;---------------------------Module-Header------------------------------;
|
|
; Module Name: texspan.asm
|
|
;
|
|
; Include file for "body" of texture routines.
|
|
;
|
|
; Created: 011/15/1995
|
|
; Author: Otto Berkes [ottob]
|
|
;
|
|
; Copyright (c) 1995 Microsoft Corporation
|
|
;----------------------------------------------------------------------;
|
|
|
|
|
|
rMask = ((1 SHL rBits) - 1) SHL rShift
|
|
gMask = ((1 SHL gBits) - 1) SHL gShift
|
|
bMask = ((1 SHL bBits) - 1) SHL bShift
|
|
|
|
|
|
if REPLACE
|
|
|
|
rRightShiftAdj = 16 - (rShift + rBits)
|
|
gRightShiftAdj = 16 - (gShift + gBits)
|
|
bRightShiftAdj = 16 - (bShift + bBits)
|
|
|
|
else
|
|
|
|
rRightShiftAdj = 16 - (rShift)
|
|
gRightShiftAdj = 16 - (gShift)
|
|
bRightShiftAdj = 16 - (bShift)
|
|
|
|
endif
|
|
|
|
TMASK_SUBDIV equ [esi].GENGC_tMaskSubDiv
|
|
TSHIFT_SUBDIV equ [esi].GENGC_tShiftSubDiv
|
|
|
|
if FAST_REPLACE
|
|
TEXPALETTE equ [esi].GENGC_texImageReplace
|
|
if (PALETTE_ONLY)
|
|
TEXIMAGE equ [esi].GENGC_texImage
|
|
else
|
|
TEXIMAGE equ [esi].GENGC_texImageReplace
|
|
endif
|
|
if PALETTE_ONLY
|
|
TEX_BPP_LOG2 = 0
|
|
elseif (BPP eq 8)
|
|
TEX_BPP_LOG2 = 0
|
|
else
|
|
TEX_BPP_LOG2 = 1
|
|
endif
|
|
else
|
|
TEXPALETTE equ [esi].GENGC_texPalette
|
|
TEXIMAGE equ [esi].GENGC_texImage
|
|
if PALETTE_ONLY
|
|
TEX_BPP_LOG2 = 0
|
|
else
|
|
TEX_BPP_LOG2 = 2
|
|
endif
|
|
endif
|
|
|
|
;;
|
|
;;
|
|
;; Macros for alpha modulation, and alpha reads
|
|
;;
|
|
;;
|
|
|
|
|
|
ALPHAMODULATE MACRO
|
|
|
|
mov ah, [esi].GENGC_aAccum+2
|
|
mov al, [edx+3]
|
|
and eax, 0ffffh
|
|
mov ch, _gbMulTable[eax]
|
|
mov [esi].GENGC_aDisplay, ch
|
|
|
|
ENDM
|
|
|
|
|
|
ALPHANOMODULATE MACRO
|
|
|
|
mov ch, [edx+3]
|
|
mov [esi].GENGC_aDisplay, ch
|
|
|
|
ENDM
|
|
|
|
|
|
;; There are AGIs and other nasties in the alpha-read code. There's
|
|
;; not much we can really do, unfortunately...
|
|
|
|
|
|
if (BPP eq 8)
|
|
|
|
ALPHAREAD MACRO
|
|
|
|
xor eax, eax
|
|
mov al, [ebx]
|
|
mov ebx, [esi].GENGC_pInvTranslateVector
|
|
mov cl, 0ffh
|
|
mov al, [ebx+eax]
|
|
mov ebx, eax
|
|
and ebx, rMask
|
|
sub cl, ch
|
|
shl ebx, gBits + bBits
|
|
mov bh, cl
|
|
mov ch, _gbMulTable[ebx]
|
|
mov ebx, eax
|
|
mov [esi].GENGC_rDisplay, ch
|
|
and ebx, gMask
|
|
shl ebx, bBits
|
|
mov bh, cl
|
|
mov ch, _gbMulTable[ebx]
|
|
mov ebx, eax
|
|
mov [esi].GENGC_gDisplay, ch
|
|
and ebx, bMask
|
|
mov bh, cl
|
|
mov ch, _gbMulTable[ebx]
|
|
mov [esi].GENGC_bDisplay, ch
|
|
|
|
ENDM
|
|
|
|
endif
|
|
|
|
if (BPP eq 16)
|
|
|
|
ALPHAREAD MACRO
|
|
|
|
mov ax, [ebx]
|
|
mov cl, 0ffh
|
|
mov ebx, eax
|
|
and ebx, rMask
|
|
sub cl, ch
|
|
shr ebx, rShift - (8 - rBits)
|
|
mov bh, cl
|
|
mov ch, _gbMulTable[ebx]
|
|
mov ebx, eax
|
|
mov [esi].GENGC_rDisplay, ch
|
|
and ebx, gMask
|
|
shr ebx, gShift - (8 - gBits)
|
|
mov bh, cl
|
|
mov ch, _gbMulTable[ebx]
|
|
mov ebx, eax
|
|
mov [esi].GENGC_gDisplay, ch
|
|
and ebx, bMask
|
|
shl ebx, (8 - bBits)
|
|
mov bh, cl
|
|
mov ch, _gbMulTable[ebx]
|
|
mov [esi].GENGC_bDisplay, ch
|
|
|
|
ENDM
|
|
|
|
elseif (BPP eq 32)
|
|
|
|
ALPHAREAD MACRO
|
|
|
|
xor eax, eax
|
|
mov cl, 0ffh
|
|
mov al, [ebx+2]
|
|
sub cl, ch
|
|
mov ah, cl
|
|
mov al, _gbMulTable[eax]
|
|
mov [esi].GENGC_rDisplay, al
|
|
mov al, [ebx+1]
|
|
mov ah, cl
|
|
mov al, _gbMulTable[eax]
|
|
mov [esi].GENGC_gDisplay, al
|
|
mov al, [ebx]
|
|
mov ah, cl
|
|
mov al, _gbMulTable[eax]
|
|
mov [esi].GENGC_bDisplay, al
|
|
|
|
ENDM
|
|
|
|
endif
|
|
|
|
|
|
;;
|
|
;;
|
|
;; Macros for advancing a single pixel unit
|
|
;;
|
|
;;
|
|
|
|
|
|
if (BPP eq 8)
|
|
PIXADVANCE MACRO var
|
|
inc var
|
|
ENDM
|
|
elseif (BPP eq 16)
|
|
PIXADVANCE MACRO var
|
|
add var, (BPP / 8)
|
|
ENDM
|
|
else
|
|
PIXADVANCE MACRO var
|
|
add var, [esi].GENGC_bytesPerPixel
|
|
ENDM
|
|
endif
|
|
|
|
if (BPP le 16)
|
|
PIXADVANCE2 MACRO var1, var2
|
|
lea var1, [var2 + (BPP / 8)]
|
|
ENDM
|
|
else
|
|
PIXADVANCE2 MACRO var1, var2
|
|
mov var1, var2
|
|
add var1, [esi].GENGC_bytesPerPixel
|
|
ENDM
|
|
endif
|
|
|
|
;;
|
|
;;
|
|
;; Macros for advancing the accumulators if the z-buffer test fails:
|
|
;;
|
|
;;
|
|
|
|
|
|
if FAST_REPLACE
|
|
|
|
ZBUFFER_FAIL_ADVANCE MACRO
|
|
mov ecx, [esi].GENGC_zAccum ;U
|
|
mov eax, [esi].GENGC_SPAN_dz ; V
|
|
mov ebx, [esi].GENGC_pixAccum ;U
|
|
add edi, 2 ; V
|
|
add ecx, eax ;U
|
|
PIXADVANCE ebx ; V
|
|
sub ebp, 010001h ;U
|
|
mov [esi].GENGC_zAccum, ecx ; V
|
|
mov [esi].GENGC_pixAccum, ebx ;U
|
|
jl doSubDiv ; V
|
|
test ebp, 08000h ;U
|
|
je loopTopNoDiv ; V
|
|
jmp spanExit
|
|
ENDM
|
|
|
|
elseif REPLACE
|
|
|
|
ZBUFFER_FAIL_ADVANCE MACRO
|
|
mov ecx, [esi].GENGC_zAccum ;U
|
|
mov eax, [esi].GENGC_SPAN_dz ; V
|
|
add edi, 2 ;U
|
|
add ecx, eax ; V
|
|
mov eax, [esi].GENGC_ditherAccum ;U
|
|
mov ebx, [esi].GENGC_pixAccum ; V
|
|
ror eax, 8 ;U
|
|
mov [esi].GENGC_zAccum, ecx ; V
|
|
PIXADVANCE ebx ;U
|
|
sub ebp, 010001h ; V
|
|
mov [esi].GENGC_pixAccum, ebx ;U
|
|
mov [esi].GENGC_ditherAccum, eax ; V
|
|
jl doSubDiv ;U
|
|
test ebp, 08000h ; V
|
|
je loopTopNoDiv ;U
|
|
jmp spanExit ; V
|
|
ENDM
|
|
|
|
elseif FLAT_SHADING
|
|
|
|
ZBUFFER_FAIL_ADVANCE MACRO
|
|
mov ecx, [esi].GENGC_zAccum ;U
|
|
mov eax, [esi].GENGC_SPAN_dz ; V
|
|
add edi, 2 ;U
|
|
add ecx, eax ; V
|
|
mov ebx, [esi].GENGC_pixAccum ;U
|
|
mov eax, [esi].GENGC_ditherAccum ; V
|
|
mov [esi].GENGC_zAccum, ecx ;U
|
|
PIXADVANCE ebx ; V
|
|
ror eax, 8 ;U
|
|
sub ebp, 010001h ; V
|
|
mov [esi].GENGC_pixAccum, ebx ;U
|
|
mov [esi].GENGC_ditherAccum, eax ; V
|
|
jl doSubDiv ;U
|
|
test ebp, 08000h ; V
|
|
je loopTopNoDiv ;U
|
|
jmp spanExit
|
|
ENDM
|
|
|
|
elseif SMOOTH_SHADING
|
|
|
|
ZBUFFER_FAIL_ADVANCE MACRO
|
|
mov ecx, [esi].GENGC_zAccum ;U
|
|
mov eax, [esi].GENGC_SPAN_dz ; V
|
|
add edi, 2 ;U
|
|
add ecx, eax ; V
|
|
mov eax, [esi].GENGC_rAccum ;U
|
|
mov [esi].GENGC_zAccum, ecx ; V
|
|
mov ebx, [esi].GENGC_SPAN_dr ;U
|
|
mov ecx, [esi].GENGC_gAccum ; V
|
|
add eax, ebx ;U
|
|
mov edx, [esi].GENGC_SPAN_dg ; V
|
|
mov [esi].GENGC_rAccum, eax ;U
|
|
add ecx, edx ; V
|
|
mov eax, [esi].GENGC_bAccum ;U
|
|
mov ebx, [esi].GENGC_SPAN_db ; V
|
|
mov [esi].GENGC_gAccum, ecx ;U
|
|
add ebx, eax ; V
|
|
mov eax, [esi].GENGC_ditherAccum ;U
|
|
mov [esi].GENGC_bAccum, ebx ; V
|
|
ror eax, 8 ;U
|
|
if ALPHA
|
|
mov ecx, [esi].GENGC_aAccum
|
|
endif
|
|
mov ebx, [esi].GENGC_pixAccum ;U
|
|
if ALPHA
|
|
add ecx, [esi].GENGC_SPAN_da
|
|
endif
|
|
PIXADVANCE ebx ;U
|
|
if ALPHA
|
|
mov [esi].GENGC_aAccum, ecx
|
|
endif
|
|
mov [esi].GENGC_pixAccum, ebx ; V
|
|
sub ebp, 010001h ;U
|
|
mov [esi].GENGC_ditherAccum, eax ; V
|
|
jl doSubDiv ;U
|
|
test ebp, 08000h ; V
|
|
je loopTopNoDiv ;U
|
|
jmp spanExit ; V
|
|
ENDM
|
|
|
|
endif
|
|
|
|
;;----------------------------------------------------------------------
|
|
;;
|
|
;; This is the start of the texture routine. Kick off the divide, and use
|
|
;; the dead time to set up all of the accumulators and other variables.
|
|
;;
|
|
;;----------------------------------------------------------------------
|
|
|
|
ZBUFFER_EARLY_OUT = 1
|
|
|
|
if ZBUFFER
|
|
push ebx ;U
|
|
push esi ; V
|
|
push edi ;U
|
|
push ebp ; V
|
|
|
|
if ZBUFFER_EARLY_OUT
|
|
|
|
mov edi, [ecx].GENGC_SPAN_zbuf ;U
|
|
mov esi, [ecx].GENGC_SPAN_z ; V
|
|
mov edx, [ecx].GENGC_SPAN_length ;U
|
|
mov ebp, [ecx].GENGC_SPAN_dz ; V
|
|
|
|
@zLoop:
|
|
|
|
mov ebx, esi ;U
|
|
mov eax, [edi] ; V
|
|
shr ebx, 16 ;U
|
|
and eax, 0ffffh ; V
|
|
cmp ebx, eax ;U
|
|
if ZCMP_L
|
|
jl @zFirstWrite ; V
|
|
else
|
|
jle @zFirstWrite ; V
|
|
endif
|
|
add edi, 2 ;U
|
|
add esi, ebp ; V
|
|
dec edx ;U
|
|
jne @zLoop ; V
|
|
|
|
pop ebp
|
|
pop edi
|
|
pop esi
|
|
pop ebx
|
|
|
|
ret 0
|
|
|
|
@zFirstWrite:
|
|
|
|
endif ;; ZBUFFER_EARLY_OUT
|
|
|
|
endif ;; ZBUFFER
|
|
|
|
|
|
;;
|
|
;; Start the divide:
|
|
;;
|
|
mov eax, [ecx].GENGC_flags
|
|
fld DWORD PTR [ecx].GENGC_SPAN_qw ;qwAccum
|
|
fld DWORD PTR [ecx].GENGC_SPAN_qw ;qwAccum qwAccum
|
|
test eax, GEN_TEXTURE_ORTHO
|
|
jne @f
|
|
fdivr __One ;1/qw qwAccum
|
|
@@:
|
|
|
|
;;
|
|
;; Save the registers that we need to:
|
|
;;
|
|
|
|
if ZBUFFER
|
|
else
|
|
push ebx ;U
|
|
push esi ; V
|
|
push edi ;U
|
|
push ebp ; V
|
|
endif
|
|
|
|
mov esi, ecx ;U
|
|
|
|
;;
|
|
;; Set up accumulators:
|
|
;;
|
|
|
|
if FAST_REPLACE
|
|
|
|
if ZBUFFER
|
|
mov eax, [esi].GENGC_SPAN_z ; V
|
|
endif
|
|
mov ebx, [esi].GENGC_SPAN_s ;U
|
|
mov ecx, [esi].GENGC_SPAN_t ; V
|
|
if ZBUFFER
|
|
mov [esi].GENGC_zAccum, eax ;U
|
|
endif
|
|
mov [esi].GENGC_sAccum, ebx ; V
|
|
mov [esi].GENGC_tAccum, ecx ;U
|
|
mov ebx, [esi].GENGC_SPAN_qw ; V
|
|
mov eax, [esi].GENGC_SPAN_y ;U
|
|
mov [esi].GENGC_qwAccum, ebx ; V
|
|
mov edx, [esi].GENGC_SPAN_ppix ;U
|
|
mov edi, [esi].GENGC_flags ; V
|
|
mov ebx, [esi].GENGC_SPAN_x ;U
|
|
test edi, SURFACE_TYPE_DIB ; V
|
|
jne @f ;U
|
|
mov edx, [esi].GENGC_ColorsBits ; V
|
|
jmp short @pixAccumDone
|
|
@@:
|
|
if (BPP eq 8)
|
|
add edx, ebx ;U
|
|
elseif (BPP eq 16)
|
|
lea edx, [edx + 2*ebx]
|
|
else
|
|
lea edx, [edx + 4*ebx]
|
|
cmp [esi].GENGC_bpp, 32
|
|
je @f
|
|
sub edx, ebx
|
|
@@:
|
|
endif
|
|
|
|
@pixAccumDone:
|
|
|
|
test edi, GEN_TEXTURE_ORTHO ; V
|
|
mov ebp, [esi].GENGC_SPAN_length ;U
|
|
je @f ; V
|
|
|
|
else
|
|
|
|
|
|
if REPLACE
|
|
else
|
|
|
|
;; Handle RGB accumulators
|
|
|
|
if FLAT_SHADING
|
|
mov eax, [ecx].GENGC_SPAN_r ;U
|
|
mov ebx, [ecx].GENGC_SPAN_g ; V
|
|
shr eax, rBits ;U
|
|
mov ecx, [esi].GENGC_SPAN_b ; V
|
|
shr ebx, gBits ;U
|
|
and eax, 0ff00h ; V
|
|
shr ecx, bBits ;U
|
|
and ebx, 0ff00h ; V
|
|
and ecx, 0ff00h ;U
|
|
mov [esi].GENGC_rAccum, eax ; V
|
|
mov [esi].GENGC_gAccum, ebx ;U
|
|
mov [esi].GENGC_bAccum, ecx ; V
|
|
else
|
|
mov eax, [ecx].GENGC_SPAN_r ;U
|
|
mov ebx, [ecx].GENGC_SPAN_g ; V
|
|
mov ecx, [esi].GENGC_SPAN_b ;U
|
|
mov [esi].GENGC_rAccum, eax ; V
|
|
mov [esi].GENGC_gAccum, ebx ;U
|
|
mov [esi].GENGC_bAccum, ecx ; V
|
|
endif ;; FLAT_SHADING
|
|
|
|
endif ;; NOT REPLACE
|
|
|
|
if ZBUFFER
|
|
mov eax, [esi].GENGC_SPAN_z ; V
|
|
endif
|
|
mov ebx, [esi].GENGC_SPAN_s ;U
|
|
mov ecx, [esi].GENGC_SPAN_t ; V
|
|
if ZBUFFER
|
|
mov [esi].GENGC_zAccum, eax ;U
|
|
endif
|
|
mov [esi].GENGC_sAccum, ebx ; V
|
|
mov [esi].GENGC_tAccum, ecx ;U
|
|
mov ebx, [esi].GENGC_SPAN_qw ; V
|
|
mov eax, [esi].GENGC_SPAN_y ;U
|
|
mov [esi].GENGC_qwAccum, ebx ; V
|
|
and eax, 03h ;U
|
|
mov ecx, [esi].GENGC_SPAN_x ; V
|
|
lea eax, [eax*4 + offset dither0] ;U
|
|
lea ecx, [ecx*8] ; V
|
|
mov edx, [esi].GENGC_SPAN_ppix ;U
|
|
mov edi, [esi].GENGC_flags ; V
|
|
mov ebx, [esi].GENGC_SPAN_x ;U
|
|
test edi, SURFACE_TYPE_DIB ; V
|
|
jne @f ;U
|
|
mov edx, [esi].GENGC_ColorsBits ; V
|
|
jmp short @pixAccumDone
|
|
@@:
|
|
if (BPP eq 8)
|
|
add edx, ebx ;U
|
|
elseif (BPP eq 16)
|
|
lea edx, [edx + 2*ebx]
|
|
else
|
|
lea edx, [edx + 4*ebx]
|
|
cmp [esi].GENGC_bpp, 32
|
|
je @f
|
|
sub edx, ebx
|
|
@@:
|
|
endif
|
|
|
|
@pixAccumDone:
|
|
|
|
mov eax, [eax] ; V
|
|
and ecx, 018h ;U
|
|
test edi, GEN_TEXTURE_ORTHO ; V
|
|
mov ebp, [esi].GENGC_SPAN_length ;U
|
|
je @f ; V
|
|
|
|
endif
|
|
|
|
mov edi, [esi].GENGC_sAccum ; V
|
|
mov ebx, [esi].GENGC_tAccum ;U
|
|
mov DWORD PTR [esi].GENGC_sResult, edi ; V
|
|
mov DWORD PTR [esi].GENGC_tResult, ebx ;U
|
|
mov edi, [esi].GENGC_flags ; V
|
|
jmp short @stResultDone1 ;U
|
|
|
|
;;
|
|
;; Kick off the next divide:
|
|
;;
|
|
|
|
@@:
|
|
|
|
fild DWORD PTR [esi].GENGC_sAccum ; s 1/qw qwAccum
|
|
fmul ST, ST(1) ; s/qw 1/qw qwAccum
|
|
fild DWORD PTr [esi].GENGC_tAccum ; t s/qw 1/qw qwAccum
|
|
fmulp ST(2), ST ; s/qw t/qw qwAccum
|
|
fistp QWORD PTR [esi].GENGC_sResult ; t/qw qwAccum
|
|
fistp QWORD PTR [esi].GENGC_tResult ; qwAccum
|
|
fadd DWORD PTR [esi].GENGC_qwStepX ; qwAccum
|
|
fld ST(0) ; qwAccum qwAccum
|
|
fdivr __One ; 1/qw qwAccum
|
|
|
|
@stResultDone1:
|
|
|
|
ror eax, cl ;UV (4)
|
|
add ebp, 070000h ;U
|
|
mov [esi].GENGC_ditherAccum, eax ; V
|
|
dec ebp ;U
|
|
mov [esi].GENGC_pixAccum, edx ; V
|
|
mov eax, [esi].GENGC_sAccum ;U
|
|
mov ebx, [esi].GENGC_tAccum ; V
|
|
add eax, [esi].GENGC_sStepX ;U
|
|
add ebx, [esi].GENGC_tStepX ; V
|
|
mov [esi].GENGC_sAccum, eax ;U
|
|
mov [esi].GENGC_tAccum, ebx ; V
|
|
mov eax, [esi].GENGC_sResult ;U
|
|
mov ebx, [esi].GENGC_tResult ; V
|
|
mov cl, TSHIFT_SUBDIV ;U
|
|
sar ebx, cl ;UV (4)
|
|
and ebx, NOT 7 ;U
|
|
|
|
if ALPHA
|
|
mov ecx, [esi].GENGC_SPAN_a
|
|
endif
|
|
|
|
test edi, GEN_TEXTURE_ORTHO ; V
|
|
mov [esi].GENGC_tResult, ebx ;U
|
|
|
|
if ALPHA
|
|
mov [esi].GENGC_aAccum, ecx
|
|
endif
|
|
|
|
je @f
|
|
mov ecx, [esi].GENGC_sAccum ; V
|
|
mov edx, [esi].GENGC_tAccum ;U
|
|
mov DWORD PTR [esi].GENGC_sResultNew, ecx ; V
|
|
mov DWORD PTR [esi].GENGC_tResultNew, edx ;U
|
|
jmp short @stResultDone2 ; V
|
|
|
|
@@:
|
|
|
|
;; We may have to burn some cycles here...
|
|
|
|
fild DWORD PTR [esi].GENGC_sAccum ; s 1/qw qwAccum
|
|
fmul ST, ST(1) ; s/qw 1/qw qwAccum
|
|
fild DWORD PTr [esi].GENGC_tAccum ; t s/qw 1/qw qwAccum
|
|
fmulp ST(2), ST ; s/qw t/qw qwAccum
|
|
fistp QWORD PTR [esi].GENGC_sResultNew; t/qw qwAccum
|
|
fistp QWORD PTR [esi].GENGC_tResultNew; qwAccum
|
|
fadd DWORD PTR [esi].GENGC_qwStepX ; qwAccum
|
|
|
|
@stResultDone2:
|
|
|
|
mov cl, TSHIFT_SUBDIV ;U
|
|
mov edx, [esi].GENGC_tResultNew ; V
|
|
sar edx, cl ;UV (4)
|
|
and edx, NOT 7 ;U
|
|
mov ecx, [esi].GENGC_sResultNew ; V
|
|
mov [esi].GENGC_tResultNew, edx ;U
|
|
sub ecx, eax ; V
|
|
sar ecx, 3 ;U
|
|
sub edx, ebx ; V
|
|
sar edx, 3 ;U
|
|
mov [esi].GENGC_subDs, ecx ; V
|
|
mov [esi].GENGC_subDt, edx ;U
|
|
mov eax, [esi].GENGC_flags ; V
|
|
mov edi, [esi].GENGC_SPAN_zbuf ;U
|
|
|
|
loopTop:
|
|
|
|
;;
|
|
;; This is the start of the outer loop. We come back here on each
|
|
;; subdivision. The key thing is to kick off the next divide:
|
|
;;
|
|
|
|
test eax, GEN_TEXTURE_ORTHO ; V
|
|
jne @f ;U
|
|
|
|
fld ST(0) ; qwAccum qwAccum
|
|
fadd DWORD PTR [esi].GENGC_qwStepX ; qwAccum+ qwAccum
|
|
fxch ST(1) ; qwAccum qwAccum+
|
|
fdivr __One ; 1/qw qwAccum+ -- let the divide rip!
|
|
|
|
@@:
|
|
|
|
loopTopNoDiv:
|
|
|
|
;;
|
|
;; This is the start of the inner loop. This is where the pixel-level
|
|
;; work happens:
|
|
;;
|
|
|
|
;;
|
|
;; First, do z-buffering is enabled:
|
|
;;
|
|
|
|
if ZBUFFER
|
|
|
|
mov eax, [edi] ;U
|
|
mov ebx, [esi].GENGC_zAccum ; V
|
|
shr ebx, 16 ;U
|
|
and eax, 0ffffh ; V
|
|
cmp ebx, eax ;U
|
|
if ZCMP_L
|
|
jl @zWrite ; V
|
|
else
|
|
jle @zWrite ; V
|
|
endif
|
|
|
|
ZBUFFER_FAIL_ADVANCE
|
|
|
|
@zWrite:
|
|
mov [edi], bx ;UV
|
|
|
|
endif ;;ZBUFFER
|
|
|
|
;;
|
|
;; Now, get pointer to current texel value in EDX. There are two cases,
|
|
;; one if there is a palette-lookup, and one if we index straight into
|
|
;; the texture.
|
|
;;
|
|
|
|
|
|
if PALETTE_ENABLED
|
|
|
|
mov ecx, TEXPALETTE ;U
|
|
mov eax, TMASK_SUBDIV ; V
|
|
test ecx, ecx ;U
|
|
je @noPalette ; V
|
|
|
|
mov edx, [esi].GENGC_tResult ; V
|
|
mov ebx, [esi].GENGC_sResult ;U
|
|
and edx, eax ; V
|
|
mov eax, [esi].GENGC_sMask ;U
|
|
and ebx, eax ; V
|
|
shr edx, 6 ;U
|
|
mov eax, DWORD PTR [esi].GENGC_sResult ; V
|
|
shr ebx, 16 ;U
|
|
mov ecx, TEXIMAGE ; V
|
|
add edx, ecx ;U
|
|
add eax, [esi].GENGC_subDs ; V
|
|
mov ecx, DWORD PTR [esi].GENGC_tResult ;U
|
|
add edx, ebx ; V
|
|
add ecx, [esi].GENGC_subDt ;U
|
|
mov DWORD PTR [esi].GENGC_sResult, eax ; V
|
|
xor eax, eax ;U
|
|
mov ebx, TEXPALETTE ; V
|
|
mov DWORD PTR [esi].GENGC_tResult, ecx ;U
|
|
mov al, [edx] ; V
|
|
lea edx, [ebx+4*eax] ;U
|
|
jmp short @paletteDone ; V
|
|
|
|
@noPalette:
|
|
|
|
endif ;;PALETTE_ENABLED
|
|
|
|
mov eax, TMASK_SUBDIV ;U
|
|
mov edx, [esi].GENGC_tResult ; V
|
|
mov ebx, [esi].GENGC_sResult ;U
|
|
and edx, eax ; V
|
|
shr edx, (6-TEX_BPP_LOG2) ;U
|
|
mov ecx, [esi].GENGC_sMask ; V
|
|
and ebx, ecx ;U
|
|
mov eax, DWORD PTR [esi].GENGC_sResult ; V
|
|
shr ebx, (16-TEX_BPP_LOG2) ;U
|
|
mov ecx, [esi].GENGC_subDs ; V
|
|
add eax, ecx ;U
|
|
add edx, ebx ; V
|
|
mov ecx, TEXIMAGE ;U
|
|
mov ebx, [esi].GENGC_subDt ; V
|
|
add edx, ecx ;U
|
|
mov ecx, DWORD PTR [esi].GENGC_tResult ; V
|
|
add ecx, ebx ;U
|
|
mov DWORD PTR [esi].GENGC_sResult, eax ; V
|
|
mov DWORD PTR [esi].GENGC_tResult, ecx ;U
|
|
|
|
if (PALETTE_ONLY)
|
|
mov al, [edx] ; V
|
|
and eax, 0ffh ;U
|
|
mov ebx, TEXPALETTE ; V
|
|
lea edx, [ebx+4*eax] ;U
|
|
endif
|
|
|
|
|
|
@paletteDone:
|
|
|
|
|
|
;;
|
|
;; We are now ready to handle each of the 4 basic modes on a case-by-case
|
|
;; basis. We will generally try to adhere to the following register
|
|
;; usage:
|
|
;; eax - red
|
|
;; ebx - green
|
|
;; ecx - blue
|
|
;; ebx, edx - framebuffer pointers
|
|
;;
|
|
|
|
if FAST_REPLACE
|
|
|
|
;;----------------------------------------------------------------------
|
|
;;
|
|
;; ** Replace mode (compressed)
|
|
;;
|
|
;;----------------------------------------------------------------------
|
|
|
|
|
|
if ALPHA
|
|
|
|
cmp BYTE PTR [edx+3], 0ffh ;U
|
|
je @noAlpha ; V
|
|
mov ebx, [esi].GENGC_pixAccum ;U ;; get ready to do read
|
|
cmp BYTE PTR [edx+3], 0 ; V
|
|
jne @alphaRead ;U
|
|
|
|
;; Alpha is 0 in the texture, so just increment all the accumulators
|
|
|
|
if ZBUFFER
|
|
mov ecx, [esi].GENGC_zAccum ;U
|
|
add edi, 2 ; V
|
|
add ecx, [esi].GENGC_SPAN_dz ;U
|
|
endif
|
|
|
|
PIXADVANCE ebx ;U
|
|
|
|
if ZBUFFER
|
|
mov [esi].GENGC_zAccum, ecx ;U
|
|
endif
|
|
|
|
ror eax, 8 ; V
|
|
sub ebp, 010001h ;U
|
|
mov [esi].GENGC_pixAccum, ebx ; V
|
|
mov [esi].GENGC_ditherAccum, eax ;U
|
|
|
|
;; Finish incrementing all of our accumulators
|
|
|
|
jl doSubDiv ; V
|
|
test ebp, 08000h ;U
|
|
je loopTopNoDiv ; V
|
|
|
|
jmp spanExit
|
|
|
|
@alphaRead:
|
|
|
|
;;
|
|
;; Get pixel value and calculate total effect with alpha
|
|
;;
|
|
|
|
;; To make this easy on ourselves, we'll use the uncompressed palette
|
|
;; to do the alpha modulation:
|
|
|
|
|
|
ALPHANOMODULATE
|
|
sub edx, [esi].GENGC_texImageReplace
|
|
add edx, [esi].GENGC_texPalette
|
|
ALPHAREAD
|
|
|
|
mov al, [edx+2] ;U get texel value
|
|
mov ah, [esi].GENGC_aDisplay
|
|
mov bl, [edx+1] ;U
|
|
mov bh, [esi].GENGC_aDisplay
|
|
mov cl, [edx] ; V
|
|
mov ch, [esi].GENGC_aDisplay
|
|
and eax, 0ffffh
|
|
and ebx, 0ffffh
|
|
and ecx, 0ffffh
|
|
mov ah, _gbMulTable[eax]
|
|
mov bh, _gbMulTable[ebx]
|
|
mov ch, _gbMulTable[ecx]
|
|
add ah, [esi].GENGC_rDisplay
|
|
add bh, [esi].GENGC_gDisplay
|
|
add ch, [esi].GENGC_bDisplay
|
|
|
|
if (BPP eq 32)
|
|
shl eax, -rRightShiftAdj
|
|
else
|
|
shr eax, rRightShiftAdj ;U
|
|
endif
|
|
mov edx, [esi].GENGC_pixAccum ; V
|
|
shr ebx, gRightShiftAdj ;U
|
|
and eax, rMask ; V
|
|
shr ecx, bRightShiftAdj ;U
|
|
and ebx, gMask ; V
|
|
and ecx, bMask ;U
|
|
or eax, ebx ; V
|
|
or eax, ecx ;U
|
|
PIXADVANCE2 ebx, edx ; V
|
|
|
|
if ZBUFFER
|
|
mov ecx, [esi].GENGC_zAccum ; V
|
|
add edi, 2 ;U
|
|
add ecx, [esi].GENGC_SPAN_dz ; V
|
|
endif
|
|
|
|
mov [esi].GENGC_pixAccum, ebx ;U
|
|
|
|
if ZBUFFER
|
|
mov [esi].GENGC_zAccum, ecx ;U
|
|
endif
|
|
|
|
if (BPP eq 8)
|
|
sub ebp, 010001h ; V
|
|
mov al, [esi].GENGC_xlatPalette[eax];U ;; AGI without z-buffering
|
|
mov [edx], al ;U
|
|
elseif (BPP eq 16)
|
|
sub ebp, 010001h
|
|
mov [edx], ax
|
|
else
|
|
mov [edx], ax
|
|
shr eax, 16
|
|
sub ebp, 010001h
|
|
mov [edx+2], al
|
|
endif
|
|
|
|
;; Finish the loop:
|
|
|
|
jl doSubDiv ; V
|
|
test ebp, 08000h ;U
|
|
je loopTopNoDiv ; V
|
|
|
|
jmp spanExit
|
|
|
|
endif ;;ALPHA
|
|
|
|
@noAlpha:
|
|
|
|
mov ebx, [esi].GENGC_pixAccum ;U
|
|
|
|
if (BPP eq 8)
|
|
mov al, [edx] ; V get texel value
|
|
elseif (BPP eq 16)
|
|
mov ax, [edx]
|
|
else
|
|
mov eax, [edx]
|
|
endif
|
|
|
|
PIXADVANCE2 ecx, ebx ;U
|
|
|
|
if ZBUFFER
|
|
mov edx, [esi].GENGC_zAccum ; V
|
|
add edi, 2 ;U
|
|
add edx, [esi].GENGC_SPAN_dz ; V
|
|
mov [esi].GENGC_zAccum, edx ;U
|
|
endif
|
|
|
|
mov [esi].GENGC_pixAccum, ecx ; V
|
|
|
|
if (BPP eq 8)
|
|
sub ebp, 010001h ;U
|
|
mov [ebx], al ; V
|
|
elseif (BPP eq 16)
|
|
sub ebp, 010001h
|
|
mov [ebx], ax
|
|
else
|
|
mov [ebx], ax
|
|
shr eax, 16
|
|
sub ebp, 010001h
|
|
mov [ebx+2], al
|
|
endif
|
|
|
|
;; Finish incrementing all of our accumulators
|
|
|
|
jl doSubDiv ;U
|
|
test ebp, 08000h ; V
|
|
je loopTopNoDiv ;U
|
|
|
|
jmp spanExit
|
|
|
|
elseif REPLACE
|
|
|
|
|
|
;;----------------------------------------------------------------------
|
|
;;
|
|
;; ** Replace mode (non-compressed)
|
|
;;
|
|
;;----------------------------------------------------------------------
|
|
|
|
if ALPHA
|
|
|
|
cmp BYTE PTR [edx+3], 0ffh ;U
|
|
je @noAlpha ; V
|
|
mov ebx, [esi].GENGC_pixAccum ;U ;; get ready to do read
|
|
cmp BYTE PTR [edx+3], 0 ; V
|
|
jne @alphaRead ;U
|
|
|
|
;; Alpha is 0 in the texture, so just increment all the accumulators
|
|
|
|
if ZBUFFER
|
|
mov ecx, [esi].GENGC_zAccum ;U
|
|
add edi, 2 ; V
|
|
add ecx, [esi].GENGC_SPAN_dz ;U
|
|
endif
|
|
|
|
mov eax, [esi].GENGC_ditherAccum ; V
|
|
|
|
if ZBUFFER
|
|
mov [esi].GENGC_zAccum, ecx ;U
|
|
endif
|
|
|
|
PIXADVANCE ebx ;U
|
|
ror eax, 8 ; V
|
|
sub ebp, 010001h ;U
|
|
mov [esi].GENGC_pixAccum, ebx ; V
|
|
mov [esi].GENGC_ditherAccum, eax ;U
|
|
|
|
;; Finish incrementing all of our accumulators
|
|
|
|
jl doSubDiv ; V
|
|
test ebp, 08000h ;U
|
|
je loopTopNoDiv ; V
|
|
|
|
jmp spanExit
|
|
|
|
@alphaRead:
|
|
|
|
;;
|
|
;; Get pixel value and calculate total effect with alpha
|
|
;;
|
|
|
|
ALPHANOMODULATE
|
|
ALPHAREAD
|
|
|
|
mov al, [edx+2] ;U get texel value
|
|
mov ah, [esi].GENGC_aDisplay
|
|
mov bl, [edx+1] ;U
|
|
mov bh, [esi].GENGC_aDisplay
|
|
mov cl, [edx] ; V
|
|
mov ch, [esi].GENGC_aDisplay
|
|
and eax, 0ffffh
|
|
and ebx, 0ffffh
|
|
and ecx, 0ffffh
|
|
mov ah, _gbMulTable[eax]
|
|
mov bh, _gbMulTable[ebx]
|
|
mov ch, _gbMulTable[ecx]
|
|
add ah, [esi].GENGC_rDisplay
|
|
add bh, [esi].GENGC_gDisplay
|
|
add ch, [esi].GENGC_bDisplay
|
|
|
|
if (BPP eq 32)
|
|
shl eax, -rRightShiftAdj
|
|
else
|
|
shr eax, rRightShiftAdj ;U
|
|
endif
|
|
mov edx, [esi].GENGC_pixAccum ; V
|
|
shr ebx, gRightShiftAdj ;U
|
|
and eax, rMask ; V
|
|
shr ecx, bRightShiftAdj ;U
|
|
and ebx, gMask ; V
|
|
and ecx, bMask ;U
|
|
or eax, ebx ; V
|
|
or eax, ecx ;U
|
|
PIXADVANCE2 ebx, edx ; V
|
|
|
|
if ZBUFFER
|
|
mov ecx, [esi].GENGC_zAccum ; V
|
|
add edi, 2 ;U
|
|
add ecx, [esi].GENGC_SPAN_dz ; V
|
|
endif
|
|
|
|
mov [esi].GENGC_pixAccum, ebx ;U
|
|
|
|
if ZBUFFER
|
|
mov [esi].GENGC_zAccum, ecx ;U
|
|
endif
|
|
|
|
if (BPP eq 8)
|
|
sub ebp, 010001h ; V
|
|
mov al, [esi].GENGC_xlatPalette[eax];U ;; AGI without z-buffering
|
|
mov [edx], al ;U
|
|
elseif (BPP eq 16)
|
|
sub ebp, 010001h
|
|
mov [edx], ax
|
|
else
|
|
mov [edx], ax
|
|
shr eax, 16
|
|
sub ebp, 010001h
|
|
mov [edx+2], al
|
|
endif
|
|
|
|
;; Finish the loop:
|
|
|
|
jl doSubDiv ; V
|
|
test ebp, 08000h ;U
|
|
je loopTopNoDiv ; V
|
|
|
|
jmp spanExit
|
|
|
|
endif ;;ALPHA
|
|
|
|
@noAlpha:
|
|
|
|
mov ah, [edx+2] ;U get texel value
|
|
mov bh, [edx+1] ; V
|
|
if (BPP eq 32)
|
|
shl eax, -rRightShiftAdj
|
|
else
|
|
shr eax, rRightShiftAdj ;U
|
|
endif
|
|
mov ch, [edx] ; V
|
|
shr ebx, gRightShiftAdj ;U
|
|
and eax, rMask ; V
|
|
shr ecx, bRightShiftAdj ;U
|
|
and ebx, gMask ; V
|
|
or eax, ebx ;U
|
|
and ecx, bMask ; V
|
|
mov edx, [esi].GENGC_pixAccum ;U
|
|
or eax, ecx ; V
|
|
PIXADVANCE2 ebx, edx ;U
|
|
|
|
if ZBUFFER
|
|
mov ecx, [esi].GENGC_zAccum ; V
|
|
add edi, 2 ;U
|
|
add ecx, [esi].GENGC_SPAN_dz ; V
|
|
mov [esi].GENGC_zAccum, ecx ;U
|
|
endif
|
|
|
|
if (BPP eq 8)
|
|
sub ebp, 010001h ; V
|
|
mov [esi].GENGC_pixAccum, ebx ;U
|
|
mov al, [esi].GENGC_xlatPalette[eax]; V
|
|
mov [edx], al ;U
|
|
elseif (BPP eq 16)
|
|
sub ebp, 010001h
|
|
mov [esi].GENGC_pixAccum, ebx
|
|
mov [edx], ax
|
|
else
|
|
mov [edx], ax
|
|
shr eax, 16
|
|
mov [esi].GENGC_pixAccum, ebx
|
|
sub ebp, 010001h
|
|
mov [edx+2], al
|
|
endif
|
|
|
|
;; Finish the loop:
|
|
|
|
jl doSubDiv ; V
|
|
test ebp, 08000h ;U
|
|
je loopTopNoDiv ; V
|
|
|
|
jmp spanExit
|
|
|
|
|
|
elseif FLAT_SHADING
|
|
|
|
;;----------------------------------------------------------------------
|
|
;;
|
|
;; ** Flat shading
|
|
;;
|
|
;;----------------------------------------------------------------------
|
|
|
|
|
|
if ALPHA
|
|
|
|
mov ebx, [esi].GENGC_pixAccum ;; get ready to do read
|
|
cmp BYTE PTR [edx+3], 0
|
|
jne @alphaRead
|
|
|
|
;; Alpha is 0 in the texture, so just increment all the accumulators
|
|
|
|
if ZBUFFER
|
|
mov ecx, [esi].GENGC_zAccum
|
|
mov eax, [esi].GENGC_SPAN_dz
|
|
add edi, 2
|
|
add ecx, eax
|
|
endif
|
|
|
|
mov eax, [esi].GENGC_ditherAccum
|
|
|
|
if ZBUFFER
|
|
mov [esi].GENGC_zAccum, ecx
|
|
endif
|
|
|
|
ror eax, 8 ;U
|
|
PIXADVANCE ebx ; V
|
|
sub ebp, 010001h ;U
|
|
mov [esi].GENGC_pixAccum, ebx ; V
|
|
mov [esi].GENGC_ditherAccum, eax ;U
|
|
|
|
;; Finish incrementing all of our accumulators
|
|
|
|
jl doSubDiv ; V
|
|
test ebp, 08000h ;U
|
|
je loopTopNoDiv ; V
|
|
jmp spanExit
|
|
|
|
@alphaRead:
|
|
|
|
cmp BYTE PTR [edx+3], 0ffh
|
|
jne @doAlpha
|
|
cmp BYTE PTR [esi].GENGC_aAccum+2, 0ffh
|
|
jne @doAlpha
|
|
|
|
;; Set mix color to 1, 0, 0, 0
|
|
|
|
mov DWORD PTR [esi].GENGC_rDisplay, 0ff000000h
|
|
jmp short @doneAlpha
|
|
|
|
;;
|
|
;; Get pixel value and calculate total effect with alpha
|
|
;;
|
|
|
|
@doAlpha:
|
|
|
|
ALPHAMODULATE
|
|
ALPHAREAD
|
|
|
|
@doneAlpha:
|
|
|
|
endif ;;ALPHA
|
|
|
|
mov ebx, [edx] ;U
|
|
mov ecx, ebx ; V
|
|
shr ebx, 16 ;U
|
|
mov edx, ecx ; V
|
|
shr ecx, 8 ;U
|
|
mov eax, [esi].GENGC_rAccum ; V
|
|
and ebx, 0ffh ;U
|
|
and ecx, 0ffh ; V
|
|
or ebx, eax ;U
|
|
mov eax, [esi].GENGC_gAccum ; V
|
|
and edx, 0ffh ;U
|
|
or ecx, eax ; V
|
|
mov eax, [esi].GENGC_bAccum ;U
|
|
or edx, eax ; V
|
|
mov ebx, DWORD PTR _gbMulTable[ebx] ;U
|
|
mov ecx, DWORD PTR _gbMulTable[ecx] ; V
|
|
mov edx, DWORD PTR _gbMulTable[edx] ;U
|
|
|
|
|
|
if ALPHA
|
|
|
|
mov bh, [esi].GENGC_aDisplay
|
|
mov ch, bh
|
|
mov dh, bh
|
|
|
|
and ebx, 0ffffh
|
|
and ecx, 0ffffh
|
|
and edx, 0ffffh
|
|
|
|
mov bl, _gbMulTable[ebx]
|
|
mov cl, _gbMulTable[ecx]
|
|
mov dl, _gbMulTable[edx]
|
|
|
|
add bl, [esi].GENGC_rDisplay
|
|
add cl, [esi].GENGC_gDisplay
|
|
add dl, [esi].GENGC_bDisplay
|
|
|
|
endif
|
|
|
|
;; do the dithering
|
|
|
|
shl ebx, (rBits+8) ;U
|
|
mov eax, [esi].GENGC_ditherAccum ; V
|
|
shl ecx, (gBits+8) ;U
|
|
and eax, 0f800h ; V
|
|
shl edx, (bBits+8) ;U
|
|
add ebx, eax ; V
|
|
add ecx, eax ;U
|
|
add edx, eax ; V
|
|
|
|
;;
|
|
;; Compose the final pixel:
|
|
;;
|
|
|
|
if (BPP eq 32)
|
|
shl ebx, -rRightShiftAdj
|
|
else
|
|
shr ebx, rRightShiftAdj ;U
|
|
endif
|
|
mov eax, [esi].GENGC_ditherAccum ; V
|
|
ror eax, 8 ;U
|
|
and ebx, rMask ; V
|
|
shr ecx, gRightShiftAdj ;U
|
|
mov [esi].GENGC_ditherAccum, eax ; V
|
|
shr edx, bRightShiftAdj ;U
|
|
and ecx, gMask ; V
|
|
or ebx, ecx ;U
|
|
and edx, bMask ; V
|
|
or ebx, edx ;U
|
|
|
|
;;
|
|
;; Advance the frame buffer pointer:
|
|
;;
|
|
|
|
mov ecx, [esi].GENGC_pixAccum ; V
|
|
mov edx, ecx ;U
|
|
if (BPP le 16)
|
|
add ecx, (BPP / 8) ; V
|
|
else
|
|
add ecx, [esi].GENGC_bytesPerPixel ; V
|
|
endif
|
|
mov [esi].GENGC_pixAccum, ecx ;U
|
|
|
|
;;
|
|
;; A good time to start incrementing all of our accumulators:
|
|
;;
|
|
|
|
if ZBUFFER
|
|
mov ecx, [esi].GENGC_zAccum ; V
|
|
mov eax, [esi].GENGC_SPAN_dz ;U
|
|
add ecx, eax ; V
|
|
add edi, 2 ;U
|
|
mov [esi].GENGC_zAccum, ecx ; V
|
|
endif
|
|
|
|
;;
|
|
;; Write the pixel into the frame buffer
|
|
;;
|
|
|
|
if (BPP eq 8)
|
|
mov al, [esi].GENGC_xlatPalette[ebx]; V
|
|
sub ebp, 010001h ;U
|
|
mov [edx], al ; V
|
|
elseif (BPP eq 16)
|
|
sub ebp, 010001h
|
|
mov [edx], bx
|
|
else
|
|
mov [edx], bx
|
|
shr ebx, 16
|
|
sub ebp, 010001h
|
|
mov [edx+2], bl
|
|
endif
|
|
|
|
;; Finish incrementing all of our accumulators
|
|
|
|
jl doSubDiv ;U
|
|
test ebp, 08000h ; V
|
|
je loopTopNoDiv ;U
|
|
|
|
elseif SMOOTH_SHADING
|
|
|
|
;;----------------------------------------------------------------------
|
|
;;
|
|
;; ** Smooth shading
|
|
;;
|
|
;;----------------------------------------------------------------------
|
|
|
|
if ALPHA
|
|
|
|
mov ebx, [esi].GENGC_pixAccum ;; get ready to do read
|
|
cmp BYTE PTR [edx+3], 0
|
|
jne @alphaRead
|
|
|
|
;; Alpha is 0 in the texture, so just increment all the accumulators
|
|
|
|
if ZBUFFER
|
|
mov ecx, [esi].GENGC_zAccum
|
|
mov eax, [esi].GENGC_SPAN_dz
|
|
add eax, ecx
|
|
add edi, 2
|
|
mov [esi].GENGC_zAccum, eax
|
|
endif
|
|
|
|
mov eax, [esi].GENGC_rAccum
|
|
mov ebx, [esi].GENGC_gAccum
|
|
mov ecx, [esi].GENGC_bAccum
|
|
add eax, [esi].GENGC_SPAN_dr
|
|
add ebx, [esi].GENGC_SPAN_dg
|
|
add ecx, [esi].GENGC_SPAN_db
|
|
mov [esi].GENGC_rAccum, eax
|
|
mov [esi].GENGC_gAccum, ebx
|
|
mov [esi].GENGC_bAccum, ecx
|
|
|
|
mov eax, [esi].GENGC_ditherAccum
|
|
mov ecx, [esi].GENGC_aAccum
|
|
|
|
ror eax, 8
|
|
mov ebx, [esi].GENGC_pixAccum
|
|
add ecx, [esi].GENGC_SPAN_da
|
|
PIXADVANCE ebx
|
|
mov [esi].GENGC_aAccum, ecx
|
|
mov [esi].GENGC_pixAccum, ebx
|
|
sub ebp, 010001h
|
|
mov [esi].GENGC_ditherAccum, eax
|
|
|
|
;; Finish incrementing all of our accumulators
|
|
|
|
jl doSubDiv ;U
|
|
test ebp, 08000h ; V
|
|
je loopTopNoDiv ;U
|
|
jmp spanExit
|
|
|
|
@alphaRead:
|
|
|
|
cmp BYTE PTR [edx+3], 0ffh
|
|
jne @doAlpha
|
|
cmp BYTE PTR [esi].GENGC_aAccum+2, 0ffh
|
|
jne @doAlpha
|
|
|
|
;; Set mix color to 1, 0, 0, 0
|
|
|
|
mov DWORD PTR [esi].GENGC_rDisplay, 0ff000000h
|
|
jmp short @doneAlpha
|
|
|
|
;;
|
|
;; Get pixel value and calculate total effect with alpha
|
|
;;
|
|
|
|
@doAlpha:
|
|
|
|
ALPHAMODULATE
|
|
ALPHAREAD
|
|
|
|
@doneAlpha:
|
|
|
|
endif ;;ALPHA
|
|
|
|
mov ebx, [esi].GENGC_rAccum ;U
|
|
mov eax, [edx] ; V
|
|
shr ebx, rBits ;U
|
|
and eax, 0ff0000h ; V
|
|
shr eax, 16 ;U
|
|
mov ecx, [esi].GENGC_gAccum ; V
|
|
shr ecx, gBits ;U
|
|
and ebx, 0ff00h ; V
|
|
or ebx, eax ;U
|
|
mov eax, [edx] ; V
|
|
shr eax, 8 ;U
|
|
mov edx, [edx] ; V
|
|
and eax, 0ffh ;U
|
|
and ecx, 0ff00h ; V
|
|
or ecx, eax ;U
|
|
mov eax, [esi].GENGC_bAccum ; V
|
|
shr eax, bBits ;U
|
|
and edx, 0ffh ; V
|
|
and eax, 0ff00h ;U
|
|
mov ebx, DWORD PTR _gbMulTable[ebx] ; V get multiplied 8-bit R value
|
|
or edx, eax ;U
|
|
mov ecx, DWORD PTR _gbMulTable[ecx] ; V get multiplied 8-bit G value
|
|
mov eax, [esi].GENGC_ditherAccum ;U
|
|
mov edx, DWORD PTR _gbMulTable[edx] ; V get multiplied 8-bit B value
|
|
|
|
|
|
if ALPHA
|
|
|
|
mov bh, [esi].GENGC_aDisplay
|
|
mov ch, bh
|
|
mov dh, bh
|
|
|
|
and ebx, 0ffffh
|
|
and ecx, 0ffffh
|
|
and edx, 0ffffh
|
|
|
|
mov bl, _gbMulTable[ebx]
|
|
mov cl, _gbMulTable[ecx]
|
|
mov dl, _gbMulTable[edx]
|
|
|
|
add bl, [esi].GENGC_rDisplay
|
|
add cl, [esi].GENGC_gDisplay
|
|
add dl, [esi].GENGC_bDisplay
|
|
|
|
endif
|
|
|
|
shl ebx, (rBits+8) ;U
|
|
and eax, 0f800h ; V
|
|
shl ecx, (gBits+8) ;U
|
|
add ebx, eax ; V
|
|
shl edx, (bBits+8) ;U
|
|
add ecx, eax ; V
|
|
|
|
if (BPP eq 32)
|
|
shl ebx, -rRightShiftAdj
|
|
else
|
|
shr ebx, rRightShiftAdj ;U
|
|
endif
|
|
add edx, eax ; V
|
|
shr ecx, gRightShiftAdj ;U
|
|
and ebx, rMask ; V
|
|
shr edx, bRightShiftAdj ;U
|
|
and ecx, gMask ; V
|
|
or ebx, ecx ;U
|
|
and edx, bMask ; V
|
|
or ebx, edx ;U
|
|
|
|
;;
|
|
;; A good time to start incrementing all of our accumulators
|
|
;;
|
|
|
|
if ZBUFFER
|
|
mov ecx, [esi].GENGC_zAccum ; V
|
|
mov eax, [esi].GENGC_SPAN_dz ;U
|
|
add eax, ecx ; V
|
|
add edi, 2 ;U
|
|
mov [esi].GENGC_zAccum, eax ; V
|
|
endif
|
|
|
|
mov eax, [esi].GENGC_rAccum ;U
|
|
mov ecx, [esi].GENGC_SPAN_dr ; V
|
|
mov edx, [esi].GENGC_gAccum ;U
|
|
add eax, ecx ; V
|
|
mov ecx, [esi].GENGC_SPAN_dg ;U
|
|
mov [esi].GENGC_rAccum, eax ; V
|
|
add edx, ecx ;U
|
|
mov eax, [esi].GENGC_bAccum ; V
|
|
mov ecx, [esi].GENGC_SPAN_db ;U
|
|
add eax, ecx ; V
|
|
mov [esi].GENGC_gAccum, edx ;U
|
|
mov [esi].GENGC_bAccum, eax ; V
|
|
|
|
mov eax, [esi].GENGC_ditherAccum ;U
|
|
mov ecx, [esi].GENGC_pixAccum ; V
|
|
ror eax, 8 ;U
|
|
mov edx, ecx ; V
|
|
if (BPP le 16)
|
|
add ecx, (BPP / 8) ;U
|
|
else
|
|
add ecx, [esi].GENGC_bytesPerPixel ;U
|
|
endif
|
|
mov [esi].GENGC_ditherAccum, eax ; V
|
|
mov [esi].GENGC_pixAccum, ecx ;U
|
|
|
|
if ALPHA
|
|
mov ecx, [esi].GENGC_aAccum
|
|
add ecx, [esi].GENGC_SPAN_da
|
|
mov [esi].GENGC_aAccum, ecx
|
|
endif
|
|
|
|
if (BPP eq 8)
|
|
mov al, [esi].GENGC_xlatPalette[ebx]; V
|
|
sub ebp, 010001h ;U
|
|
mov [edx], al ; V
|
|
elseif (BPP eq 16)
|
|
sub ebp, 010001h
|
|
mov [edx], bx
|
|
else
|
|
mov [edx], bx
|
|
shr ebx, 16
|
|
sub ebp, 010001h
|
|
mov [edx+2], bl
|
|
endif
|
|
|
|
;; Finish incrementing all of our accumulators
|
|
|
|
jl doSubDiv ;U
|
|
test ebp, 08000h ; V
|
|
je loopTopNoDiv ;U
|
|
|
|
endif ;;SMOOTH_SHADING
|
|
|
|
;;
|
|
;; This is the exit point. We need to pop the unused floating-point
|
|
;; registers off the stack, and return:
|
|
;;
|
|
|
|
spanExit:
|
|
|
|
fstp ST(0)
|
|
fstp ST(0)
|
|
|
|
pop ebp
|
|
pop edi
|
|
pop esi
|
|
pop ebx
|
|
|
|
ret 0
|
|
|
|
;;
|
|
;; This is the subdivision code. After the required number of steps, the
|
|
;; routine will jump here to calculate the next set of interpolants based
|
|
;; on subdivision:
|
|
;;
|
|
|
|
doSubDiv:
|
|
|
|
add ebp, 080000h
|
|
|
|
mov ecx, [esi].GENGC_flags
|
|
|
|
;;
|
|
;; Increment the big S and T steps:
|
|
;;
|
|
|
|
mov edx, [esi].GENGC_sAccum
|
|
|
|
test ebp, 08000h
|
|
jne short spanExit
|
|
|
|
mov ebx, [esi].GENGC_tAccum
|
|
|
|
add edx, [esi].GENGC_sStepX
|
|
add ebx, [esi].GENGC_tStepX
|
|
mov [esi].GENGC_sAccum, edx
|
|
mov [esi].GENGC_tAccum, ebx
|
|
mov eax, [esi].GENGC_sResultNew
|
|
mov ebx, [esi].GENGC_tResultNew
|
|
|
|
test ecx, GEN_TEXTURE_ORTHO
|
|
je @f
|
|
|
|
mov ecx, DWORD PTR [esi].GENGC_tAccum
|
|
mov DWORD PTR [esi].GENGC_sResultNew, edx
|
|
mov DWORD PTR [esi].GENGC_tResultNew, ecx
|
|
jmp short @stResultDone3
|
|
|
|
;;
|
|
;; Do the floating-point computation for perspective:
|
|
;;
|
|
|
|
@@:
|
|
|
|
fild DWORD PTR [esi].GENGC_sAccum ; s 1/qw qwAccum
|
|
fmul ST, ST(1) ; s/qw 1/qw qwAccum
|
|
fild DWORD PTr [esi].GENGC_tAccum ; t s/qw 1/qw qwAccum
|
|
fmulp ST(2), ST ; s/qw t/qw qwAccum
|
|
fistp QWORD PTR [esi].GENGC_sResultNew; t/qw qwAccum
|
|
fistp QWORD PTR [esi].GENGC_tResultNew; qwAccum
|
|
|
|
@stResultDone3:
|
|
|
|
;;
|
|
;; Now, calculate the per-pixel deltas:
|
|
;;
|
|
|
|
mov cl, TSHIFT_SUBDIV ;U
|
|
mov edx, [esi].GENGC_tResultNew ; V
|
|
sar edx, cl ;UV (4)
|
|
mov ecx, [esi].GENGC_sResultNew ;U
|
|
and edx, NOT 7 ; V
|
|
sub ecx, eax ;U
|
|
mov [esi].GENGC_tResultNew, edx ; V
|
|
sar ecx, 3 ;U
|
|
sub edx, ebx ; V
|
|
sar edx, 3 ;U
|
|
mov [esi].GENGC_subDs, ecx ; V
|
|
mov [esi].GENGC_subDt, edx ;U
|
|
mov [esi].GENGC_sResult, eax ; V
|
|
mov [esi].GENGC_tResult, ebx ;U
|
|
mov eax, [esi].GENGC_flags ; V
|
|
jmp loopTop ;U
|