CnC_Red_Alert/WWFLAT32/MCGAPRIM/SCALE.ASM

569 lines
15 KiB
NASM

;
; Command & Conquer Red Alert(tm)
; Copyright 2025 Electronic Arts Inc.
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
;
;***************************************************************************
;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : Westwood 32 bit Library *
;* *
;* File Name : SCALE.ASM *
;* *
;* Programmer : Phil W. Gorrow *
;* *
;* Start Date : June 16, 1994 *
;* *
;* Last Update : June 21, 1994 [PWG] *
;* New version : feb 12, 1995 [JRJ] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* VVC::Scale -- Scales a virtual viewport to another virtual viewport *
;* Normal_Draw -- jump loc for drawing scaled line of normal pixel *
;* Normal_Remapped_Draw -- jump loc for draw scaled line of remap pixel *
;* Transparent_Draw -- jump loc for scaled line of transparent pixels *
;* Transparent_Remapped_Draw -- jump loc for scaled remap trans pixels *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
INCLUDE "mcgaprim.inc"
INCLUDE ".\gbuffer.inc"
CODESEG
;***************************************************************************
;* VVC::SCALE -- Scales a virtual viewport to another virtual viewport *
;* *
;* INPUT: *
;* *
;* OUTPUT: *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;* 06/16/1994 PWG : Created. *
;*=========================================================================*
PROC Linear_Scale_To_Linear C NEAR
USES eax,ebx,ecx,edx,esi,edi
;*===================================================================
;* Define the arguements that our function takes.
;*===================================================================
ARG this:DWORD ; pointer to source view port
ARG dest:DWORD ; pointer to destination view port
ARG src_x:DWORD ; source x offset into view port
ARG src_y:DWORD ; source y offset into view port
ARG dst_x:DWORD ; dest x offset into view port
ARG dst_y:DWORD ; dest y offset into view port
ARG src_width:DWORD ; width of source rectangle
ARG src_height:DWORD ; height of source rectangle
ARG dst_width:DWORD ; width of dest rectangle
ARG dst_height:DWORD ; width of dest height
ARG trans:DWORD ; is this transparent?
ARG remap:DWORD ; pointer to table to remap source
;*===================================================================
;* Define local variables to hold the viewport characteristics
;*===================================================================
local src_x0 : dword
local src_y0 : dword
local src_x1 : dword
local src_y1 : dword
local dst_x0 : dword
local dst_y0 : dword
local dst_x1 : dword
local dst_y1 : dword
local src_win_width : dword
local dst_win_width : dword
local dy_intr : dword
local dy_frac : dword
local dy_acc : dword
local dx_frac : dword
local counter_x : dword
local counter_y : dword
local remap_counter :dword
local entry : dword
;*===================================================================
;* Check for scale error when to or from size 0,0
;*===================================================================
cmp [dst_width],0
je ??all_done
cmp [dst_height],0
je ??all_done
cmp [src_width],0
je ??all_done
cmp [src_height],0
je ??all_done
mov eax , [ src_x ]
mov ebx , [ src_y ]
mov [ src_x0 ] , eax
mov [ src_y0 ] , ebx
add eax , [ src_width ]
add ebx , [ src_height ]
mov [ src_x1 ] , eax
mov [ src_y1 ] , ebx
mov eax , [ dst_x ]
mov ebx , [ dst_y ]
mov [ dst_x0 ] , eax
mov [ dst_y0 ] , ebx
add eax , [ dst_width ]
add ebx , [ dst_height ]
mov [ dst_x1 ] , eax
mov [ dst_y1 ] , ebx
; Clip Source Rectangle against source Window boundaries.
mov esi , [ this ] ; get ptr to src
xor ecx , ecx
xor edx , edx
mov edi , [ (VideoViewPort esi) . VIVPWidth ] ; get width into register
mov eax , [ src_x0 ]
mov ebx , [ src_x1 ]
shld ecx , eax , 1
inc edi
shld edx , ebx , 1
sub eax , edi
sub ebx , edi
shld ecx , eax , 1
shld edx , ebx , 1
mov edi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register
mov eax , [ src_y0 ]
mov ebx , [ src_y1 ]
shld ecx , eax , 1
inc edi
shld edx , ebx , 1
sub eax , edi
sub ebx , edi
shld ecx , eax , 1
shld edx , ebx , 1
xor cl , 5
xor dl , 5
mov al , cl
test dl , cl
jnz ??all_done
or al , dl
jz ??clip_against_dest
mov bl , dl
test cl , 1000b
jz ??src_left_ok
xor eax , eax
mov [ src_x0 ] , eax
sub eax , [ src_x ]
imul [ dst_width ]
idiv [ src_width ]
add eax , [ dst_x ]
mov [ dst_x0 ] , eax
??src_left_ok:
test cl , 0010b
jz ??src_bottom_ok
xor eax , eax
mov [ src_y0 ] , eax
sub eax , [ src_y ]
imul [ dst_height ]
idiv [ src_height ]
add eax , [ dst_y ]
mov [ dst_y0 ] , eax
??src_bottom_ok:
test bl , 0100b
jz ??src_right_ok
mov eax , [ (VideoViewPort esi) . VIVPWidth ] ; get width into register
mov [ src_x1 ] , eax
sub eax , [ src_x ]
imul [ dst_width ]
idiv [ src_width ]
add eax , [ dst_x ]
mov [ dst_x1 ] , eax
??src_right_ok:
test bl , 0001b
jz ??clip_against_dest
mov eax , [ (VideoViewPort esi) . VIVPHeight ] ; get width into register
mov [ src_y1 ] , eax
sub eax , [ src_y ]
imul [ dst_height ]
idiv [ src_height ]
add eax , [ dst_y ]
mov [ dst_y1 ] , eax
; Clip destination Rectangle against source Window boundaries.
??clip_against_dest:
mov esi , [ dest ] ; get ptr to src
xor ecx , ecx
xor edx , edx
mov edi , [ (VideoViewPort esi) . VIVPWidth ] ; get width into register
mov eax , [ dst_x0 ]
mov ebx , [ dst_x1 ]
shld ecx , eax , 1
inc edi
shld edx , ebx , 1
sub eax , edi
sub ebx , edi
shld ecx , eax , 1
shld edx , ebx , 1
mov edi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register
mov eax , [ dst_y0 ]
mov ebx , [ dst_y1 ]
shld ecx , eax , 1
inc edi
shld edx , ebx , 1
sub eax , edi
sub ebx , edi
shld ecx , eax , 1
shld edx , ebx , 1
xor cl , 5
xor dl , 5
mov al , cl
test dl , cl
jnz ??all_done
or al , dl
jz ??do_scaling
mov bl , dl
test cl , 1000b
jz ??dst_left_ok
xor eax , eax
mov [ dst_x0 ] , eax
sub eax , [ dst_x ]
imul [ src_width ]
idiv [ dst_width ]
add eax , [ src_x ]
mov [ src_x0 ] , eax
??dst_left_ok:
test cl , 0010b
jz ??dst_bottom_ok
xor eax , eax
mov [ dst_y0 ] , eax
sub eax , [ dst_y ]
imul [ src_height ]
idiv [ dst_height ]
add eax , [ src_y ]
mov [ src_y0 ] , eax
??dst_bottom_ok:
test bl , 0100b
jz ??dst_right_ok
mov eax , [ (VideoViewPort esi) . VIVPWidth ] ; get width into register
mov [ dst_x1 ] , eax
sub eax , [ dst_x ]
imul [ src_width ]
idiv [ dst_width ]
add eax , [ src_x ]
mov [ src_x1 ] , eax
??dst_right_ok:
test bl , 0001b
jz ??do_scaling
mov eax , [ (VideoViewPort esi) . VIVPHeight ] ; get width into register
mov [ dst_y1 ] , eax
sub eax , [ dst_y ]
imul [ src_height ]
idiv [ dst_height ]
add eax , [ src_y ]
mov [ src_y1 ] , eax
??do_scaling:
cld
mov ebx , [ this ]
mov esi , [ (VideoViewPort ebx) . VIVPOffset ]
mov eax , [ (VideoViewPort ebx) . VIVPXAdd ]
add eax , [ (VideoViewPort ebx) . VIVPWidth ]
mov [ src_win_width ] , eax
mul [ src_y0 ]
add esi , [ src_x0 ]
add esi , eax
mov ebx , [ dest ]
mov edi , [ (VideoViewPort ebx) . VIVPOffset ]
mov eax , [ (VideoViewPort ebx) . VIVPXAdd ]
add eax , [ (VideoViewPort ebx) . VIVPWidth ]
mov [ dst_win_width ] , eax
mul [ dst_y0 ]
add edi , [ dst_x0 ]
add edi , eax
mov eax , [ src_height ]
xor edx , edx
mov ebx , [ dst_height ]
idiv [ dst_height ]
imul eax , [ src_win_width ]
neg ebx
mov [ dy_intr ] , eax
mov [ dy_frac ] , edx
mov [ dy_acc ] , ebx
mov eax , [ src_width ]
xor edx , edx
shl eax , 16
idiv [ dst_width ]
xor edx , edx
shld edx , eax , 16
shl eax , 16
mov ecx , [ dst_y1 ]
mov ebx , [ dst_x1 ]
sub ecx , [ dst_y0 ]
jle ??all_done
sub ebx , [ dst_x0 ]
jle ??all_done
mov [ counter_y ] , ecx
cmp [ trans ] , 0
jnz ??transparency
cmp [ remap ] , 0
jnz ??normal_remap
; *************************************************************************
; normal scale
mov ecx , ebx
and ecx , 01fh
lea ecx , [ ecx + ecx * 2 ]
shr ebx , 5
neg ecx
mov [ counter_x ] , ebx
lea ecx , [ ??ref_point + ecx + ecx * 2 ]
mov [ entry ] , ecx
??outter_loop:
push esi
push edi
xor ecx , ecx
mov ebx , [ counter_x ]
jmp [ entry ]
??inner_loop:
REPT 32
mov cl , [ esi ]
add ecx , eax
adc esi , edx
mov [ edi ] , cl
inc edi
ENDM
??ref_point:
dec ebx
jge ??inner_loop
pop edi
pop esi
add edi , [ dst_win_width ]
add esi , [ dy_intr ]
mov ebx , [ dy_acc ]
add ebx , [ dy_frac ]
jle ??skip_line
add esi , [ src_win_width ]
sub ebx , [ dst_height ]
??skip_line:
dec [ counter_y ]
mov [ dy_acc ] , ebx
jnz ??outter_loop
ret
; *************************************************************************
; normal scale with remap
??normal_remap:
mov ecx , ebx
mov [ dx_frac ], eax
and ecx , 01fh
mov eax , [ remap ]
shr ebx , 5
imul ecx , - 13
mov [ counter_x ] , ebx
lea ecx , [ ??remapref_point + ecx ]
mov [ entry ] , ecx
??remapoutter_loop:
mov ebx , [ counter_x ]
push esi
mov [ remap_counter ] , ebx
push edi
xor ecx , ecx
xor ebx , ebx
jmp [ entry ]
??remapinner_loop:
REPT 32
mov bl , [ esi ]
add ecx , [ dx_frac ]
adc esi , edx
mov cl , [ eax + ebx ]
mov [ edi ] , cl
inc edi
ENDM
??remapref_point:
dec [ remap_counter ]
jge ??remapinner_loop
pop edi
pop esi
add edi , [ dst_win_width ]
add esi , [ dy_intr ]
mov ebx , [ dy_acc ]
add ebx , [ dy_frac ]
jle ??remapskip_line
add esi , [ src_win_width ]
sub ebx , [ dst_height ]
??remapskip_line:
dec [ counter_y ]
mov [ dy_acc ] , ebx
jnz ??remapoutter_loop
ret
;****************************************************************************
; scale with trnsparency
??transparency:
cmp [ remap ] , 0
jnz ??trans_remap
; *************************************************************************
; normal scale with transparency
mov ecx , ebx
and ecx , 01fh
imul ecx , -13
shr ebx , 5
mov [ counter_x ] , ebx
lea ecx , [ ??trans_ref_point + ecx ]
mov [ entry ] , ecx
??trans_outter_loop:
xor ecx , ecx
push esi
push edi
mov ebx , [ counter_x ]
jmp [ entry ]
??trans_inner_loop:
REPT 32
local trans_pixel
mov cl , [ esi ]
test cl , cl
jz trans_pixel
mov [ edi ] , cl
trans_pixel:
add ecx , eax
adc esi , edx
inc edi
ENDM
??trans_ref_point:
dec ebx
jge ??trans_inner_loop
pop edi
pop esi
add edi , [ dst_win_width ]
add esi , [ dy_intr ]
mov ebx , [ dy_acc ]
add ebx , [ dy_frac ]
jle ??trans_skip_line
add esi , [ src_win_width ]
sub ebx , [ dst_height ]
??trans_skip_line:
dec [ counter_y ]
mov [ dy_acc ] , ebx
jnz ??trans_outter_loop
ret
; *************************************************************************
; normal scale with remap
??trans_remap:
mov ecx , ebx
mov [ dx_frac ], eax
and ecx , 01fh
mov eax , [ remap ]
shr ebx , 5
imul ecx , - 17
mov [ counter_x ] , ebx
lea ecx , [ ??trans_remapref_point + ecx ]
mov [ entry ] , ecx
??trans_remapoutter_loop:
mov ebx , [ counter_x ]
push esi
mov [ remap_counter ] , ebx
push edi
xor ecx , ecx
xor ebx , ebx
jmp [ entry ]
??trans_remapinner_loop:
REPT 32
local trans_pixel
mov bl , [ esi ]
test bl , bl
jz trans_pixel
mov cl , [ eax + ebx ]
mov [ edi ] , cl
trans_pixel:
add ecx , [ dx_frac ]
adc esi , edx
inc edi
ENDM
??trans_remapref_point:
dec [ remap_counter ]
jge ??trans_remapinner_loop
pop edi
pop esi
add edi , [ dst_win_width ]
add esi , [ dy_intr ]
mov ebx , [ dy_acc ]
add ebx , [ dy_frac ]
jle ??trans_remapskip_line
add esi , [ src_win_width ]
sub ebx , [ dst_height ]
??trans_remapskip_line:
dec [ counter_y ]
mov [ dy_acc ] , ebx
jnz ??trans_remapoutter_loop
ret
??all_done:
ret
endp
END